mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-26 02:44:08 +01:00
Compare commits
57 Commits
v5.41.0-de
...
v5.42.0-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a3a12df1a | ||
|
|
ae4b9474d3 | ||
|
|
83ccd9d3f1 | ||
|
|
526c7c05e2 | ||
|
|
d0d53d109e | ||
|
|
9d6731660b | ||
|
|
5a7e199162 | ||
|
|
0c662c8e3b | ||
|
|
08e8ead04f | ||
|
|
d238a42708 | ||
|
|
673609c2aa | ||
|
|
5f1a485e8f | ||
|
|
6961babee9 | ||
|
|
328c9b6bbe | ||
|
|
4c8b56f546 | ||
|
|
1754023dd6 | ||
|
|
328234f39a | ||
|
|
326953cfc3 | ||
|
|
725d5dc974 | ||
|
|
76b0364c5b | ||
|
|
1cbff799ad | ||
|
|
080a226614 | ||
|
|
2b71bd80c2 | ||
|
|
5cb46c4e91 | ||
|
|
52c369576d | ||
|
|
28799a548a | ||
|
|
1c80774d79 | ||
|
|
7817885cff | ||
|
|
9afe9afc67 | ||
|
|
3a8091ae00 | ||
|
|
6192ece114 | ||
|
|
5d9971444e | ||
|
|
cdfa75dd5a | ||
|
|
6f92b6c50b | ||
|
|
1e023fa1f3 | ||
|
|
00477bfebc | ||
|
|
4be00d09b7 | ||
|
|
50aca3314f | ||
|
|
15a7e540de | ||
|
|
041f7e0140 | ||
|
|
3bd76d60d6 | ||
|
|
1587178ff8 | ||
|
|
8a69240d66 | ||
|
|
7a37d858fb | ||
|
|
0ed7067459 | ||
|
|
6102644194 | ||
|
|
a89556a017 | ||
|
|
2b555f67f0 | ||
|
|
fb87199514 | ||
|
|
dd4e2cd085 | ||
|
|
fadc66816d | ||
|
|
ffd933c673 | ||
|
|
69883530b7 | ||
|
|
39971291f3 | ||
|
|
51facf9321 | ||
|
|
b83d41ca88 | ||
|
|
bfbffbd1f5 |
4
.github/workflows/build_pull_request.yml
vendored
4
.github/workflows/build_pull_request.yml
vendored
@@ -12,10 +12,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
|
||||
2
.github/workflows/open_pull_request.yml
vendored
2
.github/workflows/open_pull_request.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Open pull request
|
||||
uses: repo-sync/pull-request@v2
|
||||
|
||||
2
.github/workflows/pull_strings.yml
vendored
2
.github/workflows/pull_strings.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
ref: dev
|
||||
clean: true
|
||||
|
||||
2
.github/workflows/push_strings.yml
vendored
2
.github/workflows/push_strings.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Preprocess strings
|
||||
env:
|
||||
|
||||
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
@@ -18,10 +18,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
@@ -51,14 +51,14 @@ jobs:
|
||||
fingerprint: ${{ vars.GPG_FINGERPRINT }}
|
||||
|
||||
- name: Release
|
||||
uses: cycjimmy/semantic-release-action@v4
|
||||
uses: cycjimmy/semantic-release-action@v5
|
||||
id: release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Attest
|
||||
if: steps.release.outputs.new_release_published == 'true'
|
||||
uses: actions/attest-build-provenance@v2
|
||||
uses: actions/attest-build-provenance@v3
|
||||
with:
|
||||
subject-name: 'ReVanced Patches ${{ steps.release.outputs.new_release_git_tag }}'
|
||||
subject-path: patches/build/libs/patches-*.rvp
|
||||
|
||||
2
.github/workflows/update-gradle-wrapper.yml
vendored
2
.github/workflows/update-gradle-wrapper.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Update Gradle Wrapper
|
||||
uses: gradle-update/update-gradle-wrapper-action@v1
|
||||
|
||||
168
CHANGELOG.md
168
CHANGELOG.md
@@ -1,3 +1,171 @@
|
||||
# [5.42.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.42.0-dev.8...v5.42.0-dev.9) (2025-10-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Custom branding:** Update ReVanced logo sizing ([#6029](https://github.com/ReVanced/revanced-patches/issues/6029)) ([ae4b947](https://github.com/ReVanced/revanced-patches/commit/ae4b9474d3fb62528fc21397c19954d31605e9da))
|
||||
|
||||
# [5.42.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.42.0-dev.7...v5.42.0-dev.8) (2025-10-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Force original language:** Resolve some videos using Swedish audio track ([9d67316](https://github.com/ReVanced/revanced-patches/commit/9d6731660ba0e19b863d05d54aa04f74a879f69b))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube Music:** Add `Force original audio` patch ([#6036](https://github.com/ReVanced/revanced-patches/issues/6036)) ([d0d53d1](https://github.com/ReVanced/revanced-patches/commit/d0d53d109e451759a029326873adfa36fba12b23))
|
||||
|
||||
# [5.42.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.42.0-dev.6...v5.42.0-dev.7) (2025-10-01)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Instagram:** Add `Open links externally` patch ([#6012](https://github.com/ReVanced/revanced-patches/issues/6012)) ([08e8ead](https://github.com/ReVanced/revanced-patches/commit/08e8ead04ffff47a4608a3db7aadc8d5feccd4ad))
|
||||
|
||||
# [5.42.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.42.0-dev.5...v5.42.0-dev.6) (2025-09-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **X / Twitter:** Remove non functional and obsolete patch `Open links with app chooser` ([#6033](https://github.com/ReVanced/revanced-patches/issues/6033)) ([673609c](https://github.com/ReVanced/revanced-patches/commit/673609c2aa87988cdc138eab101b9750fe6a7b62))
|
||||
|
||||
# [5.42.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.42.0-dev.4...v5.42.0-dev.5) (2025-09-28)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube Music:** Add `Custom branding` patch ([#6007](https://github.com/ReVanced/revanced-patches/issues/6007)) ([4c8b56f](https://github.com/ReVanced/revanced-patches/commit/4c8b56f5466b244737f501654eb7c5d34b6b2f88))
|
||||
|
||||
# [5.42.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.42.0-dev.3...v5.42.0-dev.4) (2025-09-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube Music - GmsCore support:** Handle sharing links to certain apps such as Instagram ([#6026](https://github.com/ReVanced/revanced-patches/issues/6026)) ([328234f](https://github.com/ReVanced/revanced-patches/commit/328234f39ada81542e596f04e8ce410c787c15c8))
|
||||
|
||||
# [5.42.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.42.0-dev.2...v5.42.0-dev.3) (2025-09-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide end screen cards:** Hide new type of end screen card ([#6027](https://github.com/ReVanced/revanced-patches/issues/6027)) ([76b0364](https://github.com/ReVanced/revanced-patches/commit/76b0364c5b5562c6a0d178d2bbe5b220f48aaca9))
|
||||
|
||||
# [5.42.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.42.0-dev.1...v5.42.0-dev.2) (2025-09-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Instagram - Hide navigation buttons:** Resolve app startup crash ([080a226](https://github.com/ReVanced/revanced-patches/commit/080a2266146798be71789c939deef2f289697523))
|
||||
|
||||
# [5.42.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.41.1-dev.2...v5.42.0-dev.1) (2025-09-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Viber:** Add `Hide navigation buttons` patch ([#5991](https://github.com/ReVanced/revanced-patches/issues/5991)) ([5cb46c4](https://github.com/ReVanced/revanced-patches/commit/5cb46c4e9180ebc16eddb983dad73d137d8ec047))
|
||||
|
||||
## [5.41.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.41.1-dev.1...v5.41.1-dev.2) (2025-09-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube Music - Hide cast button:** Fix patching error ([28799a5](https://github.com/ReVanced/revanced-patches/commit/28799a548a73651134ef304cb6cb542cf8e55abe))
|
||||
|
||||
## [5.41.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.41.0...v5.41.1-dev.1) (2025-09-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube Music - Hide cast button:** Resolve button not hiding ([7817885](https://github.com/ReVanced/revanced-patches/commit/7817885cffed66608039ab45881537cbd3069c9d))
|
||||
|
||||
# [5.41.0](https://github.com/ReVanced/revanced-patches/compare/v5.40.0...v5.41.0) (2025-09-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Instagram - Hide navigation buttons:** Remove button based on name ([#5971](https://github.com/ReVanced/revanced-patches/issues/5971)) ([6fa4043](https://github.com/ReVanced/revanced-patches/commit/6fa404331b5162682d83fba5f38ed570c31495fc))
|
||||
* **Instagram - Limit feed to followed profiles:** Preserve favorites feed ([#5963](https://github.com/ReVanced/revanced-patches/issues/5963)) ([ef51401](https://github.com/ReVanced/revanced-patches/commit/ef514017f46025d9aef6884424caeb0670514e7a))
|
||||
* **TikTok:** Show correct dialog restart text, use correct font color for non-dark mode ([d1a1293](https://github.com/ReVanced/revanced-patches/commit/d1a12930c35f630793a0f240d4203c2ff9060158))
|
||||
* **Twitch - Settings:** Fix missing style resources ([#5970](https://github.com/ReVanced/revanced-patches/issues/5970)) ([8c22995](https://github.com/ReVanced/revanced-patches/commit/8c229954d7f232a7a472ca49f1b5e7cdc475bbcc))
|
||||
* **YouTube - Hide Shorts components:** Fix "Hide preview comment" ([#5990](https://github.com/ReVanced/revanced-patches/issues/5990)) ([dd4e2cd](https://github.com/ReVanced/revanced-patches/commit/dd4e2cd0855ccc51b94593004fdd8150ac3b41cc))
|
||||
* **YouTube - Return YouTube Dislike:** Do not show error toast if API returns 401 status ([#5949](https://github.com/ReVanced/revanced-patches/issues/5949)) ([58d088a](https://github.com/ReVanced/revanced-patches/commit/58d088ab307440a6912a867246da799b7dd6499b))
|
||||
* **YouTube - Settings:** Handle on screen back swipe gesture ([#6002](https://github.com/ReVanced/revanced-patches/issues/6002)) ([6f92b6c](https://github.com/ReVanced/revanced-patches/commit/6f92b6c50beab091f5f7ef7386579eda38cb4c66))
|
||||
* **YouTube - Settings:** Use an overlay to show search results ([#5806](https://github.com/ReVanced/revanced-patches/issues/5806)) ([ece8076](https://github.com/ReVanced/revanced-patches/commit/ece8076f7cefd752b97515014bc50fe4fd80171e))
|
||||
* **YouTube - SponsorBlock:** Show category color dot in voting dialog menu ([4be00d0](https://github.com/ReVanced/revanced-patches/commit/4be00d09b7b87dcfac324de8709af06e9f730791))
|
||||
* **YouTube - SponsorBlock:** Show category color in create new segment menu ([#5987](https://github.com/ReVanced/revanced-patches/issues/5987)) ([ffd933c](https://github.com/ReVanced/revanced-patches/commit/ffd933c6734274cdde5aaec0159b67f173f9228c))
|
||||
* **YouTube - Spoof video streams:** Update client side effects summary text ([a0a62dd](https://github.com/ReVanced/revanced-patches/commit/a0a62ddad26cfab3e04907fae5532e1ba1fdf710))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Tumblr:** Add `Disable Tumblr TV` patch ([#5959](https://github.com/ReVanced/revanced-patches/issues/5959)) ([212418b](https://github.com/ReVanced/revanced-patches/commit/212418b8db9a730ae9efa89ad2bef24952afbadd))
|
||||
* **YouTube - Hide layout components:** Add "Hide Emoji and Timestamp buttons" setting ([#5992](https://github.com/ReVanced/revanced-patches/issues/5992)) ([2b555f6](https://github.com/ReVanced/revanced-patches/commit/2b555f67f07e0de5703c630888ce2fbba3145192))
|
||||
* **YouTube - Hide layout components:** Add "Hide view count" and "Hide upload time" settings ([#5983](https://github.com/ReVanced/revanced-patches/issues/5983)) ([7a37d85](https://github.com/ReVanced/revanced-patches/commit/7a37d858fb937c6bdc2219103dac765b62600e6c))
|
||||
* **YouTube - Loop video:** Add player button to change loop video state ([#5961](https://github.com/ReVanced/revanced-patches/issues/5961)) ([dfb5407](https://github.com/ReVanced/revanced-patches/commit/dfb5407e67222e80e23c8935e04b6dbf1a43d757))
|
||||
* **YouTube - Spoof app version:** Add spoof target `20.05.46` that fixes transcript functionality ([5823f0e](https://github.com/ReVanced/revanced-patches/commit/5823f0e982e87b4a35d30feeca8a7e16edfebc5f))
|
||||
* **YouTube Music:** Add `Check watch history domain name resolution` ([#5979](https://github.com/ReVanced/revanced-patches/issues/5979)) ([8af70fe](https://github.com/ReVanced/revanced-patches/commit/8af70fe2d10c0f4da2d7e53bd00f5b3979775d5d))
|
||||
* **YouTube Music:** Add `Sanitize sharing links` patch ([#5952](https://github.com/ReVanced/revanced-patches/issues/5952)) ([45c1ee8](https://github.com/ReVanced/revanced-patches/commit/45c1ee8a12dc777a371875d90741a05cf5d8e9dd))
|
||||
* **YouTube Music:** Add `Theme` patch ([#5984](https://github.com/ReVanced/revanced-patches/issues/5984)) ([3bd76d6](https://github.com/ReVanced/revanced-patches/commit/3bd76d60d664befff29c24c9de56dac1486a6e67))
|
||||
* **YouTube:** Add `Disable video codecs` patch ([#5981](https://github.com/ReVanced/revanced-patches/issues/5981)) ([bfbffbd](https://github.com/ReVanced/revanced-patches/commit/bfbffbd1f5aa867027053e25b343a51a606216a3))
|
||||
|
||||
# [5.41.0-dev.18](https://github.com/ReVanced/revanced-patches/compare/v5.41.0-dev.17...v5.41.0-dev.18) (2025-09-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Settings:** Handle on screen back swipe gesture ([#6002](https://github.com/ReVanced/revanced-patches/issues/6002)) ([6f92b6c](https://github.com/ReVanced/revanced-patches/commit/6f92b6c50beab091f5f7ef7386579eda38cb4c66))
|
||||
|
||||
# [5.41.0-dev.17](https://github.com/ReVanced/revanced-patches/compare/v5.41.0-dev.16...v5.41.0-dev.17) (2025-09-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - SponsorBlock:** Show category color dot in voting dialog menu ([4be00d0](https://github.com/ReVanced/revanced-patches/commit/4be00d09b7b87dcfac324de8709af06e9f730791))
|
||||
|
||||
# [5.41.0-dev.16](https://github.com/ReVanced/revanced-patches/compare/v5.41.0-dev.15...v5.41.0-dev.16) (2025-09-26)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube Music:** Add `Theme` patch ([#5984](https://github.com/ReVanced/revanced-patches/issues/5984)) ([3bd76d6](https://github.com/ReVanced/revanced-patches/commit/3bd76d60d664befff29c24c9de56dac1486a6e67))
|
||||
|
||||
# [5.41.0-dev.15](https://github.com/ReVanced/revanced-patches/compare/v5.41.0-dev.14...v5.41.0-dev.15) (2025-09-25)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide layout components:** Add "Hide view count" and "Hide upload time" settings ([#5983](https://github.com/ReVanced/revanced-patches/issues/5983)) ([7a37d85](https://github.com/ReVanced/revanced-patches/commit/7a37d858fb937c6bdc2219103dac765b62600e6c))
|
||||
|
||||
# [5.41.0-dev.14](https://github.com/ReVanced/revanced-patches/compare/v5.41.0-dev.13...v5.41.0-dev.14) (2025-09-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide layout components:** Add "Hide Emoji and Timestamp buttons" setting ([#5992](https://github.com/ReVanced/revanced-patches/issues/5992)) ([2b555f6](https://github.com/ReVanced/revanced-patches/commit/2b555f67f07e0de5703c630888ce2fbba3145192))
|
||||
|
||||
# [5.41.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v5.41.0-dev.12...v5.41.0-dev.13) (2025-09-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide Shorts components:** Fix "Hide preview comment" ([#5990](https://github.com/ReVanced/revanced-patches/issues/5990)) ([dd4e2cd](https://github.com/ReVanced/revanced-patches/commit/dd4e2cd0855ccc51b94593004fdd8150ac3b41cc))
|
||||
|
||||
# [5.41.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v5.41.0-dev.11...v5.41.0-dev.12) (2025-09-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - SponsorBlock:** Show category color in create new segment menu ([#5987](https://github.com/ReVanced/revanced-patches/issues/5987)) ([ffd933c](https://github.com/ReVanced/revanced-patches/commit/ffd933c6734274cdde5aaec0159b67f173f9228c))
|
||||
|
||||
# [5.41.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v5.41.0-dev.10...v5.41.0-dev.11) (2025-09-23)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Add `Disable video codecs` patch ([#5981](https://github.com/ReVanced/revanced-patches/issues/5981)) ([bfbffbd](https://github.com/ReVanced/revanced-patches/commit/bfbffbd1f5aa867027053e25b343a51a606216a3))
|
||||
|
||||
# [5.41.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.41.0-dev.9...v5.41.0-dev.10) (2025-09-23)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package app.revanced.extension.instagram.misc.links;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class OpenLinksExternallyPatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean openExternally(String url) {
|
||||
try {
|
||||
// The "url" parameter to this function will be of the form.
|
||||
// https://l.instagram.com/?u=<actual url>&e=<tracking id>
|
||||
String actualUrl = Uri.parse(url).getQueryParameter("u");
|
||||
if (actualUrl != null) {
|
||||
Utils.openLink(actualUrl);
|
||||
return true;
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "openExternally failure", ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package app.revanced.extension.music.patches;
|
||||
|
||||
import app.revanced.extension.music.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ForceOriginalAudioPatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void setPreferredLanguage() {
|
||||
app.revanced.extension.shared.patches.ForceOriginalAudioPatch.setEnabled(
|
||||
Settings.FORCE_ORIGINAL_AUDIO.get(),
|
||||
Settings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package app.revanced.extension.music.patches.theme;
|
||||
|
||||
import app.revanced.extension.shared.theme.BaseThemePatch;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ThemePatch extends BaseThemePatch {
|
||||
|
||||
// Color constants used in relation with litho components.
|
||||
private static final int[] DARK_VALUES = {
|
||||
0xFF212121, // Comments box background.
|
||||
0xFF030303, // Button container background in album.
|
||||
0xFF000000, // Button container background in playlist.
|
||||
};
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* <p>
|
||||
* Change the color of Litho components.
|
||||
* If the color of the component matches one of the values, return the background color.
|
||||
*
|
||||
* @param originalValue The original color value.
|
||||
* @return The new or original color value.
|
||||
*/
|
||||
public static int getValue(int originalValue) {
|
||||
return processColorValue(originalValue, DARK_VALUES, null);
|
||||
}
|
||||
}
|
||||
@@ -32,4 +32,6 @@ public class Settings extends BaseSettings {
|
||||
// Miscellaneous
|
||||
public static final EnumSetting<ClientType> SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client_type",
|
||||
ClientType.ANDROID_VR_1_43_32, true, parent(SPOOF_VIDEO_STREAMS));
|
||||
|
||||
public static final BooleanSetting FORCE_ORIGINAL_AUDIO = new BooleanSetting("revanced_force_original_audio", TRUE, true);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
@@ -696,6 +697,18 @@ public class Utils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void openLink(String url) {
|
||||
try {
|
||||
Intent intent = new Intent("android.intent.action.VIEW", Uri.parse(url));
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
Logger.printInfo(() -> "Opening link with external browser: " + intent);
|
||||
getContext().startActivity(intent);
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "openLink failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public enum NetworkType {
|
||||
NONE,
|
||||
MOBILE,
|
||||
|
||||
@@ -46,7 +46,7 @@ public class CheckWatchHistoryDomainNameResolutionPatch {
|
||||
/**
|
||||
* Injection point.
|
||||
*
|
||||
* Checks if s.youtube.com is blacklisted and playback history will fail to work.
|
||||
* Checks if YouTube watch history endpoint cannot be reached.
|
||||
*/
|
||||
public static void checkDnsResolver(Activity context) {
|
||||
if (!Utils.isNetworkConnected() || !BaseSettings.CHECK_WATCH_HISTORY_DOMAIN_NAME.get()) return;
|
||||
@@ -67,28 +67,20 @@ public class CheckWatchHistoryDomainNameResolutionPatch {
|
||||
}
|
||||
|
||||
Utils.runOnMainThread(() -> {
|
||||
try {
|
||||
// Create the custom dialog.
|
||||
Pair<Dialog, LinearLayout> dialogPair = CustomDialog.create(
|
||||
context,
|
||||
str("revanced_check_watch_history_domain_name_dialog_title"), // Title.
|
||||
Html.fromHtml(str("revanced_check_watch_history_domain_name_dialog_message")), // Message (HTML).
|
||||
null, // No EditText.
|
||||
null, // OK button text.
|
||||
() -> {}, // OK button action (just dismiss).
|
||||
() -> {}, // Cancel button action (just dismiss).
|
||||
str("revanced_check_watch_history_domain_name_dialog_ignore"), // Neutral button text.
|
||||
() -> BaseSettings.CHECK_WATCH_HISTORY_DOMAIN_NAME.save(false), // Neutral button action (Ignore).
|
||||
true // Dismiss dialog on Neutral button click.
|
||||
);
|
||||
Pair<Dialog, LinearLayout> dialogPair = CustomDialog.create(
|
||||
context,
|
||||
str("revanced_check_watch_history_domain_name_dialog_title"), // Title.
|
||||
Html.fromHtml(str("revanced_check_watch_history_domain_name_dialog_message")), // Message (HTML).
|
||||
null, // No EditText.
|
||||
null, // OK button text.
|
||||
() -> {}, // OK button action (just dismiss).
|
||||
null, // No cancel button.
|
||||
str("revanced_check_watch_history_domain_name_dialog_ignore"), // Neutral button text.
|
||||
() -> BaseSettings.CHECK_WATCH_HISTORY_DOMAIN_NAME.save(false), // Neutral button action (Ignore).
|
||||
true // Dismiss dialog on Neutral button click.
|
||||
);
|
||||
|
||||
// Show the dialog.
|
||||
Dialog dialog = dialogPair.first;
|
||||
|
||||
Utils.showDialog(context, dialog, false, null);
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "checkDnsResolver dialog creation failure", ex);
|
||||
}
|
||||
Utils.showDialog(context, dialogPair.first, false, null);
|
||||
});
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "checkDnsResolver failure", ex);
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package app.revanced.extension.shared.patches;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.settings.AppLanguage;
|
||||
import app.revanced.extension.shared.spoof.ClientType;
|
||||
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ForceOriginalAudioPatch {
|
||||
|
||||
private static final String DEFAULT_AUDIO_TRACKS_SUFFIX = ".4";
|
||||
|
||||
private static volatile boolean enabled = false;
|
||||
|
||||
public static void setEnabled(boolean isEnabled, ClientType client) {
|
||||
enabled = isEnabled;
|
||||
|
||||
if (isEnabled
|
||||
&& SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams()
|
||||
&& !client.useAuth) {
|
||||
// If client spoofing does not use authentication and lacks multi-audio streams,
|
||||
// then can use any language code for the request and if that requested language is
|
||||
// not available YT uses the original audio language. Authenticated requests ignore
|
||||
// the language code and always use the account language. Use a language that is
|
||||
// not auto-dubbed by YouTube: https://support.google.com/youtube/answer/15569972
|
||||
// but the language is also supported natively by the Meta Quest device that
|
||||
// Android VR is spoofing.
|
||||
AppLanguage override = AppLanguage.NB; // Norwegian Bokmal.
|
||||
Logger.printDebug(() -> "Setting language override: " + override);
|
||||
SpoofVideoStreamsPatch.setLanguageOverride(override);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean ignoreDefaultAudioStream(boolean original) {
|
||||
if (enabled) {
|
||||
return false;
|
||||
}
|
||||
return original;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean isDefaultAudioStream(boolean isDefault, String audioTrackId, String audioTrackDisplayName) {
|
||||
try {
|
||||
if (!enabled) {
|
||||
return isDefault;
|
||||
}
|
||||
|
||||
if (audioTrackId.isEmpty()) {
|
||||
// Older app targets can have empty audio tracks and these might be placeholders.
|
||||
// The real audio tracks are called after these.
|
||||
return isDefault;
|
||||
}
|
||||
|
||||
Logger.printDebug(() -> "default: " + String.format("%-5s", isDefault) + " id: "
|
||||
+ String.format("%-8s", audioTrackId) + " name:" + audioTrackDisplayName);
|
||||
|
||||
final boolean isOriginal = audioTrackId.endsWith(DEFAULT_AUDIO_TRACKS_SUFFIX);
|
||||
if (isOriginal) {
|
||||
Logger.printDebug(() -> "Using audio: " + audioTrackId);
|
||||
}
|
||||
|
||||
return isOriginal;
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "isDefaultAudioStream failure", ex);
|
||||
return isDefault;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,8 +36,8 @@ public enum AppLanguage {
|
||||
FR,
|
||||
GL,
|
||||
GU,
|
||||
HI,
|
||||
HE, // App uses obsolete 'IW' and not the modern 'HE' ISO code.
|
||||
HI,
|
||||
HR,
|
||||
HU,
|
||||
HY,
|
||||
@@ -60,9 +60,9 @@ public enum AppLanguage {
|
||||
MR,
|
||||
MS,
|
||||
MY,
|
||||
NB,
|
||||
NE,
|
||||
NL,
|
||||
NB,
|
||||
OR,
|
||||
PA,
|
||||
PL,
|
||||
|
||||
@@ -53,7 +53,7 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
* Set by subclasses if Strings cannot be added as a resource.
|
||||
*/
|
||||
@Nullable
|
||||
protected static String restartDialogTitle, restartDialogMessage, restartDialogButtonText, confirmDialogTitle;
|
||||
protected static CharSequence restartDialogTitle, restartDialogMessage, restartDialogButtonText, confirmDialogTitle;
|
||||
|
||||
private final SharedPreferences.OnSharedPreferenceChangeListener listener = (sharedPreferences, str) -> {
|
||||
try {
|
||||
@@ -125,10 +125,13 @@ public abstract class AbstractPreferenceFragment extends PreferenceFragment {
|
||||
|
||||
showingUserDialogMessage = true;
|
||||
|
||||
CharSequence message = BulletPointPreference.formatIntoBulletPoints(
|
||||
Objects.requireNonNull(setting.userDialogMessage).toString());
|
||||
|
||||
Pair<Dialog, LinearLayout> dialogPair = CustomDialog.create(
|
||||
context,
|
||||
confirmDialogTitle, // Title.
|
||||
Objects.requireNonNull(setting.userDialogMessage).toString(), // No message.
|
||||
message,
|
||||
null, // No EditText.
|
||||
null, // OK button text.
|
||||
() -> {
|
||||
|
||||
@@ -15,7 +15,15 @@ import android.util.AttributeSet;
|
||||
@SuppressWarnings({"unused", "deprecation"})
|
||||
public class BulletPointPreference extends Preference {
|
||||
|
||||
public static SpannedString formatIntoBulletPoints(CharSequence source) {
|
||||
/**
|
||||
* Replaces bullet points with styled spans.
|
||||
*/
|
||||
public static CharSequence formatIntoBulletPoints(CharSequence source) {
|
||||
final char bulletPoint = '•';
|
||||
if (TextUtils.indexOf(source, bulletPoint) < 0) {
|
||||
return source; // Nothing to do.
|
||||
}
|
||||
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder(source);
|
||||
|
||||
int lineStart = 0;
|
||||
@@ -26,7 +34,7 @@ public class BulletPointPreference extends Preference {
|
||||
if (lineEnd < 0) lineEnd = length;
|
||||
|
||||
// Apply BulletSpan only if the line starts with the '•' character.
|
||||
if (lineEnd > lineStart && builder.charAt(lineStart) == '•') {
|
||||
if (lineEnd > lineStart && builder.charAt(lineStart) == bulletPoint) {
|
||||
int deleteEnd = lineStart + 1; // remove the bullet itself
|
||||
|
||||
// If there's a single space right after the bullet, remove that too.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.extension.youtube.settings.preference;
|
||||
package app.revanced.extension.shared.settings.preference;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
|
||||
@@ -6,17 +6,17 @@ import android.content.Context;
|
||||
import android.preference.SwitchPreference;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.shared.spoof.ClientType;
|
||||
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings({"deprecation", "unused"})
|
||||
public class ForceOriginalAudioSwitchPreference extends SwitchPreference {
|
||||
|
||||
// Spoof stream patch is not included, or is not currently spoofing to Android Studio.
|
||||
private static final boolean available = !SpoofVideoStreamsPatch.isPatchIncluded()
|
||||
|| !(Settings.SPOOF_VIDEO_STREAMS.get()
|
||||
&& Settings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.ANDROID_CREATOR);
|
||||
|| !(BaseSettings.SPOOF_VIDEO_STREAMS.get()
|
||||
&& SpoofVideoStreamsPatch.getPreferredClient() == ClientType.ANDROID_CREATOR);
|
||||
|
||||
{
|
||||
if (!available) {
|
||||
@@ -66,6 +66,10 @@ public class SpoofVideoStreamsPatch {
|
||||
StreamingDataRequest.setClientOrderToUse(availableClients, client);
|
||||
}
|
||||
|
||||
public static ClientType getPreferredClient() {
|
||||
return preferredClient;
|
||||
}
|
||||
|
||||
public static boolean spoofingToClientWithNoMultiAudioStreams() {
|
||||
return isPatchIncluded()
|
||||
&& SPOOF_STREAMING_DATA
|
||||
|
||||
@@ -42,11 +42,8 @@ final class PlayerRoutes {
|
||||
JSONObject context = new JSONObject();
|
||||
|
||||
AppLanguage language = SpoofVideoStreamsPatch.getLanguageOverride();
|
||||
if (language == null || clientType == ANDROID_VR_1_43_32) {
|
||||
if (language == null) {
|
||||
// Force original audio has not overrode the language.
|
||||
// Or if YT has fallen over to the last unauthenticated client (VR 1.43), then
|
||||
// always use the app language because forcing an audio stream of specific languages
|
||||
// can sometimes fail so it's better to try and load something rather than nothing.
|
||||
language = BaseSettings.SPOOF_VIDEO_STREAMS_LANGUAGE.get();
|
||||
}
|
||||
//noinspection ExtractMethodRecommender
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package app.revanced.extension.shared.theme;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.shared.Utils;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class BaseThemePatch {
|
||||
// Background colors.
|
||||
protected static final int BLACK_COLOR = Utils.getResourceColor("yt_black1");
|
||||
protected static final int WHITE_COLOR = Utils.getResourceColor("yt_white1");
|
||||
|
||||
/**
|
||||
* Check if a value matches any of the provided values.
|
||||
*
|
||||
* @param value The value to check.
|
||||
* @param of The array of values to compare against.
|
||||
* @return True if the value matches any of the provided values.
|
||||
*/
|
||||
protected static boolean anyEquals(int value, int... of) {
|
||||
for (int v : of) {
|
||||
if (value == v) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to process color values for Litho components.
|
||||
*
|
||||
* @param originalValue The original color value.
|
||||
* @param darkValues Array of dark mode color values to match.
|
||||
* @param lightValues Array of light mode color values to match.
|
||||
* @return The new or original color value.
|
||||
*/
|
||||
protected static int processColorValue(int originalValue, int[] darkValues, @Nullable int[] lightValues) {
|
||||
if (Utils.isDarkModeEnabled()) {
|
||||
if (anyEquals(originalValue, darkValues)) {
|
||||
return BLACK_COLOR;
|
||||
}
|
||||
} else if (lightValues != null && anyEquals(originalValue, lightValues)) {
|
||||
return WHITE_COLOR;
|
||||
}
|
||||
|
||||
return originalValue;
|
||||
}
|
||||
}
|
||||
@@ -58,10 +58,10 @@ public class CustomDialog {
|
||||
* @param dismissDialogOnNeutralClick If the dialog should be dismissed when the Neutral button is clicked.
|
||||
* @return The Dialog and its main LinearLayout container.
|
||||
*/
|
||||
public static Pair<Dialog, LinearLayout> create(Context context, String title, CharSequence message,
|
||||
@Nullable EditText editText, String okButtonText,
|
||||
public static Pair<Dialog, LinearLayout> create(Context context, CharSequence title, CharSequence message,
|
||||
@Nullable EditText editText, CharSequence okButtonText,
|
||||
Runnable onOkClick, Runnable onCancelClick,
|
||||
@Nullable String neutralButtonText,
|
||||
@Nullable CharSequence neutralButtonText,
|
||||
@Nullable Runnable onNeutralClick,
|
||||
boolean dismissDialogOnNeutralClick) {
|
||||
Logger.printDebug(() -> "Creating custom dialog with title: " + title);
|
||||
@@ -85,9 +85,9 @@ public class CustomDialog {
|
||||
* @param onNeutralClick Action to perform when the Neutral button is clicked, or null if no Neutral button is needed.
|
||||
* @param dismissDialogOnNeutralClick If the dialog should be dismissed when the Neutral button is clicked.
|
||||
*/
|
||||
private CustomDialog(Context context, String title, CharSequence message, @Nullable EditText editText,
|
||||
String okButtonText, Runnable onOkClick, Runnable onCancelClick,
|
||||
@Nullable String neutralButtonText, @Nullable Runnable onNeutralClick,
|
||||
private CustomDialog(Context context, CharSequence title, CharSequence message, @Nullable EditText editText,
|
||||
CharSequence okButtonText, Runnable onOkClick, Runnable onCancelClick,
|
||||
@Nullable CharSequence neutralButtonText, @Nullable Runnable onNeutralClick,
|
||||
boolean dismissDialogOnNeutralClick) {
|
||||
this.context = context;
|
||||
this.dialog = new Dialog(context);
|
||||
@@ -139,7 +139,7 @@ public class CustomDialog {
|
||||
*
|
||||
* @param title The title text to display.
|
||||
*/
|
||||
private void addTitle(String title) {
|
||||
private void addTitle(CharSequence title) {
|
||||
if (TextUtils.isEmpty(title)) return;
|
||||
|
||||
TextView titleView = new TextView(context);
|
||||
@@ -232,8 +232,8 @@ public class CustomDialog {
|
||||
* @param onNeutralClick Action for the Neutral button click, or null if no Neutral button.
|
||||
* @param dismissDialogOnNeutralClick If the dialog should dismiss on Neutral button click.
|
||||
*/
|
||||
private void addButtons(String okButtonText, Runnable onOkClick, Runnable onCancelClick,
|
||||
@Nullable String neutralButtonText, @Nullable Runnable onNeutralClick,
|
||||
private void addButtons(CharSequence okButtonText, Runnable onOkClick, Runnable onCancelClick,
|
||||
@Nullable CharSequence neutralButtonText, @Nullable Runnable onNeutralClick,
|
||||
boolean dismissDialogOnNeutralClick) {
|
||||
// Button container.
|
||||
LinearLayout buttonContainer = new LinearLayout(context);
|
||||
@@ -280,7 +280,7 @@ public class CustomDialog {
|
||||
* @param dismissDialog If the dialog should dismiss when the button is clicked.
|
||||
* @return The created Button.
|
||||
*/
|
||||
private Button createButton(String text, Runnable onClick, boolean isOkButton, boolean dismissDialog) {
|
||||
private Button createButton(CharSequence text, Runnable onClick, boolean isOkButton, boolean dismissDialog) {
|
||||
Button button = new Button(context, null, 0);
|
||||
button.setText(text);
|
||||
button.setTextSize(14);
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
// Do not remove. Necessary for the extension plugin to be applied to the project.
|
||||
dependencies {
|
||||
compileOnly(project(":extensions:shared:library"))
|
||||
}
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
package app.revanced.twitter.patches.links;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class ChangeLinkSharingDomainPatch {
|
||||
private static final String DOMAIN_NAME = "https://fxtwitter.com";
|
||||
private static final String LINK_FORMAT = "%s/%s/status/%s";
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static String formatResourceLink(Object... formatArgs) {
|
||||
String username = (String) formatArgs[0];
|
||||
String tweetId = (String) formatArgs[1];
|
||||
return String.format(LINK_FORMAT, DOMAIN_NAME, username, tweetId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static String formatLink(long tweetId, String username) {
|
||||
return String.format(LINK_FORMAT, DOMAIN_NAME, username, tweetId);
|
||||
}
|
||||
|
||||
@@ -2,11 +2,18 @@ package app.revanced.twitter.patches.links;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Deprecated(forRemoval = true)
|
||||
public final class OpenLinksWithAppChooserPatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void openWithChooser(final Context context, final Intent intent) {
|
||||
Log.d("ReVanced", "Opening intent with chooser: " + intent);
|
||||
Logger.printInfo(() -> "Opening intent with chooser: " + intent);
|
||||
|
||||
intent.setAction("android.intent.action.VIEW");
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import android.view.Display;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class DisableHdrPatch {
|
||||
public class DisableVideoCodecsPatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
@@ -15,5 +15,12 @@ public class DisableHdrPatch {
|
||||
? new int[0]
|
||||
: capabilities.getSupportedHdrTypes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean allowVP9() {
|
||||
return !Settings.FORCE_AVC_CODEC.get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,71 +1,17 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.settings.AppLanguage;
|
||||
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ForceOriginalAudioPatch {
|
||||
|
||||
private static final String DEFAULT_AUDIO_TRACKS_SUFFIX = ".4";
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void setPreferredLanguage() {
|
||||
if (Settings.FORCE_ORIGINAL_AUDIO.get()
|
||||
&& SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams()) {
|
||||
// If client spoofing does not use authentication and lacks multi-audio streams,
|
||||
// then can use any language code for the request and if that requested language is
|
||||
// not available YT uses the original audio language. Authenticated requests ignore
|
||||
// the language code and always use the account language. Use a language that is
|
||||
// not auto-dubbed by YouTube: https://support.google.com/youtube/answer/15569972
|
||||
// but the language is also supported natively by the Meta Quest device that
|
||||
// Android VR is spoofing.
|
||||
AppLanguage override = AppLanguage.SV;
|
||||
Logger.printDebug(() -> "Setting language override: " + override);
|
||||
SpoofVideoStreamsPatch.setLanguageOverride(override);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean ignoreDefaultAudioStream(boolean original) {
|
||||
if (Settings.FORCE_ORIGINAL_AUDIO.get()) {
|
||||
return false;
|
||||
}
|
||||
return original;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean isDefaultAudioStream(boolean isDefault, String audioTrackId, String audioTrackDisplayName) {
|
||||
try {
|
||||
if (!Settings.FORCE_ORIGINAL_AUDIO.get()) {
|
||||
return isDefault;
|
||||
}
|
||||
|
||||
if (audioTrackId.isEmpty()) {
|
||||
// Older app targets can have empty audio tracks and these might be placeholders.
|
||||
// The real audio tracks are called after these.
|
||||
return isDefault;
|
||||
}
|
||||
|
||||
Logger.printDebug(() -> "default: " + String.format("%-5s", isDefault) + " id: "
|
||||
+ String.format("%-8s", audioTrackId) + " name:" + audioTrackDisplayName);
|
||||
|
||||
final boolean isOriginal = audioTrackId.endsWith(DEFAULT_AUDIO_TRACKS_SUFFIX);
|
||||
if (isOriginal) {
|
||||
Logger.printDebug(() -> "Using audio: " + audioTrackId);
|
||||
}
|
||||
|
||||
return isOriginal;
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "isDefaultAudioStream failure", ex);
|
||||
return isDefault;
|
||||
}
|
||||
app.revanced.extension.shared.patches.ForceOriginalAudioPatch.setEnabled(
|
||||
Settings.FORCE_ORIGINAL_AUDIO.get(),
|
||||
Settings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class HideEndScreenCardsPatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void hideEndScreenCardView(View view) {
|
||||
Utils.hideViewUnderCondition(Settings.HIDE_ENDSCREEN_CARDS, view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean hideEndScreenCards() {
|
||||
return Settings.HIDE_ENDSCREEN_CARDS.get();
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class HideEndscreenCardsPatch {
|
||||
//Used by app.revanced.patches.youtube.layout.hideendscreencards.bytecode.patch.HideEndscreenCardsPatch
|
||||
public static void hideEndscreen(View view) {
|
||||
if (!Settings.HIDE_ENDSCREEN_CARDS.get()) return;
|
||||
view.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.Setting;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
@SuppressWarnings({"unused", "SpellCheckingInspection"})
|
||||
public final class MiniplayerPatch {
|
||||
|
||||
/**
|
||||
@@ -129,7 +129,7 @@ public final class MiniplayerPatch {
|
||||
(CURRENT_TYPE.isModern() && Settings.MINIPLAYER_DOUBLE_TAP_ACTION.get());
|
||||
|
||||
private static final boolean DRAG_AND_DROP_ENABLED =
|
||||
CURRENT_TYPE.isModern() && Settings.MINIPLAYER_DRAG_AND_DROP.get();
|
||||
CURRENT_TYPE.isModern() && !Settings.MINIPLAYER_DISABLE_DRAG_AND_DROP.get();
|
||||
|
||||
private static final boolean HIDE_OVERLAY_BUTTONS_ENABLED =
|
||||
Settings.MINIPLAYER_HIDE_OVERLAY_BUTTONS.get()
|
||||
@@ -145,10 +145,10 @@ public final class MiniplayerPatch {
|
||||
&& (VersionCheckPatch.IS_19_34_OR_GREATER || Settings.MINIPLAYER_HIDE_REWIND_FORWARD.get());
|
||||
|
||||
private static final boolean MINIPLAYER_ROUNDED_CORNERS_ENABLED =
|
||||
CURRENT_TYPE.isModern() && Settings.MINIPLAYER_ROUNDED_CORNERS.get();
|
||||
CURRENT_TYPE.isModern() && !Settings.MINIPLAYER_DISABLE_ROUNDED_CORNERS.get();
|
||||
|
||||
private static final boolean MINIPLAYER_HORIZONTAL_DRAG_ENABLED =
|
||||
DRAG_AND_DROP_ENABLED && Settings.MINIPLAYER_HORIZONTAL_DRAG.get();
|
||||
DRAG_AND_DROP_ENABLED && !Settings.MINIPLAYER_DISABLE_HORIZONTAL_DRAG.get();
|
||||
|
||||
/**
|
||||
* Remove a broken and always present subtitle text that is only
|
||||
@@ -173,14 +173,14 @@ public final class MiniplayerPatch {
|
||||
public static final class MiniplayerHorizontalDragAvailability implements Setting.Availability {
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return Settings.MINIPLAYER_TYPE.get().isModern() && Settings.MINIPLAYER_DRAG_AND_DROP.get();
|
||||
return Settings.MINIPLAYER_TYPE.get().isModern() && !Settings.MINIPLAYER_DISABLE_DRAG_AND_DROP.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Setting<?>> getParentSettings() {
|
||||
return List.of(
|
||||
Settings.MINIPLAYER_TYPE,
|
||||
Settings.MINIPLAYER_DRAG_AND_DROP
|
||||
Settings.MINIPLAYER_DISABLE_DRAG_AND_DROP
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -192,7 +192,7 @@ public final class MiniplayerPatch {
|
||||
return type == MODERN_4
|
||||
|| (!IS_19_20_OR_GREATER && (type == MODERN_1 || type == MODERN_3))
|
||||
|| (!IS_19_26_OR_GREATER && type == MODERN_1
|
||||
&& !Settings.MINIPLAYER_DOUBLE_TAP_ACTION.get() && !Settings.MINIPLAYER_DRAG_AND_DROP.get())
|
||||
&& !Settings.MINIPLAYER_DOUBLE_TAP_ACTION.get() && Settings.MINIPLAYER_DISABLE_DRAG_AND_DROP.get())
|
||||
|| (IS_19_29_OR_GREATER && type == MODERN_3);
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ public final class MiniplayerPatch {
|
||||
return List.of(
|
||||
Settings.MINIPLAYER_TYPE,
|
||||
Settings.MINIPLAYER_DOUBLE_TAP_ACTION,
|
||||
Settings.MINIPLAYER_DRAG_AND_DROP
|
||||
Settings.MINIPLAYER_DISABLE_DRAG_AND_DROP
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,11 @@ import app.revanced.extension.youtube.shared.PlayerType;
|
||||
@SuppressWarnings("unused")
|
||||
final class CommentsFilter extends Filter {
|
||||
|
||||
private static final String COMMENT_COMPOSER_PATH = "comment_composer.eml";
|
||||
|
||||
private final StringFilterGroup chipBar;
|
||||
private final ByteArrayFilterGroup aiCommentsSummary;
|
||||
private final StringFilterGroup emojiAndTimestampButtons;
|
||||
|
||||
public CommentsFilter() {
|
||||
var chatSummary = new StringFilterGroup(
|
||||
@@ -52,6 +55,11 @@ final class CommentsFilter extends Filter {
|
||||
"composer_short_creation_button.eml"
|
||||
);
|
||||
|
||||
emojiAndTimestampButtons = new StringFilterGroup(
|
||||
Settings.HIDE_COMMENTS_EMOJI_AND_TIMESTAMP_BUTTONS,
|
||||
"|CellType|ContainerType|ContainerType|ContainerType|ContainerType|ContainerType|"
|
||||
);
|
||||
|
||||
var previewComment = new StringFilterGroup(
|
||||
Settings.HIDE_COMMENTS_PREVIEW_COMMENT,
|
||||
"|carousel_item",
|
||||
@@ -64,11 +72,6 @@ final class CommentsFilter extends Filter {
|
||||
"super_thanks_button.eml"
|
||||
);
|
||||
|
||||
StringFilterGroup timestampButton = new StringFilterGroup(
|
||||
Settings.HIDE_COMMENTS_TIMESTAMP_BUTTON,
|
||||
"composer_timestamp_button.eml"
|
||||
);
|
||||
|
||||
addPathCallbacks(
|
||||
channelGuidelines,
|
||||
chatSummary,
|
||||
@@ -77,9 +80,9 @@ final class CommentsFilter extends Filter {
|
||||
comments,
|
||||
communityGuidelines,
|
||||
createAShort,
|
||||
emojiAndTimestampButtons,
|
||||
previewComment,
|
||||
thanksButton,
|
||||
timestampButton
|
||||
thanksButton
|
||||
|
||||
);
|
||||
}
|
||||
@@ -93,6 +96,10 @@ final class CommentsFilter extends Filter {
|
||||
&& aiCommentsSummary.check(buffer).isFiltered();
|
||||
}
|
||||
|
||||
if (matchedGroup == emojiAndTimestampButtons) {
|
||||
return path.startsWith(COMMENT_COMPOSER_PATH);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@ package app.revanced.extension.youtube.patches.components;
|
||||
import static app.revanced.extension.youtube.shared.NavigationBar.NavigationButton;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
@@ -500,4 +503,62 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
// This check is important as the shelf layout is used for the library tab playlists.
|
||||
return NavigationButton.getSelectedNavigationButton() != NavigationButton.LIBRARY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static SpannableString modifyFeedSubtitleSpan(SpannableString original, float truncationDimension) {
|
||||
try {
|
||||
final boolean hideViewCount = Settings.HIDE_VIEW_COUNT.get();
|
||||
final boolean hideUploadTime = Settings.HIDE_UPLOAD_TIME.get();
|
||||
if (!hideViewCount && !hideUploadTime) {
|
||||
return original;
|
||||
}
|
||||
|
||||
// Applies only for these specific dimensions.
|
||||
if (truncationDimension == 16f || truncationDimension == 42f) {
|
||||
String delimiter = " · ";
|
||||
final int delimiterLength = delimiter.length();
|
||||
|
||||
// Index includes the starting delimiter.
|
||||
final int viewCountStartIndex = TextUtils.indexOf(original, delimiter);
|
||||
if (viewCountStartIndex < 0) {
|
||||
return original;
|
||||
}
|
||||
|
||||
final int uploadTimeStartIndex = TextUtils.indexOf(original, delimiter,
|
||||
viewCountStartIndex + delimiterLength);
|
||||
if (uploadTimeStartIndex < 0) {
|
||||
return original;
|
||||
}
|
||||
|
||||
// Ensure there is exactly 2 delimiters.
|
||||
if (TextUtils.indexOf(original, delimiter,
|
||||
uploadTimeStartIndex + delimiterLength) >= 0) {
|
||||
return original;
|
||||
}
|
||||
|
||||
// Make a mutable copy that keeps existing span styling.
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder(original);
|
||||
|
||||
// Remove the sections.
|
||||
if (hideUploadTime) {
|
||||
builder.delete(uploadTimeStartIndex, original.length());
|
||||
}
|
||||
|
||||
if (hideViewCount) {
|
||||
builder.delete(viewCountStartIndex, uploadTimeStartIndex);
|
||||
}
|
||||
|
||||
SpannableString replacement = new SpannableString(builder);
|
||||
Logger.printDebug(() -> "Replacing feed subtitle span: " + original + " with: " + replacement);
|
||||
|
||||
return replacement;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "modifyFeedSubtitleSpan failure", ex);
|
||||
}
|
||||
|
||||
return original;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,6 +154,13 @@ public final class ShortsFilter extends Filter {
|
||||
"reel_dislike_button.eml"
|
||||
);
|
||||
|
||||
StringFilterGroup previewComment = new StringFilterGroup(
|
||||
Settings.HIDE_SHORTS_PREVIEW_COMMENT,
|
||||
// Preview comment that can popup while a Short is playing.
|
||||
// Uses no bundled icons, and instead the users profile photo is shown.
|
||||
"participation_bar.eml"
|
||||
);
|
||||
|
||||
joinButton = new StringFilterGroup(
|
||||
Settings.HIDE_SHORTS_JOIN_BUTTON,
|
||||
"sponsor_button"
|
||||
@@ -213,7 +220,7 @@ public final class ShortsFilter extends Filter {
|
||||
|
||||
addPathCallbacks(
|
||||
shortsCompactFeedVideo, joinButton, subscribeButton, paidPromotionButton,
|
||||
shortsActionBar, suggestedAction, pausedOverlayButtons, channelBar,
|
||||
shortsActionBar, suggestedAction, pausedOverlayButtons, channelBar, previewComment,
|
||||
fullVideoLinkLabel, videoTitle, useSoundButton, reelSoundMetadata, soundButton, infoPanel,
|
||||
stickers, likeFountain, likeButton, dislikeButton
|
||||
);
|
||||
@@ -243,12 +250,6 @@ public final class ShortsFilter extends Filter {
|
||||
// Suggested actions.
|
||||
//
|
||||
suggestedActionsBuffer.addAll(
|
||||
new ByteArrayFilterGroup(
|
||||
Settings.HIDE_SHORTS_PREVIEW_COMMENT,
|
||||
// Preview comment that can popup while a Short is playing.
|
||||
// Uses no bundled icons, and instead the users profile photo is shown.
|
||||
"shorts-comments-panel"
|
||||
),
|
||||
new ByteArrayFilterGroup(
|
||||
Settings.HIDE_SHORTS_SHOP_BUTTON,
|
||||
"yt_outline_bag_"
|
||||
|
||||
@@ -18,7 +18,22 @@ public class SpoofVideoStreamsPatch {
|
||||
* Injection point.
|
||||
*/
|
||||
public static void setClientOrderToUse() {
|
||||
List<ClientType> availableClients = List.of(
|
||||
final boolean forceAVC = Settings.FORCE_AVC_CODEC.get();
|
||||
|
||||
// VR 1.61 uses VP9/AV1, and cannot force AVC.
|
||||
ClientType client = Settings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get();
|
||||
if (forceAVC && client == ANDROID_VR_1_61_48) {
|
||||
client = ANDROID_VR_1_43_32; // Use VR 1.43 instead.
|
||||
}
|
||||
|
||||
List<ClientType> availableClients = forceAVC
|
||||
? List.of(
|
||||
ANDROID_VR_1_43_32,
|
||||
VISIONOS,
|
||||
ANDROID_CREATOR,
|
||||
ANDROID_VR_1_61_48,
|
||||
IPADOS)
|
||||
: List.of(
|
||||
ANDROID_VR_1_61_48,
|
||||
VISIONOS,
|
||||
ANDROID_CREATOR,
|
||||
@@ -27,6 +42,6 @@ public class SpoofVideoStreamsPatch {
|
||||
);
|
||||
|
||||
app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.setClientsToUse(
|
||||
availableClients, Settings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get());
|
||||
availableClients, client);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,13 @@
|
||||
package app.revanced.extension.youtube.patches.theme;
|
||||
|
||||
import static app.revanced.extension.youtube.patches.theme.ThemePatch.SplashScreenAnimationStyle.styleFromOrdinal;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.theme.BaseThemePatch;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ThemePatch {
|
||||
|
||||
public class ThemePatch extends BaseThemePatch {
|
||||
public enum SplashScreenAnimationStyle {
|
||||
DEFAULT(0),
|
||||
FPS_60_ONE_SECOND(1),
|
||||
@@ -43,57 +40,39 @@ public class ThemePatch {
|
||||
}
|
||||
}
|
||||
|
||||
// color constants used in relation with litho components
|
||||
// Color constants used in relation with litho components.
|
||||
private static final int[] WHITE_VALUES = {
|
||||
-1, // comments chip background
|
||||
-394759, // music related results panel background
|
||||
-83886081, // video chapters list background
|
||||
0xFFFFFFFF, // Comments chip background.
|
||||
0xFFF9F9F9, // Music related results panel background.
|
||||
0xFAFFFFFF, // Video chapters list background.
|
||||
};
|
||||
|
||||
private static final int[] DARK_VALUES = {
|
||||
-14145496, // explore drawer background
|
||||
-14606047, // comments chip background
|
||||
-15198184, // music related results panel background
|
||||
-15790321, // comments chip background (new layout)
|
||||
-98492127 // video chapters list background
|
||||
0xFF282828, // Explore drawer background.
|
||||
0xFF212121, // Comments chip background.
|
||||
0xFF181818, // Music related results panel background.
|
||||
0xFF0F0F0F, // Comments chip background (new layout).
|
||||
0xFA212121, // Video chapters list background.
|
||||
};
|
||||
|
||||
// Background colors.
|
||||
private static final int WHITE_COLOR = Utils.getResourceColor("yt_white1");
|
||||
private static final int BLACK_COLOR = Utils.getResourceColor("yt_black1");
|
||||
|
||||
private static final boolean GRADIENT_LOADING_SCREEN_ENABLED = Settings.GRADIENT_LOADING_SCREEN.get();
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*
|
||||
* <p>
|
||||
* Change the color of Litho components.
|
||||
* If the color of the component matches one of the values, return the background color .
|
||||
* If the color of the component matches one of the values, return the background color.
|
||||
*
|
||||
* @param originalValue The original color value.
|
||||
* @return The new or original color value
|
||||
* @return The new or original color value.
|
||||
*/
|
||||
public static int getValue(int originalValue) {
|
||||
if (Utils.isDarkModeEnabled()) {
|
||||
if (anyEquals(originalValue, DARK_VALUES)) return BLACK_COLOR;
|
||||
} else {
|
||||
if (anyEquals(originalValue, WHITE_VALUES)) return WHITE_COLOR;
|
||||
}
|
||||
|
||||
return originalValue;
|
||||
}
|
||||
|
||||
private static boolean anyEquals(int value, int... of) {
|
||||
for (int v : of) if (value == v) return true;
|
||||
|
||||
return false;
|
||||
return processColorValue(originalValue, DARK_VALUES, WHITE_VALUES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean gradientLoadingScreenEnabled(boolean original) {
|
||||
return GRADIENT_LOADING_SCREEN_ENABLED;
|
||||
return Settings.GRADIENT_LOADING_SCREEN.get();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,7 +87,7 @@ public class ThemePatch {
|
||||
final int replacement = style.style;
|
||||
if (original != replacement) {
|
||||
Logger.printDebug(() -> "Overriding splash screen style from: "
|
||||
+ styleFromOrdinal(original) + " to: " + style);
|
||||
+ SplashScreenAnimationStyle.styleFromOrdinal(original) + " to: " + style);
|
||||
}
|
||||
|
||||
return replacement;
|
||||
|
||||
@@ -11,6 +11,10 @@ import static app.revanced.extension.youtube.patches.ChangeHeaderPatch.HeaderLog
|
||||
import static app.revanced.extension.youtube.patches.ChangeStartPagePatch.ChangeStartPageTypeAvailability;
|
||||
import static app.revanced.extension.youtube.patches.ChangeStartPagePatch.StartPage;
|
||||
import static app.revanced.extension.youtube.patches.ExitFullscreenPatch.FullscreenMode;
|
||||
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerAnyModernAvailability;
|
||||
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerHideOverlayButtonsAvailability;
|
||||
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerHideRewindOrOverlayOpacityAvailability;
|
||||
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerHideSubtextsAvailability;
|
||||
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerHorizontalDragAvailability;
|
||||
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType;
|
||||
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MINIMAL;
|
||||
@@ -48,6 +52,10 @@ import app.revanced.extension.youtube.swipecontrols.SwipeControlsConfigurationPr
|
||||
|
||||
public class Settings extends BaseSettings {
|
||||
// Video
|
||||
public static final BooleanSetting ADVANCED_VIDEO_QUALITY_MENU = new BooleanSetting("revanced_advanced_video_quality_menu", TRUE);
|
||||
public static final BooleanSetting DISABLE_HDR_VIDEO = new BooleanSetting("revanced_disable_hdr_video", FALSE);
|
||||
public static final BooleanSetting FORCE_AVC_CODEC = new BooleanSetting("revanced_force_avc_codec", FALSE, true, "revanced_force_avc_codec_user_dialog_message");
|
||||
public static final BooleanSetting FORCE_ORIGINAL_AUDIO = new BooleanSetting("revanced_force_original_audio", FALSE, true);
|
||||
public static final IntegerSetting VIDEO_QUALITY_DEFAULT_WIFI = new IntegerSetting("revanced_video_quality_default_wifi", -2);
|
||||
public static final IntegerSetting VIDEO_QUALITY_DEFAULT_MOBILE = new IntegerSetting("revanced_video_quality_default_mobile", -2);
|
||||
public static final BooleanSetting REMEMBER_VIDEO_QUALITY_LAST_SELECTED = new BooleanSetting("revanced_remember_video_quality_last_selected", FALSE);
|
||||
@@ -56,8 +64,6 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting REMEMBER_SHORTS_QUALITY_LAST_SELECTED = new BooleanSetting("revanced_remember_shorts_quality_last_selected", FALSE);
|
||||
public static final BooleanSetting REMEMBER_VIDEO_QUALITY_LAST_SELECTED_TOAST = new BooleanSetting("revanced_remember_video_quality_last_selected_toast", TRUE, false,
|
||||
parentsAny(REMEMBER_VIDEO_QUALITY_LAST_SELECTED, REMEMBER_SHORTS_QUALITY_LAST_SELECTED));
|
||||
public static final BooleanSetting ADVANCED_VIDEO_QUALITY_MENU = new BooleanSetting("revanced_advanced_video_quality_menu", TRUE);
|
||||
public static final BooleanSetting DISABLE_HDR_VIDEO = new BooleanSetting("revanced_disable_hdr_video", FALSE);
|
||||
|
||||
// Speed
|
||||
public static final FloatSetting SPEED_TAP_AND_HOLD = new FloatSetting("revanced_speed_tap_and_hold", 2.0f, true);
|
||||
@@ -70,9 +76,6 @@ public class Settings extends BaseSettings {
|
||||
public static final StringSetting CUSTOM_PLAYBACK_SPEEDS = new StringSetting("revanced_custom_playback_speeds",
|
||||
"0.25\n0.5\n0.75\n1.0\n1.25\n1.5\n1.75\n2.0\n2.5\n3.0\n4.0\n5.0\n6.0\n7.0\n8.0", true);
|
||||
|
||||
// Audio
|
||||
public static final BooleanSetting FORCE_ORIGINAL_AUDIO = new BooleanSetting("revanced_force_original_audio", FALSE, true);
|
||||
|
||||
// Ads
|
||||
public static final BooleanSetting HIDE_CREATOR_STORE_SHELF = new BooleanSetting("revanced_hide_creator_store_shelf", TRUE);
|
||||
public static final BooleanSetting HIDE_END_SCREEN_STORE_BANNER = new BooleanSetting("revanced_hide_end_screen_store_banner", TRUE, true);
|
||||
@@ -111,7 +114,9 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting HIDE_SHOW_MORE_BUTTON = new BooleanSetting("revanced_hide_show_more_button", TRUE, true);
|
||||
public static final BooleanSetting HIDE_SURVEYS = new BooleanSetting("revanced_hide_surveys", TRUE);
|
||||
public static final BooleanSetting HIDE_TICKET_SHELF = new BooleanSetting("revanced_hide_ticket_shelf", FALSE);
|
||||
public static final BooleanSetting HIDE_UPLOAD_TIME = new BooleanSetting("revanced_hide_upload_time", FALSE, "revanced_hide_upload_time_user_dialog_message");
|
||||
public static final BooleanSetting HIDE_VIDEO_RECOMMENDATION_LABELS = new BooleanSetting("revanced_hide_video_recommendation_labels", TRUE);
|
||||
public static final BooleanSetting HIDE_VIEW_COUNT = new BooleanSetting("revanced_hide_view_count", FALSE, "revanced_hide_view_count_user_dialog_message");
|
||||
|
||||
// Alternative thumbnails
|
||||
public static final EnumSetting<ThumbnailOption> ALT_THUMBNAIL_HOME = new EnumSetting<>("revanced_alt_thumbnail_home", ThumbnailOption.ORIGINAL);
|
||||
@@ -174,15 +179,15 @@ public class Settings extends BaseSettings {
|
||||
|
||||
// Miniplayer
|
||||
public static final EnumSetting<MiniplayerType> MINIPLAYER_TYPE = new EnumSetting<>("revanced_miniplayer_type", MiniplayerType.DEFAULT, true);
|
||||
public static final BooleanSetting MINIPLAYER_DOUBLE_TAP_ACTION = new BooleanSetting("revanced_miniplayer_double_tap_action", TRUE, true, new MiniplayerPatch.MiniplayerAnyModernAvailability());
|
||||
public static final BooleanSetting MINIPLAYER_DRAG_AND_DROP = new BooleanSetting("revanced_miniplayer_drag_and_drop", TRUE, true, new MiniplayerPatch.MiniplayerAnyModernAvailability());
|
||||
public static final BooleanSetting MINIPLAYER_HORIZONTAL_DRAG = new BooleanSetting("revanced_miniplayer_horizontal_drag", FALSE, true, new MiniplayerHorizontalDragAvailability());
|
||||
public static final BooleanSetting MINIPLAYER_HIDE_OVERLAY_BUTTONS = new BooleanSetting("revanced_miniplayer_hide_overlay_buttons", FALSE, true, new MiniplayerPatch.MiniplayerHideOverlayButtonsAvailability());
|
||||
public static final BooleanSetting MINIPLAYER_HIDE_SUBTEXT = new BooleanSetting("revanced_miniplayer_hide_subtext", FALSE, true, new MiniplayerPatch.MiniplayerHideSubtextsAvailability());
|
||||
public static final BooleanSetting MINIPLAYER_DISABLE_DRAG_AND_DROP = new BooleanSetting("revanced_miniplayer_disable_drag_and_drop", FALSE, true, new MiniplayerAnyModernAvailability());
|
||||
public static final BooleanSetting MINIPLAYER_DISABLE_HORIZONTAL_DRAG = new BooleanSetting("revanced_miniplayer_disable_horizontal_drag", FALSE, true, new MiniplayerHorizontalDragAvailability());
|
||||
public static final BooleanSetting MINIPLAYER_DISABLE_ROUNDED_CORNERS = new BooleanSetting("revanced_miniplayer_disable_rounded_corners", FALSE, true, new MiniplayerAnyModernAvailability());
|
||||
public static final BooleanSetting MINIPLAYER_DOUBLE_TAP_ACTION = new BooleanSetting("revanced_miniplayer_double_tap_action", TRUE, true, new MiniplayerAnyModernAvailability());
|
||||
public static final BooleanSetting MINIPLAYER_HIDE_OVERLAY_BUTTONS = new BooleanSetting("revanced_miniplayer_hide_overlay_buttons", FALSE, true, new MiniplayerHideOverlayButtonsAvailability());
|
||||
public static final BooleanSetting MINIPLAYER_HIDE_SUBTEXT = new BooleanSetting("revanced_miniplayer_hide_subtext", FALSE, true, new MiniplayerHideSubtextsAvailability());
|
||||
public static final BooleanSetting MINIPLAYER_HIDE_REWIND_FORWARD = new BooleanSetting("revanced_miniplayer_hide_rewind_forward", TRUE, true, new MiniplayerPatch.MiniplayerHideRewindOrOverlayOpacityAvailability());
|
||||
public static final BooleanSetting MINIPLAYER_ROUNDED_CORNERS = new BooleanSetting("revanced_miniplayer_rounded_corners", TRUE, true, new MiniplayerPatch.MiniplayerAnyModernAvailability());
|
||||
public static final IntegerSetting MINIPLAYER_WIDTH_DIP = new IntegerSetting("revanced_miniplayer_width_dip", 192, true, new MiniplayerPatch.MiniplayerAnyModernAvailability());
|
||||
public static final IntegerSetting MINIPLAYER_OPACITY = new IntegerSetting("revanced_miniplayer_opacity", 100, true, new MiniplayerPatch.MiniplayerHideRewindOrOverlayOpacityAvailability());
|
||||
public static final IntegerSetting MINIPLAYER_WIDTH_DIP = new IntegerSetting("revanced_miniplayer_width_dip", 192, true, new MiniplayerAnyModernAvailability());
|
||||
public static final IntegerSetting MINIPLAYER_OPACITY = new IntegerSetting("revanced_miniplayer_opacity", 100, true, new MiniplayerHideRewindOrOverlayOpacityAvailability());
|
||||
|
||||
// External downloader
|
||||
public static final BooleanSetting EXTERNAL_DOWNLOADER = new BooleanSetting("revanced_external_downloader", FALSE);
|
||||
@@ -198,9 +203,9 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting HIDE_COMMENTS_COMMUNITY_GUIDELINES = new BooleanSetting("revanced_hide_comments_community_guidelines", TRUE);
|
||||
public static final BooleanSetting HIDE_COMMENTS_CREATE_A_SHORT_BUTTON = new BooleanSetting("revanced_hide_comments_create_a_short_button", TRUE);
|
||||
public static final BooleanSetting HIDE_COMMENTS_PREVIEW_COMMENT = new BooleanSetting("revanced_hide_comments_preview_comment", FALSE);
|
||||
public static final BooleanSetting HIDE_COMMENTS_EMOJI_AND_TIMESTAMP_BUTTONS = new BooleanSetting("revanced_hide_comments_emoji_and_timestamp_buttons", FALSE);
|
||||
public static final BooleanSetting HIDE_COMMENTS_SECTION = new BooleanSetting("revanced_hide_comments_section", FALSE);
|
||||
public static final BooleanSetting HIDE_COMMENTS_THANKS_BUTTON = new BooleanSetting("revanced_hide_comments_thanks_button", TRUE);
|
||||
public static final BooleanSetting HIDE_COMMENTS_TIMESTAMP_BUTTON = new BooleanSetting("revanced_hide_comments_timestamp_button", FALSE);
|
||||
|
||||
// Description
|
||||
public static final BooleanSetting HIDE_AI_GENERATED_VIDEO_SUMMARY_SECTION = new BooleanSetting("revanced_hide_ai_generated_video_summary_section", FALSE);
|
||||
|
||||
@@ -152,7 +152,7 @@ public class YouTubeActivityHook extends BaseActivityHook {
|
||||
* @return if the original activity finish method should be allowed to run.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static boolean handleFinish() {
|
||||
public static boolean handleBackPress() {
|
||||
return YouTubeSearchViewController.handleFinish(searchViewController);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ public class SponsorBlockUtils {
|
||||
SegmentCategory[] categories = SegmentCategory.categoriesWithoutHighlights();
|
||||
CharSequence[] titles = new CharSequence[categories.length];
|
||||
for (int i = 0, length = categories.length; i < length; i++) {
|
||||
titles[i] = categories[i].getTitle().toString();
|
||||
titles[i] = categories[i].getTitleWithColorDot();
|
||||
}
|
||||
|
||||
newUserCreatedSegmentCategory = null;
|
||||
@@ -302,7 +302,7 @@ public class SponsorBlockUtils {
|
||||
|
||||
SpannableStringBuilder spannableBuilder = new SpannableStringBuilder();
|
||||
|
||||
spannableBuilder.append(segment.category.getTitle().toString());
|
||||
spannableBuilder.append(segment.category.getTitleWithColorDot());
|
||||
spannableBuilder.append('\n');
|
||||
|
||||
String startTime = formatSegmentTime(segment.start);
|
||||
@@ -336,8 +336,8 @@ public class SponsorBlockUtils {
|
||||
Utils.verifyOnMainThread();
|
||||
final SegmentCategory[] values = SegmentCategory.categoriesWithoutHighlights();
|
||||
CharSequence[] titles = new CharSequence[values.length];
|
||||
for (int i = 0, length = values.length; i < length; i++) {
|
||||
titles[i] = values[i].getTitle().toString();
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
titles[i] = values[i].getTitleWithColorDot();
|
||||
}
|
||||
|
||||
new AlertDialog.Builder(context)
|
||||
|
||||
@@ -5,8 +5,12 @@ import static app.revanced.extension.youtube.settings.Settings.*;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.text.style.RelativeSizeSpan;
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -83,6 +87,8 @@ public enum SegmentCategory {
|
||||
MUSIC_OFFTOPIC,
|
||||
};
|
||||
|
||||
public static final String COLOR_DOT_STRING = "⬤";
|
||||
|
||||
public static final float CATEGORY_DEFAULT_OPACITY = 0.7f;
|
||||
|
||||
private static final Map<String, SegmentCategory> mValuesMap = new HashMap<>(2 * categoriesWithoutUnsubmitted.length);
|
||||
@@ -324,6 +330,32 @@ public enum SegmentCategory {
|
||||
return title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SpannableString} that starts with a colored dot followed by the provided text.
|
||||
*/
|
||||
private static SpannableString getCategoryColorDotSpan(String text, @ColorInt int color) {
|
||||
SpannableString dotSpan = new SpannableString(COLOR_DOT_STRING + text);
|
||||
dotSpan.setSpan(new ForegroundColorSpan(color), 0, 1,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
dotSpan.setSpan(new RelativeSizeSpan(1.5f), 0, 1,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
return dotSpan;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the category title with a colored dot.
|
||||
*/
|
||||
public SpannableString getTitleWithColorDot(@ColorInt int categoryColor) {
|
||||
return getCategoryColorDotSpan(" " + title, categoryColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the category title with a colored dot.
|
||||
*/
|
||||
public SpannableString getTitleWithColorDot() {
|
||||
return getTitleWithColorDot(color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the skip button text based on segment position.
|
||||
*
|
||||
|
||||
@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
|
||||
org.gradle.parallel = true
|
||||
android.useAndroidX = true
|
||||
kotlin.code.style = official
|
||||
version = 5.41.0-dev.10
|
||||
version = 5.42.0-dev.9
|
||||
|
||||
@@ -284,6 +284,10 @@ public final class app/revanced/patches/instagram/misc/extension/SharedExtension
|
||||
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/instagram/misc/links/OpenLinksExternallyPatchKt {
|
||||
public static final fun getOpenLinksExternallyPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/instagram/misc/signature/SignatureCheckPatchKt {
|
||||
public static final fun getSignatureCheckPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -372,6 +376,10 @@ public final class app/revanced/patches/music/interaction/permanentshuffle/Perma
|
||||
public static final fun getPermanentShufflePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/layout/branding/CustomBrandingPatchKt {
|
||||
public static final fun getCustomBrandingPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/layout/castbutton/HideCastButtonKt {
|
||||
public static final fun getHideCastButton ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -388,6 +396,10 @@ public final class app/revanced/patches/music/layout/premium/HideGetPremiumPatch
|
||||
public static final fun getHideGetPremiumPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/layout/theme/ThemePatchKt {
|
||||
public static final fun getThemePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/layout/upgradebutton/HideUpgradeButtonPatchKt {
|
||||
public static final fun getHideUpgradeButton ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static final fun getRemoveUpgradeButton ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
@@ -447,9 +459,14 @@ public final class app/revanced/patches/music/misc/spoof/UserAgentClientSpoofPat
|
||||
public static final fun getUserAgentClientSpoofPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/misc/tracks/ForceOriginalAudioPatchKt {
|
||||
public static final fun getForceOriginalAudioPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/playservice/VersionCheckPatchKt {
|
||||
public static final fun getVersionCheckPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
public static final fun is_7_33_or_greater ()Z
|
||||
public static final fun is_8_10_or_greater ()Z
|
||||
public static final fun is_8_11_or_greater ()Z
|
||||
public static final fun is_8_15_or_greater ()Z
|
||||
}
|
||||
@@ -733,6 +750,11 @@ public final class app/revanced/patches/serviceportalbund/detection/root/RootDet
|
||||
public static final fun getRootDetectionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/layout/theme/LithoColorHookPatchKt {
|
||||
public static final fun getLithoColorHookPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static final fun getLithoColorOverrideHook ()Lkotlin/jvm/functions/Function2;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/misc/checks/BaseCheckEnvironmentPatchKt {
|
||||
public static final fun checkEnvironmentPatch (Lapp/revanced/patcher/Fingerprint;Lapp/revanced/patcher/patch/Patch;[Ljava/lang/String;)Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1297,6 +1319,10 @@ public final class app/revanced/patches/viber/ads/HideAdsPatchKt {
|
||||
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/viber/misc/navbar/HideNavigationButtonsKt {
|
||||
public static final fun getHideNavigationButtonsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/vsco/misc/pro/UnlockProPatchKt {
|
||||
public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1398,8 +1424,8 @@ public final class app/revanced/patches/youtube/layout/formfactor/ChangeFormFact
|
||||
public static final fun getChangeFormFactorPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/hide/endscreencards/HideEndscreenCardsPatchKt {
|
||||
public static final fun getHideEndscreenCardsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public final class app/revanced/patches/youtube/layout/hide/endscreencards/HideEndScreenCardsPatchKt {
|
||||
public static final fun getHideEndScreenCardsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/hide/endscreensuggestion/HideEndScreenSuggestedVideoPatchKt {
|
||||
@@ -1727,6 +1753,10 @@ public final class app/revanced/patches/youtube/video/audio/ForceOriginalAudioPa
|
||||
public static final fun getForceOriginalAudioPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/video/codecs/DisableVideoCodecsPatchKt {
|
||||
public static final fun getDisableVideoCodecsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/video/hdr/DisableHdrPatchKt {
|
||||
public static final fun getDisableHdrPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package app.revanced.patches.instagram.hide.navigation
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.booleanOption
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.instagram.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.util.addInstructionsAtControlFlowLabel
|
||||
import app.revanced.util.findFreeRegister
|
||||
import app.revanced.util.getReference
|
||||
@@ -24,6 +25,8 @@ val hideNavigationButtonsPatch = bytecodePatch(
|
||||
) {
|
||||
compatibleWith("com.instagram.android")
|
||||
|
||||
dependsOn(sharedExtensionPatch)
|
||||
|
||||
val hideReels by booleanOption(
|
||||
key = "hideReels",
|
||||
default = true,
|
||||
@@ -69,20 +72,22 @@ val hideNavigationButtonsPatch = bytecodePatch(
|
||||
const-string v$freeRegister2, "$enumNameField"
|
||||
invoke-static { v$buttonsListRegister, v$freeRegister, v$freeRegister2 }, $EXTENSION_CLASS_DESCRIPTOR->removeNavigationButtonByName(Ljava/util/List;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
|
||||
move-result-object v$buttonsListRegister
|
||||
"""
|
||||
"""
|
||||
}
|
||||
|
||||
if (hideReels!!)
|
||||
if (hideReels!!) {
|
||||
addInstructionsAtControlFlowLabel(
|
||||
returnIndex,
|
||||
instructionsRemoveButtonByName("fragment_clips")
|
||||
)
|
||||
}
|
||||
|
||||
if (hideCreate!!)
|
||||
if (hideCreate!!) {
|
||||
addInstructionsAtControlFlowLabel(
|
||||
returnIndex,
|
||||
instructionsRemoveButtonByName("fragment_share")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package app.revanced.patches.instagram.misc.links
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal const val TARGET_STRING = "Tracking.ARG_CLICK_SOURCE"
|
||||
|
||||
internal val inAppBrowserFunctionFingerprint = fingerprint {
|
||||
returns("Z")
|
||||
strings("TrackingInfo.ARG_MODULE_NAME", TARGET_STRING)
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package app.revanced.patches.instagram.misc.links
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.instagram.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/instagram/misc/links/OpenLinksExternallyPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val openLinksExternallyPatch = bytecodePatch(
|
||||
name = "Open links externally",
|
||||
description = "Changes links to always open in your external browser, instead of the in-app browser.",
|
||||
use = false,
|
||||
) {
|
||||
|
||||
dependsOn(sharedExtensionPatch)
|
||||
|
||||
compatibleWith("com.instagram.android")
|
||||
|
||||
execute {
|
||||
inAppBrowserFunctionFingerprint.let {
|
||||
val stringMatchIndex = it.stringMatches?.first { match -> match.string == TARGET_STRING }!!.index
|
||||
|
||||
it.method.apply {
|
||||
val urlResultObjIndex = indexOfFirstInstructionOrThrow(
|
||||
stringMatchIndex, Opcode.MOVE_OBJECT_FROM16
|
||||
)
|
||||
|
||||
// Register that contains the url after moving from a higher register.
|
||||
val urlRegister = getInstruction<TwoRegisterInstruction>(urlResultObjIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
urlResultObjIndex + 1,
|
||||
"""
|
||||
invoke-static { v$urlRegister }, $EXTENSION_CLASS_DESCRIPTOR->openExternally(Ljava/lang/String;)Z
|
||||
move-result v$urlRegister
|
||||
return v$urlRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package app.revanced.patches.music.layout.branding
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.shared.layout.branding.baseCustomBrandingPatch
|
||||
import app.revanced.patches.shared.misc.mapping.get
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.indexOfFirstInstructionReversed
|
||||
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
private val disableSplashAnimationPatch = bytecodePatch {
|
||||
|
||||
dependsOn(resourceMappingPatch)
|
||||
|
||||
execute {
|
||||
// The existing YT animation usually only shows for a fraction of a second,
|
||||
// and the existing animation does not match the new splash screen
|
||||
// causing the original YT Music logo to momentarily flash on screen as the animation starts.
|
||||
//
|
||||
// Could replace the lottie animation file with our own custom animation (app_launch.json),
|
||||
// but the animation is not always the same size as the launch screen and it's still
|
||||
// barely shown. Instead turn off the animation entirely (app will also launch a little faster).
|
||||
cairoSplashAnimationConfigFingerprint.method.apply {
|
||||
val mainActivityLaunchAnimation = resourceMappings["layout", "main_activity_launch_animation"]
|
||||
val literalIndex = indexOfFirstLiteralInstructionOrThrow(
|
||||
mainActivityLaunchAnimation
|
||||
)
|
||||
val insertIndex = indexOfFirstInstructionReversed(literalIndex) {
|
||||
this.opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>()?.name == "setContentView"
|
||||
} + 1
|
||||
val jumpIndex = indexOfFirstInstructionOrThrow(insertIndex) {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>()?.parameterTypes?.firstOrNull() == "Ljava/lang/Runnable;"
|
||||
} + 1
|
||||
|
||||
addInstructionsWithLabels(
|
||||
insertIndex,
|
||||
"goto :skip_animation",
|
||||
ExternalLabel("skip_animation", getInstruction(jumpIndex))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const val APP_NAME = "YT Music ReVanced"
|
||||
|
||||
@Suppress("unused")
|
||||
val customBrandingPatch = baseCustomBrandingPatch(
|
||||
defaultAppName = APP_NAME,
|
||||
appNameValues = mapOf(
|
||||
"YT Music ReVanced" to APP_NAME,
|
||||
"Music ReVanced" to "Music ReVanced",
|
||||
"Music" to "Music",
|
||||
"YT Music" to "YT Music",
|
||||
),
|
||||
resourceFolder = "custom-branding/music",
|
||||
iconResourceFileNames = arrayOf(
|
||||
"adaptiveproduct_youtube_music_2024_q4_background_color_108",
|
||||
"adaptiveproduct_youtube_music_2024_q4_foreground_color_108",
|
||||
"ic_launcher_release",
|
||||
),
|
||||
monochromeIconFileNames = arrayOf("ic_app_icons_themed_youtube_music.xml"),
|
||||
|
||||
block = {
|
||||
dependsOn(disableSplashAnimationPatch)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.29.52",
|
||||
"8.10.52"
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
package app.revanced.patches.music.layout.branding
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patches.music.shared.YOUTUBE_MUSIC_MAIN_ACTIVITY_CLASS_TYPE
|
||||
|
||||
internal val cairoSplashAnimationConfigFingerprint = fingerprint {
|
||||
returns("V")
|
||||
parameters("Landroid/os/Bundle;")
|
||||
custom { method, classDef ->
|
||||
method.name == "onCreate" && method.definingClass == YOUTUBE_MUSIC_MAIN_ACTIVITY_CLASS_TYPE
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,9 @@ import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.music.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.music.misc.settings.settingsPatch
|
||||
import app.revanced.patches.shared.misc.mapping.get
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
|
||||
@@ -29,6 +32,7 @@ val hideCastButton = bytecodePatch(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
resourceMappingPatch
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
@@ -39,6 +43,8 @@ val hideCastButton = bytecodePatch(
|
||||
)
|
||||
|
||||
execute {
|
||||
playerOverlayChip = resourceMappings["id", "player_overlay_chip"]
|
||||
|
||||
addResources("music", "layout.castbutton.hideCastButton")
|
||||
|
||||
PreferenceScreen.GENERAL.addPreferences(
|
||||
@@ -59,7 +65,7 @@ val hideCastButton = bytecodePatch(
|
||||
|
||||
playerOverlayChipFingerprint.method.apply {
|
||||
val resourceIndex = indexOfFirstLiteralInstructionOrThrow(playerOverlayChip)
|
||||
val targetIndex = indexOfFirstInstructionOrThrow(resourceIndex, Opcode.MOVE_RESULT)
|
||||
val targetIndex = indexOfFirstInstructionOrThrow(resourceIndex, Opcode.MOVE_RESULT_OBJECT)
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
|
||||
@@ -4,6 +4,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
||||
@@ -35,7 +36,23 @@ val navigationBarPatch = bytecodePatch(
|
||||
resourceMappingPatch,
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch
|
||||
addResourcesPatch,
|
||||
resourcePatch {
|
||||
execute {
|
||||
// Ensure the first ImageView has 'layout_weight' to stay properly sized
|
||||
// when the TextView is hidden.
|
||||
document("res/layout/image_with_text_tab.xml").use { document ->
|
||||
val imageView = document.getElementsByTagName("ImageView").item(0)
|
||||
imageView?.let {
|
||||
if (it.attributes.getNamedItem("android:layout_weight") == null) {
|
||||
val attr = document.createAttribute("android:layout_weight")
|
||||
attr.value = "0.5"
|
||||
it.attributes.setNamedItem(attr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
@@ -46,10 +63,7 @@ val navigationBarPatch = bytecodePatch(
|
||||
)
|
||||
|
||||
execute {
|
||||
text1 = resourceMappings[
|
||||
"id",
|
||||
"text1",
|
||||
]
|
||||
text1 = resourceMappings["id", "text1"]
|
||||
|
||||
addResources("music", "layout.navigationbar.navigationBarPatch")
|
||||
|
||||
@@ -71,9 +85,7 @@ val navigationBarPatch = bytecodePatch(
|
||||
)
|
||||
|
||||
tabLayoutTextFingerprint.method.apply {
|
||||
/**
|
||||
* Hide navigation labels.
|
||||
*/
|
||||
// Hide navigation labels.
|
||||
val constIndex = indexOfFirstLiteralInstructionOrThrow(text1)
|
||||
val targetIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.CHECK_CAST)
|
||||
val targetParameter = getInstruction<ReferenceInstruction>(targetIndex).reference
|
||||
@@ -87,9 +99,7 @@ val navigationBarPatch = bytecodePatch(
|
||||
"invoke-static { v$targetRegister }, $EXTENSION_CLASS_DESCRIPTOR->hideNavigationLabel(Landroid/widget/TextView;)V"
|
||||
)
|
||||
|
||||
/**
|
||||
* Set navigation enum and hide navigation buttons.
|
||||
*/
|
||||
// Set navigation enum and hide navigation buttons.
|
||||
val enumIndex = tabLayoutTextFingerprint.patternMatch!!.startIndex + 3
|
||||
val enumRegister = getInstruction<OneRegisterInstruction>(enumIndex).registerA
|
||||
val insertEnumIndex = indexOfFirstInstructionOrThrow(Opcode.AND_INT_LIT8) - 2
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package app.revanced.patches.music.layout.theme
|
||||
|
||||
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.shared.layout.theme.THEME_DEFAULT_DARK_COLOR_NAMES
|
||||
import app.revanced.patches.shared.layout.theme.baseThemePatch
|
||||
import app.revanced.patches.shared.layout.theme.baseThemeResourcePatch
|
||||
import app.revanced.patches.shared.layout.theme.darkThemeBackgroundColorOption
|
||||
import app.revanced.patches.shared.misc.settings.overrideThemeColors
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/music/patches/theme/ThemePatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val themePatch = baseThemePatch(
|
||||
extensionClassDescriptor = EXTENSION_CLASS_DESCRIPTOR,
|
||||
|
||||
block = {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
baseThemeResourcePatch(
|
||||
darkColorNames = THEME_DEFAULT_DARK_COLOR_NAMES + setOf(
|
||||
"yt_black_pure",
|
||||
"yt_black_pure_opacity80",
|
||||
"ytm_color_grey_12",
|
||||
"material_grey_800"
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.29.52",
|
||||
"8.10.52"
|
||||
)
|
||||
)
|
||||
},
|
||||
|
||||
executeBlock = {
|
||||
overrideThemeColors(
|
||||
null,
|
||||
darkThemeBackgroundColorOption.value!!
|
||||
)
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,44 @@
|
||||
package app.revanced.patches.music.misc.fileprovider
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.packagename.setOrGetFallbackPackageName
|
||||
import app.revanced.patches.music.utils.fix.fileprovider.fileProviderResolverFingerprint
|
||||
|
||||
internal fun fileProviderPatch(
|
||||
youtubePackageName: String,
|
||||
musicPackageName: String
|
||||
) = bytecodePatch(
|
||||
description = "Fixes broken YouTube Music file provider that prevents sharing with specific apps such as Instagram."
|
||||
) {
|
||||
finalize {
|
||||
// Must do modification last, so change package name value is correctly set.
|
||||
val musicChangedPackageName = setOrGetFallbackPackageName(musicPackageName)
|
||||
|
||||
// For some reason, if the app gets "android.support.FILE_PROVIDER_PATHS",
|
||||
// the package name of YouTube is used, not the package name of the YT Music.
|
||||
//
|
||||
// There is no issue in the stock YT Music, but this is an issue in the GmsCore Build.
|
||||
// https://github.com/ReVanced/revanced-patches/issues/55
|
||||
//
|
||||
// To solve this issue, replace the package name of YouTube with YT Music's package name.
|
||||
fileProviderResolverFingerprint.method.addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "com.google.android.youtube.fileprovider"
|
||||
invoke-static { p1, v0 }, Ljava/util/Objects;->equals(Ljava/lang/Object;Ljava/lang/Object;)Z
|
||||
move-result v0
|
||||
if-nez v0, :fix
|
||||
const-string v0, "$youtubePackageName.fileprovider"
|
||||
invoke-static { p1, v0 }, Ljava/util/Objects;->equals(Ljava/lang/Object;Ljava/lang/Object;)Z
|
||||
move-result v0
|
||||
if-nez v0, :fix
|
||||
goto :ignore
|
||||
:fix
|
||||
const-string p1, "$musicChangedPackageName.fileprovider"
|
||||
:ignore
|
||||
nop
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package app.revanced.patches.music.utils.fix.fileprovider
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal val fileProviderResolverFingerprint = fingerprint {
|
||||
returns("L")
|
||||
strings(
|
||||
"android.support.FILE_PROVIDER_PATHS",
|
||||
"Name must not be empty"
|
||||
)
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import app.revanced.patches.music.misc.gms.Constants.REVANCED_MUSIC_PACKAGE_NAME
|
||||
import app.revanced.patches.music.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.music.misc.settings.settingsPatch
|
||||
import app.revanced.patches.music.misc.spoof.spoofVideoStreamsPatch
|
||||
import app.revanced.patches.music.misc.fileprovider.fileProviderPatch
|
||||
import app.revanced.patches.shared.castContextFetchFingerprint
|
||||
import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.IntentPreference
|
||||
@@ -60,6 +61,10 @@ private fun gmsCoreSupportResourcePatch(
|
||||
) {
|
||||
dependsOn(
|
||||
addResourcesPatch,
|
||||
settingsPatch
|
||||
settingsPatch,
|
||||
fileProviderPatch(
|
||||
MUSIC_PACKAGE_NAME,
|
||||
REVANCED_MUSIC_PACKAGE_NAME
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import app.revanced.patches.all.misc.packagename.setOrGetFallbackPackageName
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.music.misc.gms.Constants.MUSIC_PACKAGE_NAME
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.BasePreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.BasePreferenceScreen
|
||||
@@ -108,7 +109,8 @@ val settingsPatch = bytecodePatch(
|
||||
modifyActivityForSettingsInjection(
|
||||
googleApiActivityFingerprint.classDef,
|
||||
googleApiActivityFingerprint.method,
|
||||
GOOGLE_API_ACTIVITY_HOOK_CLASS_DESCRIPTOR
|
||||
GOOGLE_API_ACTIVITY_HOOK_CLASS_DESCRIPTOR,
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
@@ -125,7 +127,7 @@ fun newIntent(settingsName: String) = IntentPreference.Intent(
|
||||
targetClass = "com.google.android.gms.common.api.GoogleApiActivity"
|
||||
) {
|
||||
// The package name change has to be reflected in the intent.
|
||||
setOrGetFallbackPackageName("com.google.android.apps.youtube.music")
|
||||
setOrGetFallbackPackageName(MUSIC_PACKAGE_NAME)
|
||||
}
|
||||
|
||||
object PreferenceScreen : BasePreferenceScreen() {
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package app.revanced.patches.music.misc.tracks
|
||||
|
||||
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.music.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.music.misc.settings.settingsPatch
|
||||
import app.revanced.patches.music.playservice.is_8_10_or_greater
|
||||
import app.revanced.patches.music.playservice.versionCheckPatch
|
||||
import app.revanced.patches.music.shared.mainActivityOnCreateFingerprint
|
||||
import app.revanced.patches.shared.misc.audio.forceOriginalAudioPatch
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/music/patches/ForceOriginalAudioPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val forceOriginalAudioPatch = forceOriginalAudioPatch(
|
||||
block = {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
versionCheckPatch
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.29.52",
|
||||
"8.10.52"
|
||||
)
|
||||
)
|
||||
},
|
||||
fixUseLocalizedAudioTrackFlag = is_8_10_or_greater,
|
||||
mainActivityOnCreateFingerprint = mainActivityOnCreateFingerprint,
|
||||
subclassExtensionClassDescriptor = EXTENSION_CLASS_DESCRIPTOR,
|
||||
preferenceScreen = PreferenceScreen.MISC,
|
||||
)
|
||||
@@ -7,6 +7,8 @@ import app.revanced.util.findPlayStoreServicesVersion
|
||||
|
||||
var is_7_33_or_greater = false
|
||||
private set
|
||||
var is_8_10_or_greater = false
|
||||
private set
|
||||
var is_8_11_or_greater = false
|
||||
private set
|
||||
var is_8_15_or_greater = false
|
||||
@@ -22,6 +24,7 @@ val versionCheckPatch = resourcePatch(
|
||||
|
||||
// All bug fix releases always seem to use the same play store version as the minor version.
|
||||
is_7_33_or_greater = 245199000 <= playStoreServicesVersion
|
||||
is_8_10_or_greater = 244799000 <= playStoreServicesVersion
|
||||
is_8_11_or_greater = 251199000 <= playStoreServicesVersion
|
||||
is_8_15_or_greater = 251530000 <= playStoreServicesVersion
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package app.revanced.patches.reddit.customclients.boostforreddit.fix.redgifs
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patches.reddit.customclients.CREATE_NEW_CLIENT_METHOD
|
||||
import app.revanced.patches.reddit.customclients.boostforreddit.misc.extension.sharedExtensionPatch
|
||||
@@ -27,9 +26,7 @@ val fixRedgifsApi = fixRedgifsApiPatch(
|
||||
}
|
||||
replaceInstruction(
|
||||
index,
|
||||
"""
|
||||
invoke-static { }, ${EXTENSION_CLASS_DESCRIPTOR}->$CREATE_NEW_CLIENT_METHOD
|
||||
"""
|
||||
"invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->$CREATE_NEW_CLIENT_METHOD"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
package app.revanced.patches.shared.layout.branding
|
||||
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.ResourcePatchBuilder
|
||||
import app.revanced.patcher.patch.ResourcePatchContext
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patcher.patch.stringOption
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.Utils.trimIndentMultiline
|
||||
import app.revanced.util.copyResources
|
||||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
import java.util.logging.Logger
|
||||
|
||||
private const val REVANCED_ICON = "ReVanced*Logo" // Can never be a valid path.
|
||||
|
||||
internal val mipmapDirectories = arrayOf(
|
||||
// Target app does not have ldpi icons.
|
||||
"mdpi",
|
||||
"hdpi",
|
||||
"xhdpi",
|
||||
"xxhdpi",
|
||||
"xxxhdpi",
|
||||
).map { "mipmap-$it" }.toTypedArray()
|
||||
|
||||
private fun formatResourceFileList(resourceNames: Array<String>) = resourceNames.joinToString("\n") { "- $it" }
|
||||
|
||||
/**
|
||||
* Attempts to fix unescaped and invalid characters not allowed for an Android app name.
|
||||
*/
|
||||
private fun escapeAppName(name: String): String? {
|
||||
// Remove ASCII control characters.
|
||||
val cleanedName = name.filter { it.code >= 32 }
|
||||
|
||||
// Replace invalid XML characters with escaped equivalents.
|
||||
val escapedName = cleanedName
|
||||
.replace("&", "&") // Must be first to avoid double-escaping.
|
||||
.replace("<", "<")
|
||||
.replace(">", ">")
|
||||
.replace(Regex("(?<!&)\""), """)
|
||||
|
||||
// Trim empty spacing.
|
||||
val trimmed = escapedName.trim()
|
||||
|
||||
return trimmed.ifBlank { null }
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared custom branding patch for YouTube and YT Music.
|
||||
*/
|
||||
internal fun baseCustomBrandingPatch(
|
||||
defaultAppName: String,
|
||||
appNameValues: Map<String, String>,
|
||||
resourceFolder: String,
|
||||
iconResourceFileNames: Array<String>,
|
||||
monochromeIconFileNames: Array<String>,
|
||||
block: ResourcePatchBuilder.() -> Unit = {},
|
||||
executeBlock: ResourcePatchContext.() -> Unit = {}
|
||||
): ResourcePatch = resourcePatch(
|
||||
name = "Custom branding",
|
||||
description = "Applies a custom app name and icon. Defaults to \"$defaultAppName\" and the ReVanced logo.",
|
||||
use = false,
|
||||
) {
|
||||
val iconResourceFileNamesPng = iconResourceFileNames.map { "$it.png" }.toTypedArray<String>()
|
||||
|
||||
val appName by stringOption(
|
||||
key = "appName",
|
||||
default = defaultAppName,
|
||||
values = appNameValues,
|
||||
title = "App name",
|
||||
description = "The name of the app.",
|
||||
)
|
||||
|
||||
val iconPath by stringOption(
|
||||
key = "iconPath",
|
||||
default = REVANCED_ICON,
|
||||
values = mapOf("ReVanced Logo" to REVANCED_ICON),
|
||||
title = "App icon",
|
||||
description = """
|
||||
The icon to apply to the app.
|
||||
|
||||
If a path to a folder is provided, the folder must contain the following folders:
|
||||
|
||||
${formatResourceFileList(mipmapDirectories)}
|
||||
|
||||
Each of these folders must contain the following files:
|
||||
|
||||
${formatResourceFileList(iconResourceFileNamesPng)}
|
||||
|
||||
Optionally, a 'drawable' folder with the monochrome icon files:
|
||||
|
||||
${formatResourceFileList(monochromeIconFileNames)}
|
||||
""".trimIndentMultiline(),
|
||||
)
|
||||
|
||||
block()
|
||||
|
||||
execute {
|
||||
val mipmapIconResourceGroups = mipmapDirectories.map { directory ->
|
||||
ResourceGroup(
|
||||
directory,
|
||||
*iconResourceFileNamesPng,
|
||||
)
|
||||
}
|
||||
|
||||
val iconPathTrimmed = iconPath!!.trim()
|
||||
if (iconPathTrimmed == REVANCED_ICON) {
|
||||
// Replace mipmap icons with preset patch icons.
|
||||
mipmapIconResourceGroups.forEach { groupResources ->
|
||||
copyResources(resourceFolder, groupResources)
|
||||
}
|
||||
|
||||
// Replace monochrome icons.
|
||||
monochromeIconFileNames.forEach { fileName ->
|
||||
copyResources(
|
||||
resourceFolder,
|
||||
ResourceGroup("drawable", fileName)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
val filePath = File(iconPathTrimmed)
|
||||
val resourceDirectory = get("res")
|
||||
|
||||
// Replace
|
||||
mipmapIconResourceGroups.forEach { groupResources ->
|
||||
val groupResourceDirectoryName = groupResources.resourceDirectoryName
|
||||
val fromDirectory = filePath.resolve(groupResourceDirectoryName)
|
||||
val toDirectory = resourceDirectory.resolve(groupResourceDirectoryName)
|
||||
|
||||
groupResources.resources.forEach { iconFileName ->
|
||||
Files.write(
|
||||
toDirectory.resolve(iconFileName).toPath(),
|
||||
fromDirectory.resolve(iconFileName).readBytes(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Copy all monochrome icons if provided.
|
||||
monochromeIconFileNames.forEach { fileName ->
|
||||
val replacementMonochrome = filePath.resolve("drawable").resolve(fileName)
|
||||
if (replacementMonochrome.exists()) {
|
||||
Files.write(
|
||||
resourceDirectory.resolve("drawable").resolve(fileName).toPath(),
|
||||
replacementMonochrome.readBytes(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Change the app name.
|
||||
escapeAppName(appName!!)?.let { escapedAppName ->
|
||||
val newValue = "android:label=\"$escapedAppName\""
|
||||
|
||||
val manifest = get("AndroidManifest.xml")
|
||||
val original = manifest.readText()
|
||||
val replacement = original
|
||||
// YouTube
|
||||
.replace("android:label=\"@string/application_name\"", newValue)
|
||||
// YT Music
|
||||
.replace("android:label=\"@string/app_launcher_name\"", newValue)
|
||||
|
||||
if (original == replacement) {
|
||||
Logger.getLogger(this::class.java.name).warning(
|
||||
"Could not replace manifest app name"
|
||||
)
|
||||
}
|
||||
|
||||
manifest.writeText(replacement)
|
||||
}
|
||||
|
||||
executeBlock() // Must be after the main code to rename the new icons for YouTube 19.34+.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
package app.revanced.patches.shared.layout.theme
|
||||
|
||||
import app.revanced.patcher.patch.BytecodePatchBuilder
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patcher.patch.stringOption
|
||||
import app.revanced.util.childElementsSequence
|
||||
import java.util.Locale
|
||||
|
||||
internal const val THEME_COLOR_OPTION_DESCRIPTION = "Can be a hex color (#RRGGBB) or a color resource reference."
|
||||
|
||||
internal val THEME_DEFAULT_DARK_COLOR_NAMES = setOf(
|
||||
"yt_black0", "yt_black1", "yt_black1_opacity95", "yt_black1_opacity98",
|
||||
"yt_black2", "yt_black3", "yt_black4", "yt_status_bar_background_dark",
|
||||
"material_grey_850"
|
||||
)
|
||||
|
||||
internal val THEME_DEFAULT_LIGHT_COLOR_NAMES = setOf(
|
||||
"yt_white1", "yt_white1_opacity95", "yt_white1_opacity98",
|
||||
"yt_white2", "yt_white3", "yt_white4"
|
||||
)
|
||||
|
||||
/**
|
||||
* @param colorString #AARRGGBB #RRGGBB, or an Android color resource name.
|
||||
*/
|
||||
internal fun validateColorName(colorString: String): Boolean {
|
||||
if (colorString.startsWith("#")) {
|
||||
// #RRGGBB or #AARRGGBB
|
||||
val hex = colorString.substring(1).uppercase(Locale.US)
|
||||
|
||||
if (hex.length == 8) {
|
||||
// Transparent colors will crash the app.
|
||||
if (hex[0] != 'F' || hex[1] != 'F') {
|
||||
return false
|
||||
}
|
||||
} else if (hex.length != 6) {
|
||||
return false
|
||||
}
|
||||
|
||||
return hex.all { it.isDigit() || it in 'A'..'F' }
|
||||
}
|
||||
|
||||
if (colorString.startsWith("@android:color/")) {
|
||||
// Cannot easily validate Android built-in colors, so assume it's a correct color.
|
||||
return true
|
||||
}
|
||||
|
||||
// Allow any color name, because if it's invalid it will
|
||||
// throw an exception during resource compilation.
|
||||
return colorString.startsWith("@color/")
|
||||
}
|
||||
|
||||
/**
|
||||
* Dark theme color option for YouTube and YT Music Theme patches.
|
||||
*/
|
||||
internal val darkThemeBackgroundColorOption = stringOption(
|
||||
key = "darkThemeBackgroundColor",
|
||||
default = "@android:color/black",
|
||||
values = mapOf(
|
||||
"Pure black" to "@android:color/black",
|
||||
"Material You" to "@android:color/system_neutral1_900",
|
||||
"Classic (old YouTube)" to "#212121",
|
||||
"Catppuccin (Mocha)" to "#181825",
|
||||
"Dark pink" to "#290025",
|
||||
"Dark blue" to "#001029",
|
||||
"Dark green" to "#002905",
|
||||
"Dark yellow" to "#282900",
|
||||
"Dark orange" to "#291800",
|
||||
"Dark red" to "#290000",
|
||||
),
|
||||
title = "Dark theme background color",
|
||||
description = THEME_COLOR_OPTION_DESCRIPTION
|
||||
)
|
||||
|
||||
/**
|
||||
* Shared theme patch for YouTube and YT Music.
|
||||
*/
|
||||
internal fun baseThemePatch(
|
||||
extensionClassDescriptor: String,
|
||||
block: BytecodePatchBuilder.() -> Unit = {},
|
||||
executeBlock: BytecodePatchContext.() -> Unit = {}
|
||||
) = bytecodePatch(
|
||||
name = "Theme",
|
||||
description = "Adds options for theming and applies a custom background theme " +
|
||||
"(dark background theme defaults to pure black).",
|
||||
) {
|
||||
darkThemeBackgroundColorOption()
|
||||
|
||||
block()
|
||||
|
||||
dependsOn(lithoColorHookPatch)
|
||||
|
||||
execute {
|
||||
executeBlock()
|
||||
|
||||
lithoColorOverrideHook(extensionClassDescriptor, "getValue")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun baseThemeResourcePatch(
|
||||
darkColorNames: Set<String> = THEME_DEFAULT_DARK_COLOR_NAMES,
|
||||
lightColorNames: Set<String> = THEME_DEFAULT_LIGHT_COLOR_NAMES,
|
||||
lightColorReplacement: (() -> String)? = null
|
||||
) = resourcePatch {
|
||||
|
||||
execute {
|
||||
// After patch option validators are fixed https://github.com/ReVanced/revanced-patcher/issues/372
|
||||
// This should changed to a patch option validator.
|
||||
val darkColor by darkThemeBackgroundColorOption
|
||||
if (!validateColorName(darkColor!!)) {
|
||||
throw PatchException("Invalid dark theme color: $darkColor")
|
||||
}
|
||||
|
||||
val lightColor = lightColorReplacement?.invoke()
|
||||
if (lightColor != null && !validateColorName(lightColor)) {
|
||||
throw PatchException("Invalid light theme color: $lightColor")
|
||||
}
|
||||
|
||||
document("res/values/colors.xml").use { document ->
|
||||
val resourcesNode = document.getElementsByTagName("resources").item(0)
|
||||
|
||||
resourcesNode.childElementsSequence().forEach { node ->
|
||||
val name = node.getAttribute("name")
|
||||
when {
|
||||
name in darkColorNames -> node.textContent = darkColor
|
||||
lightColor != null && name in lightColorNames -> node.textContent = lightColor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package app.revanced.patches.shared.layout.theme
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val lithoOnBoundsChangeFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PROTECTED, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
parameters("Landroid/graphics/Rect;")
|
||||
opcodes(
|
||||
Opcode.IGET,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_NEZ,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.RETURN_VOID,
|
||||
)
|
||||
custom { method, _ ->
|
||||
method.name == "onBoundsChange"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package app.revanced.patches.shared.layout.theme
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
|
||||
lateinit var lithoColorOverrideHook: (targetMethodClass: String, targetMethodName: String) -> Unit
|
||||
private set
|
||||
|
||||
val lithoColorHookPatch = bytecodePatch(
|
||||
description = "Adds a hook to set color of Litho components.",
|
||||
) {
|
||||
|
||||
execute {
|
||||
var insertionIndex = lithoOnBoundsChangeFingerprint.patternMatch!!.endIndex - 1
|
||||
|
||||
lithoColorOverrideHook = { targetMethodClass, targetMethodName ->
|
||||
lithoOnBoundsChangeFingerprint.method.addInstructions(
|
||||
insertionIndex,
|
||||
"""
|
||||
invoke-static { p1 }, $targetMethodClass->$targetMethodName(I)I
|
||||
move-result p1
|
||||
"""
|
||||
)
|
||||
insertionIndex += 2
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.video.audio
|
||||
package app.revanced.patches.shared.misc.audio
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.containsLiteralInstruction
|
||||
@@ -7,10 +7,14 @@ import com.android.tools.smali.dexlib2.AccessFlags
|
||||
internal val formatStreamModelToStringFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("Ljava/lang/String;")
|
||||
custom { method, classDef ->
|
||||
method.name == "toString" && classDef.type ==
|
||||
"Lcom/google/android/libraries/youtube/innertube/model/media/FormatStreamModel;"
|
||||
custom { method, _ ->
|
||||
method.name == "toString"
|
||||
}
|
||||
strings(
|
||||
// Strings are partial matches.
|
||||
"isDefaultAudioTrack=",
|
||||
"audioTrackId="
|
||||
)
|
||||
}
|
||||
|
||||
internal const val AUDIO_STREAM_IGNORE_DEFAULT_FEATURE_FLAG = 45666189L
|
||||
@@ -20,7 +24,6 @@ internal val selectAudioStreamFingerprint = fingerprint {
|
||||
returns("L")
|
||||
custom { method, _ ->
|
||||
method.parameters.size > 2 // Method has a large number of parameters and may change.
|
||||
&& method.parameters[1].type == "Lcom/google/android/libraries/youtube/innertube/model/media/PlayerConfigModel;"
|
||||
&& method.containsLiteralInstruction(AUDIO_STREAM_IGNORE_DEFAULT_FEATURE_FLAG)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package app.revanced.patches.shared.misc.audio
|
||||
|
||||
import app.revanced.patcher.Fingerprint
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatchBuilder
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.BasePreferenceScreen
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.util.findMethodFromToString
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.insertLiteralOverride
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableField
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/shared/patches/ForceOriginalAudioPatch;"
|
||||
|
||||
/**
|
||||
* Patch shared with YouTube and YT Music.
|
||||
*/
|
||||
internal fun forceOriginalAudioPatch(
|
||||
block: BytecodePatchBuilder.() -> Unit = {},
|
||||
executeBlock: BytecodePatchContext.() -> Unit = {},
|
||||
fixUseLocalizedAudioTrackFlag: Boolean,
|
||||
mainActivityOnCreateFingerprint: Fingerprint,
|
||||
subclassExtensionClassDescriptor: String,
|
||||
preferenceScreen: BasePreferenceScreen.Screen
|
||||
) = bytecodePatch(
|
||||
name = "Force original audio",
|
||||
description = "Adds an option to always use the original audio track.",
|
||||
) {
|
||||
|
||||
block()
|
||||
|
||||
dependsOn(addResourcesPatch)
|
||||
|
||||
execute {
|
||||
addResources("shared", "misc.audio.forceOriginalAudioPatch")
|
||||
|
||||
preferenceScreen.addPreferences(
|
||||
SwitchPreference(
|
||||
key = "revanced_force_original_audio",
|
||||
tag = "app.revanced.extension.shared.settings.preference.ForceOriginalAudioSwitchPreference"
|
||||
)
|
||||
)
|
||||
|
||||
mainActivityOnCreateFingerprint.method.addInstruction(
|
||||
0,
|
||||
"invoke-static { }, $subclassExtensionClassDescriptor->setPreferredLanguage()V"
|
||||
)
|
||||
|
||||
// Disable feature flag that ignores the default track flag
|
||||
// and instead overrides to the user region language.
|
||||
if (fixUseLocalizedAudioTrackFlag) {
|
||||
selectAudioStreamFingerprint.method.insertLiteralOverride(
|
||||
AUDIO_STREAM_IGNORE_DEFAULT_FEATURE_FLAG,
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->ignoreDefaultAudioStream(Z)Z"
|
||||
)
|
||||
}
|
||||
|
||||
formatStreamModelToStringFingerprint.let {
|
||||
val isDefaultAudioTrackMethod = it.originalMethod.findMethodFromToString("isDefaultAudioTrack=")
|
||||
val audioTrackDisplayNameMethod = it.originalMethod.findMethodFromToString("audioTrackDisplayName=")
|
||||
val audioTrackIdMethod = it.originalMethod.findMethodFromToString("audioTrackId=")
|
||||
|
||||
it.classDef.apply {
|
||||
// Add a new field to store the override.
|
||||
val helperFieldName = "patch_isDefaultAudioTrackOverride"
|
||||
fields.add(
|
||||
ImmutableField(
|
||||
type,
|
||||
helperFieldName,
|
||||
"Ljava/lang/Boolean;",
|
||||
// Boolean is a 100% immutable class (all fields are final)
|
||||
// and safe to write to a shared field without volatile/synchronization,
|
||||
// but without volatile the field can show stale data
|
||||
// and the same field is calculated more than once by different threads.
|
||||
AccessFlags.PRIVATE.value or AccessFlags.VOLATILE.value,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
).toMutable()
|
||||
)
|
||||
|
||||
// Add a helper method because the isDefaultAudioTrack() has only 2 registers and 3 are needed.
|
||||
val helperMethodClass = type
|
||||
val helperMethodName = "patch_isDefaultAudioTrack"
|
||||
val helperMethod = ImmutableMethod(
|
||||
helperMethodClass,
|
||||
helperMethodName,
|
||||
listOf(ImmutableMethodParameter("Z", null, null)),
|
||||
"Z",
|
||||
AccessFlags.PRIVATE.value,
|
||||
null,
|
||||
null,
|
||||
MutableMethodImplementation(6),
|
||||
).toMutable().apply {
|
||||
addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
iget-object v0, p0, $helperMethodClass->$helperFieldName:Ljava/lang/Boolean;
|
||||
if-eqz v0, :call_extension
|
||||
invoke-virtual { v0 }, Ljava/lang/Boolean;->booleanValue()Z
|
||||
move-result v3
|
||||
return v3
|
||||
|
||||
:call_extension
|
||||
invoke-virtual { p0 }, $audioTrackIdMethod
|
||||
move-result-object v1
|
||||
|
||||
invoke-virtual { p0 }, $audioTrackDisplayNameMethod
|
||||
move-result-object v2
|
||||
|
||||
invoke-static { p1, v1, v2 }, $EXTENSION_CLASS_DESCRIPTOR->isDefaultAudioStream(ZLjava/lang/String;Ljava/lang/String;)Z
|
||||
move-result v3
|
||||
|
||||
invoke-static { v3 }, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;
|
||||
move-result-object v0
|
||||
iput-object v0, p0, $helperMethodClass->$helperFieldName:Ljava/lang/Boolean;
|
||||
return v3
|
||||
"""
|
||||
)
|
||||
}
|
||||
methods.add(helperMethod)
|
||||
|
||||
// Modify isDefaultAudioTrack() to call extension helper method.
|
||||
isDefaultAudioTrackMethod.apply {
|
||||
val index = indexOfFirstInstructionOrThrow(Opcode.RETURN)
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
addInstructions(
|
||||
index,
|
||||
"""
|
||||
invoke-direct { p0, v$register }, $helperMethodClass->$helperMethodName(Z)Z
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
executeBlock()
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ internal fun sanitizeSharingLinksPatch(
|
||||
replaceMusicLinksWithYouTube: Boolean = false
|
||||
) = bytecodePatch(
|
||||
name = "Sanitize sharing links",
|
||||
description = "Adds an option to remove the tracking parameter from links you share.",
|
||||
description = "Adds an option to remove the tracking query parameter from shared links.",
|
||||
) {
|
||||
block()
|
||||
|
||||
|
||||
@@ -26,26 +26,26 @@ fun settingsPatch (
|
||||
preferences: Set<BasePreference>,
|
||||
) = settingsPatch(listOf(rootPreference), preferences)
|
||||
|
||||
private var themeForegroundColor : String? = null
|
||||
private var themeBackgroundColor : String? = null
|
||||
private var lightThemeColor : String? = null
|
||||
private var darkThemeColor : String? = null
|
||||
|
||||
/**
|
||||
* Sets the default theme colors used in various ReVanced specific settings menus.
|
||||
* By default these colors are white and black, but instead can be set to the
|
||||
* same color the target app uses for it's own settings.
|
||||
*/
|
||||
fun overrideThemeColors(foregroundColor: String, backgroundColor: String) {
|
||||
themeForegroundColor = foregroundColor
|
||||
themeBackgroundColor = backgroundColor
|
||||
fun overrideThemeColors(lightThemeColorString: String?, darkThemeColorString: String) {
|
||||
lightThemeColor = lightThemeColorString
|
||||
darkThemeColor = darkThemeColorString
|
||||
}
|
||||
|
||||
private val settingsColorPatch = bytecodePatch {
|
||||
finalize {
|
||||
if (themeForegroundColor != null) {
|
||||
themeLightColorResourceNameFingerprint.method.returnEarly(themeForegroundColor!!)
|
||||
if (lightThemeColor != null) {
|
||||
themeLightColorResourceNameFingerprint.method.returnEarly(lightThemeColor!!)
|
||||
}
|
||||
if (themeBackgroundColor != null) {
|
||||
themeDarkColorResourceNameFingerprint.method.returnEarly(themeBackgroundColor!!)
|
||||
if (darkThemeColor != null) {
|
||||
themeDarkColorResourceNameFingerprint.method.returnEarly(darkThemeColor!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,8 @@ val dynamicColorPatch = resourcePatch(
|
||||
) {
|
||||
compatibleWith(
|
||||
"com.twitter.android"(
|
||||
"10.86.0-release.0",
|
||||
"10.60.0-release.0",
|
||||
"10.48.0-release.0"
|
||||
"10.86.0-release.0",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package app.revanced.patches.twitter.misc.extension
|
||||
|
||||
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.twitter.misc.extension.hooks.applicationInitHook
|
||||
|
||||
val sharedExtensionPatch = sharedExtensionPatch("twitter")
|
||||
val sharedExtensionPatch = sharedExtensionPatch("twitter", applicationInitHook)
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package app.revanced.patches.twitter.misc.extension.hooks
|
||||
|
||||
import app.revanced.patches.shared.misc.extension.extensionHook
|
||||
|
||||
internal val applicationInitHook =
|
||||
extensionHook {
|
||||
custom { method, classDef ->
|
||||
classDef.type == "Lcom/twitter/app/TwitterApplication;" && method.name == "onCreate"
|
||||
}
|
||||
}
|
||||
@@ -13,11 +13,8 @@ fun hookPatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.twitter.android"(
|
||||
// Only v10.85 uses Pairip and requires additional changes to work.
|
||||
"10.86.0-release.0",
|
||||
// Confirmed to not show reply ads. Slightly newer versions may also work.
|
||||
"10.60.0-release.0",
|
||||
"10.48.0-release.0"
|
||||
"10.86.0-release.0",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -39,9 +39,8 @@ val changeLinkSharingDomainPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.twitter.android"(
|
||||
"10.86.0-release.0",
|
||||
"10.60.0-release.0",
|
||||
"10.48.0-release.0"
|
||||
"10.86.0-release.0",
|
||||
)
|
||||
)
|
||||
|
||||
@@ -54,28 +53,28 @@ val changeLinkSharingDomainPatch = bytecodePatch(
|
||||
)
|
||||
|
||||
execute {
|
||||
val replacementIndex =
|
||||
linkSharingDomainFingerprint.stringMatches!!.first().index
|
||||
val domainRegister =
|
||||
linkSharingDomainFingerprint.method.getInstruction<OneRegisterInstruction>(replacementIndex).registerA
|
||||
linkSharingDomainFingerprint.let {
|
||||
val replacementIndex = it.stringMatches!!.first().index
|
||||
val domainRegister = it.method.getInstruction<OneRegisterInstruction>(
|
||||
replacementIndex
|
||||
).registerA
|
||||
|
||||
linkSharingDomainFingerprint.method.replaceInstruction(
|
||||
replacementIndex,
|
||||
"const-string v$domainRegister, \"https://$domainName\"",
|
||||
)
|
||||
|
||||
// Replace the domain name when copying a link with "Copy link" button.
|
||||
linkBuilderFingerprint.method.apply {
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static { p0, p1, p2 }, $EXTENSION_CLASS_DESCRIPTOR->formatLink(JLjava/lang/String;)Ljava/lang/String;
|
||||
move-result-object p0
|
||||
return-object p0
|
||||
""",
|
||||
it.method.replaceInstruction(
|
||||
replacementIndex,
|
||||
"const-string v$domainRegister, \"https://$domainName\"",
|
||||
)
|
||||
}
|
||||
|
||||
// Replace the domain name when copying a link with "Copy link" button.
|
||||
linkBuilderFingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static { p0, p1, p2 }, $EXTENSION_CLASS_DESCRIPTOR->formatLink(JLjava/lang/String;)Ljava/lang/String;
|
||||
move-result-object p0
|
||||
return-object p0
|
||||
"""
|
||||
)
|
||||
|
||||
// Used in the Share via... dialog.
|
||||
linkResourceGetterFingerprint.method.apply {
|
||||
val templateIdConstIndex = indexOfFirstLiteralInstructionOrThrow(tweetShareLinkTemplateId)
|
||||
|
||||
@@ -4,12 +4,12 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.twitter.misc.extension.sharedExtensionPatch
|
||||
|
||||
@Deprecated("Patch is obsolete and no longer needed with the highest supported app target. " +
|
||||
"This patch will soon be deleted.")
|
||||
@Suppress("unused")
|
||||
val openLinksWithAppChooserPatch = bytecodePatch(
|
||||
name = "Open links with app chooser",
|
||||
description = "Instead of opening links directly, open them with an app chooser. " +
|
||||
"As a result you can select a browser to open the link with.",
|
||||
use = false,
|
||||
"As a result you can select a browser to open the link with.",
|
||||
) {
|
||||
dependsOn(sharedExtensionPatch)
|
||||
|
||||
@@ -18,7 +18,7 @@ val openLinksWithAppChooserPatch = bytecodePatch(
|
||||
execute {
|
||||
val methodReference =
|
||||
"Lapp/revanced/extension/twitter/patches/links/OpenLinksWithAppChooserPatch;->" +
|
||||
"openWithChooser(Landroid/content/Context;Landroid/content/Intent;)V"
|
||||
"openWithChooser(Landroid/content/Context;Landroid/content/Intent;)V"
|
||||
|
||||
openLinkFingerprint.method.addInstructions(
|
||||
0,
|
||||
|
||||
@@ -10,9 +10,8 @@ val sanitizeSharingLinksPatch = bytecodePatch(
|
||||
) {
|
||||
compatibleWith(
|
||||
"com.twitter.android"(
|
||||
"10.86.0-release.0",
|
||||
"10.60.0-release.0",
|
||||
"10.48.0-release.0"
|
||||
"10.86.0-release.0",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package app.revanced.patches.viber.misc.navbar
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
internal val tabIdClassFingerprint = fingerprint {
|
||||
strings("shouldShowTabId")
|
||||
}
|
||||
|
||||
context(BytecodePatchContext)
|
||||
internal val shouldShowTabIdMethodFingerprint get() = fingerprint {
|
||||
parameters("I", "I")
|
||||
returns("Z")
|
||||
custom { methodDef, classDef ->
|
||||
classDef == tabIdClassFingerprint.classDef
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package app.revanced.patches.viber.misc.navbar
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.patch.booleanOption
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import java.util.logging.Logger
|
||||
import kotlin.collections.joinToString
|
||||
|
||||
|
||||
private const val instructionsFooter = """
|
||||
# If we reach this, it means that this tab has been disabled by user
|
||||
const/4 v0, 0
|
||||
return v0 # return false as "This tab is not enabled"
|
||||
|
||||
# Proceed with default execution
|
||||
:continue
|
||||
nop
|
||||
"""
|
||||
|
||||
@Suppress("unused")
|
||||
val hideNavigationButtonsPatch = bytecodePatch(
|
||||
name = "Hide navigation buttons",
|
||||
description = "Permanently hides navigation bar buttons, such as Explore and Marketplace.",
|
||||
use = false
|
||||
) {
|
||||
compatibleWith("com.viber.voip")
|
||||
|
||||
val hideOptions = AllowedNavigationItems.entries.associateWith {
|
||||
booleanOption(
|
||||
key = it.key,
|
||||
default = it.defaultHideOption,
|
||||
title = it.title,
|
||||
description = it.description,
|
||||
)
|
||||
}
|
||||
|
||||
execute {
|
||||
// Items that won't be forcefully hidden.
|
||||
val allowedItems = hideOptions.filter { (option, enabled) -> enabled.value != true }
|
||||
|
||||
if (allowedItems.size == AllowedNavigationItems.entries.size) {
|
||||
return@execute Logger.getLogger(this::class.java.name).warning(
|
||||
"No hide navigation buttons options are enabled. No changes made."
|
||||
)
|
||||
}
|
||||
|
||||
val injectionInstructions = allowedItems
|
||||
.map { it.key.buildAllowInstruction() }
|
||||
.joinToString("\n") + instructionsFooter
|
||||
|
||||
shouldShowTabIdMethodFingerprint
|
||||
.method
|
||||
.addInstructionsWithLabels(0, injectionInstructions)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigation items taken from source code.
|
||||
* They appear in code like new NavigationItem(0, R.string.bottom_tab_chats, R.drawable.ic_tab_chats).
|
||||
*/
|
||||
private enum class AllowedNavigationItems(
|
||||
val defaultHideOption: Boolean,
|
||||
private val itemName: String,
|
||||
private vararg val ids: Int
|
||||
) {
|
||||
CHATS(false, "Chats", 0),
|
||||
CALLS(false, "Calls", 1, 7),
|
||||
EXPLORE(true, "Explore", 2),
|
||||
MORE(false, "More", 3),
|
||||
PAY(true, "Pay", 5),
|
||||
CAMERA(true, "Camera", 6),
|
||||
MARKETPLACE(true, "Marketplace", 8);
|
||||
|
||||
val key = "hide$itemName"
|
||||
val title = "Hide $itemName"
|
||||
val description = "Permanently hides the $itemName button."
|
||||
|
||||
fun buildAllowInstruction(): String =
|
||||
ids.joinToString("\n") { id ->
|
||||
"""
|
||||
const/4 v0, $id # If tabId == $id ($itemName), don't hide it
|
||||
if-eq p1, v0, :continue
|
||||
"""
|
||||
}
|
||||
}
|
||||
@@ -1,141 +1,60 @@
|
||||
package app.revanced.patches.youtube.layout.branding
|
||||
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patcher.patch.stringOption
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.Utils.trimIndentMultiline
|
||||
import app.revanced.util.copyResources
|
||||
import java.io.File
|
||||
import app.revanced.patches.shared.layout.branding.baseCustomBrandingPatch
|
||||
import app.revanced.patches.shared.layout.branding.mipmapDirectories
|
||||
import java.nio.file.Files
|
||||
|
||||
private const val REVANCED_ICON = "ReVanced*Logo" // Can never be a valid path.
|
||||
private const val APP_NAME = "YouTube ReVanced"
|
||||
|
||||
private val iconResourceFileNames = arrayOf(
|
||||
"adaptiveproduct_youtube_background_color_108",
|
||||
"adaptiveproduct_youtube_foreground_color_108",
|
||||
"ic_launcher",
|
||||
"ic_launcher_round",
|
||||
).map { "$it.png" }.toTypedArray()
|
||||
|
||||
private val iconResourceFileNamesNew = mapOf(
|
||||
private val youtubeIconResourceFileNames_19_34 = mapOf(
|
||||
"adaptiveproduct_youtube_foreground_color_108" to "adaptiveproduct_youtube_2024_q4_foreground_color_108",
|
||||
"adaptiveproduct_youtube_background_color_108" to "adaptiveproduct_youtube_2024_q4_background_color_108",
|
||||
)
|
||||
|
||||
private val mipmapDirectories = arrayOf(
|
||||
"xxxhdpi",
|
||||
"xxhdpi",
|
||||
"xhdpi",
|
||||
"hdpi",
|
||||
"mdpi",
|
||||
).map { "mipmap-$it" }
|
||||
|
||||
@Suppress("unused")
|
||||
val customBrandingPatch = resourcePatch(
|
||||
name = "Custom branding",
|
||||
description = "Applies a custom app name and icon. Defaults to \"YouTube ReVanced\" and the ReVanced logo.",
|
||||
use = false,
|
||||
) {
|
||||
dependsOn(versionCheckPatch)
|
||||
val customBrandingPatch = baseCustomBrandingPatch(
|
||||
defaultAppName = APP_NAME,
|
||||
appNameValues = mapOf(
|
||||
"YouTube ReVanced" to APP_NAME,
|
||||
"YT ReVanced" to "YT ReVanced",
|
||||
"YT" to "YT",
|
||||
"YouTube" to "YouTube",
|
||||
),
|
||||
resourceFolder = "custom-branding/youtube",
|
||||
iconResourceFileNames = arrayOf(
|
||||
"adaptiveproduct_youtube_background_color_108",
|
||||
"adaptiveproduct_youtube_foreground_color_108",
|
||||
"ic_launcher",
|
||||
"ic_launcher_round",
|
||||
),
|
||||
monochromeIconFileNames = arrayOf(
|
||||
"adaptive_monochrome_ic_youtube_launcher.xml",
|
||||
"ringo2_adaptive_monochrome_ic_youtube_launcher.xml"
|
||||
),
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.34.42",
|
||||
"20.07.39",
|
||||
"20.13.41",
|
||||
"20.14.43",
|
||||
)
|
||||
)
|
||||
|
||||
val appName by stringOption(
|
||||
key = "appName",
|
||||
default = APP_NAME,
|
||||
values = mapOf(
|
||||
"YouTube ReVanced" to APP_NAME,
|
||||
"YT ReVanced" to "YT ReVanced",
|
||||
"YT" to "YT",
|
||||
"YouTube" to "YouTube",
|
||||
),
|
||||
title = "App name",
|
||||
description = "The name of the app.",
|
||||
)
|
||||
|
||||
val icon by stringOption(
|
||||
key = "iconPath",
|
||||
default = REVANCED_ICON,
|
||||
values = mapOf("ReVanced Logo" to REVANCED_ICON),
|
||||
title = "App icon",
|
||||
description = """
|
||||
The icon to apply to the app.
|
||||
|
||||
If a path to a folder is provided, the folder must contain the following folders:
|
||||
|
||||
${mipmapDirectories.joinToString("\n") { "- $it" }}
|
||||
|
||||
Each of these folders must contain the following files:
|
||||
|
||||
${iconResourceFileNames.joinToString("\n") { "- $it" }}
|
||||
""".trimIndentMultiline(),
|
||||
)
|
||||
|
||||
execute {
|
||||
icon?.let { icon ->
|
||||
// Change the app icon.
|
||||
mipmapDirectories.map { directory ->
|
||||
ResourceGroup(
|
||||
directory,
|
||||
*iconResourceFileNames,
|
||||
)
|
||||
}.let { resourceGroups ->
|
||||
if (icon != REVANCED_ICON) {
|
||||
val path = File(icon)
|
||||
val resourceDirectory = get("res")
|
||||
|
||||
resourceGroups.forEach { group ->
|
||||
val fromDirectory = path.resolve(group.resourceDirectoryName)
|
||||
val toDirectory = resourceDirectory.resolve(group.resourceDirectoryName)
|
||||
|
||||
group.resources.forEach { iconFileName ->
|
||||
Files.write(
|
||||
toDirectory.resolve(iconFileName).toPath(),
|
||||
fromDirectory.resolve(iconFileName).readBytes(),
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resourceGroups.forEach { copyResources("custom-branding", it) }
|
||||
}
|
||||
}
|
||||
|
||||
if (is_19_34_or_greater) {
|
||||
val resourceDirectory = get("res")
|
||||
|
||||
mipmapDirectories.forEach { directory ->
|
||||
val targetDirectory = resourceDirectory.resolve(directory)
|
||||
|
||||
iconResourceFileNamesNew.forEach { (old, new) ->
|
||||
val oldFile = targetDirectory.resolve("$old.png")
|
||||
val newFile = targetDirectory.resolve("$new.png")
|
||||
|
||||
Files.write(newFile.toPath(), oldFile.readBytes())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
appName?.let { name ->
|
||||
// Change the app name.
|
||||
val manifest = get("AndroidManifest.xml")
|
||||
manifest.writeText(
|
||||
manifest.readText()
|
||||
.replace(
|
||||
"android:label=\"@string/application_name",
|
||||
"android:label=\"$name",
|
||||
),
|
||||
block = {
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.34.42",
|
||||
"20.07.39",
|
||||
"20.13.41",
|
||||
"20.14.43",
|
||||
)
|
||||
)
|
||||
},
|
||||
|
||||
executeBlock = {
|
||||
val resourceDirectory = get("res")
|
||||
|
||||
mipmapDirectories.forEach { directory ->
|
||||
val targetDirectory = resourceDirectory.resolve(directory)
|
||||
|
||||
youtubeIconResourceFileNames_19_34.forEach { (old, new) ->
|
||||
val oldFile = targetDirectory.resolve("$old.png")
|
||||
val newFile = targetDirectory.resolve("$new.png")
|
||||
|
||||
Files.write(newFile.toPath(), oldFile.readBytes())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
package app.revanced.patches.youtube.layout.hide.endscreencards
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.containsLiteralInstruction
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
internal val layoutCircleFingerprint = fingerprint {
|
||||
returns("Landroid/view/View;")
|
||||
@@ -38,3 +43,19 @@ internal val layoutVideoFingerprint = fingerprint {
|
||||
)
|
||||
literal { layoutVideo }
|
||||
}
|
||||
|
||||
internal val showEndscreenCardsFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
parameters("L")
|
||||
custom { method, classDef ->
|
||||
classDef.methods.count() == 5
|
||||
&& method.containsLiteralInstruction(0)
|
||||
&& method.containsLiteralInstruction(5)
|
||||
&& method.containsLiteralInstruction(8)
|
||||
&& method.indexOfFirstInstruction {
|
||||
val reference = getReference<FieldReference>()
|
||||
reference?.type == "Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"
|
||||
} >= 0
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.revanced.patches.youtube.layout.hide.endscreencards
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
@@ -11,6 +12,8 @@ import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_43_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
@@ -22,7 +25,7 @@ internal var layoutIcon = -1L
|
||||
internal var layoutVideo = -1L
|
||||
private set
|
||||
|
||||
private val hideEndscreenCardsResourcePatch = resourcePatch {
|
||||
private val hideEndScreenCardsResourcePatch = resourcePatch {
|
||||
dependsOn(
|
||||
settingsPatch,
|
||||
resourceMappingPatch,
|
||||
@@ -30,7 +33,7 @@ private val hideEndscreenCardsResourcePatch = resourcePatch {
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("youtube", "layout.hide.endscreencards.hideEndscreenCardsResourcePatch")
|
||||
addResources("youtube", "layout.hide.endscreencards.hideEndScreenCardsResourcePatch")
|
||||
|
||||
PreferenceScreen.PLAYER.addPreferences(
|
||||
SwitchPreference("revanced_hide_endscreen_cards"),
|
||||
@@ -45,16 +48,17 @@ private val hideEndscreenCardsResourcePatch = resourcePatch {
|
||||
}
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/HideEndscreenCardsPatch;"
|
||||
"Lapp/revanced/extension/youtube/patches/HideEndScreenCardsPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val hideEndscreenCardsPatch = bytecodePatch(
|
||||
val hideEndScreenCardsPatch = bytecodePatch(
|
||||
name = "Hide end screen cards",
|
||||
description = "Adds an option to hide suggested video cards at the end of videos.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
hideEndscreenCardsResourcePatch,
|
||||
hideEndScreenCardsResourcePatch,
|
||||
versionCheckPatch
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
@@ -78,9 +82,24 @@ val hideEndscreenCardsPatch = bytecodePatch(
|
||||
|
||||
addInstruction(
|
||||
insertIndex,
|
||||
"invoke-static { v$viewRegister }, $EXTENSION_CLASS_DESCRIPTOR->hideEndscreen(Landroid/view/View;)V",
|
||||
"invoke-static { v$viewRegister }, " +
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->hideEndScreenCardView(Landroid/view/View;)V",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (is_19_43_or_greater) {
|
||||
showEndscreenCardsFingerprint.method.addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->hideEndScreenCards()Z
|
||||
move-result v0
|
||||
if-eqz v0, :show
|
||||
return-void
|
||||
:show
|
||||
nop
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,3 +147,17 @@ internal val showFloatingMicrophoneButtonFingerprint = fingerprint {
|
||||
)
|
||||
literal { fabButtonId }
|
||||
}
|
||||
|
||||
internal val hideViewCountFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returns("Ljava/lang/CharSequence;")
|
||||
|
||||
opcodes(
|
||||
Opcode.RETURN_OBJECT,
|
||||
Opcode.CONST_STRING,
|
||||
Opcode.RETURN_OBJECT,
|
||||
)
|
||||
strings(
|
||||
"Has attachmentRuns but drawableRequester is missing.",
|
||||
)
|
||||
}
|
||||
@@ -36,6 +36,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
||||
|
||||
var expandButtonDownId = -1L
|
||||
private set
|
||||
@@ -161,9 +162,9 @@ val hideLayoutComponentsPatch = bytecodePatch(
|
||||
SwitchPreference("revanced_hide_comments_section"),
|
||||
SwitchPreference("revanced_hide_comments_community_guidelines"),
|
||||
SwitchPreference("revanced_hide_comments_create_a_short_button"),
|
||||
SwitchPreference("revanced_hide_comments_emoji_and_timestamp_buttons"),
|
||||
SwitchPreference("revanced_hide_comments_preview_comment"),
|
||||
SwitchPreference("revanced_hide_comments_thanks_button"),
|
||||
SwitchPreference("revanced_hide_comments_timestamp_button"),
|
||||
),
|
||||
sorting = PreferenceScreenPreference.Sorting.UNSORTED,
|
||||
),
|
||||
@@ -239,6 +240,8 @@ val hideLayoutComponentsPatch = bytecodePatch(
|
||||
SwitchPreference("revanced_hide_surveys"),
|
||||
SwitchPreference("revanced_hide_ticket_shelf"),
|
||||
SwitchPreference("revanced_hide_video_recommendation_labels"),
|
||||
SwitchPreference("revanced_hide_view_count"),
|
||||
SwitchPreference("revanced_hide_upload_time"),
|
||||
SwitchPreference("revanced_hide_doodles"),
|
||||
)
|
||||
|
||||
@@ -397,6 +400,39 @@ val hideLayoutComponentsPatch = bytecodePatch(
|
||||
|
||||
// endregion
|
||||
|
||||
|
||||
// region hide view count
|
||||
|
||||
hideViewCountFingerprint.method.apply {
|
||||
val startIndex = hideViewCountFingerprint.patternMatch!!.startIndex
|
||||
var returnStringRegister = getInstruction<OneRegisterInstruction>(startIndex).registerA
|
||||
|
||||
// Find the instruction where the text dimension is retrieved.
|
||||
val applyDimensionIndex = indexOfFirstInstructionReversedOrThrow {
|
||||
val reference = getReference<MethodReference>()
|
||||
opcode == Opcode.INVOKE_STATIC &&
|
||||
reference?.definingClass == "Landroid/util/TypedValue;" &&
|
||||
reference.returnType == "F" &&
|
||||
reference.name == "applyDimension" &&
|
||||
reference.parameterTypes == listOf("I", "F", "Landroid/util/DisplayMetrics;")
|
||||
}
|
||||
|
||||
// A float value is passed which is used to determine subtitle text size.
|
||||
val floatDimensionRegister = getInstruction<OneRegisterInstruction>(
|
||||
applyDimensionIndex + 1
|
||||
).registerA
|
||||
|
||||
addInstructions(
|
||||
applyDimensionIndex - 1,
|
||||
"""
|
||||
invoke-static { v$returnStringRegister, v$floatDimensionRegister }, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->modifyFeedSubtitleSpan(Landroid/text/SpannableString;F)Landroid/text/SpannableString;
|
||||
move-result-object v$returnStringRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region hide filter bar
|
||||
|
||||
/**
|
||||
|
||||
@@ -186,15 +186,15 @@ val miniplayerPatch = bytecodePatch(
|
||||
if (!is_19_29_or_greater) {
|
||||
preferences += SwitchPreference("revanced_miniplayer_double_tap_action")
|
||||
}
|
||||
preferences += SwitchPreference("revanced_miniplayer_drag_and_drop")
|
||||
preferences += SwitchPreference("revanced_miniplayer_disable_drag_and_drop")
|
||||
}
|
||||
|
||||
if (is_19_43_or_greater) {
|
||||
preferences += SwitchPreference("revanced_miniplayer_horizontal_drag")
|
||||
preferences += SwitchPreference("revanced_miniplayer_disable_horizontal_drag")
|
||||
}
|
||||
|
||||
if (is_19_36_or_greater) {
|
||||
preferences += SwitchPreference("revanced_miniplayer_rounded_corners")
|
||||
preferences += SwitchPreference("revanced_miniplayer_disable_rounded_corners")
|
||||
}
|
||||
|
||||
preferences += SwitchPreference("revanced_miniplayer_hide_subtext")
|
||||
|
||||
@@ -10,13 +10,12 @@ import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patches.shared.layout.theme.lithoColorHookPatch
|
||||
import app.revanced.patches.shared.layout.theme.lithoColorOverrideHook
|
||||
import app.revanced.patches.shared.misc.mapping.get
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||
import app.revanced.patches.youtube.layout.theme.lithoColorHookPatch
|
||||
import app.revanced.patches.youtube.layout.theme.lithoColorOverrideHook
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_46_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_49_or_greater
|
||||
@@ -108,11 +107,6 @@ private val seekbarColorResourcePatch = resourcePatch {
|
||||
scaleNode.replaceChild(replacementNode, shapeNode)
|
||||
}
|
||||
|
||||
|
||||
if (!is_19_25_or_greater) {
|
||||
return@execute
|
||||
}
|
||||
|
||||
ytYoutubeMagentaColorId = resourceMappings[
|
||||
"color",
|
||||
"yt_youtube_magenta",
|
||||
@@ -260,10 +254,6 @@ val seekbarColorPatch = bytecodePatch(
|
||||
|
||||
lithoColorOverrideHook(EXTENSION_CLASS_DESCRIPTOR, "getLithoColor")
|
||||
|
||||
if (!is_19_25_or_greater) {
|
||||
return@execute
|
||||
}
|
||||
|
||||
// 19.25+ changes
|
||||
|
||||
arrayOf(
|
||||
|
||||
@@ -161,7 +161,7 @@ val openShortsInRegularPlayerPatch = bytecodePatch(
|
||||
addInstructions(
|
||||
index + 1,
|
||||
"""
|
||||
invoke-static { v$register }, ${EXTENSION_CLASS_DESCRIPTOR}->overrideBackPressToExit(Z)Z
|
||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->overrideBackPressToExit(Z)Z
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -3,27 +3,6 @@ package app.revanced.patches.youtube.layout.theme
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patches.youtube.shared.YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
|
||||
import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val lithoThemeFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PROTECTED, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
parameters("Landroid/graphics/Rect;")
|
||||
opcodes(
|
||||
Opcode.IGET,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_NEZ,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.RETURN_VOID,
|
||||
)
|
||||
custom { method, _ ->
|
||||
method.name == "onBoundsChange"
|
||||
}
|
||||
}
|
||||
|
||||
internal const val GRADIENT_LOADING_SCREEN_AB_CONSTANT = 45412406L
|
||||
|
||||
|
||||
@@ -1,28 +1,19 @@
|
||||
package app.revanced.patches.youtube.layout.theme
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
|
||||
|
||||
@Deprecated("Function was moved", ReplaceWith("app.revanced.patches.shared.layout.theme.lithoColorOverrideHook"))
|
||||
@Suppress("unused")
|
||||
lateinit var lithoColorOverrideHook: (targetMethodClass: String, targetMethodName: String) -> Unit
|
||||
private set
|
||||
|
||||
val lithoColorHookPatch = bytecodePatch(
|
||||
description = "Adds a hook to set color of Litho components.",
|
||||
) {
|
||||
@Deprecated("Patch was moved", ReplaceWith("app.revanced.patches.shared.layout.theme.lithoColorHookPatch"))
|
||||
@Suppress("unused")
|
||||
val lithoColorHookPatch = bytecodePatch{
|
||||
dependsOn(app.revanced.patches.shared.layout.theme.lithoColorHookPatch)
|
||||
|
||||
execute {
|
||||
|
||||
var insertionIndex = lithoThemeFingerprint.patternMatch!!.endIndex - 1
|
||||
|
||||
lithoColorOverrideHook = { targetMethodClass, targetMethodName ->
|
||||
lithoThemeFingerprint.method.addInstructions(
|
||||
insertionIndex,
|
||||
"""
|
||||
invoke-static { p1 }, $targetMethodClass->$targetMethodName(I)I
|
||||
move-result p1
|
||||
""",
|
||||
)
|
||||
insertionIndex += 2
|
||||
}
|
||||
lithoColorOverrideHook = app.revanced.patches.shared.layout.theme.lithoColorOverrideHook
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
package app.revanced.patches.youtube.layout.theme
|
||||
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patcher.patch.stringOption
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.layout.theme.THEME_COLOR_OPTION_DESCRIPTION
|
||||
import app.revanced.patches.shared.layout.theme.baseThemePatch
|
||||
import app.revanced.patches.shared.layout.theme.baseThemeResourcePatch
|
||||
import app.revanced.patches.shared.layout.theme.darkThemeBackgroundColorOption
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.settings.overrideThemeColors
|
||||
import app.revanced.patches.shared.misc.settings.preference.BasePreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.InputType
|
||||
import app.revanced.patches.shared.misc.settings.preference.ListPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceCategory
|
||||
@@ -17,126 +19,54 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
||||
import app.revanced.patches.youtube.layout.seekbar.seekbarColorPatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_47_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.util.childElementsSequence
|
||||
import app.revanced.util.forEachChildElement
|
||||
import app.revanced.util.insertLiteralOverride
|
||||
import org.w3c.dom.Element
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/theme/ThemePatch;"
|
||||
|
||||
val themePatch = bytecodePatch(
|
||||
name = "Theme",
|
||||
description = "Adds options for theming and applies a custom background theme " +
|
||||
"(dark background theme defaults to amoled black).",
|
||||
) {
|
||||
val amoledBlackColor = "@android:color/black"
|
||||
val whiteColor = "@android:color/white"
|
||||
val themePatch = baseThemePatch(
|
||||
extensionClassDescriptor = EXTENSION_CLASS_DESCRIPTOR,
|
||||
|
||||
val darkThemeBackgroundColor by stringOption(
|
||||
key = "darkThemeBackgroundColor",
|
||||
default = amoledBlackColor,
|
||||
values = mapOf(
|
||||
"Amoled black" to amoledBlackColor,
|
||||
"Material You" to "@android:color/system_neutral1_900",
|
||||
"Classic (old YouTube)" to "#FF212121",
|
||||
"Catppuccin (Mocha)" to "#FF181825",
|
||||
"Dark pink" to "#FF290025",
|
||||
"Dark blue" to "#FF001029",
|
||||
"Dark green" to "#FF002905",
|
||||
"Dark yellow" to "#FF282900",
|
||||
"Dark orange" to "#FF291800",
|
||||
"Dark red" to "#FF290000",
|
||||
),
|
||||
title = "Dark theme background color",
|
||||
description = "Can be a hex color (#AARRGGBB) or a color resource reference.",
|
||||
)
|
||||
block = {
|
||||
val lightThemeBackgroundColor by stringOption(
|
||||
key = "lightThemeBackgroundColor",
|
||||
default = "@android:color/white",
|
||||
values = mapOf(
|
||||
"White" to "@android:color/white",
|
||||
"Material You" to "@android:color/system_neutral1_50",
|
||||
"Catppuccin (Latte)" to "#E6E9EF",
|
||||
"Light pink" to "#FCCFF3",
|
||||
"Light blue" to "#D1E0FF",
|
||||
"Light green" to "#CCFFCC",
|
||||
"Light yellow" to "#FDFFCC",
|
||||
"Light orange" to "#FFE6CC",
|
||||
"Light red" to "#FFD6D6",
|
||||
),
|
||||
title = "Light theme background color",
|
||||
description = THEME_COLOR_OPTION_DESCRIPTION
|
||||
)
|
||||
|
||||
val lightThemeBackgroundColor by stringOption(
|
||||
key = "lightThemeBackgroundColor",
|
||||
default = whiteColor,
|
||||
values = mapOf(
|
||||
"White" to whiteColor,
|
||||
"Material You" to "@android:color/system_neutral1_50",
|
||||
"Catppuccin (Latte)" to "#FFE6E9EF",
|
||||
"Light pink" to "#FFFCCFF3",
|
||||
"Light blue" to "#FFD1E0FF",
|
||||
"Light green" to "#FFCCFFCC",
|
||||
"Light yellow" to "#FFFDFFCC",
|
||||
"Light orange" to "#FFFFE6CC",
|
||||
"Light red" to "#FFFFD6D6",
|
||||
),
|
||||
title = "Light theme background color",
|
||||
description = "Can be a hex color (#AARRGGBB) or a color resource reference.",
|
||||
)
|
||||
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
lithoColorHookPatch,
|
||||
seekbarColorPatch,
|
||||
versionCheckPatch,
|
||||
resourcePatch {
|
||||
dependsOn(
|
||||
settingsPatch,
|
||||
resourceMappingPatch,
|
||||
)
|
||||
val themeResourcePatch = resourcePatch {
|
||||
dependsOn(resourceMappingPatch)
|
||||
|
||||
execute {
|
||||
val preferences = mutableSetOf<BasePreference>(
|
||||
SwitchPreference("revanced_seekbar_custom_color"),
|
||||
TextPreference("revanced_seekbar_custom_color_primary",
|
||||
tag = "app.revanced.extension.shared.settings.preference.ColorPickerPreference",
|
||||
inputType = InputType.TEXT_CAP_CHARACTERS),
|
||||
overrideThemeColors(
|
||||
lightThemeBackgroundColor!!,
|
||||
darkThemeBackgroundColorOption.value!!
|
||||
)
|
||||
|
||||
if (is_19_25_or_greater) {
|
||||
preferences += TextPreference("revanced_seekbar_custom_color_accent",
|
||||
tag = "app.revanced.extension.shared.settings.preference.ColorPickerPreference",
|
||||
inputType = InputType.TEXT_CAP_CHARACTERS)
|
||||
}
|
||||
|
||||
PreferenceScreen.SEEKBAR.addPreferences(
|
||||
PreferenceCategory(
|
||||
titleKey = null,
|
||||
sorting = Sorting.UNSORTED,
|
||||
tag = "app.revanced.extension.shared.settings.preference.NoTitlePreferenceCategory",
|
||||
preferences = preferences
|
||||
)
|
||||
)
|
||||
|
||||
overrideThemeColors(lightThemeBackgroundColor!!, darkThemeBackgroundColor!!)
|
||||
|
||||
// Edit theme colors via resources.
|
||||
document("res/values/colors.xml").use { document ->
|
||||
val resourcesNode = document.getElementsByTagName("resources").item(0) as Element
|
||||
|
||||
resourcesNode.childElementsSequence().forEach { node ->
|
||||
when (node.getAttribute("name")) {
|
||||
"yt_black0", "yt_black1", "yt_black1_opacity95", "yt_black1_opacity98",
|
||||
"yt_black2", "yt_black3", "yt_black4", "yt_status_bar_background_dark",
|
||||
"material_grey_850",
|
||||
-> node.textContent = darkThemeBackgroundColor
|
||||
|
||||
"yt_white1", "yt_white1_opacity95", "yt_white1_opacity98",
|
||||
"yt_white2", "yt_white3", "yt_white4",
|
||||
-> node.textContent = lightThemeBackgroundColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun addColorResource(
|
||||
resourceFile: String,
|
||||
colorName: String,
|
||||
colorValue: String,
|
||||
) {
|
||||
document(resourceFile).use { document ->
|
||||
val resourcesNode = document.getElementsByTagName("resources").item(0) as Element
|
||||
val resourcesNode =
|
||||
document.getElementsByTagName("resources").item(0) as Element
|
||||
|
||||
resourcesNode.appendChild(
|
||||
document.createElement("color").apply {
|
||||
@@ -150,18 +80,31 @@ val themePatch = bytecodePatch(
|
||||
|
||||
// Add a dynamic background color to the colors.xml file.
|
||||
val splashBackgroundColorKey = "revanced_splash_background_color"
|
||||
addColorResource("res/values/colors.xml", splashBackgroundColorKey, lightThemeBackgroundColor!!)
|
||||
addColorResource("res/values-night/colors.xml", splashBackgroundColorKey, darkThemeBackgroundColor!!)
|
||||
addColorResource(
|
||||
"res/values/colors.xml",
|
||||
splashBackgroundColorKey,
|
||||
lightThemeBackgroundColor!!
|
||||
)
|
||||
addColorResource(
|
||||
"res/values-night/colors.xml",
|
||||
splashBackgroundColorKey,
|
||||
darkThemeBackgroundColorOption.value!!
|
||||
)
|
||||
|
||||
// Edit splash screen files and change the background color,
|
||||
// Edit splash screen files and change the background color.
|
||||
arrayOf(
|
||||
"res/drawable/quantum_launchscreen_youtube.xml",
|
||||
"res/drawable-sw600dp/quantum_launchscreen_youtube.xml",
|
||||
).forEach editSplashScreen@{ resourceFileName ->
|
||||
document(resourceFileName).use { document ->
|
||||
document.getElementsByTagName("layer-list").item(0).forEachChildElement { node ->
|
||||
document.getElementsByTagName(
|
||||
"layer-list"
|
||||
).item(0).forEachChildElement { node ->
|
||||
if (node.hasAttribute("android:drawable")) {
|
||||
node.setAttribute("android:drawable", "@color/$splashBackgroundColorKey")
|
||||
node.setAttribute(
|
||||
"android:drawable",
|
||||
"@color/$splashBackgroundColorKey"
|
||||
)
|
||||
return@editSplashScreen
|
||||
}
|
||||
}
|
||||
@@ -172,7 +115,6 @@ val themePatch = bytecodePatch(
|
||||
|
||||
// Fix the splash screen dark mode background color.
|
||||
// In 19.32+ the dark mode splash screen is white and fades to black.
|
||||
// Maybe it's a bug in YT, or maybe it intentionally. Who knows.
|
||||
document("res/values-night-v27/styles.xml").use { document ->
|
||||
// Create a night mode specific override for the splash screen background.
|
||||
val style = document.createElement("style")
|
||||
@@ -195,29 +137,63 @@ val themePatch = bytecodePatch(
|
||||
style.appendChild(styleItem)
|
||||
}
|
||||
|
||||
val resourcesNode = document.getElementsByTagName("resources").item(0) as Element
|
||||
val resourcesNode =
|
||||
document.getElementsByTagName("resources").item(0) as Element
|
||||
resourcesNode.appendChild(style)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.34.42",
|
||||
"20.07.39",
|
||||
"20.13.41",
|
||||
"20.14.43",
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
seekbarColorPatch,
|
||||
baseThemeResourcePatch(
|
||||
lightColorReplacement = { lightThemeBackgroundColor!! }
|
||||
),
|
||||
themeResourcePatch
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.34.42",
|
||||
"20.07.39",
|
||||
"20.13.41",
|
||||
"20.14.43",
|
||||
)
|
||||
)
|
||||
},
|
||||
|
||||
executeBlock = {
|
||||
addResources("youtube", "layout.theme.themePatch")
|
||||
|
||||
PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
||||
SwitchPreference("revanced_gradient_loading_screen")
|
||||
)
|
||||
|
||||
val preferences = mutableSetOf(
|
||||
SwitchPreference("revanced_seekbar_custom_color"),
|
||||
TextPreference(
|
||||
"revanced_seekbar_custom_color_primary",
|
||||
tag = "app.revanced.extension.shared.settings.preference.ColorPickerPreference",
|
||||
inputType = InputType.TEXT_CAP_CHARACTERS
|
||||
),
|
||||
TextPreference(
|
||||
"revanced_seekbar_custom_color_accent",
|
||||
tag = "app.revanced.extension.shared.settings.preference.ColorPickerPreference",
|
||||
inputType = InputType.TEXT_CAP_CHARACTERS
|
||||
)
|
||||
)
|
||||
|
||||
PreferenceScreen.SEEKBAR.addPreferences(
|
||||
PreferenceCategory(
|
||||
titleKey = null,
|
||||
sorting = Sorting.UNSORTED,
|
||||
tag = "app.revanced.extension.shared.settings.preference.NoTitlePreferenceCategory",
|
||||
preferences = preferences
|
||||
)
|
||||
)
|
||||
|
||||
if (is_19_47_or_greater) {
|
||||
PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
||||
ListPreference("revanced_splash_screen_animation_style")
|
||||
@@ -236,7 +212,5 @@ val themePatch = bytecodePatch(
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->getLoadingScreenType(I)I"
|
||||
)
|
||||
}
|
||||
|
||||
lithoColorOverrideHook(EXTENSION_CLASS_DESCRIPTOR, "getValue")
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@@ -164,7 +164,7 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig
|
||||
|
||||
addInstruction(
|
||||
index + 1,
|
||||
"invoke-static { v$register }, ${EXTENSION_CLASS_DESCRIPTOR}->setToolbar(Landroid/widget/FrameLayout;)V"
|
||||
"invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->setToolbar(Landroid/widget/FrameLayout;)V"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ var is_19_32_or_greater = false
|
||||
@Deprecated("19.34.42 is the lowest supported version")
|
||||
var is_19_33_or_greater = false
|
||||
private set
|
||||
@Deprecated("19.34.42 is the lowest supported version")
|
||||
var is_19_34_or_greater = false
|
||||
private set
|
||||
var is_19_35_or_greater = false
|
||||
|
||||
@@ -218,7 +218,8 @@ val settingsPatch = bytecodePatch(
|
||||
modifyActivityForSettingsInjection(
|
||||
licenseActivityOnCreateFingerprint.classDef,
|
||||
licenseActivityOnCreateFingerprint.method,
|
||||
YOUTUBE_ACTIVITY_HOOK_CLASS_DESCRIPTOR
|
||||
YOUTUBE_ACTIVITY_HOOK_CLASS_DESCRIPTOR,
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
@@ -233,7 +234,8 @@ val settingsPatch = bytecodePatch(
|
||||
internal fun modifyActivityForSettingsInjection(
|
||||
activityOnCreateClass: MutableClass,
|
||||
activityOnCreateMethod: MutableMethod,
|
||||
extensionClassType: String
|
||||
extensionClassType: String,
|
||||
isYouTubeMusic: Boolean
|
||||
) {
|
||||
// Modify Activity and remove all existing layout code.
|
||||
// Must modify an existing activity and cannot add a new activity to the manifest,
|
||||
@@ -275,7 +277,7 @@ internal fun modifyActivityForSettingsInjection(
|
||||
// Override finish() to intercept back gesture.
|
||||
ImmutableMethod(
|
||||
activityOnCreateClass.type,
|
||||
"finish",
|
||||
if (isYouTubeMusic) "finish" else "onBackPressed",
|
||||
emptyList(),
|
||||
"V",
|
||||
AccessFlags.PUBLIC.value,
|
||||
@@ -283,13 +285,16 @@ internal fun modifyActivityForSettingsInjection(
|
||||
null,
|
||||
MutableMethodImplementation(3),
|
||||
).toMutable().apply {
|
||||
// Slightly different hooks are needed, otherwise the back button can behave wrong.
|
||||
val extensionMethodName = if (isYouTubeMusic) "handleFinish" else "handleBackPress"
|
||||
val invokeFinishOpcode = if (isYouTubeMusic) "invoke-super" else "invoke-virtual"
|
||||
|
||||
addInstructions(
|
||||
"""
|
||||
invoke-static {}, $extensionClassType->handleFinish()Z
|
||||
invoke-static {}, $extensionClassType->$extensionMethodName()Z
|
||||
move-result v0
|
||||
if-nez v0, :search_handled
|
||||
invoke-super { p0 }, Landroid/app/Activity;->finish()V
|
||||
return-void
|
||||
$invokeFinishOpcode { p0 }, Landroid/app/Activity;->finish()V
|
||||
:search_handled
|
||||
return-void
|
||||
"""
|
||||
|
||||
@@ -1,159 +1,36 @@
|
||||
package app.revanced.patches.youtube.video.audio
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.shared.misc.audio.forceOriginalAudioPatch
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_07_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
|
||||
import app.revanced.util.findMethodFromToString
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.insertLiteralOverride
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableField
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/ForceOriginalAudioPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val forceOriginalAudioPatch = bytecodePatch(
|
||||
name = "Force original audio",
|
||||
description = "Adds an option to always use the original audio track.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
versionCheckPatch
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.34.42",
|
||||
"20.07.39",
|
||||
"20.13.41",
|
||||
"20.14.43",
|
||||
val forceOriginalAudioPatch = forceOriginalAudioPatch(
|
||||
block = {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
versionCheckPatch
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("youtube", "video.audio.forceOriginalAudioPatch")
|
||||
|
||||
PreferenceScreen.VIDEO.addPreferences(
|
||||
SwitchPreference(
|
||||
key = "revanced_force_original_audio",
|
||||
tag = "app.revanced.extension.youtube.settings.preference.ForceOriginalAudioSwitchPreference"
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.34.42",
|
||||
"20.07.39",
|
||||
"20.13.41",
|
||||
"20.14.43",
|
||||
)
|
||||
)
|
||||
|
||||
mainActivityOnCreateFingerprint.method.addInstruction(
|
||||
0,
|
||||
"invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->setPreferredLanguage()V"
|
||||
)
|
||||
|
||||
// Disable feature flag that ignores the default track flag
|
||||
// and instead overrides to the user region language.
|
||||
if (is_20_07_or_greater) {
|
||||
selectAudioStreamFingerprint.method.insertLiteralOverride(
|
||||
AUDIO_STREAM_IGNORE_DEFAULT_FEATURE_FLAG,
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->ignoreDefaultAudioStream(Z)Z"
|
||||
)
|
||||
}
|
||||
|
||||
formatStreamModelToStringFingerprint.let {
|
||||
val isDefaultAudioTrackMethod = it.originalMethod.findMethodFromToString("isDefaultAudioTrack=")
|
||||
val audioTrackDisplayNameMethod = it.originalMethod.findMethodFromToString("audioTrackDisplayName=")
|
||||
val audioTrackIdMethod = it.originalMethod.findMethodFromToString("audioTrackId=")
|
||||
|
||||
it.classDef.apply {
|
||||
// Add a new field to store the override.
|
||||
val helperFieldName = "patch_isDefaultAudioTrackOverride"
|
||||
fields.add(
|
||||
ImmutableField(
|
||||
type,
|
||||
helperFieldName,
|
||||
"Ljava/lang/Boolean;",
|
||||
// Boolean is a 100% immutable class (all fields are final)
|
||||
// and safe to write to a shared field without volatile/synchronization,
|
||||
// but without volatile the field can show stale data
|
||||
// and the same field is calculated more than once by different threads.
|
||||
AccessFlags.PRIVATE.value or AccessFlags.VOLATILE.value,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
).toMutable()
|
||||
)
|
||||
|
||||
// Add a helper method because the isDefaultAudioTrack() has only 2 registers and 3 are needed.
|
||||
val helperMethodClass = type
|
||||
val helperMethodName = "patch_isDefaultAudioTrack"
|
||||
val helperMethod = ImmutableMethod(
|
||||
helperMethodClass,
|
||||
helperMethodName,
|
||||
listOf(ImmutableMethodParameter("Z", null, null)),
|
||||
"Z",
|
||||
AccessFlags.PRIVATE.value,
|
||||
null,
|
||||
null,
|
||||
MutableMethodImplementation(6),
|
||||
).toMutable().apply {
|
||||
addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
iget-object v0, p0, $helperMethodClass->$helperFieldName:Ljava/lang/Boolean;
|
||||
if-eqz v0, :call_extension
|
||||
invoke-virtual { v0 }, Ljava/lang/Boolean;->booleanValue()Z
|
||||
move-result v3
|
||||
return v3
|
||||
|
||||
:call_extension
|
||||
invoke-virtual { p0 }, $audioTrackIdMethod
|
||||
move-result-object v1
|
||||
|
||||
invoke-virtual { p0 }, $audioTrackDisplayNameMethod
|
||||
move-result-object v2
|
||||
|
||||
invoke-static { p1, v1, v2 }, $EXTENSION_CLASS_DESCRIPTOR->isDefaultAudioStream(ZLjava/lang/String;Ljava/lang/String;)Z
|
||||
move-result v3
|
||||
|
||||
invoke-static { v3 }, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;
|
||||
move-result-object v0
|
||||
iput-object v0, p0, $helperMethodClass->$helperFieldName:Ljava/lang/Boolean;
|
||||
return v3
|
||||
"""
|
||||
)
|
||||
}
|
||||
methods.add(helperMethod)
|
||||
|
||||
// Modify isDefaultAudioTrack() to call extension helper method.
|
||||
isDefaultAudioTrackMethod.apply {
|
||||
val index = indexOfFirstInstructionOrThrow(Opcode.RETURN)
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
addInstructions(
|
||||
index,
|
||||
"""
|
||||
invoke-direct { p0, v$register }, $helperMethodClass->$helperMethodName(Z)Z
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
fixUseLocalizedAudioTrackFlag = is_20_07_or_greater,
|
||||
mainActivityOnCreateFingerprint = mainActivityOnCreateFingerprint,
|
||||
subclassExtensionClassDescriptor = EXTENSION_CLASS_DESCRIPTOR,
|
||||
preferenceScreen = PreferenceScreen.VIDEO,
|
||||
)
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package app.revanced.patches.youtube.video.codecs
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.util.getReference
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/DisableVideoCodecsPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val disableVideoCodecsPatch = bytecodePatch(
|
||||
name = "Disable video codecs",
|
||||
description = "Adds options to disable HDR and VP9 codecs.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
/**
|
||||
* Override all calls of `getSupportedHdrTypes`.
|
||||
*/
|
||||
transformInstructionsPatch(
|
||||
filterMap = filterMap@{ classDef, _, instruction, instructionIndex ->
|
||||
if (classDef.type.startsWith("Lapp/revanced/")) {
|
||||
return@filterMap null
|
||||
}
|
||||
|
||||
val reference = instruction.getReference<MethodReference>()
|
||||
if (reference?.definingClass =="Landroid/view/Display\$HdrCapabilities;"
|
||||
&& reference.name == "getSupportedHdrTypes") {
|
||||
return@filterMap instruction to instructionIndex
|
||||
}
|
||||
return@filterMap null
|
||||
},
|
||||
transform = { method, entry ->
|
||||
val (instruction, index) = entry
|
||||
val register = (instruction as FiveRegisterInstruction).registerC
|
||||
|
||||
method.replaceInstruction(
|
||||
index,
|
||||
"invoke-static/range { v$register .. v$register }, $EXTENSION_CLASS_DESCRIPTOR->" +
|
||||
"disableHdrVideo(Landroid/view/Display\$HdrCapabilities;)[I",
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.34.42",
|
||||
"20.07.39",
|
||||
"20.13.41",
|
||||
"20.14.43",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("youtube", "video.codecs.disableVideoCodecsPatch")
|
||||
|
||||
PreferenceScreen.VIDEO.addPreferences(
|
||||
SwitchPreference("revanced_disable_hdr_video"),
|
||||
SwitchPreference("revanced_force_avc_codec")
|
||||
)
|
||||
|
||||
vp9CapabilityFingerprint.method.addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->allowVP9()Z
|
||||
move-result v0
|
||||
if-nez v0, :default
|
||||
return v0
|
||||
:default
|
||||
nop
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.youtube.video.codecs
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val vp9CapabilityFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("Z")
|
||||
strings(
|
||||
"vp9_supported",
|
||||
"video/x-vnd.on2.vp9"
|
||||
)
|
||||
}
|
||||
@@ -1,71 +1,10 @@
|
||||
package app.revanced.patches.youtube.video.hdr
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.util.getReference
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/DisableHdrPatch;"
|
||||
import app.revanced.patches.youtube.video.codecs.disableVideoCodecsPatch
|
||||
|
||||
@Deprecated("Patch was renamed", ReplaceWith("disableVideoCodecsPatch"))
|
||||
@Suppress("unused")
|
||||
val disableHdrPatch = bytecodePatch(
|
||||
name = "Disable HDR video",
|
||||
description = "Adds an option to disable video HDR.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
// Override all calls of `getSupportedHdrTypes`.
|
||||
transformInstructionsPatch(
|
||||
filterMap = filterMap@{ classDef, _, instruction, instructionIndex ->
|
||||
if (classDef.type.startsWith("Lapp/revanced/")) {
|
||||
return@filterMap null
|
||||
}
|
||||
|
||||
val reference = instruction.getReference<MethodReference>()
|
||||
if (reference?.definingClass =="Landroid/view/Display\$HdrCapabilities;"
|
||||
&& reference.name == "getSupportedHdrTypes") {
|
||||
return@filterMap instruction to instructionIndex
|
||||
}
|
||||
return@filterMap null
|
||||
},
|
||||
transform = { method, entry ->
|
||||
val (instruction, index) = entry
|
||||
val register = (instruction as FiveRegisterInstruction).registerC
|
||||
|
||||
method.replaceInstruction(
|
||||
index,
|
||||
"invoke-static/range { v$register .. v$register }, $EXTENSION_CLASS_DESCRIPTOR->" +
|
||||
"disableHdrVideo(Landroid/view/Display\$HdrCapabilities;)[I",
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.34.42",
|
||||
"20.07.39",
|
||||
"20.13.41",
|
||||
"20.14.43",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("youtube", "video.hdr.disableHdrPatch")
|
||||
|
||||
PreferenceScreen.VIDEO.addPreferences(
|
||||
SwitchPreference("revanced_disable_hdr_video")
|
||||
)
|
||||
}
|
||||
}
|
||||
val disableHdrPatch = bytecodePatch{
|
||||
dependsOn(disableVideoCodecsPatch)
|
||||
}
|
||||
@@ -26,7 +26,6 @@ internal val videoQualityItemOnClickFingerprint = fingerprint {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal val videoQualityMenuOptionsFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.STATIC)
|
||||
returns("[L")
|
||||
|
||||
@@ -14,12 +14,12 @@ internal val settingsMenuVideoQualityGroup = mutableSetOf<BasePreference>()
|
||||
@Suppress("unused")
|
||||
val videoQualityPatch = bytecodePatch(
|
||||
name = "Video quality",
|
||||
description = "Adds options to use the advanced video quality menu and set default video qualities."
|
||||
description = "Adds options to set default video qualities and always use the advanced video quality menu."
|
||||
) {
|
||||
dependsOn(
|
||||
rememberVideoQualityPatch,
|
||||
advancedVideoQualityMenuPatch,
|
||||
videoQualityDialogButtonPatch,
|
||||
videoQualityDialogButtonPatch
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
|
||||
@@ -22,6 +22,8 @@ Second \"item\" text"</string>
|
||||
<app id="shared">
|
||||
<patch id="misc.checks.checkEnvironmentPatch">
|
||||
</patch>
|
||||
<patch id="misc.dns.checkWatchHistoryDomainNameResolutionPatch">
|
||||
</patch>
|
||||
<patch id="misc.settings.settingsResourcePatch">
|
||||
<!-- Settings about dialog. -->
|
||||
<!-- NOTE: the about strings above are duplicated in the TikTok about screen code,
|
||||
@@ -32,6 +34,9 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
</patch>
|
||||
<patch id="misc.audio.forceOriginalAudioPatch">
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
</patch>
|
||||
<patch id="misc.privacy.sanitizeSharingLinksPatch">
|
||||
@@ -57,6 +62,8 @@ Second \"item\" text"</string>
|
||||
<!-- 'Visit Community' should be translated with the same localized wording that YouTube displays. -->
|
||||
<!-- 'Visit store' should be translated with the same localized wording that YouTube displays. -->
|
||||
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
|
||||
<!-- Translations should lanaguge similar to revanced_hide_upload_time_user_dialog_message -->
|
||||
<!-- Translations should lanaguge similar to revanced_hide_view_count_user_dialog_message -->
|
||||
<!-- For localization, it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word.
|
||||
This is because keywords can be in any language, and showing an example in the localized script helps convey this. -->
|
||||
<!-- Translations _must_ use a localized example. For languages that do not use spaces between words (Chinese, Japanese, etc.) the English AI example should be used since no localized examples exist. Or if using machine translations, or if nobody wants to think of a localized example, then the English 'ai' example should be left as-is. -->
|
||||
@@ -131,7 +138,7 @@ Second \"item\" text"</string>
|
||||
<patch id="layout.buttons.overlay.hidePlayerOverlayButtonsPatch">
|
||||
<!-- This button does not display any text, but 'Captions' should be translated using the same wording used as the translation of 'revanced_hide_player_flyout_captions_title'. -->
|
||||
</patch>
|
||||
<patch id="layout.hide.endscreencards.hideEndscreenCardsResourcePatch">
|
||||
<patch id="layout.hide.endscreencards.hideEndScreenCardsResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.hide.fullscreenambientmode.disableFullscreenAmbientModePatch">
|
||||
</patch>
|
||||
@@ -209,8 +216,6 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="misc.announcements.announcementsPatch">
|
||||
</patch>
|
||||
<patch id="misc.dns.checkWatchHistoryDomainNameResolutionPatch">
|
||||
</patch>
|
||||
<patch id="misc.loopvideo.loopVideoPatch">
|
||||
</patch>
|
||||
<patch id="misc.loopvideo.button.loopVideoButtonPatch">
|
||||
@@ -225,9 +230,6 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="misc.links.openLinksExternallyPatch">
|
||||
</patch>
|
||||
<patch id="video.audio.forceOriginalAudioPatch">
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
</patch>
|
||||
<patch id="video.quality.rememberVideoQualityPatch">
|
||||
<!-- Translations should use the same text as 'revanced_custom_playback_speeds_auto'. -->
|
||||
</patch>
|
||||
@@ -239,7 +241,7 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="video.speed.remember.rememberPlaybackSpeedPatch">
|
||||
</patch>
|
||||
<patch id="video.hdr.disableHdrPatch">
|
||||
<patch id="video.codecs.disableVideoCodecsPatch">
|
||||
</patch>
|
||||
<patch id="video.quality.advancedVideoQualityMenuPatch">
|
||||
</patch>
|
||||
|
||||
@@ -22,6 +22,8 @@ Second \"item\" text"</string>
|
||||
<app id="shared">
|
||||
<patch id="misc.checks.checkEnvironmentPatch">
|
||||
</patch>
|
||||
<patch id="misc.dns.checkWatchHistoryDomainNameResolutionPatch">
|
||||
</patch>
|
||||
<patch id="misc.settings.settingsResourcePatch">
|
||||
<!-- Settings about dialog. -->
|
||||
<!-- NOTE: the about strings above are duplicated in the TikTok about screen code,
|
||||
@@ -32,6 +34,9 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
</patch>
|
||||
<patch id="misc.audio.forceOriginalAudioPatch">
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
</patch>
|
||||
<patch id="misc.privacy.sanitizeSharingLinksPatch">
|
||||
@@ -57,6 +62,8 @@ Second \"item\" text"</string>
|
||||
<!-- 'Visit Community' should be translated with the same localized wording that YouTube displays. -->
|
||||
<!-- 'Visit store' should be translated with the same localized wording that YouTube displays. -->
|
||||
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
|
||||
<!-- Translations should lanaguge similar to revanced_hide_upload_time_user_dialog_message -->
|
||||
<!-- Translations should lanaguge similar to revanced_hide_view_count_user_dialog_message -->
|
||||
<!-- For localization, it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word.
|
||||
This is because keywords can be in any language, and showing an example in the localized script helps convey this. -->
|
||||
<!-- Translations _must_ use a localized example. For languages that do not use spaces between words (Chinese, Japanese, etc.) the English AI example should be used since no localized examples exist. Or if using machine translations, or if nobody wants to think of a localized example, then the English 'ai' example should be left as-is. -->
|
||||
@@ -131,7 +138,7 @@ Second \"item\" text"</string>
|
||||
<patch id="layout.buttons.overlay.hidePlayerOverlayButtonsPatch">
|
||||
<!-- This button does not display any text, but 'Captions' should be translated using the same wording used as the translation of 'revanced_hide_player_flyout_captions_title'. -->
|
||||
</patch>
|
||||
<patch id="layout.hide.endscreencards.hideEndscreenCardsResourcePatch">
|
||||
<patch id="layout.hide.endscreencards.hideEndScreenCardsResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.hide.fullscreenambientmode.disableFullscreenAmbientModePatch">
|
||||
</patch>
|
||||
@@ -209,8 +216,6 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="misc.announcements.announcementsPatch">
|
||||
</patch>
|
||||
<patch id="misc.dns.checkWatchHistoryDomainNameResolutionPatch">
|
||||
</patch>
|
||||
<patch id="misc.loopvideo.loopVideoPatch">
|
||||
</patch>
|
||||
<patch id="misc.loopvideo.button.loopVideoButtonPatch">
|
||||
@@ -225,9 +230,6 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="misc.links.openLinksExternallyPatch">
|
||||
</patch>
|
||||
<patch id="video.audio.forceOriginalAudioPatch">
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
</patch>
|
||||
<patch id="video.quality.rememberVideoQualityPatch">
|
||||
<!-- Translations should use the same text as 'revanced_custom_playback_speeds_auto'. -->
|
||||
</patch>
|
||||
@@ -239,7 +241,7 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="video.speed.remember.rememberPlaybackSpeedPatch">
|
||||
</patch>
|
||||
<patch id="video.hdr.disableHdrPatch">
|
||||
<patch id="video.codecs.disableVideoCodecsPatch">
|
||||
</patch>
|
||||
<patch id="video.quality.advancedVideoQualityMenuPatch">
|
||||
</patch>
|
||||
|
||||
@@ -21,7 +21,7 @@ Second \"item\" text"</string>
|
||||
<resources>
|
||||
<app id="shared">
|
||||
<patch id="misc.checks.checkEnvironmentPatch">
|
||||
<string name="revanced_check_environment_failed_title">فشلت الفحوصات</string>
|
||||
<string name="revanced_check_environment_failed_title">فشلت عمليات التحقق</string>
|
||||
<string name="revanced_check_environment_dialog_open_official_source_button">فتح الموقع الرسمي</string>
|
||||
<string name="revanced_check_environment_dialog_ignore_button">تجاهل</string>
|
||||
<string name="revanced_check_environment_failed_message"><h5>لا يبدو أن هذا التطبيق قد تم تعديله من قبلك.</h5><br>قد لا يعمل هذا التطبيق بشكل صحيح، <b>قد يكون ضارًا أو حتى خطيرًا للاستخدام</b>.<br><br>تشير هذه الفحوصات إلى أن هذا التطبيق تم تعديله مسبقًا أو تم الحصول عليه من شخص آخر:<br><br><small>%1$s</small><br>يوصى بشدة بـ <b>إلغاء تثبيت هذا التطبيق وتعديله بنفسك</b> للتأكد من أنك تستخدم تطبيقًا معتمدًا وآمنًا.<p><br>في حالة تجاهل هذا التحذير، سيتم عرضه مرتين فقط.</string>
|
||||
@@ -31,6 +31,11 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time_days">تم التعديل منذ %s يوم</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time_invalid">تاريخ بناء APK تالف</string>
|
||||
</patch>
|
||||
<patch id="misc.dns.checkWatchHistoryDomainNameResolutionPatch">
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_title">تحذير</string>
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_message">لم يتم حفظ سجل المشاهدة الخاص بك.<br><br>من المرجح أن يكون السبب في ذلك هو مانع إعلانات DNS أو وكيل الشبكة.<br><br>لإصلاح هذه المشكلة، قم بإضافة <b>s.youtube.com</b> إلى القائمة البيضاء أو قم بإيقاف تشغيل جميع أدوات حظر DNS ووكلاء البروكسي.</string>
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_ignore">لا تعرض مرة أخرى</string>
|
||||
</patch>
|
||||
<patch id="misc.settings.settingsResourcePatch">
|
||||
<string name="revanced_settings_submenu_title">الإعدادات</string>
|
||||
<string name="revanced_settings_confirm_user_dialog_title">هل أنت متأكد أنك تريد المتابعة؟</string>
|
||||
@@ -53,9 +58,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_settings_search_clear_history">مسح سجل البحث</string>
|
||||
<string name="revanced_settings_search_clear_history_message">هل أنت متأكد أنك تريد مسح كل سجل البحث؟</string>
|
||||
<string name="revanced_settings_search_tips_title">نصائح البحث</string>
|
||||
<string name="revanced_settings_search_tips_summary">"• انقر فوق مسار للتنقل إليه
|
||||
• اضغط مطولاً على إعداد للتنقل إليه
|
||||
• اضغط على Enter لحفظ استعلام بحث في السجل
|
||||
<string name="revanced_settings_search_tips_summary">"• انقر على مسار للانتقال إليه
|
||||
• اضغط مطولًا على إعداد للانتقال إليه
|
||||
• اضغط على Enter لحفظ استعلام البحث في السجل
|
||||
• يتجاهل البحث حالة الأحرف وعلامات الترقيم
|
||||
• تظهر الإعدادات الرئيسية فوق الإعدادات الفرعية المعطلة"</string>
|
||||
<string name="revanced_settings_search_empty_history_title">سجل البحث فارغ</string>
|
||||
@@ -76,7 +81,7 @@ Second \"item\" text"</string>
|
||||
<!-- Settings about dialog. -->
|
||||
<string name="revanced_settings_about_links_body">أنت تستخدم إصدار ReVanced Patches <i>%s</i></string>
|
||||
<string name="revanced_settings_about_links_dev_header">ملاحظة</string>
|
||||
<string name="revanced_settings_about_links_dev_body">هذه النسخة هي إصدار مسبق وقد تواجه مشكلات غير متوقعة</string>
|
||||
<string name="revanced_settings_about_links_dev_body">هذه النسخة هي إصدار ما قبل الإصدار وقد تواجه مشكلات غير متوقعة</string>
|
||||
<string name="revanced_settings_about_links_header">الروابط الرسمية</string>
|
||||
<!-- NOTE: the about strings above are duplicated in the TikTok about screen code,
|
||||
and changes made here must also be made there. -->
|
||||
@@ -89,7 +94,7 @@ Second \"item\" text"</string>
|
||||
<string name="gms_core_dialog_title">الإجراء مطلوب</string>
|
||||
<string name="gms_core_dialog_not_whitelisted_not_allowed_in_background_message">"لا يملك MicroG GmsCore صلاحية التشغيل في الخلفية.
|
||||
|
||||
اتبع دليل \"لا تقتل تطبيقي\" لهاتفك، وطبّق التعليمات لتثبيت MicroG.
|
||||
اتبع دليل \"لا تغلق تطبيقي\" لهاتفك، وطبّق التعليمات على تثبيت MicroG.
|
||||
|
||||
هذا مطلوب لعمل التطبيق."</string>
|
||||
<string name="gms_core_dialog_open_website_text">فتح الموقع</string>
|
||||
@@ -103,18 +108,25 @@ Second \"item\" text"</string>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<string name="revanced_spoof_video_streams_screen_title">Spoof Video Streams</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">تزييف تدفقات الفيديو الخاصة بالعميل لمنع حدوث مشكلات أثناء التشغيل</string>
|
||||
<string name="revanced_spoof_video_streams_screen_title">انتحال بثوث الفيديو</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">انتحال بثوث الفيديو الخاصة بالعميل لمنع مشكلات التشغيل</string>
|
||||
<string name="revanced_spoof_video_streams_screen_title">Spoof Video Streams</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">تزييف بثوث الفيديو الخاصة بالعميل لمنع مشكلات التشغيل</string>
|
||||
<string name="revanced_spoof_video_streams_title">Spoof Video Streams</string>
|
||||
<string name="revanced_spoof_video_streams_summary_on">"تدفقات الفيديو مزورة
|
||||
<string name="revanced_spoof_video_streams_summary_on">"يتم تزييف تدفقات الفيديو
|
||||
|
||||
إذا كنت مستخدمًا لـ YouTube Premium، فقد لا يكون هذا الإعداد مطلوبًا"</string>
|
||||
<string name="revanced_spoof_video_streams_summary_off">"لم يتم انتحال بثوث الفيديو
|
||||
<string name="revanced_spoof_video_streams_summary_off">"لا يتم تزييف تدفقات الفيديو
|
||||
|
||||
قد لا يعمل التشغيل"</string>
|
||||
قد لا يعمل تشغيل الفيديو"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">قد يؤدي إيقاف تشغيل هذا الإعداد إلى مشكلات في التشغيل.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">العميل الافتراضي</string>
|
||||
</patch>
|
||||
<patch id="misc.audio.forceOriginalAudioPatch">
|
||||
<string name="revanced_force_original_audio_title">فرض لغة الصوت الأصلية</string>
|
||||
<string name="revanced_force_original_audio_summary_on">استخدام لغة الصوت الأصلية</string>
|
||||
<string name="revanced_force_original_audio_summary_off">استخدام الصوت الافتراضي</string>
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
<string name="revanced_force_original_audio_not_available">لاستخدام هذه الميزة، غيّر \"تزوير تدفقات الفيديو\" إلى أي عميل باستثناء Android Studio</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">تصحيح الأخطاء</string>
|
||||
<string name="revanced_debug_screen_summary">تمكين أو تعطيل خيارات تصحيح الأخطاء</string>
|
||||
@@ -141,19 +153,19 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_debug_logs_clear_toast">تم مسح السجلات</string>
|
||||
</patch>
|
||||
<patch id="misc.privacy.sanitizeSharingLinksPatch">
|
||||
<string name="revanced_sanitize_sharing_links_title">إزالة معلمة تتبع الاستعلام</string>
|
||||
<string name="revanced_sanitize_sharing_links_summary_on">يتم إزالة معلمة استعلام التتبع من الروابط</string>
|
||||
<string name="revanced_sanitize_sharing_links_summary_off">لا يتم إزالة معلمة استعلام التتبع من الروابط</string>
|
||||
<string name="revanced_sanitize_sharing_links_title">تطهير روابط المشاركة</string>
|
||||
<string name="revanced_sanitize_sharing_links_summary_on">تمت إزالة معلمة استعلام التتبع من الروابط عند المشاركة</string>
|
||||
<string name="revanced_sanitize_sharing_links_summary_off">لم تتم إزالة معلمة استعلام التتبع من الروابط عند المشاركة</string>
|
||||
<string name="revanced_replace_music_with_youtube_title">تغيير روابط المشاركة إلى youtube.com</string>
|
||||
<string name="revanced_replace_music_with_youtube_summary_on">تستخدم الروابط المشتركة youtube.com</string>
|
||||
<string name="revanced_replace_music_with_youtube_summary_off">تستخدم الروابط المشتركة music.youtube.com</string>
|
||||
<string name="revanced_replace_music_with_youtube_summary_on">تستخدم روابط المشاركة youtube.com</string>
|
||||
<string name="revanced_replace_music_with_youtube_summary_off">تستخدم روابط المشاركة music.youtube.com</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="youtube">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
<string name="revanced_settings_screen_00_about_title">لمحة</string>
|
||||
<string name="revanced_settings_screen_01_ads_title">الإعلانات</string>
|
||||
<string name="revanced_settings_screen_02_alt_thumbnails_title">مُصغَّرات فيديو بديلة</string>
|
||||
<string name="revanced_settings_screen_02_alt_thumbnails_title">مصغرات فيديو بديلة</string>
|
||||
<string name="revanced_settings_screen_03_feed_title">الموجز</string>
|
||||
<string name="revanced_settings_screen_04_general_title">عام</string>
|
||||
<string name="revanced_settings_screen_05_player_title">المشغل</string>
|
||||
@@ -200,23 +212,23 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_crowdfunding_box_summary_on">تم إخفاء مربع التمويل الجماعي</string>
|
||||
<string name="revanced_hide_crowdfunding_box_summary_off">يتم عرض مربع التمويل الجماعي</string>
|
||||
<string name="revanced_hide_expandable_card_title">إخفاء البطاقة القابلة للتوسيع</string>
|
||||
<string name="revanced_hide_expandable_card_summary_on">البطاقة القابلة للتوسيع أسفل مقاطع الفيديو مخفية</string>
|
||||
<string name="revanced_hide_expandable_card_summary_off">البطاقة القابلة للتوسيع أسفل مقاطع الفيديو معروضة</string>
|
||||
<string name="revanced_hide_expandable_card_summary_on">تم إخفاء البطاقة القابلة للتوسيع أسفل مقاطع الفيديو</string>
|
||||
<string name="revanced_hide_expandable_card_summary_off">يتم عرض البطاقة القابلة للتوسيع أسفل مقاطع الفيديو</string>
|
||||
<string name="revanced_hide_floating_microphone_button_title">إخفاء زر الميكروفون العائم</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_on">زر الميكروفون العائم في البحث مخفي</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_off">يظهر زر الميكروفون العائم في البحث</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_on">تم إخفاء زر الميكروفون العائم في البحث</string>
|
||||
<string name="revanced_hide_floating_microphone_button_summary_off">يتم عرض زر الميكروفون العائم في البحث</string>
|
||||
<string name="revanced_hide_horizontal_shelves_title">إخفاء الرفوف الأفقية</string>
|
||||
<string name="revanced_hide_horizontal_shelves_summary_on">"الأرفف الأفقية مخفية، مثل:
|
||||
<string name="revanced_hide_horizontal_shelves_summary_on">"تم إخفاء الأرفف الأفقية، مثل:
|
||||
• الأخبار العاجلة
|
||||
• متابعة المشاهدة
|
||||
• استكشاف المزيد من القنوات
|
||||
• الأكثر صلة
|
||||
• التسوق
|
||||
• شاهدها مرة أخرى"</string>
|
||||
<string name="revanced_hide_horizontal_shelves_summary_off">الأرفف الأفقية معروضة</string>
|
||||
• أريد أن اشاهدها مرة أخرى"</string>
|
||||
<string name="revanced_hide_horizontal_shelves_summary_off">يتم عرض الأرفف الأفقية</string>
|
||||
<string name="revanced_hide_image_shelf_title">إخفاء رف الصور</string>
|
||||
<string name="revanced_hide_image_shelf_summary_on">رف الصور في نتائج البحث مخفي</string>
|
||||
<string name="revanced_hide_image_shelf_summary_off">رف الصور في نتائج البحث معروض</string>
|
||||
<string name="revanced_hide_image_shelf_summary_on">تم إخفاء رف الصور في نتائج البحث</string>
|
||||
<string name="revanced_hide_image_shelf_summary_off">يتم عرض رف الصور في نتائج البحث</string>
|
||||
<string name="revanced_hide_latest_posts_title">إخفاء آخر المشاركات</string>
|
||||
<string name="revanced_hide_latest_posts_summary_on">تم إخفاء أحدث المشاركات</string>
|
||||
<string name="revanced_hide_latest_posts_summary_off">يتم عرض أحدث المشاركات</string>
|
||||
@@ -229,33 +241,33 @@ Second \"item\" text"</string>
|
||||
<!-- 'Notify me' should be translated using the same localized wording YouTube displays.
|
||||
This item appear in the Subscriptions feed for future livestreams or unreleased videos. -->
|
||||
<string name="revanced_hide_notify_me_button_title">إخفاء زر \'تنبيهي\'</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_on">زر إشعاري مخفي</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_off">زر إشعاري معروض</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_on">تم إخفاء زر تنبيهي</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_off">يتم عرض زر تنبيهي</string>
|
||||
<string name="revanced_hide_playables_title">إخفاء هيّا نلعب</string>
|
||||
<string name="revanced_hide_playables_summary_on">تم إخفاء هيّا نلعب</string>
|
||||
<string name="revanced_hide_playables_summary_off">يتم عرض هيّا نلعب</string>
|
||||
<!-- 'Show more' should be translated with the same localized wording that YouTube displays.
|
||||
This button usually appears when searching for a YT creator. -->
|
||||
<string name="revanced_hide_show_more_button_title">إخفاء زر \'عرض المزيد\'</string>
|
||||
<string name="revanced_hide_show_more_button_summary_on">زر إظهار المزيد في نتائج البحث مخفي</string>
|
||||
<string name="revanced_hide_show_more_button_summary_off">زر إظهار المزيد في نتائج البحث معروض</string>
|
||||
<string name="revanced_hide_show_more_button_summary_on">تم إخفاء زر عرض المزيد في نتائج البحث</string>
|
||||
<string name="revanced_hide_show_more_button_summary_off">يتم إظهار زر عرض المزيد في نتائج البحث</string>
|
||||
<string name="revanced_hide_surveys_title">إخفاء الاستبيانات</string>
|
||||
<string name="revanced_hide_surveys_summary_on">الاستطلاعات مخفية</string>
|
||||
<string name="revanced_hide_surveys_summary_off">الاستطلاعات معروضة</string>
|
||||
<string name="revanced_hide_surveys_summary_on">تم إخفاء الاستبيانات</string>
|
||||
<string name="revanced_hide_surveys_summary_off">يتم عرض الاستبيانات</string>
|
||||
<string name="revanced_hide_ticket_shelf_title">إخفاء رف التذاكر</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_on">تم إخفاء رف التذاكر</string>
|
||||
<string name="revanced_hide_ticket_shelf_summary_off">يتم عرض رف التذاكر</string>
|
||||
<!-- 'People also watched' and 'You might also like' should be translated using the same localized wording YouTube displays. -->
|
||||
<string name="revanced_hide_video_recommendation_labels_title">إخفاء تسميات توصيات الفيديو</string>
|
||||
<string name="revanced_hide_video_recommendation_labels_summary_on">تسميات \'شاهد المستخدمون أيضاً\' و\'قد يعجبك أيضاً\' في نتائج البحث مخفية</string>
|
||||
<string name="revanced_hide_video_recommendation_labels_summary_off">تسميات \'شاهد المستخدمون أيضاً\' و\'قد يعجبك أيضاً\' في نتائج البحث معروضة</string>
|
||||
<string name="revanced_hide_video_recommendation_labels_summary_on">تم إخفاء تسميات \'شاهد المستخدمون أيضًا\' و\'قد يعجبك أيضًا\' في نتائج البحث</string>
|
||||
<string name="revanced_hide_video_recommendation_labels_summary_off">يتم عرض تسميات \'شاهد المستخدمون أيضًا\' و\'قد يعجبك أيضًا\' في نتائج البحث</string>
|
||||
<!-- https://logos.fandom.com/wiki/YouTube/Yoodles -->
|
||||
<string name="revanced_hide_doodles_title">إخفاء رسومات YouTube</string>
|
||||
<string name="revanced_hide_doodles_summary_on">رسوم Doodles المتحركة في شعار YouTube مخفية</string>
|
||||
<string name="revanced_hide_doodles_summary_off">يتم عرض رسوم متحركة Doodles من YouTube على الشعار</string>
|
||||
<string name="revanced_hide_doodles_user_dialog_message">"تظهر \"\"Doodles\"\" على YouTube بضعة أيام كل عام.
|
||||
<string name="revanced_hide_doodles_summary_on">تم إخفاء رسوم Doodles المتحركة على شعار YouTube</string>
|
||||
<string name="revanced_hide_doodles_summary_off">يتم عرض رسوم Doodles المتحركة على شعار YouTube</string>
|
||||
<string name="revanced_hide_doodles_user_dialog_message">"تظهر رسومات YouTube Doodles لعدة أيام كل عام.
|
||||
|
||||
إذا كان يتم عرض \"Doodle\" حاليًا في منطقتك وإذا كان إعداد الإخفاء هذا قيد التشغيل، فسيتم أيضًا إخفاء شريط التصفية أسفل شريط البحث."</string>
|
||||
إذا كانت رسومات Doodles تظهر حاليًا في منطقتك وكان إعداد الإخفاء هذا قيد التشغيل، فسيتم أيضًا إخفاء شريط الفلتر الموجود أسفل شريط البحث."</string>
|
||||
<string name="revanced_hide_channel_bar_title">إخفاء شريط القناة</string>
|
||||
<string name="revanced_hide_channel_bar_summary_on">تم إخفاء شريط القناة</string>
|
||||
<string name="revanced_hide_channel_bar_summary_off">يتم عرض شريط القناة</string>
|
||||
@@ -271,17 +283,17 @@ Second \"item\" text"</string>
|
||||
<!-- 'Join' should be translated using the same localized wording YouTube displays.
|
||||
This appears in the video player for certain videos. -->
|
||||
<string name="revanced_hide_join_membership_button_title">إخفاء زر الانضمام</string>
|
||||
<string name="revanced_hide_join_membership_button_summary_on">زر الانضمام مخفي</string>
|
||||
<string name="revanced_hide_join_membership_button_summary_off">زر الانضمام معروض</string>
|
||||
<string name="revanced_hide_join_membership_button_summary_on">تم إخفاء زر الانضمام</string>
|
||||
<string name="revanced_hide_join_membership_button_summary_off">يتم عرض زر الانضمام</string>
|
||||
<string name="revanced_hide_medical_panels_title">إخفاء اللوحات الطبية</string>
|
||||
<string name="revanced_hide_medical_panels_summary_on">تم إخفاء اللوحات الطبية</string>
|
||||
<string name="revanced_hide_medical_panels_summary_off">يتم عرض اللوحات الطبية</string>
|
||||
<string name="revanced_hide_quick_actions_title">إخفاء الإجراءات السريعة</string>
|
||||
<string name="revanced_hide_quick_actions_summary_on">الإجراءات السريعة في وضع ملء الشاشة مخفية</string>
|
||||
<string name="revanced_hide_quick_actions_summary_off">الإجراءات السريعة في وضع ملء الشاشة معروضة</string>
|
||||
<string name="revanced_hide_related_videos_title">إخفاء مقاطع الفيديو ذات الصلة</string>
|
||||
<string name="revanced_hide_related_videos_summary_on">مقاطع الفيديو ذات الصلة في الإجراءات السريعة مخفية</string>
|
||||
<string name="revanced_hide_related_videos_summary_off">مقاطع الفيديو ذات الصلة في الإجراءات السريعة معروضة</string>
|
||||
<string name="revanced_hide_quick_actions_summary_on">تم إخفاء الإجراءات السريعة في ملء الشاشة</string>
|
||||
<string name="revanced_hide_quick_actions_summary_off">يتم عرض الإجراءات السريعة في ملء الشاشة</string>
|
||||
<string name="revanced_hide_related_videos_title">إخفاء الفيديوهات ذات الصلة</string>
|
||||
<string name="revanced_hide_related_videos_summary_on">تم إخفاء الفيديوهات ذات الصلة في الإجراءات السريعة</string>
|
||||
<string name="revanced_hide_related_videos_summary_off">يتم عرض الفيديوهات ذات الصلة في الإجراءات السريعة</string>
|
||||
<string name="revanced_hide_subscribers_community_guidelines_title">إخفاء إرشادات المشتركين</string>
|
||||
<string name="revanced_hide_subscribers_community_guidelines_summary_on">تم إخفاء إرشادات مجتمع المشتركين</string>
|
||||
<string name="revanced_hide_subscribers_community_guidelines_summary_off">يتم عرض إرشادات مجتمع المشتركين</string>
|
||||
@@ -289,11 +301,11 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_timed_reactions_summary_on">تم إخفاء ردود الفعل المؤقتة</string>
|
||||
<string name="revanced_hide_timed_reactions_summary_off">يتم عرض ردود الفعل المؤقتة</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_title">إخفاء \'ملخص الفيديو الذي تم إنشاؤه بواسطة الذكاء الاصطناعي\'</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">قسم ملخص الفيديو الذي تم إنشاؤه بواسطة الذكاء الاصطناعي مخفي</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">قسم ملخص الفيديو الذي تم إنشاؤه بواسطة الذكاء الاصطناعي معروض</string>
|
||||
<string name="revanced_hide_ask_section_title">إخفاء \"Ask\"</string>
|
||||
<string name="revanced_hide_ask_section_summary_on">تم إخفاء قسم \"Ask\"</string>
|
||||
<string name="revanced_hide_ask_section_summary_off">يتم عرض قسم \"Ask\"</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">تم إخفاء قسم ملخص الفيديو الذي تم إنشاؤه بواسطة AI</string>
|
||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">يتم عرض قسم ملخص الفيديو الذي تم إنشاؤه بواسطة AI</string>
|
||||
<string name="revanced_hide_ask_section_title">إخفاء طرح سؤال</string>
|
||||
<string name="revanced_hide_ask_section_summary_on">تم إخفاء قسم طرح سؤال</string>
|
||||
<string name="revanced_hide_ask_section_summary_off">يتم عرض قسم طرح سؤال</string>
|
||||
<string name="revanced_hide_attributes_section_title">إخفاء الصفات</string>
|
||||
<string name="revanced_hide_attributes_section_summary_on">تم إخفاء أقسام الأماكن المميزة، الألعاب، الموسيقى والأشخاص المذكورون</string>
|
||||
<string name="revanced_hide_attributes_section_summary_off">يتم عرض أقسام الأماكن المميزة، الألعاب، الموسيقى والأشخاص المذكورون</string>
|
||||
@@ -318,71 +330,71 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_description_components_screen_title">وصف الفيديو</string>
|
||||
<string name="revanced_hide_description_components_screen_summary">إخفاء أو عرض مكونات وصف الفيديو</string>
|
||||
<string name="revanced_hide_filter_bar_screen_title">شريط التصفية</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">إخفاء أو إظهار شريط الفلترة في الموجزات ومقاطع الفيديو ذات الصلة ونتائج البحث وسجل المشاهدة</string>
|
||||
<string name="revanced_hide_filter_bar_screen_summary">إخفاء أو عرض شريط الفلترة في الموجزات والفيديوهات ذات الصلة ونتائج البحث وسجل المشاهدة</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_title">إخفاء في الموجز</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_on">مخفي في الموجز</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_off">معروض في الموجز</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_feed_summary_off">يُعرض في الموجز</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_title">إخفاء في الفيديوهات ذات الصلة</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">مخفي في الفيديوهات ذات الصلة</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">يُعرض في الفيديوهات ذات الصلة</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_title">إخفاء في نتائج البحث</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_on">مخفي في نتائج البحث</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_search_summary_off">يُعرض في نتائج البحث</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">إخفاء في سجل المشاهدة</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">مخفي في سجل المشاهدة</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">معروض في سجل المشاهدة</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_title">إخفاء في السجلّ</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_on">مخفي في السجلّ</string>
|
||||
<string name="revanced_hide_filter_bar_feed_in_history_summary_off">يُعرض في السجلّ</string>
|
||||
<string name="revanced_channel_screen_title">صفحة القناة</string>
|
||||
<string name="revanced_channel_screen_summary">إخفاء أو إظهار مكونات صفحة القناة</string>
|
||||
<string name="revanced_channel_screen_summary">إخفاء أو عرض مكونات صفحة القناة</string>
|
||||
<!-- 'For You' should be translated using the same localized wording YouTube displays. -->
|
||||
<string name="revanced_hide_for_you_shelf_title">إخفاء رف \'مقترحات لك\'</string>
|
||||
<string name="revanced_hide_for_you_shelf_summary_on">رف \"لك\" مخفي</string>
|
||||
<string name="revanced_hide_for_you_shelf_summary_off">رف \"لك\" معروض</string>
|
||||
<string name="revanced_hide_for_you_shelf_summary_on">تم إخفاء رف مقترح لك</string>
|
||||
<string name="revanced_hide_for_you_shelf_summary_off">يتم عرض رف مقترح لك</string>
|
||||
<string name="revanced_hide_links_preview_title">إخفاء معاينة الروابط</string>
|
||||
<string name="revanced_hide_links_preview_summary_on">معاينة الروابط مخفية</string>
|
||||
<string name="revanced_hide_links_preview_summary_off">معاينة الروابط معروضة</string>
|
||||
<string name="revanced_hide_links_preview_summary_on">تم إخفاء معاينة الروابط</string>
|
||||
<string name="revanced_hide_links_preview_summary_off">يتم عرض معاينة الروابط</string>
|
||||
<string name="revanced_hide_members_shelf_title">إخفاء رف الأعضاء</string>
|
||||
<string name="revanced_hide_members_shelf_summary_on">رف الأعضاء مخفي</string>
|
||||
<string name="revanced_hide_members_shelf_summary_on">تم إخفاء رف الأعضاء</string>
|
||||
<string name="revanced_hide_members_shelf_summary_off">يتم عرض رف الأعضاء</string>
|
||||
<!-- 'Visit Community' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_visit_community_button_title">إخفاء زر \"زيارة المنتدى\"</string>
|
||||
<string name="revanced_hide_visit_community_button_summary_on">زر \"زيارة المنتدى\" مخفي</string>
|
||||
<string name="revanced_hide_visit_community_button_summary_off">زر زيارة المجتمع معروض</string>
|
||||
<string name="revanced_hide_visit_community_button_title">إخفاء زر \'زيارة المجتمع\'</string>
|
||||
<string name="revanced_hide_visit_community_button_summary_on">تم إخفاء زر زيارة المجتمع</string>
|
||||
<string name="revanced_hide_visit_community_button_summary_off">يتم عرض زر زيارة المجتمع</string>
|
||||
<!-- 'Visit store' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_visit_store_button_title">إخفاء زر \'زيارة المتجر\' على صفحات القناة</string>
|
||||
<string name="revanced_hide_visit_store_button_summary_on">زر زيارة المتجر مخفي</string>
|
||||
<string name="revanced_hide_visit_store_button_summary_off">زر زيارة المتجر معروض</string>
|
||||
<string name="revanced_hide_visit_store_button_title">إخفاء زر \'زيارة المتجر\'</string>
|
||||
<string name="revanced_hide_visit_store_button_summary_on">تم إخفاء زر زيارة المتجر</string>
|
||||
<string name="revanced_hide_visit_store_button_summary_off">يتم عرض زر زيارة المتجر</string>
|
||||
<string name="revanced_comments_screen_title">التعليقات</string>
|
||||
<string name="revanced_comments_screen_summary">إخفاء أو عرض مكونات قسم التعليقات</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_title">إخفاء ملخص الدردشة بالذكاء الاصطناعي</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">ملخص الدردشة بالذكاء الاصطناعي مخفي</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">ملخص الدردشة بالذكاء الاصطناعي معروض</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_title">إخفاء ملخص محادثات الذكاء الاصطناعي</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">تم إخفاء ملخص محادثة الذكاء الاصطناعي</string>
|
||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">يتم عرض ملخص محادثة الذكاء الاصطناعي</string>
|
||||
<string name="revanced_hide_comments_ai_summary_title">إخفاء ملخص تعليقات الذكاء الاصطناعي</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_on">ملخص تعليقات الذكاء الاصطناعي مخفي</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_off">ملخص تعليقات الذكاء الاصطناعي معروض</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_on">تم إخفاء ملخص تعليقات الذكاء الاصطناعي</string>
|
||||
<string name="revanced_hide_comments_ai_summary_summary_off">يتم عرض ملخص تعليقات الذكاء الاصطناعي</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_title">إخفاء إرشادات القناة</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_on">إرشادات القناة مخفية</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_off">إرشادات القناة معروضة</string>
|
||||
<string name="revanced_hide_comments_by_members_header_title">إخفاء رأس \'تعليقات الأعضاء\'</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_on">تم إخفاء إرشادات القناة</string>
|
||||
<string name="revanced_hide_comments_channel_guidelines_summary_off">يتم عرض إرشادات القناة</string>
|
||||
<string name="revanced_hide_comments_by_members_header_title">إخفاء علامة \'تعليقات بواسطة الأعضاء\'</string>
|
||||
<string name="revanced_hide_comments_by_members_header_summary_on">تم إخفاء علامة تعليقات من الأعضاء</string>
|
||||
<string name="revanced_hide_comments_by_members_header_summary_off">يتم عرض علامة تعليقات من الأعضاء</string>
|
||||
<string name="revanced_hide_comments_section_title">إخفاء قسم التعليقات</string>
|
||||
<string name="revanced_hide_comments_section_summary_on">تم إخفاء قسم التعليقات</string>
|
||||
<string name="revanced_hide_comments_section_summary_off">يتم عرض قسم التعليقات</string>
|
||||
<string name="revanced_hide_comments_community_guidelines_title">إخفاء إرشادات المنتدى</string>
|
||||
<string name="revanced_hide_comments_community_guidelines_summary_on">إرشادات المجتمع مخفية</string>
|
||||
<string name="revanced_hide_comments_community_guidelines_summary_off">إرشادات المجتمع معروضة</string>
|
||||
<string name="revanced_hide_comments_community_guidelines_title">إخفاء إرشادات المجتمع</string>
|
||||
<string name="revanced_hide_comments_community_guidelines_summary_on">تم إخفاء إرشادات المجتمع</string>
|
||||
<string name="revanced_hide_comments_community_guidelines_summary_off">يتم عرض إرشادات المجتمع</string>
|
||||
<string name="revanced_hide_comments_create_a_short_button_title">إخفاء زر \'إنشاء Short\'</string>
|
||||
<string name="revanced_hide_comments_create_a_short_button_summary_on">تم إخفاء زر إنشاء Short</string>
|
||||
<string name="revanced_hide_comments_create_a_short_button_summary_off">يتم عرض زر إنشاء Short</string>
|
||||
<string name="revanced_hide_comments_emoji_and_timestamp_buttons_title">إخفاء أزرار الرموز التعبيرية والطابع الزمني</string>
|
||||
<string name="revanced_hide_comments_emoji_and_timestamp_buttons_summary_on">تم إخفاء أزرار الرموز التعبيرية والطوابع الزمنية</string>
|
||||
<string name="revanced_hide_comments_emoji_and_timestamp_buttons_summary_off">يتم عرض أزرار الرموز التعبيرية والطوابع الزمنية</string>
|
||||
<string name="revanced_hide_comments_preview_comment_title">إخفاء تعليق المعاينة</string>
|
||||
<string name="revanced_hide_comments_preview_comment_summary_on">تم إخفاء تعليق المعاينة</string>
|
||||
<string name="revanced_hide_comments_preview_comment_summary_off">يتم عرض تعليق المعاينة</string>
|
||||
<string name="revanced_hide_comments_thanks_button_title">إخفاء زر شكرًا</string>
|
||||
<string name="revanced_hide_comments_thanks_button_summary_on">تم إخفاء زر شكرًا</string>
|
||||
<string name="revanced_hide_comments_thanks_button_summary_off">يتم عرض زر شكرًا</string>
|
||||
<string name="revanced_hide_comments_timestamp_button_title">إخفاء زر الطابع الزمني</string>
|
||||
<string name="revanced_hide_comments_timestamp_button_summary_on">زر الطابع الزمني مخفي</string>
|
||||
<string name="revanced_hide_comments_timestamp_button_summary_off">زر الطابع الزمني معروض</string>
|
||||
<string name="revanced_custom_filter_screen_title">فلتر مخصص</string>
|
||||
<string name="revanced_custom_filter_screen_summary">إخفاء المكونات باستخدام فلاتر مخصصة</string>
|
||||
<string name="revanced_custom_filter_title">تمكين الفلتر المخصص</string>
|
||||
@@ -392,15 +404,29 @@ Second \"item\" text"</string>
|
||||
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
|
||||
<string name="revanced_custom_filter_strings_summary">قائمة سلاسل منشئ مسار المكونات المراد تصفيتها مفصولة بسطر جديد</string>
|
||||
<string name="revanced_custom_filter_toast_invalid_syntax">فلتر مخصص غير صالح: %s</string>
|
||||
<string name="revanced_hide_keyword_content_screen_title">إخفاء محتوى الكلمات المفتاحية</string>
|
||||
<string name="revanced_hide_view_count_title">إخفاء عدد المشاهدات</string>
|
||||
<string name="revanced_hide_view_count_summary_on">تم إخفاء عدد المشاهدات في الموجز ونتائج البحث</string>
|
||||
<string name="revanced_hide_view_count_summary_off">يتم عرض عدد المشاهدات في الموجز ونتائج البحث</string>
|
||||
<!-- Translations should lanaguge similar to revanced_hide_upload_time_user_dialog_message -->
|
||||
<string name="revanced_hide_view_count_user_dialog_message">"القيود:
|
||||
• رفوف Shorts وصفحات القنوات ونتائج البحث قد تظل تعرض أعداد المشاهدات
|
||||
• هذه الميزة لا تعمل مع عامل الشكل Automotive"</string>
|
||||
<string name="revanced_hide_upload_time_title">إخفاء وقت التحميل</string>
|
||||
<string name="revanced_hide_upload_time_summary_on">تم إخفاء وقت التحميل في الموجز ونتائج البحث</string>
|
||||
<string name="revanced_hide_upload_time_summary_off">يتم عرض وقت التحميل في الموجز ونتائج البحث</string>
|
||||
<!-- Translations should lanaguge similar to revanced_hide_view_count_user_dialog_message -->
|
||||
<string name="revanced_hide_upload_time_user_dialog_message">"القيود:
|
||||
• قد تظل أرفف Shorts وصفحات القنوات ونتائج البحث تُظهر أوقات التحميل
|
||||
• هذه الميزة لا تعمل مع عامل الشكل Automotive"</string>
|
||||
<string name="revanced_hide_keyword_content_screen_title">إخفاء محتوى بالكلمات المفتاحية</string>
|
||||
<string name="revanced_hide_keyword_content_screen_summary">إخفاء فيديوهات البحث والموجز باستخدام فلاتر الكلمات المفتاحية</string>
|
||||
<string name="revanced_hide_keyword_content_home_title">إخفاء فيديوهات الصفحة الرئيسية بواسطة الكلمات المفتاحية</string>
|
||||
<string name="revanced_hide_keyword_content_home_summary_on">تتم تصفية الفيديوهات في علامة التبويب \"الصفحة الرئيسية\" حسب الكلمات المفتاحية</string>
|
||||
<string name="revanced_hide_keyword_content_home_summary_off">لا تتم تصفية الفيديوهات في علامة التبويب \"الصفحة الرئيسية\" حسب الكلمات المفتاحية</string>
|
||||
<string name="revanced_hide_keyword_content_home_summary_on">تتم تصفية الفيديوهات في علامة التبويب \'الصفحة الرئيسية\' حسب الكلمات المفتاحية</string>
|
||||
<string name="revanced_hide_keyword_content_home_summary_off">لا تتم تصفية الفيديوهات في علامة التبويب \'الصفحة الرئيسية\' حسب الكلمات المفتاحية</string>
|
||||
<string name="revanced_hide_keyword_content_search_title">إخفاء نتائج البحث عن طريق الكلمات المفتاحية</string>
|
||||
<string name="revanced_hide_keyword_content_search_summary_on">يتم تصفية نتائج البحث حسب الكلمات المفتاحية</string>
|
||||
<string name="revanced_hide_keyword_content_search_summary_off">لا يتم تصفية نتائج البحث حسب الكلمات المفتاحية</string>
|
||||
<string name="revanced_hide_keyword_content_subscriptions_title">إخفاء الفيديوهات الخاصة بالاشتراك عن طريق الكلمات المفتاحية</string>
|
||||
<string name="revanced_hide_keyword_content_subscriptions_title">إخفاء الفيديوهات الخاصة بالاشتراكات عن طريق الكلمات المفتاحية</string>
|
||||
<string name="revanced_hide_keyword_content_subscriptions_summary_on">يتم تصفية الفيديوهات في علامة التبويب الاشتراكات حسب الكلمات المفتاحية</string>
|
||||
<string name="revanced_hide_keyword_content_subscriptions_summary_off">لا يتم تصفية الفيديوهات في علامة التبويب الاشتراكات حسب الكلمات المفتاحية</string>
|
||||
<string name="revanced_hide_keyword_content_phrases_title">الكلمات المفتاحية المراد إخفاؤها</string>
|
||||
@@ -411,7 +437,7 @@ Second \"item\" text"</string>
|
||||
يمكن أن تكون الكلمات عبارة عن أسماء قنوات أو أي نص يظهر في عناوين الفيديوهات
|
||||
|
||||
يجب إدخال الكلمات التي تحتوي على أحرف كبيرة في المنتصف بنفس الحالة (على سبيل المثال: iPhone, TikTok, LeBlanc)"</string>
|
||||
<string name="revanced_hide_keyword_content_about_title">حول تصفية الكلمات المفتاحية</string>
|
||||
<string name="revanced_hide_keyword_content_about_title">لمحة عن تصفية الكلمات المفتاحية</string>
|
||||
<string name="revanced_hide_keyword_content_about_summary">"الصفحة الرئيسية/الاشتراكات/نتائج البحث يتم تصفيتها لإخفاء المحتوى الذي يتطابق مع كلمات البحث
|
||||
|
||||
القيود
|
||||
@@ -420,21 +446,21 @@ Second \"item\" text"</string>
|
||||
• البحث عن كلمة ما قد لا يعطي نتائج"</string>
|
||||
<string name="revanced_hide_keyword_content_about_whole_words_title">مطابقة الكلمات بأكملها</string>
|
||||
<!-- Translations _must_ use a localized example. For languages that do not use spaces between words (Chinese, Japanese, etc.) the English AI example should be used since no localized examples exist. Or if using machine translations, or if nobody wants to think of a localized example, then the English 'ai' example should be left as-is. -->
|
||||
<string name="revanced_hide_keyword_content_about_whole_words_summary">سيؤدي وضع علامة اقتباس مزدوجة حول كلمة رئيسية/عبارة إلى منع التطابقات الجزئية لعناوين الفيديو وأسماء القنوات.<br><br>على سبيل المثال،<br><b>\"ai\"</b> سيخفي الفيديو: <b>How does AI work?</b><br>ولكن لن يخفي: <b>What does fair use mean?</b></string>
|
||||
<string name="revanced_hide_keyword_content_about_whole_words_summary">سيؤدي وضع علامة اقتباس مزدوجة حول كلمة مفتاحية/عبارة إلى منع التطابقات الجزئية لعناوين الفيديو وأسماء القنوات<br><br>على سبيل المثال،<br><b>\"ai\"</b> سيخفي الفيديو: <b>How does AI work?</b><br><b>ولكن لن يخفي:<b>What does fair use mean?</b></string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="revanced_hide_keyword_toast_invalid_common">لا يمكن استخدام الكلمة المفتاحية: %s</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_common_whole_word_required">إضافة اقتباسات لاستخدام الكلمة المفتاحية: %s</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_conflicting">الكلمة المفتاحية لها بيانات متضاربة: %s</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_conflicting">الكلمة المفتاحية بها تعريفات متعارضة: %s</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_length">الكلمة المفتاحية قصيرة جدًا وتتطلب اقتباسات: %s</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">الكلمة المفتاحية سوف تخفي جميع الفيديوهات: %s</string>
|
||||
</patch>
|
||||
<patch id="ad.general.hideAdsResourcePatch">
|
||||
<string name="revanced_hide_creator_store_shelf_title">إخفاء رف متجر المبدع</string>
|
||||
<string name="revanced_hide_creator_store_shelf_summary_on">رف متجر المنشئ أسفل مشغل الفيديو مخفي</string>
|
||||
<string name="revanced_hide_creator_store_shelf_summary_off">يتم عرض رف متجر المنشئ تحت مشغل الفيديو</string>
|
||||
<string name="revanced_hide_creator_store_shelf_title">إخفاء رف متجر المنشئ</string>
|
||||
<string name="revanced_hide_creator_store_shelf_summary_on">تم إخفاء رف متجر المنشئ أسفل مشغل الفيديو</string>
|
||||
<string name="revanced_hide_creator_store_shelf_summary_off">يتم عرض رف متجر المنشئ أسفل مشغل الفيديو</string>
|
||||
<string name="revanced_hide_end_screen_store_banner_title">إخفاء لافتة شاشة المتجر النهائية</string>
|
||||
<string name="revanced_hide_end_screen_store_banner_summary_on">لافتة متجر الشاشة النهائية مخفية</string>
|
||||
<string name="revanced_hide_end_screen_store_banner_summary_off">لافتة متجر الشاشة النهائية معروضة</string>
|
||||
<string name="revanced_hide_end_screen_store_banner_summary_on">تم إخفاء لافتة المتجر بالشاشة النهائية</string>
|
||||
<string name="revanced_hide_end_screen_store_banner_summary_off">يتم عرض لافتة المتجر بالشاشة النهائية</string>
|
||||
<string name="revanced_hide_fullscreen_ads_title">إخفاء إعلانات ملء الشاشة</string>
|
||||
<string name="revanced_hide_fullscreen_ads_summary_on">"يتم إخفاء إعلانات ملء الشاشة
|
||||
|
||||
@@ -455,11 +481,11 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_self_sponsor_ads_summary_on">تم إخفاء بطاقات الرعاية الذاتية</string>
|
||||
<string name="revanced_hide_self_sponsor_ads_summary_off">يتم عرض بطاقات الرعاية الذاتية</string>
|
||||
<string name="revanced_hide_shopping_links_title">إخفاء روابط التسوق</string>
|
||||
<string name="revanced_hide_shopping_links_summary_on">روابط التسوق في وصف الفيديو مخفية</string>
|
||||
<string name="revanced_hide_shopping_links_summary_on">تم إخفاء روابط التسوق في وصف الفيديو</string>
|
||||
<string name="revanced_hide_shopping_links_summary_off">يتم عرض روابط التسوق في وصف الفيديو</string>
|
||||
<string name="revanced_hide_view_products_banner_title">إخفاء لافتة \'عرض المنتجات\'</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_on">لافتة عرض المنتجات في تراكب الفيديو مخفية</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_off">لافتة عرض المنتجات في تراكب الفيديو معروضة</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_on">تم إخفاء لافتة عرض المنتجات في واجهة الفيديو</string>
|
||||
<string name="revanced_hide_view_products_banner_summary_off">يتم عرض لافتة عرض المنتجات في واجهة الفيديو</string>
|
||||
<string name="revanced_hide_web_search_results_title">إخفاء نتائج بحث الويب</string>
|
||||
<string name="revanced_hide_web_search_results_summary_on">تم إخفاء نتائج البحث على الويب</string>
|
||||
<string name="revanced_hide_web_search_results_summary_off">يتم عرض نتائج البحث على الويب</string>
|
||||
@@ -492,8 +518,8 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.signintotv.disableSignInToTvPopupPatch">
|
||||
<string name="revanced_disable_signin_to_tv_popup_title">تعطيل النافذة المنبثقة لتسجيل الدخول إلى التلفزيون</string>
|
||||
<string name="revanced_disable_signin_to_tv_popup_summary_on">النافذة المنبثقة لتسجيل الدخول إلى التلفزيون معطلة</string>
|
||||
<string name="revanced_disable_signin_to_tv_popup_summary_off">النافذة المنبثقة لتسجيل الدخول إلى التلفزيون مفعلة</string>
|
||||
<string name="revanced_disable_signin_to_tv_popup_summary_on">تم تعطيل نافذة تسجيل الدخول إلى التلفزيون</string>
|
||||
<string name="revanced_disable_signin_to_tv_popup_summary_off">تم تمكين نافذة تسجيل الدخول إلى التلفزيون</string>
|
||||
</patch>
|
||||
<patch id="interaction.doubletap.disableDoubleTapActionsPatch">
|
||||
<string name="revanced_disable_chapter_skip_double_tap_title">تعطيل تخطي الفصل بالنقر المزدوج</string>
|
||||
@@ -507,7 +533,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_external_downloader_summary_on">يتم عرض زر التنزيل في المشغل</string>
|
||||
<string name="revanced_external_downloader_summary_off">لا يتم عرض زر التنزيل في المشغل</string>
|
||||
<!-- 'Download action button' should be translated using the same wording as the translation of 'revanced_hide_download_button_title'. -->
|
||||
<string name="revanced_external_downloader_action_button_title">تجاوز زر إجراء التنزيل</string>
|
||||
<string name="revanced_external_downloader_action_button_title">تجاوز زر إجراء زر التنزيل</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_on">يفتح زر التنزيل أداة التنزيل الخارجية</string>
|
||||
<string name="revanced_external_downloader_action_button_summary_off">يفتح زر التنزيل أداة التنزيل الأصلية داخل التطبيق</string>
|
||||
<string name="revanced_external_downloader_name_title">اسم حزمة أداة التنزيل</string>
|
||||
@@ -523,8 +549,8 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="interaction.seekbar.disablePreciseSeekingGesturePatch">
|
||||
<string name="revanced_disable_precise_seeking_gesture_title">تعطيل إيماءة التمرير الدقيقة</string>
|
||||
<string name="revanced_disable_precise_seeking_gesture_summary_on">تم تعطيل الإيماءة</string>
|
||||
<string name="revanced_disable_precise_seeking_gesture_summary_off">تم تمكين الإيماءة</string>
|
||||
<string name="revanced_disable_precise_seeking_gesture_summary_on">تم تعطيل إيماءة التمرير الدقيقة</string>
|
||||
<string name="revanced_disable_precise_seeking_gesture_summary_off">تم تمكين إيماءة التمرير الدقيقة</string>
|
||||
</patch>
|
||||
<patch id="interaction.seekbar.enableSeekbarTappingPatch">
|
||||
<string name="revanced_seekbar_tapping_title">تمكين النقر للتمرير</string>
|
||||
@@ -532,19 +558,19 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_seekbar_tapping_summary_off">تم تعطيل النقر للتمرير</string>
|
||||
</patch>
|
||||
<patch id="interaction.swipecontrols.swipeControlsResourcePatch">
|
||||
<string name="revanced_swipe_brightness_title">التحكم بالسطوع عن طريق ايماءة التمرير</string>
|
||||
<string name="revanced_swipe_brightness_summary_on">"تم تمكين التمرير السريع لضبط السطوع في وضع ملء الشاشة
|
||||
<string name="revanced_swipe_brightness_title">تمكين إيماءة السطوع</string>
|
||||
<string name="revanced_swipe_brightness_summary_on">"تم تمكين إيماءة مستوى السطوع في وضع ملء الشاشة
|
||||
|
||||
اضبط السطوع عن طريق التمرير عموديًا على الجانب الأيسر من الشاشة"</string>
|
||||
<string name="revanced_swipe_brightness_summary_off">تم تعطيل التمرير السريع لضبط السطوع في وضع ملء الشاشة</string>
|
||||
<string name="revanced_swipe_volume_title">تمكين التحكم بالصوت عن طريق إيماءة التمرير</string>
|
||||
<string name="revanced_swipe_volume_summary_on">"تم تمكين التمرير السريع لضبط مستوى الصوت في وضع ملء الشاشة
|
||||
اضبط مستوى السطوع بالتمرير عموديًا على يسار الشاشة"</string>
|
||||
<string name="revanced_swipe_brightness_summary_off">تم تعطيل إيماءة مستوى السطوع في وضع ملء الشاشة</string>
|
||||
<string name="revanced_swipe_volume_title">تمكين إيماءة الصوت</string>
|
||||
<string name="revanced_swipe_volume_summary_on">"تم تمكين إيماءة مستوى الصوت في وضع ملء الشاشة
|
||||
|
||||
اضبط مستوى الصوت عن طريق التمرير عموديًا على الجانب الأيمن من الشاشة"</string>
|
||||
<string name="revanced_swipe_volume_summary_off">تم تعطيل التمرير السريع لضبط مستوى الصوت في وضع ملء الشاشة</string>
|
||||
<string name="revanced_swipe_press_to_engage_title">تمكين الضغط على إيماءة التمرير السريع</string>
|
||||
<string name="revanced_swipe_press_to_engage_summary_on">تم تمكين الضغط للتمرير السريع</string>
|
||||
<string name="revanced_swipe_press_to_engage_summary_off">تم تعطيل الضغط للتمرير السريع</string>
|
||||
<string name="revanced_swipe_volume_summary_off">تم تعطيل إيماءة مستوى الصوت في وضع ملء الشاشة</string>
|
||||
<string name="revanced_swipe_press_to_engage_title">تمكين الضغط لتمرير الإيماءة</string>
|
||||
<string name="revanced_swipe_press_to_engage_summary_on">تم تمكين الضغط لتمرير الإيماءة</string>
|
||||
<string name="revanced_swipe_press_to_engage_summary_off">تم تعطيل الضغط لتمرير الإيماءة</string>
|
||||
<string name="revanced_swipe_haptic_feedback_title">الاهتزاز عند الضغط</string>
|
||||
<string name="revanced_swipe_haptic_feedback_summary_on">تم تمكين الاهتزاز عند الضغط</string>
|
||||
<string name="revanced_swipe_haptic_feedback_summary_off">تم تعطيل الاهتزاز عند الضغط</string>
|
||||
@@ -557,29 +583,29 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_swipe_lowest_value_enable_auto_brightness_overlay_text">تلقائي</string>
|
||||
<string name="revanced_swipe_overlay_timeout_title">مهلة واجهة التمرير</string>
|
||||
<string name="revanced_swipe_overlay_timeout_summary">مقدار الوقت الذي تظهر فيه واجهة التمرير بعد التغيير بجزء الثانية</string>
|
||||
<string name="revanced_swipe_overlay_background_opacity_title">تعتيم خلفية واجهة التمرير السريع</string>
|
||||
<string name="revanced_swipe_overlay_background_opacity_summary">قيمة التعتيم بين 0-100</string>
|
||||
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">يجب أن يكون تعتيم التمرير السريع بين 0-100</string>
|
||||
<string name="revanced_swipe_overlay_progress_brightness_color_title">لون سطوع واجهة التمرير</string>
|
||||
<string name="revanced_swipe_overlay_progress_brightness_color_summary">لون شريط التقدم لعناصر التحكم في السطوع</string>
|
||||
<string name="revanced_swipe_overlay_progress_volume_color_title">لون مستوى صوت واجهة التمرير</string>
|
||||
<string name="revanced_swipe_overlay_progress_volume_color_summary">لون شريط التقدم لعناصر التحكم في مستوى الصوت</string>
|
||||
<string name="revanced_swipe_text_overlay_size_title">حجم نص واجهة التمرير</string>
|
||||
<string name="revanced_swipe_text_overlay_size_summary">حجم النص لواجهة التمرير بين 1-30</string>
|
||||
<string name="revanced_swipe_overlay_background_opacity_title">تعتيم خلفية واجهة التمرير</string>
|
||||
<string name="revanced_swipe_overlay_background_opacity_summary">قيمة الشفافية بين 0-100</string>
|
||||
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">يجب أن تكون شفافية التمرير بين 0-100</string>
|
||||
<string name="revanced_swipe_overlay_progress_brightness_color_title">لون نمط إيماءة السطوع</string>
|
||||
<string name="revanced_swipe_overlay_progress_brightness_color_summary">لون شريط عناصر التحكم في مستوى السطوع</string>
|
||||
<string name="revanced_swipe_overlay_progress_volume_color_title">لون نمط إيماءة الصوت</string>
|
||||
<string name="revanced_swipe_overlay_progress_volume_color_summary">لون شريط عناصر التحكم في مستوى الصوت</string>
|
||||
<string name="revanced_swipe_text_overlay_size_title">حجم نص نمط إيماءة التمرير</string>
|
||||
<string name="revanced_swipe_text_overlay_size_summary">حجم النص لنمط التمرير بين 1-30</string>
|
||||
<string name="revanced_swipe_text_overlay_size_invalid_toast">يجب أن يكون حجم النص بين 1-30</string>
|
||||
<string name="revanced_swipe_threshold_title">مقدار حد التمرير</string>
|
||||
<string name="revanced_swipe_threshold_summary">الحد الأدنى من التمرير قبل اكتشاف الإيماءة</string>
|
||||
<string name="revanced_swipe_volume_sensitivity_title">حساسية إيماءة تمرير مستوى الصوت</string>
|
||||
<string name="revanced_swipe_threshold_summary">مقدار الحد الأقصى لحدوث التمرير</string>
|
||||
<string name="revanced_swipe_volume_sensitivity_title">حساسية تمرير مستوى الصوت</string>
|
||||
<string name="revanced_swipe_volume_sensitivity_summary">مقدار تغير مستوى الصوت لكل تمريرة</string>
|
||||
<string name="revanced_swipe_overlay_style_title">نمط واجهة التمرير</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_1">واجهة أفقية</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_2">واجهة أفقية (الأدنى - الأعلى)</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_3">واجهة أفقية (الأدنى - المنتصف)</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_4">واجهة دائرية</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_5">واجهة دائرية (الأدنى)</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_6">واجهة عمودية</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_7">واجهة عمودية (الأدنى)</string>
|
||||
<string name="revanced_swipe_change_video_title">تمكين إيماءة التمرير لتغيير الفيديو</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_1">النمط الافقي</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_2">النمط الأفقي (الأدنى - الأعلى)</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_3">النمط الأفقي (الأدنى - المنتصف)</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_4">النمط الدائري</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_5">النمط الدائري (الأدنى)</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_6">النمط العمودي</string>
|
||||
<string name="revanced_swipe_overlay_style_entry_7">النمط العمودي (الأدنى)</string>
|
||||
<string name="revanced_swipe_change_video_title">تمكين إيماءة التمرير لتغيير الفيديوهات</string>
|
||||
<string name="revanced_swipe_change_video_summary_on">سيؤدي التمرير في وضع ملء الشاشة إلى التغيير للفيديو التالي/السابق</string>
|
||||
<string name="revanced_swipe_change_video_summary_off">لن يؤدي التمرير في وضع ملء الشاشة إلى التغيير للفيديو التالي/السابق</string>
|
||||
</patch>
|
||||
@@ -591,9 +617,9 @@ Second \"item\" text"</string>
|
||||
<patch id="layout.buttons.action.hideButtonsPatch">
|
||||
<string name="revanced_hide_buttons_screen_title">أزرار الإجراء</string>
|
||||
<string name="revanced_hide_buttons_screen_summary">إخفاء أو عرض الأزرار تحت الفيديوهات</string>
|
||||
<string name="revanced_disable_like_subscribe_glow_title">إيقاف تفعيل توهج الإعجاب والاشتراك</string>
|
||||
<string name="revanced_disable_like_subscribe_glow_summary_on">لن يتوهَّج زرّي أعجبني واشتراك عند ذكرهما</string>
|
||||
<string name="revanced_disable_like_subscribe_glow_summary_off">سيتوهَّج زرّي أعجبني واشتراك عند ذكرهما</string>
|
||||
<string name="revanced_disable_like_subscribe_glow_title">تعطيل توهج الإعجاب والاشتراك</string>
|
||||
<string name="revanced_disable_like_subscribe_glow_summary_on">لن يتوهج زر أعجبني والاشتراك عند الإشارة إليه</string>
|
||||
<string name="revanced_disable_like_subscribe_glow_summary_off">سيتوهَّج زر أعجبني والاشتراك عند الإشارة إليه </string>
|
||||
<string name="revanced_hide_like_dislike_button_title">إخفاء أعجبني ولم يعجبني</string>
|
||||
<string name="revanced_hide_like_dislike_button_summary_on">تم إخفاء أزرار أعجبني ولم يعجبني</string>
|
||||
<string name="revanced_hide_like_dislike_button_summary_off">يتم عرض أزرار أعجبني ولم يعجبني</string>
|
||||
@@ -603,12 +629,12 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_share_button_summary_off">يتم عرض زر مشاركة</string>
|
||||
<!-- 'Stop ads' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_stop_ads_button_title">إخفاء إيقاف الإعلانات</string>
|
||||
<string name="revanced_hide_stop_ads_button_summary_on">زر إيقاف الإعلانات مخفي</string>
|
||||
<string name="revanced_hide_stop_ads_button_summary_off">زر إيقاف الإعلانات معروض</string>
|
||||
<string name="revanced_hide_stop_ads_button_summary_on">تم إخفاء زر إيقاف الإعلانات</string>
|
||||
<string name="revanced_hide_stop_ads_button_summary_off">يتم عرض زر إيقاف الإعلانات</string>
|
||||
<!-- Button does not have any text and is only shown as an icon, and only when the video information area is collapsed to a compact state. -->
|
||||
<string name="revanced_hide_comments_button_title">إخفاء التعليقات</string>
|
||||
<string name="revanced_hide_comments_button_summary_on">زر التعليقات مخفي</string>
|
||||
<string name="revanced_hide_comments_button_summary_off">زر التعليقات ظاهر</string>
|
||||
<string name="revanced_hide_comments_button_summary_on">تم إخفاء زر التعليقات</string>
|
||||
<string name="revanced_hide_comments_button_summary_off">يتم عرض زر التعليقات</string>
|
||||
<!-- 'Report' should be translated with the same localized wording that YouTube displays.
|
||||
This button usually only shows on live streams. -->
|
||||
<string name="revanced_hide_report_button_title">إخفاء الإبلاغ</string>
|
||||
@@ -619,39 +645,39 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_remix_button_summary_on">تم إخفاء زر ريمكس</string>
|
||||
<string name="revanced_hide_remix_button_summary_off">يتم عرض زر ريمكس</string>
|
||||
<!-- 'Download' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_download_button_title">إخفاء التنزيل</string>
|
||||
<string name="revanced_hide_download_button_summary_on">تم إخفاء زر التنزيل</string>
|
||||
<string name="revanced_hide_download_button_summary_off">يتم عرض زر التنزيل</string>
|
||||
<string name="revanced_hide_download_button_title">إخفاء تنزيل</string>
|
||||
<string name="revanced_hide_download_button_summary_on">تم إخفاء زر تنزيل</string>
|
||||
<string name="revanced_hide_download_button_summary_off">يتم عرض زر تنزيل</string>
|
||||
<!-- 'Hype' should be translated with the same localized wording that YouTube displays.
|
||||
This button only shows on videos uploaded by the logged in user. -->
|
||||
<string name="revanced_hide_hype_button_title">إخفاء الضجة</string>
|
||||
<string name="revanced_hide_hype_button_summary_on">زر الضجة مخفي</string>
|
||||
<string name="revanced_hide_hype_button_summary_off">يظهر زر الحماس</string>
|
||||
<string name="revanced_hide_hype_button_title">إخفاء التشجيع</string>
|
||||
<string name="revanced_hide_hype_button_summary_on">تم إخفاء زر التشجيع</string>
|
||||
<string name="revanced_hide_hype_button_summary_off">يتم عرض زر التشجيع</string>
|
||||
<!-- 'Promote' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_promote_button_title">إخفاء الترويج</string>
|
||||
<string name="revanced_hide_promote_button_summary_on">زر الترويج مخفي</string>
|
||||
<string name="revanced_hide_promote_button_summary_off">زر الترويج ظاهر</string>
|
||||
<string name="revanced_hide_promote_button_summary_on">تم إخفاء زر الترويج</string>
|
||||
<string name="revanced_hide_promote_button_summary_off">يتم عرض زر الترويج</string>
|
||||
<!-- 'Thanks' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_thanks_button_title">إخفاء شكرًا</string>
|
||||
<string name="revanced_hide_thanks_button_summary_on">تم إخفاء زر شكرًا</string>
|
||||
<string name="revanced_hide_thanks_button_summary_off">يتم عرض زر شكرًا</string>
|
||||
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
|
||||
This button only shows if the user ip is from specific region such as the USA or EU. -->
|
||||
<string name="revanced_hide_ask_button_title">إخفاء \"Ask\"</string>
|
||||
<string name="revanced_hide_ask_button_summary_on">تم إخفاء زر \"Ask\"</string>
|
||||
<string name="revanced_hide_ask_button_summary_off">يتم عرض زر \"Ask\"</string>
|
||||
<string name="revanced_hide_ask_button_title">إخفاء طرح سؤال</string>
|
||||
<string name="revanced_hide_ask_button_summary_on">تم إخفاء زر طرح سؤال</string>
|
||||
<string name="revanced_hide_ask_button_summary_off">يتم عرض زر طرح سؤال</string>
|
||||
<!-- 'Clip' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_clip_button_title">إخفاء المقطع</string>
|
||||
<string name="revanced_hide_clip_button_summary_on">تم إخفاء زر إنشاء مقطع</string>
|
||||
<string name="revanced_hide_clip_button_summary_off">يتم عرض زر إنشاء مقطع</string>
|
||||
<string name="revanced_hide_clip_button_summary_on">تم إخفاء زر المقطع</string>
|
||||
<string name="revanced_hide_clip_button_summary_off">يتم عرض زر المقطع</string>
|
||||
<!-- 'Shop' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_shop_button_title">إخفاء المتجر</string>
|
||||
<string name="revanced_hide_shop_button_summary_on">زر المتجر مخفي</string>
|
||||
<string name="revanced_hide_shop_button_summary_off">زر المتجر معروض</string>
|
||||
<string name="revanced_hide_shop_button_summary_on">تم إخفاء زر المتجر</string>
|
||||
<string name="revanced_hide_shop_button_summary_off">يتم عرض زر المتجر</string>
|
||||
<!-- 'Save' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_save_button_title">إخفاء حفظ</string>
|
||||
<string name="revanced_hide_save_button_summary_on">زر الحفظ مخفي</string>
|
||||
<string name="revanced_hide_save_button_summary_off">زر الحفظ معروض</string>
|
||||
<string name="revanced_hide_save_button_summary_on">تم إخفاء زر حفظ</string>
|
||||
<string name="revanced_hide_save_button_summary_off">يتم عرض زر حفظ</string>
|
||||
</patch>
|
||||
<patch id="layout.buttons.navigation.navigationButtonsPatch">
|
||||
<string name="revanced_navigation_buttons_screen_title">أزرار التنقل</string>
|
||||
@@ -665,7 +691,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_shorts_button_summary_on">تم إخفاء زر Shorts</string>
|
||||
<string name="revanced_hide_shorts_button_summary_off">يتم عرض زر Shorts</string>
|
||||
<!-- 'Create' has no display name. Translate normally. -->
|
||||
<string name="revanced_hide_create_button_title">إخفاء الإنشاء</string>
|
||||
<string name="revanced_hide_create_button_title">إخفاء إنشاء</string>
|
||||
<string name="revanced_hide_create_button_summary_on">تم إخفاء زر الإنشاء</string>
|
||||
<string name="revanced_hide_create_button_summary_off">يتم عرض زر الإنشاء</string>
|
||||
<!-- 'Subscriptions' should be translated using the same localized wording YouTube displays the tab. -->
|
||||
@@ -676,7 +702,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_notifications_button_summary_on">تم إخفاء زر الإشعارات</string>
|
||||
<string name="revanced_hide_notifications_button_summary_off">يتم عرض زر الإشعارات</string>
|
||||
<!-- 'Notifications' should be translated using the same localized wording YouTube displays the tab. -->
|
||||
<string name="revanced_switch_create_with_notifications_button_title">تبديل الإنشاء مع الإشعارات</string>
|
||||
<string name="revanced_switch_create_with_notifications_button_title">تبديل الإنشاء بالإشعارات</string>
|
||||
<string name="revanced_switch_create_with_notifications_button_summary_on">"تم تبديل زر الإنشاء بـزر الإشعارات
|
||||
|
||||
ملاحظة: يؤدي تمكين هذا أيضًا إلى إخفاء إعلانات الفيديو بالقوة"</string>
|
||||
@@ -778,7 +804,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_player_previous_next_buttons_summary_on">تم إخفاء الأزرار</string>
|
||||
<string name="revanced_hide_player_previous_next_buttons_summary_off">يتم عرض الأزرار</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.endscreencards.hideEndscreenCardsResourcePatch">
|
||||
<patch id="layout.hide.endscreencards.hideEndScreenCardsResourcePatch">
|
||||
<string name="revanced_hide_endscreen_cards_title">إخفاء بطاقات شاشة النهاية</string>
|
||||
<string name="revanced_hide_endscreen_cards_summary_on">تم إخفاء بطاقات شاشة النهاية</string>
|
||||
<string name="revanced_hide_endscreen_cards_summary_off">يتم عرض بطاقات شاشة النهاية</string>
|
||||
@@ -1333,25 +1359,25 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_miniplayer_type_entry_5">حديث 2</string>
|
||||
<string name="revanced_miniplayer_type_entry_6">حديث 3</string>
|
||||
<string name="revanced_miniplayer_type_entry_7">حديث 4</string>
|
||||
<string name="revanced_miniplayer_rounded_corners_title">تمكين الزوايا المستديرة</string>
|
||||
<string name="revanced_miniplayer_rounded_corners_summary_on">الزوايا مستديرة</string>
|
||||
<string name="revanced_miniplayer_rounded_corners_summary_off">الزوايا مربعة</string>
|
||||
<string name="revanced_miniplayer_disable_rounded_corners_title">تعطيل الزوايا الدائرية</string>
|
||||
<string name="revanced_miniplayer_disable_rounded_corners_summary_on">الزوايا مربعة</string>
|
||||
<string name="revanced_miniplayer_disable_rounded_corners_summary_off">الزوايا مستديرة</string>
|
||||
<string name="revanced_miniplayer_double_tap_action_title">تمكين النقر المزدوج والضغط لتغيير الحجم</string>
|
||||
<string name="revanced_miniplayer_double_tap_action_summary_on">"تم تمكين إجراء الضغط المزدوج والضغط لتغيير الحجم
|
||||
|
||||
• النقر المزدوج لزيادة حجم المشغل المصغر
|
||||
• النقر المزدوج مرة أخرى لاستعادة الحجم الأصلي"</string>
|
||||
<string name="revanced_miniplayer_double_tap_action_summary_off">إجراء النقر المزدوج والضغط لتغيير الحجم معطل</string>
|
||||
<string name="revanced_miniplayer_drag_and_drop_title">تمكين السحب والإفلات</string>
|
||||
<string name="revanced_miniplayer_drag_and_drop_summary_on">"السحب والإفلات مفعلان
|
||||
<string name="revanced_miniplayer_disable_drag_and_drop_title">تعطيل السحب والإفلات</string>
|
||||
<string name="revanced_miniplayer_disable_drag_and_drop_summary_on">تم تعطيل السحب والإفلات</string>
|
||||
<string name="revanced_miniplayer_disable_drag_and_drop_summary_off">"السحب والإفلات مفعلان
|
||||
|
||||
يمكن سحب المشغل المصغر إلى أي زاوية من الشاشة"</string>
|
||||
<string name="revanced_miniplayer_drag_and_drop_summary_off">تم تعطيل السحب والإفلات</string>
|
||||
<string name="revanced_miniplayer_horizontal_drag_title">تمكين إيماءة السحب الأفقية</string>
|
||||
<string name="revanced_miniplayer_horizontal_drag_summary_on">"تم تمكين إيماءة السحب الأفقية
|
||||
<string name="revanced_miniplayer_disable_horizontal_drag_title">تعطيل إيماءة السحب الأفقي</string>
|
||||
<string name="revanced_miniplayer_disable_horizontal_drag_summary_on">تم تعطيل إيماءة السحب الأفقية</string>
|
||||
<string name="revanced_miniplayer_disable_horizontal_drag_summary_off">"تم تمكين إيماءة السحب الأفقية
|
||||
|
||||
يمكن سحب المشغل المصغر خارج الشاشة إلى اليسار أو اليمين"</string>
|
||||
<string name="revanced_miniplayer_horizontal_drag_summary_off">تم تعطيل إيماءة السحب الأفقية</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_title">إخفاء أزرار الواجهة</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_summary_on">تم إخفاء أزرار الواجهة</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_summary_off">يتم عرض أزرار الواجهة</string>
|
||||
@@ -1443,11 +1469,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_announcements_connection_failed">فشل الاتصال بموفر الإعلانات</string>
|
||||
<string name="revanced_announcements_dialog_dismiss">تجاهل</string>
|
||||
</patch>
|
||||
<patch id="misc.dns.checkWatchHistoryDomainNameResolutionPatch">
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_title">تحذير</string>
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_message">لم يتم حفظ سجل المشاهدة الخاص بك.<br><br>من المرجح أن يكون السبب في ذلك هو مانع إعلانات DNS أو وكيل الشبكة.<br><br>لإصلاح هذه المشكلة، قم بإضافة <b>s.youtube.com</b> إلى القائمة البيضاء أو قم بإيقاف تشغيل جميع أدوات حظر DNS ووكلاء البروكسي.</string>
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_ignore">لا تعرض مرة أخرى</string>
|
||||
</patch>
|
||||
<patch id="misc.loopvideo.loopVideoPatch">
|
||||
<string name="revanced_loop_video_title">تفعيل تكرار الفيديو</string>
|
||||
<string name="revanced_loop_video_summary_on">سيتم تكرار الفيديو</string>
|
||||
@@ -1499,13 +1520,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_external_browser_summary_on">فتح الروابط في متصفح خارجي</string>
|
||||
<string name="revanced_external_browser_summary_off">فتح الروابط في متصفح داخل التطبيق</string>
|
||||
</patch>
|
||||
<patch id="video.audio.forceOriginalAudioPatch">
|
||||
<string name="revanced_force_original_audio_title">فرض لغة الصوت الأصلية</string>
|
||||
<string name="revanced_force_original_audio_summary_on">استخدام لغة الصوت الأصلية</string>
|
||||
<string name="revanced_force_original_audio_summary_off">استخدام الصوت الافتراضي</string>
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
<string name="revanced_force_original_audio_not_available">لاستخدام هذه الميزة، غيّر \"تزوير تدفقات الفيديو\" إلى أي عميل باستثناء Android Studio</string>
|
||||
</patch>
|
||||
<patch id="video.quality.rememberVideoQualityPatch">
|
||||
<!-- Translations should use the same text as 'revanced_custom_playback_speeds_auto'. -->
|
||||
<string name="revanced_video_quality_default_entry_1">تلقائي</string>
|
||||
@@ -1562,10 +1576,22 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_playback_speed_default_title">سرعة التشغيل الافتراضية</string>
|
||||
<string name="revanced_remember_playback_speed_toast">تغيير السرعة الافتراضية إلى: %s</string>
|
||||
</patch>
|
||||
<patch id="video.hdr.disableHdrPatch">
|
||||
<patch id="video.codecs.disableVideoCodecsPatch">
|
||||
<string name="revanced_disable_hdr_video_title">تعطيل فيديو HDR</string>
|
||||
<string name="revanced_disable_hdr_video_summary_on">تم تعطيل فيديو HDR</string>
|
||||
<string name="revanced_disable_hdr_video_summary_off">تم تمكين فيديو HDR</string>
|
||||
<string name="revanced_force_avc_codec_title">فرض AVC (H.264)</string>
|
||||
<string name="revanced_force_avc_codec_summary_on">تم فرض برنامج ترميز الفيديو على AVC (H.264)</string>
|
||||
<string name="revanced_force_avc_codec_summary_off">يتم تحديد برنامج ترميز الفيديو تلقائيًا</string>
|
||||
<string name="revanced_force_avc_codec_user_dialog_message">"الفوائد:
|
||||
• يمكن أن يحسن عمر البطارية
|
||||
• يمكن أن يستعيد دقة الفيديو المفقودة على الأجهزة القديمة
|
||||
|
||||
القيود:
|
||||
• أقصى دقة هي 1080p
|
||||
• تشغيل الفيديو سيستهلك المزيد من بيانات الإنترنت مقارنةً بـ VP9 أو AV1
|
||||
• لن تستخدم فيديوهات HDR ترميز AVC
|
||||
• لا يمكن لبعض الأجهزة فرض AVC"</string>
|
||||
</patch>
|
||||
<patch id="video.quality.advancedVideoQualityMenuPatch">
|
||||
<string name="revanced_advanced_video_quality_menu_title">عرض قائمة جودة الفيديو المتقدمة</string>
|
||||
|
||||
@@ -22,6 +22,9 @@ Second \"item\" text"</string>
|
||||
<app id="shared">
|
||||
<patch id="misc.checks.checkEnvironmentPatch">
|
||||
</patch>
|
||||
<patch id="misc.dns.checkWatchHistoryDomainNameResolutionPatch">
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_title">সকীয়নি</string>
|
||||
</patch>
|
||||
<patch id="misc.settings.settingsResourcePatch">
|
||||
<!-- Settings about dialog. -->
|
||||
<!-- NOTE: the about strings above are duplicated in the TikTok about screen code,
|
||||
@@ -32,6 +35,9 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
</patch>
|
||||
<patch id="misc.audio.forceOriginalAudioPatch">
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
</patch>
|
||||
<patch id="misc.privacy.sanitizeSharingLinksPatch">
|
||||
@@ -57,6 +63,8 @@ Second \"item\" text"</string>
|
||||
<!-- 'Visit Community' should be translated with the same localized wording that YouTube displays. -->
|
||||
<!-- 'Visit store' should be translated with the same localized wording that YouTube displays. -->
|
||||
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
|
||||
<!-- Translations should lanaguge similar to revanced_hide_upload_time_user_dialog_message -->
|
||||
<!-- Translations should lanaguge similar to revanced_hide_view_count_user_dialog_message -->
|
||||
<!-- For localization, it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word.
|
||||
This is because keywords can be in any language, and showing an example in the localized script helps convey this. -->
|
||||
<!-- Translations _must_ use a localized example. For languages that do not use spaces between words (Chinese, Japanese, etc.) the English AI example should be used since no localized examples exist. Or if using machine translations, or if nobody wants to think of a localized example, then the English 'ai' example should be left as-is. -->
|
||||
@@ -131,7 +139,7 @@ Second \"item\" text"</string>
|
||||
<patch id="layout.buttons.overlay.hidePlayerOverlayButtonsPatch">
|
||||
<!-- This button does not display any text, but 'Captions' should be translated using the same wording used as the translation of 'revanced_hide_player_flyout_captions_title'. -->
|
||||
</patch>
|
||||
<patch id="layout.hide.endscreencards.hideEndscreenCardsResourcePatch">
|
||||
<patch id="layout.hide.endscreencards.hideEndScreenCardsResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.hide.fullscreenambientmode.disableFullscreenAmbientModePatch">
|
||||
</patch>
|
||||
@@ -210,9 +218,6 @@ Second \"item\" text"</string>
|
||||
<patch id="misc.announcements.announcementsPatch">
|
||||
<string name="revanced_announcements_dialog_dismiss">খাৰিজ কৰক</string>
|
||||
</patch>
|
||||
<patch id="misc.dns.checkWatchHistoryDomainNameResolutionPatch">
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_title">সকীয়নি</string>
|
||||
</patch>
|
||||
<patch id="misc.loopvideo.loopVideoPatch">
|
||||
</patch>
|
||||
<patch id="misc.loopvideo.button.loopVideoButtonPatch">
|
||||
@@ -227,9 +232,6 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="misc.links.openLinksExternallyPatch">
|
||||
</patch>
|
||||
<patch id="video.audio.forceOriginalAudioPatch">
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
</patch>
|
||||
<patch id="video.quality.rememberVideoQualityPatch">
|
||||
<!-- Translations should use the same text as 'revanced_custom_playback_speeds_auto'. -->
|
||||
</patch>
|
||||
@@ -241,7 +243,7 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="video.speed.remember.rememberPlaybackSpeedPatch">
|
||||
</patch>
|
||||
<patch id="video.hdr.disableHdrPatch">
|
||||
<patch id="video.codecs.disableVideoCodecsPatch">
|
||||
</patch>
|
||||
<patch id="video.quality.advancedVideoQualityMenuPatch">
|
||||
</patch>
|
||||
|
||||
@@ -31,6 +31,11 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time_days">%s gün əvvəl yamaqlanıb</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time_invalid">APK qurulma vaxtı pozulub</string>
|
||||
</patch>
|
||||
<patch id="misc.dns.checkWatchHistoryDomainNameResolutionPatch">
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_title">Xәbәrdarlıq</string>
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_message">Baxış tarixçəniz saxlanmır.<br><br>Bu çox güman ki, DNS reklam bloklayıcı və ya şəbəkə proksisinə görədir.<br><br>.Bunu düzəltmək üçün s.youtube.com-u</b> <b>ağ siyahıya salın və ya bütün DNS bloklayıcıları və proksiləri bağlayın.</string>
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_ignore">Təkrar göstərmə</string>
|
||||
</patch>
|
||||
<patch id="misc.settings.settingsResourcePatch">
|
||||
<string name="revanced_settings_submenu_title">Tənzimləmələr</string>
|
||||
<string name="revanced_settings_confirm_user_dialog_title">Davam etmək istədiyinizə əminsiniz?</string>
|
||||
@@ -60,9 +65,9 @@ Second \"item\" text"</string>
|
||||
• Valideyn tənzimləmələri qapadılan uşaq tənzimləmələrin üstündə görünür"</string>
|
||||
<string name="revanced_settings_search_empty_history_title">Axtarış tarixçəsi boşdur</string>
|
||||
<string name="revanced_settings_search_empty_history_summary">Axtarış tarixçəsini saxlamaq üçün axtarış sorğusu yazın və Daxil Et basın</string>
|
||||
<string name="revanced_settings_search_history_title">Axtarış tarixçəsi tənzimləməsin göstər</string>
|
||||
<string name="revanced_settings_search_history_summary_on">Axtarış tarixçəsi tənzimləməsi göstərilir</string>
|
||||
<string name="revanced_settings_search_history_summary_off">Axtarış tarixçəsi tənzimləməsi göstərilmir</string>
|
||||
<string name="revanced_settings_search_history_title">Tənzimləmə axtarış tarixçəsin göstər</string>
|
||||
<string name="revanced_settings_search_history_summary_on">Tənzimləmə axtarış tarixçəsi göstərilir</string>
|
||||
<string name="revanced_settings_search_history_summary_off">Tənzimləmə axtarış tarixçəsi görünmür</string>
|
||||
<string name="revanced_show_menu_icons_title">ReVanced tənzimləmə nişanların göstər</string>
|
||||
<string name="revanced_show_menu_icons_summary_on">Tənzimləmə nişanları göstərilir</string>
|
||||
<string name="revanced_show_menu_icons_summary_off">Tənzimləmə nişanları göstərilmir</string>
|
||||
@@ -115,6 +120,13 @@ Oynatma işləməyə bilər"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">Bu tənzimləməni qapatmaq oynatma problemlərinə səbəb ola bilər.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">İlkin qəbuledici</string>
|
||||
</patch>
|
||||
<patch id="misc.audio.forceOriginalAudioPatch">
|
||||
<string name="revanced_force_original_audio_title">Orijinal səs dilini zorla</string>
|
||||
<string name="revanced_force_original_audio_summary_on">Orijinal səs dilini istifadə</string>
|
||||
<string name="revanced_force_original_audio_summary_off">İlkin səs istifadəsi</string>
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
<string name="revanced_force_original_audio_not_available">Bu funksiyanı istifadə etmək üçün \"Video yayımları saxtalaşdırı\" Android Studio savayı istənilən qəbulediciyə dəyiş</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">Sazlama</string>
|
||||
<string name="revanced_debug_screen_summary">Sazlama seçimlərini aktiv/qeyri-aktiv et</string>
|
||||
@@ -141,9 +153,9 @@ Gözlənilməz hallardan xəbərdar olmayacaqsınız."</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Qeydlər silindi</string>
|
||||
</patch>
|
||||
<patch id="misc.privacy.sanitizeSharingLinksPatch">
|
||||
<string name="revanced_sanitize_sharing_links_title">İzləmə sorğusu faktorun sil</string>
|
||||
<string name="revanced_sanitize_sharing_links_summary_on">İzləmə sorğusu faktoru bağlantılardan silinir</string>
|
||||
<string name="revanced_sanitize_sharing_links_summary_off">İzləmə sorğusu faktoru bağlantılardan silinmir</string>
|
||||
<string name="revanced_sanitize_sharing_links_title">Paylaşım linklərin təmizlə</string>
|
||||
<string name="revanced_sanitize_sharing_links_summary_on">İzləmə sorğusu faktoru paylaşılan linklərdən silinir</string>
|
||||
<string name="revanced_sanitize_sharing_links_summary_off">İzləmə sorğusu faktoru paylaşılan linklərdən silinmir</string>
|
||||
<string name="revanced_replace_music_with_youtube_title">Paylaşma keçidlərini youtube.com-a dəyişdir</string>
|
||||
<string name="revanced_replace_music_with_youtube_summary_on">Paylaşılan keçidlər youtube.com istifadə edir</string>
|
||||
<string name="revanced_replace_music_with_youtube_summary_off">Paylaşılan keçidlər music.youtube.com istifadə edir</string>
|
||||
@@ -374,15 +386,15 @@ Hər halda, bunu aktivləşdirmə IP ünvanınız kimi bəzi istifadəçi məlum
|
||||
<string name="revanced_hide_comments_create_a_short_button_title">\"Shorts Yarat\" düyməsini gizlət</string>
|
||||
<string name="revanced_hide_comments_create_a_short_button_summary_on">Short yarat düyməsi gizlidir</string>
|
||||
<string name="revanced_hide_comments_create_a_short_button_summary_off">Short yarat düyməsi görünür</string>
|
||||
<string name="revanced_hide_comments_emoji_and_timestamp_buttons_title">Emoji və Vaxt damğası düymələrini gizlət</string>
|
||||
<string name="revanced_hide_comments_emoji_and_timestamp_buttons_summary_on">Emoji və Vaxt damğası düymələri gizlədilib</string>
|
||||
<string name="revanced_hide_comments_emoji_and_timestamp_buttons_summary_off">Emoji və Vaxt damğası düymələri görünür</string>
|
||||
<string name="revanced_hide_comments_preview_comment_title">Önbaxış şərhin gizlət</string>
|
||||
<string name="revanced_hide_comments_preview_comment_summary_on">Önbaxış şərhi gizlədilib</string>
|
||||
<string name="revanced_hide_comments_preview_comment_summary_off">Önbaxış şərhi göstərilir</string>
|
||||
<string name="revanced_hide_comments_thanks_button_title">Təşəkkür Düyməsini Gizlət</string>
|
||||
<string name="revanced_hide_comments_thanks_button_summary_on">Təşəkkür düyməsi gizlidir</string>
|
||||
<string name="revanced_hide_comments_thanks_button_summary_off">Təşəkkür düyməsi göstərilir</string>
|
||||
<string name="revanced_hide_comments_timestamp_button_title">Vaxt damğası düyməsin gizlət</string>
|
||||
<string name="revanced_hide_comments_timestamp_button_summary_on">Vaxt damğası düyməsi gizlidir</string>
|
||||
<string name="revanced_hide_comments_timestamp_button_summary_off">Vaxt möhürü düyməsi göstərilir</string>
|
||||
<string name="revanced_custom_filter_screen_title">Şəxsi filtr</string>
|
||||
<string name="revanced_custom_filter_screen_summary">Fərdi filtrlər işlədərək elementləri gizlət</string>
|
||||
<string name="revanced_custom_filter_title">Fərdi filtri aktivləşdir</string>
|
||||
@@ -392,6 +404,20 @@ Hər halda, bunu aktivləşdirmə IP ünvanınız kimi bəzi istifadəçi məlum
|
||||
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
|
||||
<string name="revanced_custom_filter_strings_summary">Yeni sətirlə ayrılmış filtr üçün element yol qurucusu sətirlərinin siyahısı</string>
|
||||
<string name="revanced_custom_filter_toast_invalid_syntax">Etibarsız fərdi filtr: %s</string>
|
||||
<string name="revanced_hide_view_count_title">Baxış sayını gizlət</string>
|
||||
<string name="revanced_hide_view_count_summary_on">Baxış sayı lentdə və axtarış nəticələrində gizlədilib</string>
|
||||
<string name="revanced_hide_view_count_summary_off">Baxış sayı lentdə və axtarış nəticələrində göstərilib</string>
|
||||
<!-- Translations should lanaguge similar to revanced_hide_upload_time_user_dialog_message -->
|
||||
<string name="revanced_hide_view_count_user_dialog_message">"Məhdudiyyətlər:
|
||||
• Shorts rəfləri, kanal səhifələri və axtarış nəticələri hələ də baxış saylarını göstərə bilər
|
||||
• Bu funksiya avtomobil form faktoru ilə işləmir"</string>
|
||||
<string name="revanced_hide_upload_time_title">Yükləmə vaxtını gizlət</string>
|
||||
<string name="revanced_hide_upload_time_summary_on">Yükləmə vaxtı lentdə və axtarış nəticələrində gizlədilib</string>
|
||||
<string name="revanced_hide_upload_time_summary_off">Yükləmə vaxtı lentdə və axtarış nəticələrində göstərilir</string>
|
||||
<!-- Translations should lanaguge similar to revanced_hide_view_count_user_dialog_message -->
|
||||
<string name="revanced_hide_upload_time_user_dialog_message">"Məhdudiyyətlər:
|
||||
• Shorts rəflərində, kanal səhifələrində və axtarış nəticələrində yükləmə vaxtları hələ də göstərilə bilər
|
||||
• Bu funksiya avtomobil form faktoru ilə işləmir"</string>
|
||||
<string name="revanced_hide_keyword_content_screen_title">Açar söz məzmununu gizlət</string>
|
||||
<string name="revanced_hide_keyword_content_screen_summary">Açar söz filtrləri ilə axtarış və axın videolarını gizlət</string>
|
||||
<string name="revanced_hide_keyword_content_home_title">Ev videolarını açar sözlərə görə gizlət</string>
|
||||
@@ -778,7 +804,7 @@ Səs treki menyusunu göstərmək üçün \"Video yayımları saxtalaşdır\"ı
|
||||
<string name="revanced_hide_player_previous_next_buttons_summary_on">Düymələr gizlidir</string>
|
||||
<string name="revanced_hide_player_previous_next_buttons_summary_off">Düymələr göstərilir</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.endscreencards.hideEndscreenCardsResourcePatch">
|
||||
<patch id="layout.hide.endscreencards.hideEndScreenCardsResourcePatch">
|
||||
<string name="revanced_hide_endscreen_cards_title">Son ekran kartlarını gizlət</string>
|
||||
<string name="revanced_hide_endscreen_cards_summary_on">Son ekran kartları gizlidir</string>
|
||||
<string name="revanced_hide_endscreen_cards_summary_off">Son ekran kartları göstərilir</string>
|
||||
@@ -1265,7 +1291,7 @@ Bu tətbiqin görünüşün və xüsusiyyətlərin dəyişdirəcək, lakin bilin
|
||||
Sonradan qapadılarsa, UI səhvlərin önləmək üçün tətbiq məlumatların silmək tövsiyə olunur."</string>
|
||||
<string name="revanced_spoof_app_version_target_title">Saxta tətbiq versiyası hədəfi</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_1">20.13.41 - Yığılmayan video fəaliyyət cizgisin bərpa et</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_2">20.05.46 - Transkript funksionallığını bərpa edin</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_2">20.05.46 - Transkript xüsusiyyətin bərpa et</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_3">19.35.36 - Köhnə Shorts oynadıcı işarələrin bərpa et</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_4">19.01.34 - Köhnə fəaliyyət simvolların bərpa et</string>
|
||||
</patch>
|
||||
@@ -1332,25 +1358,25 @@ Məhdudiyyət: Alətlər cizgisindəki geri düyməsin istifadə işləməyə bi
|
||||
<string name="revanced_miniplayer_type_entry_5">Müasir 2</string>
|
||||
<string name="revanced_miniplayer_type_entry_6">Müasir 3</string>
|
||||
<string name="revanced_miniplayer_type_entry_7">Müasir 4</string>
|
||||
<string name="revanced_miniplayer_rounded_corners_title">Dairəvi küncləri aktivləşdir</string>
|
||||
<string name="revanced_miniplayer_rounded_corners_summary_on">Künclər dairəvidir</string>
|
||||
<string name="revanced_miniplayer_rounded_corners_summary_off">Künclər kvadratdır</string>
|
||||
<string name="revanced_miniplayer_disable_rounded_corners_title">Dəyirmi küncləri qapat</string>
|
||||
<string name="revanced_miniplayer_disable_rounded_corners_summary_on">Künclər kvadratdır</string>
|
||||
<string name="revanced_miniplayer_disable_rounded_corners_summary_off">Künclər dairəvidir</string>
|
||||
<string name="revanced_miniplayer_double_tap_action_title">Ölçüsünü dəyişmək üçün cüt toxunmanı və çimdikləməni aktiv et</string>
|
||||
<string name="revanced_miniplayer_double_tap_action_summary_on">"Ölçüsün dəyişmək üçün cüt kliklə və çimdiklə
|
||||
|
||||
• Kiçik oynadıcı ölçüsün artırmaq üçün cüt toxun
|
||||
• Orijinal ölçünü bərpa etmək üçün təkrar cüt toxun"</string>
|
||||
<string name="revanced_miniplayer_double_tap_action_summary_off">Ölçüsünü dəyişdirmək üçün cüt toxunma fəaliyyəti və çimdikləmə yoxdur</string>
|
||||
<string name="revanced_miniplayer_drag_and_drop_title">\"Sürüklə və burax\"ı aktivləşdir</string>
|
||||
<string name="revanced_miniplayer_drag_and_drop_summary_on">"Sürüklə və burax aktivdir
|
||||
<string name="revanced_miniplayer_disable_drag_and_drop_title">Sürüklə və burax-ı qapat</string>
|
||||
<string name="revanced_miniplayer_disable_drag_and_drop_summary_on">\"Sürüklə və burax\" aktiv deyil</string>
|
||||
<string name="revanced_miniplayer_disable_drag_and_drop_summary_off">"Sürüklə və burax aktivdir
|
||||
|
||||
Kiçik oynadıcı ekranın istənilən küncünə sürüklənə bilər"</string>
|
||||
<string name="revanced_miniplayer_drag_and_drop_summary_off">\"Sürüklə və burax\" aktiv deyil</string>
|
||||
<string name="revanced_miniplayer_horizontal_drag_title">Üfüqi sürükləmə jestini aktivləşdir</string>
|
||||
<string name="revanced_miniplayer_horizontal_drag_summary_on">"Üfüqi sürükləmə jesti aktivdir
|
||||
<string name="revanced_miniplayer_disable_horizontal_drag_title">Üfüqi sürükləmə jestini qapat</string>
|
||||
<string name="revanced_miniplayer_disable_horizontal_drag_summary_on">Üfüqi sürükləmə jesti qapatıldı</string>
|
||||
<string name="revanced_miniplayer_disable_horizontal_drag_summary_off">"Üfüqi sürükləmə jesti aktivdir
|
||||
|
||||
Kiçik oynadıcı ekrandan sola və ya sağa sürüklənə bilər"</string>
|
||||
<string name="revanced_miniplayer_horizontal_drag_summary_off">Üfüqi sürükləmə jesti qapatıldı</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_title">Örtük düymələrini gizlət</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_summary_on">Örtük düymələri gizlidir</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_summary_off">Örtük düymələri görünür</string>
|
||||
@@ -1442,11 +1468,6 @@ DeArrow haqqında ətraflı öyrənmək üçün bura toxun"</string>
|
||||
<string name="revanced_announcements_connection_failed">Elan provayderinə bağlanmaq olmadı</string>
|
||||
<string name="revanced_announcements_dialog_dismiss">Ləğv et</string>
|
||||
</patch>
|
||||
<patch id="misc.dns.checkWatchHistoryDomainNameResolutionPatch">
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_title">Xәbәrdarlıq</string>
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_message">Baxış tarixçəniz saxlanmır.<br><br>Bu çox güman ki, DNS reklam bloklayıcı və ya şəbəkə proksisinə görədir.<br><br>.Bunu düzəltmək üçün s.youtube.com-u</b> <b>ağ siyahıya salın və ya bütün DNS bloklayıcıları və proksiləri bağlayın.</string>
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_ignore">Təkrar göstərmə</string>
|
||||
</patch>
|
||||
<patch id="misc.loopvideo.loopVideoPatch">
|
||||
<string name="revanced_loop_video_title">Video təkrarlamanı aktivləşdir</string>
|
||||
<string name="revanced_loop_video_summary_on">Video təkrarlanacaq</string>
|
||||
@@ -1498,13 +1519,6 @@ Bunu aktivləşdirmə daha yüksək video keyfiyyətləri əngəlin silə bilər
|
||||
<string name="revanced_external_browser_summary_on">Xarici brauzerdə bağlantıların açılması</string>
|
||||
<string name="revanced_external_browser_summary_off">Tətbiqdaxili brauzerdə bağlantıların açılması</string>
|
||||
</patch>
|
||||
<patch id="video.audio.forceOriginalAudioPatch">
|
||||
<string name="revanced_force_original_audio_title">Orijinal səs dilini zorla</string>
|
||||
<string name="revanced_force_original_audio_summary_on">Orijinal səs dilini istifadə</string>
|
||||
<string name="revanced_force_original_audio_summary_off">İlkin səs istifadəsi</string>
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
<string name="revanced_force_original_audio_not_available">Bu funksiyanı istifadə etmək üçün \"Video yayımları saxtalaşdırı\" Android Studio savayı istənilən qəbulediciyə dəyiş</string>
|
||||
</patch>
|
||||
<patch id="video.quality.rememberVideoQualityPatch">
|
||||
<!-- Translations should use the same text as 'revanced_custom_playback_speeds_auto'. -->
|
||||
<string name="revanced_video_quality_default_entry_1">Avtomatik</string>
|
||||
@@ -1561,10 +1575,22 @@ Bunu aktivləşdirmə daha yüksək video keyfiyyətləri əngəlin silə bilər
|
||||
<string name="revanced_playback_speed_default_title">İlkin oynatma sürəti</string>
|
||||
<string name="revanced_remember_playback_speed_toast">İlkin sürət %s kimi dəyişdirildi</string>
|
||||
</patch>
|
||||
<patch id="video.hdr.disableHdrPatch">
|
||||
<patch id="video.codecs.disableVideoCodecsPatch">
|
||||
<string name="revanced_disable_hdr_video_title">HDR Videonu Qapat</string>
|
||||
<string name="revanced_disable_hdr_video_summary_on">HDR video qapalıdır</string>
|
||||
<string name="revanced_disable_hdr_video_summary_off">HDR video aktivdir</string>
|
||||
<string name="revanced_force_avc_codec_title">AVC (H.264) -i Məcbur et</string>
|
||||
<string name="revanced_force_avc_codec_summary_on">Video kodlayıcı AVC (H.264) - ə məcbur edilir</string>
|
||||
<string name="revanced_force_avc_codec_summary_off">Video kodlayıcı birbaşa müəyyən edilir</string>
|
||||
<string name="revanced_force_avc_codec_user_dialog_message">"Faydalar:
|
||||
• Batareya ömrünü uzada bilər
|
||||
• Köhnə cihazlarda çatışmayan video ayırdetmələrin bərpa edə bilər
|
||||
|
||||
Məhdudiyyətlər:
|
||||
• Maksimum ayırdetmə 1080p-dir
|
||||
• Video oynatma VP9 və ya AV1-dən daha çox internet məlumatı işlədəcək
|
||||
• HDR videoları AVC istifadə etməyəcək
|
||||
• Bəzi cihazlar AVC-ni zorlaya bilməz"</string>
|
||||
</patch>
|
||||
<patch id="video.quality.advancedVideoQualityMenuPatch">
|
||||
<string name="revanced_advanced_video_quality_menu_title">Qabaqcıl video keyfiyyət siyahısın göstər</string>
|
||||
|
||||
@@ -31,6 +31,11 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time_days">Адкарэктавана %s дзён таму</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time_invalid">Дата стварэння APK пашкоджана</string>
|
||||
</patch>
|
||||
<patch id="misc.dns.checkWatchHistoryDomainNameResolutionPatch">
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_title">Увага</string>
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_message">Ваша гісторыя прагляду не захоўваецца.<br><br>Гэта, хутчэй за ўсё, выклікана DNS-блакіроўшчыкам рэкламы або сеткавым праксі.<br><br>Каб выправіць гэта, дадайце <b>s.youtube.com</b> у белы спіс або адключыце ўсе DNS-блакіроўшчыкі і праксі.</string>
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_ignore">Больш не паказваць</string>
|
||||
</patch>
|
||||
<patch id="misc.settings.settingsResourcePatch">
|
||||
<string name="revanced_settings_submenu_title">Налады</string>
|
||||
<string name="revanced_settings_confirm_user_dialog_title">Вы ўпэўнены, што хочаце працягнуць?</string>
|
||||
@@ -115,6 +120,13 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">Адключэнне гэтай налады можа выклікаць праблемы з прайграваннем.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">Клиент по умолчанию</string>
|
||||
</patch>
|
||||
<patch id="misc.audio.forceOriginalAudioPatch">
|
||||
<string name="revanced_force_original_audio_title">Вымушаная арыгінальная мова аўдыё</string>
|
||||
<string name="revanced_force_original_audio_summary_on">Выкарыстоўваць арыгінальную мову аўдыя</string>
|
||||
<string name="revanced_force_original_audio_summary_off">Выкарыстанне аўдыё па змаўчанні</string>
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
<string name="revanced_force_original_audio_not_available">Каб выкарыстаць гэтую функцыю, змяніце \'Падмена відэаструменяў\' на любога кліента, акрамя Android Studio</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">Адладка</string>
|
||||
<string name="revanced_debug_screen_summary">Уключыць або выключыць параметры адладкі</string>
|
||||
@@ -141,9 +153,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Лагі ачышчаны</string>
|
||||
</patch>
|
||||
<patch id="misc.privacy.sanitizeSharingLinksPatch">
|
||||
<string name="revanced_sanitize_sharing_links_title">Выдаліць параметр запыту адсочвання</string>
|
||||
<string name="revanced_sanitize_sharing_links_summary_on">Параметр запыту адсочвання выдалены са спасылак</string>
|
||||
<string name="revanced_sanitize_sharing_links_summary_off">Параметр адсочвання запыту не выдаляецца са спасылак</string>
|
||||
<string name="revanced_sanitize_sharing_links_title">Ачысціць спасылкі для абагульвання</string>
|
||||
<string name="revanced_sanitize_sharing_links_summary_on">Параметр запыту адсочвання выдалены з абагуленых спасылак</string>
|
||||
<string name="revanced_sanitize_sharing_links_summary_off">Параметр запыту адсочвання не выдалены з абагуленых спасылак</string>
|
||||
<string name="revanced_replace_music_with_youtube_title">Змяніць спасылкі для абагульвання на youtube.com</string>
|
||||
<string name="revanced_replace_music_with_youtube_summary_on">Агульныя спасылкі выкарыстоўваюць youtube.com</string>
|
||||
<string name="revanced_replace_music_with_youtube_summary_off">Агульныя спасылкі выкарыстоўваюць music.youtube.com</string>
|
||||
@@ -374,15 +386,15 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_comments_create_a_short_button_title">Схаваць кнопку \"Створиць Short\"</string>
|
||||
<string name="revanced_hide_comments_create_a_short_button_summary_on">Кнопка «Стварыць Shorts» схаваная</string>
|
||||
<string name="revanced_hide_comments_create_a_short_button_summary_off">Кнопка «Стварыць Shorts» паказаная</string>
|
||||
<string name="revanced_hide_comments_emoji_and_timestamp_buttons_title">Схаваць кнопкі эмодзі і пазнак часу</string>
|
||||
<string name="revanced_hide_comments_emoji_and_timestamp_buttons_summary_on">Кнопкі эмодзі і пазнак часу схаваны</string>
|
||||
<string name="revanced_hide_comments_emoji_and_timestamp_buttons_summary_off">Кнопкі эмодзі і пазнак часу паказаны</string>
|
||||
<string name="revanced_hide_comments_preview_comment_title">Схаваць каментарый для папярэдняга прагляду</string>
|
||||
<string name="revanced_hide_comments_preview_comment_summary_on">Каментарый перад праглядам схаваны</string>
|
||||
<string name="revanced_hide_comments_preview_comment_summary_off">Паказваецца папярэдні прагляд каментарыя</string>
|
||||
<string name="revanced_hide_comments_thanks_button_title">Схаваць кнопку \"Дзякуй\"\"</string>
|
||||
<string name="revanced_hide_comments_thanks_button_summary_on">Кнопка падзякі схавана</string>
|
||||
<string name="revanced_hide_comments_thanks_button_summary_off">Паказана кнопка падзякі</string>
|
||||
<string name="revanced_hide_comments_timestamp_button_title">Схаваць кнопку \"Пазнака часу\"</string>
|
||||
<string name="revanced_hide_comments_timestamp_button_summary_on">Кнопка часу схаваная</string>
|
||||
<string name="revanced_hide_comments_timestamp_button_summary_off">Кнопка часу паказаная</string>
|
||||
<string name="revanced_custom_filter_screen_title">Карыстальніцкі фільтр</string>
|
||||
<string name="revanced_custom_filter_screen_summary">Схавайце кампаненты з дапамогай карыстацкіх фільтраў</string>
|
||||
<string name="revanced_custom_filter_title">Уключыць карыстальніцкі фільтр</string>
|
||||
@@ -392,6 +404,20 @@ Second \"item\" text"</string>
|
||||
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
|
||||
<string name="revanced_custom_filter_strings_summary">Спіс радкоў канструктара шляхоў кампанентаў для фільтрацыі, раздзеленых новым радком</string>
|
||||
<string name="revanced_custom_filter_toast_invalid_syntax">Няправільны карыстацкі фільтр: %s</string>
|
||||
<string name="revanced_hide_view_count_title">Схаваць колькасць праглядаў</string>
|
||||
<string name="revanced_hide_view_count_summary_on">Колькасць праглядаў схавана ў стужцы і выніках пошуку</string>
|
||||
<string name="revanced_hide_view_count_summary_off">Колькасць праглядаў паказана ў стужцы і выніках пошуку</string>
|
||||
<!-- Translations should lanaguge similar to revanced_hide_upload_time_user_dialog_message -->
|
||||
<string name="revanced_hide_view_count_user_dialog_message">"Абмежаванні:
|
||||
• На паліцах Shorts, старонках каналаў і ў выніках пошуку ўсё яшчэ можа адлюстроўвацца колькасць праглядаў
|
||||
• Гэта функцыя не працуе з аўтамабільным форм-фактарам"</string>
|
||||
<string name="revanced_hide_upload_time_title">Схаваць час загрузкі</string>
|
||||
<string name="revanced_hide_upload_time_summary_on">Час загрузкі схаваны ў стужцы і выніках пошуку</string>
|
||||
<string name="revanced_hide_upload_time_summary_off">Час загрузкі паказаны ў стужцы і выніках пошуку</string>
|
||||
<!-- Translations should lanaguge similar to revanced_hide_view_count_user_dialog_message -->
|
||||
<string name="revanced_hide_upload_time_user_dialog_message">"Абмежаванні:
|
||||
• На паліцах Shorts, старонках каналаў і ў выніках пошуку ўсё яшчэ можа адлюстроўвацца час загрузкі
|
||||
• Гэтая функцыя не працуе з аўтамабільным форм-фактарам"</string>
|
||||
<string name="revanced_hide_keyword_content_screen_title">Схаваць змест ключавых слоў</string>
|
||||
<string name="revanced_hide_keyword_content_screen_summary">Схавайце відэа для пошуку і стужкі з дапамогай фільтраў па ключавых словах</string>
|
||||
<string name="revanced_hide_keyword_content_home_title">Схаваць хатняе відэа па ключавых словах</string>
|
||||
@@ -778,7 +804,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_player_previous_next_buttons_summary_on">Кнопкі схаваныя</string>
|
||||
<string name="revanced_hide_player_previous_next_buttons_summary_off">Паказваюцца кнопкі</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.endscreencards.hideEndscreenCardsResourcePatch">
|
||||
<patch id="layout.hide.endscreencards.hideEndScreenCardsResourcePatch">
|
||||
<string name="revanced_hide_endscreen_cards_title">Схаваць карткі канцавога экрана</string>
|
||||
<string name="revanced_hide_endscreen_cards_summary_on">Карткі канцавога экрана схаваны</string>
|
||||
<string name="revanced_hide_endscreen_cards_summary_off">Паказваюцца карткі канцавога экрана</string>
|
||||
@@ -1334,25 +1360,25 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_miniplayer_type_entry_5">Сучасны 2</string>
|
||||
<string name="revanced_miniplayer_type_entry_6">Сучасны 3</string>
|
||||
<string name="revanced_miniplayer_type_entry_7">Сучасны 4</string>
|
||||
<string name="revanced_miniplayer_rounded_corners_title">Включить закругленные углы</string>
|
||||
<string name="revanced_miniplayer_rounded_corners_summary_on">Углы закруглены</string>
|
||||
<string name="revanced_miniplayer_rounded_corners_summary_off">Углы квадратные</string>
|
||||
<string name="revanced_miniplayer_disable_rounded_corners_title">Адключыць закругленыя вуглы</string>
|
||||
<string name="revanced_miniplayer_disable_rounded_corners_summary_on">Углы квадратные</string>
|
||||
<string name="revanced_miniplayer_disable_rounded_corners_summary_off">Углы закруглены</string>
|
||||
<string name="revanced_miniplayer_double_tap_action_title">Включить двойное нажатие и масштабирование с помощьющипка</string>
|
||||
<string name="revanced_miniplayer_double_tap_action_summary_on">"Уключана дзеянне «подвойнае націсканне» і «шчыпкі для змены памеру»
|
||||
|
||||
• Подвойнае націсканне, каб павялічыць памер міні-прайгравальніка
|
||||
• Подвойнае націсканне яшчэ раз, каб аднавіць першапачатковы памер"</string>
|
||||
<string name="revanced_miniplayer_double_tap_action_summary_off">Двойное нажатие и scalewithpinch отключены</string>
|
||||
<string name="revanced_miniplayer_drag_and_drop_title">Включить перетаскивание</string>
|
||||
<string name="revanced_miniplayer_drag_and_drop_summary_on">"Уключана перацягванне і кіданне
|
||||
<string name="revanced_miniplayer_disable_drag_and_drop_title">Адключыць перацягванне</string>
|
||||
<string name="revanced_miniplayer_disable_drag_and_drop_summary_on">Перетаскивание отключено</string>
|
||||
<string name="revanced_miniplayer_disable_drag_and_drop_summary_off">"Уключана перацягванне і кіданне
|
||||
|
||||
Міні-прайгравальнік можна перацягнуць у любы куток экрана"</string>
|
||||
<string name="revanced_miniplayer_drag_and_drop_summary_off">Перетаскивание отключено</string>
|
||||
<string name="revanced_miniplayer_horizontal_drag_title">Включить горизонтальный жест перетаскивания</string>
|
||||
<string name="revanced_miniplayer_horizontal_drag_summary_on">"Уключаны жэст гарызантальнага перацягвання
|
||||
<string name="revanced_miniplayer_disable_horizontal_drag_title">Адключыць гарызантальны жэст перацягвання</string>
|
||||
<string name="revanced_miniplayer_disable_horizontal_drag_summary_on">Горизонтальный жест перетаскивания отключен</string>
|
||||
<string name="revanced_miniplayer_disable_horizontal_drag_summary_off">"Уключаны жэст гарызантальнага перацягвання
|
||||
|
||||
Міні-прайгравальнік можна перацягнуць за межы экрана ўлева ці ўправа"</string>
|
||||
<string name="revanced_miniplayer_horizontal_drag_summary_off">Горизонтальный жест перетаскивания отключен</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_title">Схаваць кнопкі накладання</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_summary_on">Кнопкі накладання схаваныя</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_summary_off">Кнопкі накладання паказаны</string>
|
||||
@@ -1444,11 +1470,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_announcements_connection_failed">Не ўдалося падключыцца да пастаўшчыка аб\"яў</string>
|
||||
<string name="revanced_announcements_dialog_dismiss">расслабіцца</string>
|
||||
</patch>
|
||||
<patch id="misc.dns.checkWatchHistoryDomainNameResolutionPatch">
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_title">Увага</string>
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_message">Ваша гісторыя прагляду не захоўваецца.<br><br>Гэта, хутчэй за ўсё, выклікана DNS-блакіроўшчыкам рэкламы або сеткавым праксі.<br><br>Каб выправіць гэта, дадайце <b>s.youtube.com</b> у белы спіс або адключыце ўсе DNS-блакіроўшчыкі і праксі.</string>
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_ignore">Больш не паказваць</string>
|
||||
</patch>
|
||||
<patch id="misc.loopvideo.loopVideoPatch">
|
||||
<string name="revanced_loop_video_title">Уключыць зацыкленае відэа</string>
|
||||
<string name="revanced_loop_video_summary_on">Відэа будзе зацыклена</string>
|
||||
@@ -1500,13 +1521,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_external_browser_summary_on">Адкрыццё спасылак у знешнім браўзеры</string>
|
||||
<string name="revanced_external_browser_summary_off">Адкрыццё спасылак ва ўбудаваным браўзеры</string>
|
||||
</patch>
|
||||
<patch id="video.audio.forceOriginalAudioPatch">
|
||||
<string name="revanced_force_original_audio_title">Вымушаная арыгінальная мова аўдыё</string>
|
||||
<string name="revanced_force_original_audio_summary_on">Выкарыстоўваць арыгінальную мову аўдыя</string>
|
||||
<string name="revanced_force_original_audio_summary_off">Выкарыстанне аўдыё па змаўчанні</string>
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
<string name="revanced_force_original_audio_not_available">Каб выкарыстаць гэтую функцыю, змяніце \'Падмена відэаструменяў\' на любога кліента, акрамя Android Studio</string>
|
||||
</patch>
|
||||
<patch id="video.quality.rememberVideoQualityPatch">
|
||||
<!-- Translations should use the same text as 'revanced_custom_playback_speeds_auto'. -->
|
||||
<string name="revanced_video_quality_default_entry_1">Аўто</string>
|
||||
@@ -1563,10 +1577,22 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_playback_speed_default_title">Стандартная хуткасць прайгравання</string>
|
||||
<string name="revanced_remember_playback_speed_toast">Хуткасць па змаўчанні зменена на: %s</string>
|
||||
</patch>
|
||||
<patch id="video.hdr.disableHdrPatch">
|
||||
<patch id="video.codecs.disableVideoCodecsPatch">
|
||||
<string name="revanced_disable_hdr_video_title">Адключыць відэа ў фармаце HDR</string>
|
||||
<string name="revanced_disable_hdr_video_summary_on">Відэа ў фармаце HDR адключана</string>
|
||||
<string name="revanced_disable_hdr_video_summary_off">Відэа ў фармаце HDR уключана</string>
|
||||
<string name="revanced_force_avc_codec_title">Прымусіць AVC (H.264)</string>
|
||||
<string name="revanced_force_avc_codec_summary_on">Відэакодэк прымусова ўсталяваны на AVC (H.264)</string>
|
||||
<string name="revanced_force_avc_codec_summary_off">Відэакодэк вызначаецца аўтаматычна</string>
|
||||
<string name="revanced_force_avc_codec_user_dialog_message">"Перавагі:
|
||||
• Можа палепшыць час працы батарэі
|
||||
• Можа аднавіць адсутныя разрозненні відэа на старой прыладзе
|
||||
|
||||
Абмежаванні:
|
||||
• Максімальнае разрозненне - 1080p
|
||||
• Прайграванне відэа будзе выкарыстоўваць больш інтэрнэт-дадзеных, чым VP9 або AV1
|
||||
• HDR-відэа не будуць выкарыстоўваць AVC
|
||||
• Некаторыя прылады не могуць прымусова выкарыстоўваць AVC"</string>
|
||||
</patch>
|
||||
<patch id="video.quality.advancedVideoQualityMenuPatch">
|
||||
<string name="revanced_advanced_video_quality_menu_title">Паказаць пашыранае меню якасці відэа</string>
|
||||
|
||||
@@ -31,6 +31,11 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time_days">Коригирано преди %s дни</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time_invalid">Датата на компилация на APK е повредена</string>
|
||||
</patch>
|
||||
<patch id="misc.dns.checkWatchHistoryDomainNameResolutionPatch">
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_title">Предупреждение</string>
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_message">Историята ви на гледане не се запазва.<br><br>Това най-вероятно е причинено от DNS блокиращ реклами или мрежов прокси.<br><br>За да коригирате това, поставете <b>s.youtube в белия списък.com</b> или изключете всички DNS блокери и проксита.</string>
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_ignore">Не показвай отново</string>
|
||||
</patch>
|
||||
<patch id="misc.settings.settingsResourcePatch">
|
||||
<string name="revanced_settings_submenu_title">Настройки</string>
|
||||
<string name="revanced_settings_confirm_user_dialog_title">Сигурни ли сте, че искате да продължите?</string>
|
||||
@@ -115,6 +120,13 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">Изключването на тази настройка може да причини проблеми с възпроизвеждането.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">Клиент по подразбиране</string>
|
||||
</patch>
|
||||
<patch id="misc.audio.forceOriginalAudioPatch">
|
||||
<string name="revanced_force_original_audio_title">Принудително оригинално аудио език</string>
|
||||
<string name="revanced_force_original_audio_summary_on">Използване на оригиналния език на аудиото</string>
|
||||
<string name="revanced_force_original_audio_summary_off">Използване на аудио по подразбиране</string>
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
<string name="revanced_force_original_audio_not_available">За да използвате тази функция, променете \'Фалшифициране на видео потоци\' на всеки клиент, освен Android Studio</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">Отстраняване на грешки</string>
|
||||
<string name="revanced_debug_screen_summary">Активиране или деактивиране на отстраняването на грешки</string>
|
||||
@@ -141,9 +153,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Логовете са изчистени</string>
|
||||
</patch>
|
||||
<patch id="misc.privacy.sanitizeSharingLinksPatch">
|
||||
<string name="revanced_sanitize_sharing_links_title">Премахнете параметъра на заявката за проследяване</string>
|
||||
<string name="revanced_sanitize_sharing_links_summary_on">Параметърът на заявката за проследяване е премахнат от връзките</string>
|
||||
<string name="revanced_sanitize_sharing_links_summary_off">Параметърът на заявката за проследяване не е премахнат от връзките</string>
|
||||
<string name="revanced_sanitize_sharing_links_title">Почистване на връзки за споделяне</string>
|
||||
<string name="revanced_sanitize_sharing_links_summary_on">Параметърът за проследяване се премахва от споделените връзки</string>
|
||||
<string name="revanced_sanitize_sharing_links_summary_off">Параметърът за проследяване не се премахва от споделените връзки</string>
|
||||
<string name="revanced_replace_music_with_youtube_title">Промяна на връзките за споделяне към youtube.com</string>
|
||||
<string name="revanced_replace_music_with_youtube_summary_on">Споделените връзки използват youtube.com</string>
|
||||
<string name="revanced_replace_music_with_youtube_summary_off">Споделените връзки използват music.youtube.com</string>
|
||||
@@ -374,15 +386,15 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_comments_create_a_short_button_title">Бутон за създаване на Shorts</string>
|
||||
<string name="revanced_hide_comments_create_a_short_button_summary_on">Бутонът \"Създаване на Short\" е скрит</string>
|
||||
<string name="revanced_hide_comments_create_a_short_button_summary_off">Бутонът \"Създаване на Short\" е показан</string>
|
||||
<string name="revanced_hide_comments_emoji_and_timestamp_buttons_title">Скриване на бутоните за емоджи и клеймо за време</string>
|
||||
<string name="revanced_hide_comments_emoji_and_timestamp_buttons_summary_on">Бутоните за емоджи и клеймо за време са скрити</string>
|
||||
<string name="revanced_hide_comments_emoji_and_timestamp_buttons_summary_off">Бутоните за емоджи и клеймо за време са показани</string>
|
||||
<string name="revanced_hide_comments_preview_comment_title">Преглед на коментари</string>
|
||||
<string name="revanced_hide_comments_preview_comment_summary_on">Прегледа на коментари е скрит</string>
|
||||
<string name="revanced_hide_comments_preview_comment_summary_off">Прегледа на коментари се показва</string>
|
||||
<string name="revanced_hide_comments_thanks_button_title">Скрий бутона за харесване</string>
|
||||
<string name="revanced_hide_comments_thanks_button_summary_on">Бутона за благодарност е скрит</string>
|
||||
<string name="revanced_hide_comments_thanks_button_summary_off">Бутона за благодарност се показва</string>
|
||||
<string name="revanced_hide_comments_timestamp_button_title">Скриване на бутона за клеймо за време</string>
|
||||
<string name="revanced_hide_comments_timestamp_button_summary_on">Бутонът за времеви печат е скрит</string>
|
||||
<string name="revanced_hide_comments_timestamp_button_summary_off">Бутонът за времеви печат е показан</string>
|
||||
<string name="revanced_custom_filter_screen_title">Потребителски филтър</string>
|
||||
<string name="revanced_custom_filter_screen_summary">Скриване на компоненти с помощта на потребителски филтри</string>
|
||||
<string name="revanced_custom_filter_title">Активиране на потребителските филтри</string>
|
||||
@@ -392,6 +404,20 @@ Second \"item\" text"</string>
|
||||
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
|
||||
<string name="revanced_custom_filter_strings_summary">Списък с низове за изграждане на пътя на компонента, които да се филтрират, разделени с нов ред</string>
|
||||
<string name="revanced_custom_filter_toast_invalid_syntax">Невалиден потребителски филтър: %s</string>
|
||||
<string name="revanced_hide_view_count_title">Скриване на броя на преглежданията</string>
|
||||
<string name="revanced_hide_view_count_summary_on">Броят на преглежданията е скрит във фийда и резултатите от търсенето</string>
|
||||
<string name="revanced_hide_view_count_summary_off">Броят на преглежданията е показан във фийда и резултатите от търсенето</string>
|
||||
<!-- Translations should lanaguge similar to revanced_hide_upload_time_user_dialog_message -->
|
||||
<string name="revanced_hide_view_count_user_dialog_message">"Ограничения:
|
||||
• Рафтовете с Shorts, страниците на каналите и резултатите от търсенето може все още да показват броя на преглежданията
|
||||
• Тази функция не работи с автомобилен форм фактор"</string>
|
||||
<string name="revanced_hide_upload_time_title">Скриване на часа на качване</string>
|
||||
<string name="revanced_hide_upload_time_summary_on">Часът на качване е скрит в емисията и резултатите от търсенето</string>
|
||||
<string name="revanced_hide_upload_time_summary_off">Часът на качване е показан в емисията и резултатите от търсенето</string>
|
||||
<!-- Translations should lanaguge similar to revanced_hide_view_count_user_dialog_message -->
|
||||
<string name="revanced_hide_upload_time_user_dialog_message">"Ограничения:
|
||||
• Рафтовете с Shorts, страниците на канали и резултатите от търсене може все още да показват часове на качване
|
||||
• Тази функция не работи с автомобилни форм-фактори"</string>
|
||||
<string name="revanced_hide_keyword_content_screen_title">Скриване на съдържанието с ключови думи</string>
|
||||
<string name="revanced_hide_keyword_content_screen_summary">Скриване на видеоклипове в резултатите от търсенуя и в новинарския поток с помощта на филтри с ключови думи</string>
|
||||
<string name="revanced_hide_keyword_content_home_title">Скриване на видеоклипове в началната страница с ключови думи</string>
|
||||
@@ -778,7 +804,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_player_previous_next_buttons_summary_on">Бутоните са скрити</string>
|
||||
<string name="revanced_hide_player_previous_next_buttons_summary_off">Бутоните се показват</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.endscreencards.hideEndscreenCardsResourcePatch">
|
||||
<patch id="layout.hide.endscreencards.hideEndScreenCardsResourcePatch">
|
||||
<string name="revanced_hide_endscreen_cards_title">Скриване на препоръките в края</string>
|
||||
<string name="revanced_hide_endscreen_cards_summary_on">Препоръките в края са скрити</string>
|
||||
<string name="revanced_hide_endscreen_cards_summary_off">Препоръките в края се показват</string>
|
||||
@@ -1333,25 +1359,25 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_miniplayer_type_entry_5">Модерен 2</string>
|
||||
<string name="revanced_miniplayer_type_entry_6">Модерен 3</string>
|
||||
<string name="revanced_miniplayer_type_entry_7">Модерен 4</string>
|
||||
<string name="revanced_miniplayer_rounded_corners_title">Активирайте заоблени ъгли</string>
|
||||
<string name="revanced_miniplayer_rounded_corners_summary_on">Ъглите са заоблени</string>
|
||||
<string name="revanced_miniplayer_rounded_corners_summary_off">Ъглите са нормални</string>
|
||||
<string name="revanced_miniplayer_disable_rounded_corners_title">Деактивиране на заоблени ъгли</string>
|
||||
<string name="revanced_miniplayer_disable_rounded_corners_summary_on">Ъглите са нормални</string>
|
||||
<string name="revanced_miniplayer_disable_rounded_corners_summary_off">Ъглите са заоблени</string>
|
||||
<string name="revanced_miniplayer_double_tap_action_title">Активирайте двойното докосване и щипване за преоразмеряване</string>
|
||||
<string name="revanced_miniplayer_double_tap_action_summary_on">"Активирано е двойно докосване и щипка за преоразмеряване
|
||||
|
||||
• Двойно докосване за увеличаване на размера на мини плейъра
|
||||
• Двойно докосване отново, за да възстановите оригиналния размер"</string>
|
||||
<string name="revanced_miniplayer_double_tap_action_summary_off">Двойно докосване и щипване за преоразмеряване е деактивирано</string>
|
||||
<string name="revanced_miniplayer_drag_and_drop_title">Разрешете плъзгане и местене</string>
|
||||
<string name="revanced_miniplayer_drag_and_drop_summary_on">"Включено е плъзгане и пускане
|
||||
<string name="revanced_miniplayer_disable_drag_and_drop_title">Деактивиране на плъзгане и пускане</string>
|
||||
<string name="revanced_miniplayer_disable_drag_and_drop_summary_on">Плъзгането и преместването е деактивирано</string>
|
||||
<string name="revanced_miniplayer_disable_drag_and_drop_summary_off">"Включено е плъзгане и пускане
|
||||
|
||||
Мини плейърът може да бъде плъзган до всеки ъгъл на екрана"</string>
|
||||
<string name="revanced_miniplayer_drag_and_drop_summary_off">Плъзгането и преместването е деактивирано</string>
|
||||
<string name="revanced_miniplayer_horizontal_drag_title">Активиране на хоризонтално плъзгане</string>
|
||||
<string name="revanced_miniplayer_horizontal_drag_summary_on">"Активиран е хоризонтален жест за плъзгане
|
||||
<string name="revanced_miniplayer_disable_horizontal_drag_title">Деактивиране на хоризонтален жест за плъзгане</string>
|
||||
<string name="revanced_miniplayer_disable_horizontal_drag_summary_on">Жестът за хоризонтално плъзгане е деактивиран</string>
|
||||
<string name="revanced_miniplayer_disable_horizontal_drag_summary_off">"Активиран е хоризонтален жест за плъзгане
|
||||
|
||||
Мини плейърът може да бъде плъзган извън екрана наляво или надясно"</string>
|
||||
<string name="revanced_miniplayer_horizontal_drag_summary_off">Жестът за хоризонтално плъзгане е деактивиран</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_title">Скриване на бутоните за наслагване</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_summary_on">Бутоните за наслагване са скрити</string>
|
||||
<string name="revanced_miniplayer_hide_overlay_buttons_summary_off">Бутоните за наслагване са показани</string>
|
||||
@@ -1443,11 +1469,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_announcements_connection_failed">Неуспешно свързване с доставчик на съобщения</string>
|
||||
<string name="revanced_announcements_dialog_dismiss">Отхвърли</string>
|
||||
</patch>
|
||||
<patch id="misc.dns.checkWatchHistoryDomainNameResolutionPatch">
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_title">Предупреждение</string>
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_message">Историята ви на гледане не се запазва.<br><br>Това най-вероятно е причинено от DNS блокиращ реклами или мрежов прокси.<br><br>За да коригирате това, поставете <b>s.youtube в белия списък.com</b> или изключете всички DNS блокери и проксита.</string>
|
||||
<string name="revanced_check_watch_history_domain_name_dialog_ignore">Не показвай отново</string>
|
||||
</patch>
|
||||
<patch id="misc.loopvideo.loopVideoPatch">
|
||||
<string name="revanced_loop_video_title">Активиране на повторение на видеото</string>
|
||||
<string name="revanced_loop_video_summary_on">Видеоклипът ще се повтаря</string>
|
||||
@@ -1499,13 +1520,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_external_browser_summary_on">Отваряне на връзки във външен браузър</string>
|
||||
<string name="revanced_external_browser_summary_off">Отваряне на връзки във вграден браузър</string>
|
||||
</patch>
|
||||
<patch id="video.audio.forceOriginalAudioPatch">
|
||||
<string name="revanced_force_original_audio_title">Принудително оригинално аудио език</string>
|
||||
<string name="revanced_force_original_audio_summary_on">Използване на оригиналния език на аудиото</string>
|
||||
<string name="revanced_force_original_audio_summary_off">Използване на аудио по подразбиране</string>
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
<string name="revanced_force_original_audio_not_available">За да използвате тази функция, променете \'Фалшифициране на видео потоци\' на всеки клиент, освен Android Studio</string>
|
||||
</patch>
|
||||
<patch id="video.quality.rememberVideoQualityPatch">
|
||||
<!-- Translations should use the same text as 'revanced_custom_playback_speeds_auto'. -->
|
||||
<string name="revanced_video_quality_default_entry_1">Авто</string>
|
||||
@@ -1562,10 +1576,22 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_playback_speed_default_title">Скорост на възпроизвеждане по подразбиране</string>
|
||||
<string name="revanced_remember_playback_speed_toast">Скоростта по подразбиране е променена на: %s</string>
|
||||
</patch>
|
||||
<patch id="video.hdr.disableHdrPatch">
|
||||
<patch id="video.codecs.disableVideoCodecsPatch">
|
||||
<string name="revanced_disable_hdr_video_title">Деактивиране на HDR видео</string>
|
||||
<string name="revanced_disable_hdr_video_summary_on">HDR видеото е деактивирано</string>
|
||||
<string name="revanced_disable_hdr_video_summary_off">HDR видеото е активирано</string>
|
||||
<string name="revanced_force_avc_codec_title">Принуди AVC (H.264)</string>
|
||||
<string name="revanced_force_avc_codec_summary_on">Видео кодекът е принуден да бъде AVC (H.264)</string>
|
||||
<string name="revanced_force_avc_codec_summary_off">Видео кодекът се определя автоматично</string>
|
||||
<string name="revanced_force_avc_codec_user_dialog_message">"Предимства:
|
||||
• Може да подобри живота на батерията
|
||||
• Може да възстанови липсващи видео резолюции на по-стари устройства
|
||||
|
||||
Ограничения:
|
||||
• Максималната резолюция е 1080p
|
||||
• Възпроизвеждането на видео ще използва повече интернет данни от VP9 или AV1
|
||||
• HDR видеоклиповете няма да използват AVC
|
||||
• Някои устройства не могат да принудят AVC"</string>
|
||||
</patch>
|
||||
<patch id="video.quality.advancedVideoQualityMenuPatch">
|
||||
<string name="revanced_advanced_video_quality_menu_title">Показване на менюто за разширено качество на видеото</string>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user