diff --git a/.github/workflows/build_pull_request.yml b/.github/workflows/build_pull_request.yml index b47e2e0b4..d77db8634 100644 --- a/.github/workflows/build_pull_request.yml +++ b/.github/workflows/build_pull_request.yml @@ -19,11 +19,11 @@ jobs: - name: Setup Java uses: actions/setup-java@v4 with: - distribution: "temurin" - java-version: "17" + distribution: 'temurin' + java-version: '17' - name: Cache Gradle - uses: burrunan/gradle-cache-action@v1 + uses: burrunan/gradle-cache-action@v3 - name: Build env: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3b682722f..849205933 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,24 +13,23 @@ jobs: permissions: contents: write packages: write + id-token: write + attestations: write runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: - # Make sure the release step uses its own credentials: - # https://github.com/cycjimmy/semantic-release-action#private-packages - persist-credentials: false fetch-depth: 0 - name: Setup Java uses: actions/setup-java@v4 with: - distribution: "temurin" - java-version: "17" + distribution: 'temurin' + java-version: '17' - name: Cache Gradle - uses: burrunan/gradle-cache-action@v1 + uses: burrunan/gradle-cache-action@v3 - name: Build env: @@ -40,7 +39,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: "lts/*" + node-version: 'lts/*' cache: 'npm' - name: Install dependencies @@ -54,6 +53,14 @@ jobs: fingerprint: ${{ vars.GPG_FINGERPRINT }} - name: Release + uses: cycjimmy/semantic-release-action@v4 + id: release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: npm exec semantic-release + + - name: Attest + if: steps.release.outputs.new_release_published == 'true' + uses: actions/attest-build-provenance@v2 + with: + subject-name: 'ReVanced Patches ${{ steps.release.outputs.new_release_git_tag }}' + subject-path: patches/build/libs/patches-*.rvp diff --git a/.releaserc b/.releaserc index b3d61b10b..ee495bf96 100644 --- a/.releaserc +++ b/.releaserc @@ -22,7 +22,7 @@ { "assets": [ "CHANGELOG.md", - "gradle.properties", + "gradle.properties" ], "message": "chore: Release v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" } @@ -33,16 +33,16 @@ "assets": [ { "path": "patches/build/libs/patches-!(*sources*|*javadoc*).rvp?(.asc)" - }, + } ], - successComment: false + "successComment": false } ], [ "@saithodev/semantic-release-backmerge", { - backmergeBranches: [{"from": "main", "to": "dev"}], - clearWorkspace: true + "backmergeBranches": [{"from": "main", "to": "dev"}], + "clearWorkspace": true } ] ] diff --git a/CHANGELOG.md b/CHANGELOG.md index 72c9e19f3..f17f18353 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,223 @@ +# [5.26.0](https://github.com/ReVanced/revanced-patches/compare/v5.25.0...v5.26.0) (2025-06-04) + + +### Bug Fixes + +* **Spotify - Custom theme:** Apply accent color in more places ([#5039](https://github.com/ReVanced/revanced-patches/issues/5039)) ([9357887](https://github.com/ReVanced/revanced-patches/commit/9357887b6fca7aaf34dfb0163645b6a998e1db76)) +* **YouTube - Hide Shorts components:** Disable A/B player that prevents hiding buttons ([#5104](https://github.com/ReVanced/revanced-patches/issues/5104)) ([835b7bd](https://github.com/ReVanced/revanced-patches/commit/835b7bd7bd667abd632822c98898972e5124dbb6)) +* **YouTube:** Support A/B Shorts layout for RYD and component hiding ([#5081](https://github.com/ReVanced/revanced-patches/issues/5081)) ([8ecacaa](https://github.com/ReVanced/revanced-patches/commit/8ecacaad27162d9380014a9a13ac9220b12257b2)) + + +### Features + +* **Proton Mail:** Add `Remove free accounts limit` patch ([#4970](https://github.com/ReVanced/revanced-patches/issues/4970)) ([b0440ad](https://github.com/ReVanced/revanced-patches/commit/b0440ad6af0e190e516974ce896dcc54c8d2e122)) +* **Spotify:** Add `Hide Create button` patch ([#5062](https://github.com/ReVanced/revanced-patches/issues/5062)) ([3201681](https://github.com/ReVanced/revanced-patches/commit/32016819d2adbdfdd5e028941d56feda36d20b00)) +* **Sync for Reddit:** Add `Fix post thumbnails` patch ([e1ec30c](https://github.com/ReVanced/revanced-patches/commit/e1ec30c5b07560a39d7b8ab293b0c1f39fd59ef2)) +* **YouTube - Hide Shorts components:** Add option to hide comment panel ([#5102](https://github.com/ReVanced/revanced-patches/issues/5102)) ([22b9bee](https://github.com/ReVanced/revanced-patches/commit/22b9beedd3243a8d6a5635f591b91cdcf307be37)) +* **YouTube - Playback Speed:** Use modern custom speed dialog ([#5069](https://github.com/ReVanced/revanced-patches/issues/5069)) ([9a1e6ca](https://github.com/ReVanced/revanced-patches/commit/9a1e6ca178d9833ee2c681fb130b9290a4e89cd8)) + +# [5.26.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.26.0-dev.7...v5.26.0-dev.8) (2025-06-04) + + +### Bug Fixes + +* **YouTube - Hide Shorts components:** Disable A/B player that prevents hiding buttons ([#5104](https://github.com/ReVanced/revanced-patches/issues/5104)) ([835b7bd](https://github.com/ReVanced/revanced-patches/commit/835b7bd7bd667abd632822c98898972e5124dbb6)) + +# [5.26.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.26.0-dev.6...v5.26.0-dev.7) (2025-06-04) + + +### Features + +* **YouTube - Hide Shorts components:** Add option to hide comment panel ([#5102](https://github.com/ReVanced/revanced-patches/issues/5102)) ([22b9bee](https://github.com/ReVanced/revanced-patches/commit/22b9beedd3243a8d6a5635f591b91cdcf307be37)) + +# [5.26.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.26.0-dev.5...v5.26.0-dev.6) (2025-06-03) + + +### Features + +* **Sync for Reddit:** Add `Fix post thumbnails` patch ([e1ec30c](https://github.com/ReVanced/revanced-patches/commit/e1ec30c5b07560a39d7b8ab293b0c1f39fd59ef2)) + +# [5.26.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.26.0-dev.4...v5.26.0-dev.5) (2025-06-03) + + +### Bug Fixes + +* **Spotify - Custom theme:** Apply accent color in more places ([#5039](https://github.com/ReVanced/revanced-patches/issues/5039)) ([9357887](https://github.com/ReVanced/revanced-patches/commit/9357887b6fca7aaf34dfb0163645b6a998e1db76)) + +# [5.26.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.26.0-dev.3...v5.26.0-dev.4) (2025-06-03) + + +### Features + +* **Spotify:** Add `Hide Create button` patch ([#5062](https://github.com/ReVanced/revanced-patches/issues/5062)) ([3201681](https://github.com/ReVanced/revanced-patches/commit/32016819d2adbdfdd5e028941d56feda36d20b00)) + +# [5.26.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.26.0-dev.2...v5.26.0-dev.3) (2025-06-01) + + +### Features + +* **YouTube - Playback Speed:** Use modern custom speed dialog ([#5069](https://github.com/ReVanced/revanced-patches/issues/5069)) ([9a1e6ca](https://github.com/ReVanced/revanced-patches/commit/9a1e6ca178d9833ee2c681fb130b9290a4e89cd8)) + +# [5.26.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.26.0-dev.1...v5.26.0-dev.2) (2025-06-01) + + +### Bug Fixes + +* **YouTube:** Support A/B Shorts layout for RYD and component hiding ([#5081](https://github.com/ReVanced/revanced-patches/issues/5081)) ([8ecacaa](https://github.com/ReVanced/revanced-patches/commit/8ecacaad27162d9380014a9a13ac9220b12257b2)) + +# [5.26.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.25.0...v5.26.0-dev.1) (2025-05-30) + + +### Features + +* **Proton Mail:** Add `Remove free accounts limit` patch ([#4970](https://github.com/ReVanced/revanced-patches/issues/4970)) ([b0440ad](https://github.com/ReVanced/revanced-patches/commit/b0440ad6af0e190e516974ce896dcc54c8d2e122)) + +# [5.25.0](https://github.com/ReVanced/revanced-patches/compare/v5.24.0...v5.25.0) (2025-05-29) + + +### Bug Fixes + +* **Disable Pairip license check:** Change patch to default off ([74b6a94](https://github.com/ReVanced/revanced-patches/commit/74b6a94577ac3f73b04bd0cce98fb7011a6607fd)) +* **Hide ADB status:** Resolve app crash on startup ([#5029](https://github.com/ReVanced/revanced-patches/issues/5029)) ([1abebd5](https://github.com/ReVanced/revanced-patches/commit/1abebd5f3b73250c6638d2d8a274b92ea8268924)) +* **Messenger:** Remove outdated `Disable switching emoji to sticker` patch ([#5044](https://github.com/ReVanced/revanced-patches/issues/5044)) ([7b182ca](https://github.com/ReVanced/revanced-patches/commit/7b182cab825ee3a4a3ca528c744c9d2a351c7cf8)) +* **Spotify Lite:** Remove obsolete `Enable on demand` patch ([#5046](https://github.com/ReVanced/revanced-patches/issues/5046)) ([4886d47](https://github.com/ReVanced/revanced-patches/commit/4886d47506c94b03c1f190ecc4947d3d91df6a47)) +* **YouTube - GmsCore support:** Restore patch functionality from prior merge ([7686bbe](https://github.com/ReVanced/revanced-patches/commit/7686bbe975644e1e582fa52f166879da5694ed93)) +* **YouTube - Hide ads:** Hide new type of general ad ([#5004](https://github.com/ReVanced/revanced-patches/issues/5004)) ([37e59d2](https://github.com/ReVanced/revanced-patches/commit/37e59d2771528c631dc13e73dac095fec95c6485)) +* **YouTube - Open Shorts in regular player:** Do not exit app when pressing back button in regular player ([#5020](https://github.com/ReVanced/revanced-patches/issues/5020)) ([3384f8d](https://github.com/ReVanced/revanced-patches/commit/3384f8dd0ff2a345f2e387f4ed1570079a83ccb6)) +* **YouTube:** Better handle incorrect duplicate translations ([20abac5](https://github.com/ReVanced/revanced-patches/commit/20abac52121fbecb65d87d0982f3380e1cf4e20e)) +* **Yuka - Unlock premium:** Remove broken patch that is no longer supported ([#5018](https://github.com/ReVanced/revanced-patches/issues/5018)) ([fac6e59](https://github.com/ReVanced/revanced-patches/commit/fac6e59d281e21e57abdcfc899cd1aeb18e5c2b8)) + + +### Features + +* Add `Disable pairip license check` patch ([#4927](https://github.com/ReVanced/revanced-patches/issues/4927)) ([42d2c27](https://github.com/ReVanced/revanced-patches/commit/42d2c277982ef63e6ad42d85e46f13c3ab50243c)) +* **Messenger:** Add `Remove Meta AI` patch ([#4945](https://github.com/ReVanced/revanced-patches/issues/4945)) ([012dff7](https://github.com/ReVanced/revanced-patches/commit/012dff7b6511b9e519ccac96f6713cf1a1b327b4)) +* **Prime Video:** Add `Rename shared permissions` patch ([#5049](https://github.com/ReVanced/revanced-patches/issues/5049)) ([80f1fc6](https://github.com/ReVanced/revanced-patches/commit/80f1fc629e30e391bd5877f07dbdf4b6613bd1cf)) +* **Spotify:** Add `Fix Facebook login` patch ([#5023](https://github.com/ReVanced/revanced-patches/issues/5023)) ([34932dc](https://github.com/ReVanced/revanced-patches/commit/34932dc43933d346a5a3adadc62c0dbd38a633b5)) +* **Threads:** Hide Ads ([#5064](https://github.com/ReVanced/revanced-patches/issues/5064)) ([3c4cecb](https://github.com/ReVanced/revanced-patches/commit/3c4cecb966c2f99bfde99552686dda19ade5f67e)) +* **YouTube - Enable debugging:** Add settings menu to share debug logs ([#5021](https://github.com/ReVanced/revanced-patches/issues/5021)) ([1ec4a88](https://github.com/ReVanced/revanced-patches/commit/1ec4a88464a2a2810c02cf072950b618d183779a)) +* **YouTube - Settings:** Add a color picker ([#4981](https://github.com/ReVanced/revanced-patches/issues/4981)) ([1e0e398](https://github.com/ReVanced/revanced-patches/commit/1e0e398574329173aff11a4dc9acfc3fcdeabe16)) +* **YouTube - Swipe controls:** Add separate color settings for the brightness and volume bars ([#5043](https://github.com/ReVanced/revanced-patches/issues/5043)) ([80f50e8](https://github.com/ReVanced/revanced-patches/commit/80f50e8c50ca6a8366b7fd7b01459fb16fa1074a)) +* **YouTube:** Add `Disable haptic feedback` patch ([#5033](https://github.com/ReVanced/revanced-patches/issues/5033)) ([bbe7974](https://github.com/ReVanced/revanced-patches/commit/bbe79744a513c96f9016476e8435f999e94c45d7)) + +# [5.25.0-dev.14](https://github.com/ReVanced/revanced-patches/compare/v5.25.0-dev.13...v5.25.0-dev.14) (2025-05-29) + + +### Features + +* **Threads:** Hide Ads ([#5064](https://github.com/ReVanced/revanced-patches/issues/5064)) ([3c4cecb](https://github.com/ReVanced/revanced-patches/commit/3c4cecb966c2f99bfde99552686dda19ade5f67e)) + +# [5.25.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v5.25.0-dev.12...v5.25.0-dev.13) (2025-05-28) + + +### Features + +* **Prime Video:** Add `Rename shared permissions` patch ([#5049](https://github.com/ReVanced/revanced-patches/issues/5049)) ([80f1fc6](https://github.com/ReVanced/revanced-patches/commit/80f1fc629e30e391bd5877f07dbdf4b6613bd1cf)) + +# [5.25.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v5.25.0-dev.11...v5.25.0-dev.12) (2025-05-28) + + +### Features + +* **YouTube - Swipe controls:** Add separate color settings for the brightness and volume bars ([#5043](https://github.com/ReVanced/revanced-patches/issues/5043)) ([80f50e8](https://github.com/ReVanced/revanced-patches/commit/80f50e8c50ca6a8366b7fd7b01459fb16fa1074a)) + +# [5.25.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v5.25.0-dev.10...v5.25.0-dev.11) (2025-05-27) + + +### Features + +* **YouTube - Enable debugging:** Add settings menu to share debug logs ([#5021](https://github.com/ReVanced/revanced-patches/issues/5021)) ([1ec4a88](https://github.com/ReVanced/revanced-patches/commit/1ec4a88464a2a2810c02cf072950b618d183779a)) +* **YouTube:** Add `Disable haptic feedback` patch ([#5033](https://github.com/ReVanced/revanced-patches/issues/5033)) ([bbe7974](https://github.com/ReVanced/revanced-patches/commit/bbe79744a513c96f9016476e8435f999e94c45d7)) + +# [5.25.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v5.25.0-dev.9...v5.25.0-dev.10) (2025-05-27) + + +### Bug Fixes + +* **Messenger:** Remove outdated `Disable switching emoji to sticker` patch ([#5044](https://github.com/ReVanced/revanced-patches/issues/5044)) ([7b182ca](https://github.com/ReVanced/revanced-patches/commit/7b182cab825ee3a4a3ca528c744c9d2a351c7cf8)) +* **Spotify Lite:** Remove obsolete `Enable on demand` patch ([#5046](https://github.com/ReVanced/revanced-patches/issues/5046)) ([4886d47](https://github.com/ReVanced/revanced-patches/commit/4886d47506c94b03c1f190ecc4947d3d91df6a47)) + +# [5.25.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.25.0-dev.8...v5.25.0-dev.9) (2025-05-26) + + +### Features + +* **Spotify:** Add `Fix Facebook login` patch ([#5023](https://github.com/ReVanced/revanced-patches/issues/5023)) ([34932dc](https://github.com/ReVanced/revanced-patches/commit/34932dc43933d346a5a3adadc62c0dbd38a633b5)) +* **YouTube - Settings:** Add a color picker ([#4981](https://github.com/ReVanced/revanced-patches/issues/4981)) ([1e0e398](https://github.com/ReVanced/revanced-patches/commit/1e0e398574329173aff11a4dc9acfc3fcdeabe16)) + +# [5.25.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.25.0-dev.8...v5.25.0-dev.9) (2025-05-26) + + +### Features + +* **Spotify:** Add `Fix Facebook login` patch ([#5023](https://github.com/ReVanced/revanced-patches/issues/5023)) ([34932dc](https://github.com/ReVanced/revanced-patches/commit/34932dc43933d346a5a3adadc62c0dbd38a633b5)) +* **YouTube - Settings:** Add a color picker ([#4981](https://github.com/ReVanced/revanced-patches/issues/4981)) ([1e0e398](https://github.com/ReVanced/revanced-patches/commit/1e0e398574329173aff11a4dc9acfc3fcdeabe16)) + +# [5.25.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.25.0-dev.8...v5.25.0-dev.9) (2025-05-26) + + +### Features + +* **Spotify:** Add `Fix Facebook login` patch ([#5023](https://github.com/ReVanced/revanced-patches/issues/5023)) ([34932dc](https://github.com/ReVanced/revanced-patches/commit/34932dc43933d346a5a3adadc62c0dbd38a633b5)) +* **YouTube - Settings:** Add a color picker ([#4981](https://github.com/ReVanced/revanced-patches/issues/4981)) ([1e0e398](https://github.com/ReVanced/revanced-patches/commit/1e0e398574329173aff11a4dc9acfc3fcdeabe16)) + +# [5.25.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.25.0-dev.7...v5.25.0-dev.8) (2025-05-25) + + +### Bug Fixes + +* **Hide ADB status:** Resolve app crash on startup ([#5029](https://github.com/ReVanced/revanced-patches/issues/5029)) ([1abebd5](https://github.com/ReVanced/revanced-patches/commit/1abebd5f3b73250c6638d2d8a274b92ea8268924)) + +# [5.25.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.25.0-dev.6...v5.25.0-dev.7) (2025-05-24) + + +### Bug Fixes + +* **YouTube - Open Shorts in regular player:** Do not exit app when pressing back button in regular player ([#5020](https://github.com/ReVanced/revanced-patches/issues/5020)) ([3384f8d](https://github.com/ReVanced/revanced-patches/commit/3384f8dd0ff2a345f2e387f4ed1570079a83ccb6)) + +# [5.25.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.25.0-dev.5...v5.25.0-dev.6) (2025-05-23) + + +### Bug Fixes + +* **Yuka - Unlock premium:** Remove broken patch that is no longer supported ([#5018](https://github.com/ReVanced/revanced-patches/issues/5018)) ([fac6e59](https://github.com/ReVanced/revanced-patches/commit/fac6e59d281e21e57abdcfc899cd1aeb18e5c2b8)) + +# [5.25.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.25.0-dev.4...v5.25.0-dev.5) (2025-05-22) + + +### Bug Fixes + +* **YouTube:** Better handle incorrect duplicate translations ([20abac5](https://github.com/ReVanced/revanced-patches/commit/20abac52121fbecb65d87d0982f3380e1cf4e20e)) + +# [5.25.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.25.0-dev.3...v5.25.0-dev.4) (2025-05-22) + + +### Bug Fixes + +* **YouTube - GmsCore support:** Restore patch functionality from prior merge ([7686bbe](https://github.com/ReVanced/revanced-patches/commit/7686bbe975644e1e582fa52f166879da5694ed93)) + +# [5.25.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.25.0-dev.2...v5.25.0-dev.3) (2025-05-22) + + +### Bug Fixes + +* **YouTube - Hide ads:** Hide new type of general ad ([#5004](https://github.com/ReVanced/revanced-patches/issues/5004)) ([37e59d2](https://github.com/ReVanced/revanced-patches/commit/37e59d2771528c631dc13e73dac095fec95c6485)) + +# [5.25.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.25.0-dev.1...v5.25.0-dev.2) (2025-05-22) + + +### Bug Fixes + +* **Disable Pairip license check:** Change patch to default off ([74b6a94](https://github.com/ReVanced/revanced-patches/commit/74b6a94577ac3f73b04bd0cce98fb7011a6607fd)) + +# [5.25.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.24.0...v5.25.0-dev.1) (2025-05-22) + + +### Features + +* Add `Disable pairip license check` patch ([#4927](https://github.com/ReVanced/revanced-patches/issues/4927)) ([42d2c27](https://github.com/ReVanced/revanced-patches/commit/42d2c277982ef63e6ad42d85e46f13c3ab50243c)) +* **Messenger:** Add `Remove Meta AI` patch ([#4945](https://github.com/ReVanced/revanced-patches/issues/4945)) ([012dff7](https://github.com/ReVanced/revanced-patches/commit/012dff7b6511b9e519ccac96f6713cf1a1b327b4)) + # [5.24.0](https://github.com/ReVanced/revanced-patches/compare/v5.23.0...v5.24.0) (2025-05-19) diff --git a/extensions/messenger/build.gradle.kts b/extensions/messenger/build.gradle.kts new file mode 100644 index 000000000..8cf6305c1 --- /dev/null +++ b/extensions/messenger/build.gradle.kts @@ -0,0 +1,3 @@ +dependencies { + compileOnly(project(":extensions:shared:library")) +} diff --git a/extensions/messenger/src/main/AndroidManifest.xml b/extensions/messenger/src/main/AndroidManifest.xml new file mode 100644 index 000000000..9b65eb06c --- /dev/null +++ b/extensions/messenger/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/extensions/messenger/src/main/java/app/revanced/extension/messenger/metaai/RemoveMetaAIPatch.java b/extensions/messenger/src/main/java/app/revanced/extension/messenger/metaai/RemoveMetaAIPatch.java new file mode 100644 index 000000000..94684f687 --- /dev/null +++ b/extensions/messenger/src/main/java/app/revanced/extension/messenger/metaai/RemoveMetaAIPatch.java @@ -0,0 +1,15 @@ +package app.revanced.extension.messenger.metaai; + +@SuppressWarnings("unused") +public class RemoveMetaAIPatch { + public static boolean overrideConfigBool(long id, boolean value) { + // It seems like all configs starting with 363219 are related to Meta AI. + // A list of specific ones that need disabling would probably be better, + // but these config numbers seem to change slightly with each update. + // These first 6 digits don't though. + if (Long.toString(id).startsWith("363219")) + return false; + + return value; + } +} diff --git a/extensions/shared/library/src/main/java/app/revanced/extension/shared/Logger.java b/extensions/shared/library/src/main/java/app/revanced/extension/shared/Logger.java index 9df38ac99..edf57e9c1 100644 --- a/extensions/shared/library/src/main/java/app/revanced/extension/shared/Logger.java +++ b/extensions/shared/library/src/main/java/app/revanced/extension/shared/Logger.java @@ -1,15 +1,26 @@ package app.revanced.extension.shared; +import static app.revanced.extension.shared.settings.BaseSettings.DEBUG; +import static app.revanced.extension.shared.settings.BaseSettings.DEBUG_STACKTRACE; +import static app.revanced.extension.shared.settings.BaseSettings.DEBUG_TOAST_ON_ERROR; + import android.util.Log; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import app.revanced.extension.shared.settings.BaseSettings; import java.io.PrintWriter; import java.io.StringWriter; -import static app.revanced.extension.shared.settings.BaseSettings.*; +import app.revanced.extension.shared.settings.BaseSettings; +import app.revanced.extension.shared.settings.preference.LogBufferManager; +/** + * ReVanced specific logger. Logging is done to standard device log (accessible thru ADB), + * and additionally accessible thru {@link LogBufferManager}. + * + * All methods are thread safe. + */ public class Logger { /** @@ -17,99 +28,159 @@ public class Logger { */ @FunctionalInterface public interface LogMessage { + /** + * @return Logger string message. This method is only called if logging is enabled. + */ @NonNull String buildMessageString(); + } - /** - * @return For outer classes, this returns {@link Class#getSimpleName()}. - * For static, inner, or anonymous classes, this returns the simple name of the enclosing class. - *
- * For example, each of these classes return 'SomethingView': - * - * com.company.SomethingView - * com.company.SomethingView$StaticClass - * com.company.SomethingView$1 - * - */ - private String findOuterClassSimpleName() { - var selfClass = this.getClass(); + private enum LogLevel { + DEBUG, + INFO, + ERROR + } - String fullClassName = selfClass.getName(); - final int dollarSignIndex = fullClassName.indexOf('$'); - if (dollarSignIndex < 0) { - return selfClass.getSimpleName(); // Already an outer class. + /** + * Log tag prefix. Only used for system logging. + */ + private static final String REVANCED_LOG_TAG_PREFIX = "revanced: "; + + private static final String LOGGER_CLASS_NAME = Logger.class.getName(); + + /** + * @return For outer classes, this returns {@link Class#getSimpleName()}. + * For static, inner, or anonymous classes, this returns the simple name of the enclosing class. + *
+ * For example, each of these classes returns 'SomethingView': + * + * com.company.SomethingView + * com.company.SomethingView$StaticClass + * com.company.SomethingView$1 + * + */ + private static String getOuterClassSimpleName(Object obj) { + Class logClass = obj.getClass(); + String fullClassName = logClass.getName(); + final int dollarSignIndex = fullClassName.indexOf('$'); + if (dollarSignIndex < 0) { + return logClass.getSimpleName(); // Already an outer class. + } + + // Class is inner, static, or anonymous. + // Parse the simple name full name. + // A class with no package returns index of -1, but incrementing gives index zero which is correct. + final int simpleClassNameStartIndex = fullClassName.lastIndexOf('.') + 1; + return fullClassName.substring(simpleClassNameStartIndex, dollarSignIndex); + } + + /** + * Internal method to handle logging to Android Log and {@link LogBufferManager}. + * Appends the log message, stack trace (if enabled), and exception (if present) to logBuffer + * with class name but without 'revanced:' prefix. + * + * @param logLevel The log level. + * @param message Log message object. + * @param ex Optional exception. + * @param includeStackTrace If the current stack should be included. + * @param showToast If a toast is to be shown. + */ + private static void logInternal(LogLevel logLevel, LogMessage message, @Nullable Throwable ex, + boolean includeStackTrace, boolean showToast) { + // It's very important that no Settings are used in this method, + // as this code is used when a context is not set and thus referencing + // a setting will crash the app. + String messageString = message.buildMessageString(); + String className = getOuterClassSimpleName(message); + + String logText = messageString; + + // Append exception message if present. + if (ex != null) { + var exceptionMessage = ex.getMessage(); + if (exceptionMessage != null) { + logText += "\nException: " + exceptionMessage; } + } - // Class is inner, static, or anonymous. - // Parse the simple name full name. - // A class with no package returns index of -1, but incrementing gives index zero which is correct. - final int simpleClassNameStartIndex = fullClassName.lastIndexOf('.') + 1; - return fullClassName.substring(simpleClassNameStartIndex, dollarSignIndex); + if (includeStackTrace) { + var sw = new StringWriter(); + new Throwable().printStackTrace(new PrintWriter(sw)); + String stackTrace = sw.toString(); + // Remove the stacktrace elements of this class. + final int loggerIndex = stackTrace.lastIndexOf(LOGGER_CLASS_NAME); + final int loggerBegins = stackTrace.indexOf('\n', loggerIndex); + logText += stackTrace.substring(loggerBegins); + } + + // Do not include "revanced:" prefix in clipboard logs. + String managerToastString = className + ": " + logText; + LogBufferManager.appendToLogBuffer(managerToastString); + + String logTag = REVANCED_LOG_TAG_PREFIX + className; + switch (logLevel) { + case DEBUG: + if (ex == null) Log.d(logTag, logText); + else Log.d(logTag, logText, ex); + break; + case INFO: + if (ex == null) Log.i(logTag, logText); + else Log.i(logTag, logText, ex); + break; + case ERROR: + if (ex == null) Log.e(logTag, logText); + else Log.e(logTag, logText, ex); + break; + } + + if (showToast) { + Utils.showToastLong(managerToastString); } } - private static final String REVANCED_LOG_PREFIX = "revanced: "; - /** * Logs debug messages under the outer class name of the code calling this method. - * Whenever possible, the log string should be constructed entirely inside {@link LogMessage#buildMessageString()} - * so the performance cost of building strings is paid only if {@link BaseSettings#DEBUG} is enabled. + *

+ * Whenever possible, the log string should be constructed entirely inside + * {@link LogMessage#buildMessageString()} so the performance cost of + * building strings is paid only if {@link BaseSettings#DEBUG} is enabled. */ - public static void printDebug(@NonNull LogMessage message) { + public static void printDebug(LogMessage message) { printDebug(message, null); } /** * Logs debug messages under the outer class name of the code calling this method. - * Whenever possible, the log string should be constructed entirely inside {@link LogMessage#buildMessageString()} - * so the performance cost of building strings is paid only if {@link BaseSettings#DEBUG} is enabled. + *

+ * Whenever possible, the log string should be constructed entirely inside + * {@link LogMessage#buildMessageString()} so the performance cost of + * building strings is paid only if {@link BaseSettings#DEBUG} is enabled. */ - public static void printDebug(@NonNull LogMessage message, @Nullable Exception ex) { + public static void printDebug(LogMessage message, @Nullable Exception ex) { if (DEBUG.get()) { - String logMessage = message.buildMessageString(); - String logTag = REVANCED_LOG_PREFIX + message.findOuterClassSimpleName(); - - if (DEBUG_STACKTRACE.get()) { - var builder = new StringBuilder(logMessage); - var sw = new StringWriter(); - new Throwable().printStackTrace(new PrintWriter(sw)); - - builder.append('\n').append(sw); - logMessage = builder.toString(); - } - - if (ex == null) { - Log.d(logTag, logMessage); - } else { - Log.d(logTag, logMessage, ex); - } + logInternal(LogLevel.DEBUG, message, ex, DEBUG_STACKTRACE.get(), false); } } /** * Logs information messages using the outer class name of the code calling this method. */ - public static void printInfo(@NonNull LogMessage message) { + public static void printInfo(LogMessage message) { printInfo(message, null); } /** * Logs information messages using the outer class name of the code calling this method. */ - public static void printInfo(@NonNull LogMessage message, @Nullable Exception ex) { - String logTag = REVANCED_LOG_PREFIX + message.findOuterClassSimpleName(); - String logMessage = message.buildMessageString(); - if (ex == null) { - Log.i(logTag, logMessage); - } else { - Log.i(logTag, logMessage, ex); - } + public static void printInfo(LogMessage message, @Nullable Exception ex) { + logInternal(LogLevel.INFO, message, ex, DEBUG_STACKTRACE.get(), false); } /** * Logs exceptions under the outer class name of the code calling this method. + * Appends the log message, exception (if present), and toast message (if enabled) to logBuffer. */ - public static void printException(@NonNull LogMessage message) { + public static void printException(LogMessage message) { printException(message, null); } @@ -122,35 +193,23 @@ public class Logger { * @param message log message * @param ex exception (optional) */ - public static void printException(@NonNull LogMessage message, @Nullable Throwable ex) { - String messageString = message.buildMessageString(); - String outerClassSimpleName = message.findOuterClassSimpleName(); - String logMessage = REVANCED_LOG_PREFIX + outerClassSimpleName; - if (ex == null) { - Log.e(logMessage, messageString); - } else { - Log.e(logMessage, messageString, ex); - } - if (DEBUG_TOAST_ON_ERROR.get()) { - Utils.showToastLong(outerClassSimpleName + ": " + messageString); - } + public static void printException(LogMessage message, @Nullable Throwable ex) { + logInternal(LogLevel.ERROR, message, ex, DEBUG_STACKTRACE.get(), DEBUG_TOAST_ON_ERROR.get()); } /** * Logging to use if {@link BaseSettings#DEBUG} or {@link Utils#getContext()} may not be initialized. * Normally this method should not be used. */ - public static void initializationInfo(@NonNull Class callingClass, @NonNull String message) { - Log.i(REVANCED_LOG_PREFIX + callingClass.getSimpleName(), message); + public static void initializationInfo(LogMessage message) { + logInternal(LogLevel.INFO, message, null, false, false); } /** * Logging to use if {@link BaseSettings#DEBUG} or {@link Utils#getContext()} may not be initialized. * Normally this method should not be used. */ - public static void initializationException(@NonNull Class callingClass, @NonNull String message, - @Nullable Exception ex) { - Log.e(REVANCED_LOG_PREFIX + callingClass.getSimpleName(), message, ex); + public static void initializationException(LogMessage message, @Nullable Exception ex) { + logInternal(LogLevel.ERROR, message, ex, false, false); } - -} \ No newline at end of file +} diff --git a/extensions/shared/library/src/main/java/app/revanced/extension/shared/Utils.java b/extensions/shared/library/src/main/java/app/revanced/extension/shared/Utils.java index 3cb809a2d..111a0dd77 100644 --- a/extensions/shared/library/src/main/java/app/revanced/extension/shared/Utils.java +++ b/extensions/shared/library/src/main/java/app/revanced/extension/shared/Utils.java @@ -1,7 +1,11 @@ package app.revanced.extension.shared; import android.annotation.SuppressLint; -import android.app.*; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.app.Fragment; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; @@ -18,6 +22,8 @@ import android.os.Looper; import android.preference.Preference; import android.preference.PreferenceGroup; import android.preference.PreferenceScreen; +import android.util.Pair; +import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; @@ -357,15 +363,17 @@ public class Utils { public static Context getContext() { if (context == null) { - Logger.initializationException(Utils.class, "Context is not set by extension hook, returning null", null); + Logger.initializationException(() -> "Context is not set by extension hook, returning null", null); } return context; } public static void setContext(Context appContext) { + // Intentionally use logger before context is set, + // to expose any bugs in the 'no context available' logger method. + Logger.initializationInfo(() -> "Set context: " + appContext); // Must initially set context to check the app language. context = appContext; - Logger.initializationInfo(Utils.class, "Set context: " + appContext); AppLanguage language = BaseSettings.REVANCED_LANGUAGE.get(); if (language != AppLanguage.DEFAULT) { @@ -377,8 +385,9 @@ public class Utils { } } - public static void setClipboard(@NonNull String text) { - android.content.ClipboardManager clipboard = (android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + public static void setClipboard(CharSequence text) { + android.content.ClipboardManager clipboard = (android.content.ClipboardManager) context + .getSystemService(Context.CLIPBOARD_SERVICE); android.content.ClipData clip = android.content.ClipData.newPlainText("ReVanced", text); clipboard.setPrimaryClip(clip); } @@ -542,24 +551,25 @@ public class Utils { private static void showToast(@NonNull String messageToToast, int toastDuration) { Objects.requireNonNull(messageToToast); runOnMainThreadNowOrLater(() -> { - if (context == null) { - Logger.initializationException(Utils.class, "Cannot show toast (context is null): " + messageToToast, null); - } else { - Logger.printDebug(() -> "Showing toast: " + messageToToast); - Toast.makeText(context, messageToToast, toastDuration).show(); - } - } - ); + Context currentContext = context; + + if (currentContext == null) { + Logger.initializationException(() -> "Cannot show toast (context is null): " + messageToToast, null); + } else { + Logger.printDebug(() -> "Showing toast: " + messageToToast); + Toast.makeText(currentContext, messageToToast, toastDuration).show(); + } + }); } - public static boolean isDarkModeEnabled(Context context) { - Configuration config = context.getResources().getConfiguration(); + public static boolean isDarkModeEnabled() { + Configuration config = Resources.getSystem().getConfiguration(); final int currentNightMode = config.uiMode & Configuration.UI_MODE_NIGHT_MASK; return currentNightMode == Configuration.UI_MODE_NIGHT_YES; } public static boolean isLandscapeOrientation() { - final int orientation = context.getResources().getConfiguration().orientation; + final int orientation = Resources.getSystem().getConfiguration().orientation; return orientation == Configuration.ORIENTATION_LANDSCAPE; } @@ -573,7 +583,7 @@ public class Utils { } /** - * Automatically logs any exceptions the runnable throws + * Automatically logs any exceptions the runnable throws. */ public static void runOnMainThreadDelayed(@NonNull Runnable runnable, long delayMillis) { Runnable loggingRunnable = () -> { @@ -599,14 +609,14 @@ public class Utils { } /** - * @return if the calling thread is on the main thread + * @return if the calling thread is on the main thread. */ public static boolean isCurrentlyOnMainThread() { return Looper.getMainLooper().isCurrentThread(); } /** - * @throws IllegalStateException if the calling thread is _off_ the main thread + * @throws IllegalStateException if the calling thread is _off_ the main thread. */ public static void verifyOnMainThread() throws IllegalStateException { if (!isCurrentlyOnMainThread()) { @@ -615,7 +625,7 @@ public class Utils { } /** - * @throws IllegalStateException if the calling thread is _on_ the main thread + * @throws IllegalStateException if the calling thread is _on_ the main thread. */ public static void verifyOffMainThread() throws IllegalStateException { if (isCurrentlyOnMainThread()) { @@ -629,13 +639,23 @@ public class Utils { OTHER, } + /** + * Calling extension code must ensure the un-patched app has the permission + * android.permission.ACCESS_NETWORK_STATE, otherwise the app will crash + * if this method is used. + */ public static boolean isNetworkConnected() { NetworkType networkType = getNetworkType(); return networkType == NetworkType.MOBILE || networkType == NetworkType.OTHER; } - @SuppressLint({"MissingPermission", "deprecation"}) // Permission already included in YouTube. + /** + * Calling extension code must ensure the un-patched app has the permission + * android.permission.ACCESS_NETWORK_STATE, otherwise the app will crash + * if this method is used. + */ + @SuppressLint({"MissingPermission", "deprecation"}) public static NetworkType getNetworkType() { Context networkContext = getContext(); if (networkContext == null) { @@ -738,9 +758,9 @@ public class Utils { * then the preferences are left unsorted. */ @SuppressWarnings("deprecation") - public static void sortPreferenceGroups(@NonNull PreferenceGroup group) { + public static void sortPreferenceGroups(PreferenceGroup group) { Sort groupSort = Sort.fromKey(group.getKey(), Sort.UNSORTED); - SortedMap preferences = new TreeMap<>(); + List> preferences = new ArrayList<>(); for (int i = 0, prefCount = group.getPreferenceCount(); i < prefCount; i++) { Preference preference = group.getPreference(i); @@ -769,17 +789,22 @@ public class Utils { throw new IllegalStateException(); } - preferences.put(sortValue, preference); + preferences.add(new Pair<>(sortValue, preference)); } + //noinspection ComparatorCombinators + Collections.sort(preferences, (pair1, pair2) + -> pair1.first.compareTo(pair2.first)); + int index = 0; - for (Preference pref : preferences.values()) { + for (Pair pair : preferences) { int order = index++; + Preference pref = pair.second; // Move any screens, intents, and the one off About preference to the top. if (pref instanceof PreferenceScreen || pref instanceof ReVancedAboutPreference || pref.getIntent() != null) { - // Arbitrary high number. + // Any arbitrary large number. order -= 1000; } @@ -843,6 +868,20 @@ public class Utils { return getResourceColor(colorString); } + /** + * Converts dip value to actual device pixels. + * + * @param dip The density-independent pixels value + * @return The device pixel value + */ + public static int dipToPixels(float dip) { + return (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + dip, + Resources.getSystem().getDisplayMetrics() + ); + } + public static int clamp(int value, int lower, int upper) { return Math.max(lower, Math.min(value, upper)); } diff --git a/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ColorPickerPreference.java b/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ColorPickerPreference.java new file mode 100644 index 000000000..e9f24ea61 --- /dev/null +++ b/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ColorPickerPreference.java @@ -0,0 +1,442 @@ +package app.revanced.extension.shared.settings.preference; + +import static app.revanced.extension.shared.StringRef.str; +import static app.revanced.extension.shared.Utils.getResourceIdentifier; + +import android.app.AlertDialog; +import android.content.Context; +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Build; +import android.os.Bundle; +import android.preference.EditTextPreference; +import android.text.Editable; +import android.text.InputType; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.TextWatcher; +import android.text.style.ForegroundColorSpan; +import android.text.style.RelativeSizeSpan; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.ColorInt; + +import java.util.Locale; +import java.util.regex.Pattern; + +import app.revanced.extension.shared.Logger; +import app.revanced.extension.shared.Utils; +import app.revanced.extension.shared.settings.Setting; +import app.revanced.extension.shared.settings.StringSetting; + +/** + * A custom preference for selecting a color via a hexadecimal code or a color picker dialog. + * Extends {@link EditTextPreference} to display a colored dot in the widget area, + * reflecting the currently selected color. The dot is dimmed when the preference is disabled. + */ +@SuppressWarnings({"unused", "deprecation"}) +public class ColorPickerPreference extends EditTextPreference { + + /** + * Character to show the color appearance. + */ + public static final String COLOR_DOT_STRING = "⬤"; + + /** + * Length of a valid color string of format #RRGGBB. + */ + public static final int COLOR_STRING_LENGTH = 7; + + /** + * Matches everything that is not a hex number/letter. + */ + private static final Pattern PATTERN_NOT_HEX = Pattern.compile("[^0-9A-Fa-f]"); + + /** + * Alpha for dimming when the preference is disabled. + */ + private static final float DISABLED_ALPHA = 0.5f; // 50% + + /** + * View displaying a colored dot in the widget area. + */ + private View widgetColorDot; + + /** + * Current color in RGB format (without alpha). + */ + @ColorInt + private int currentColor; + + /** + * Associated setting for storing the color value. + */ + private StringSetting colorSetting; + + /** + * Dialog TextWatcher for the EditText to monitor color input changes. + */ + private TextWatcher colorTextWatcher; + + /** + * Dialog TextView displaying a colored dot for the selected color preview in the dialog. + */ + private TextView dialogColorPreview; + + /** + * Dialog color picker view. + */ + private ColorPickerView dialogColorPickerView; + + /** + * Removes non valid hex characters, converts to all uppercase, + * and adds # character to the start if not present. + */ + public static String cleanupColorCodeString(String colorString) { + // Remove non-hex chars, convert to uppercase, and ensure correct length + String result = "#" + PATTERN_NOT_HEX.matcher(colorString) + .replaceAll("").toUpperCase(Locale.ROOT); + + if (result.length() < COLOR_STRING_LENGTH) { + return result; + } + + return result.substring(0, COLOR_STRING_LENGTH); + } + + /** + * @param color RGB color, without an alpha channel. + * @return #RRGGBB hex color string + */ + public static String getColorString(@ColorInt int color) { + String colorString = String.format("#%06X", color); + if ((color & 0xFF000000) != 0) { + // Likely a bug somewhere. + Logger.printException(() -> "getColorString: color has alpha channel: " + colorString); + } + return colorString; + } + + /** + * Creates a Spanned object for a colored dot using SpannableString. + * + * @param color The RGB color (without alpha). + * @return A Spanned object with the colored dot. + */ + public static Spanned getColorDot(@ColorInt int color) { + SpannableString spannable = new SpannableString(COLOR_DOT_STRING); + spannable.setSpan(new ForegroundColorSpan(color | 0xFF000000), 0, COLOR_DOT_STRING.length(), + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + spannable.setSpan(new RelativeSizeSpan(1.5f), 0, 1, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + return spannable; + } + + public ColorPickerPreference(Context context) { + super(context); + init(); + } + + public ColorPickerPreference(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public ColorPickerPreference(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + /** + * Initializes the preference by setting up the EditText, loading the color, and set the widget layout. + */ + private void init() { + colorSetting = (StringSetting) Setting.getSettingFromPath(getKey()); + if (colorSetting == null) { + Logger.printException(() -> "Could not find color setting for: " + getKey()); + } + + EditText editText = getEditText(); + editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS + | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + editText.setAutofillHints((String) null); + } + + // Set the widget layout to a custom layout containing the colored dot. + setWidgetLayoutResource(getResourceIdentifier("revanced_color_dot_widget", "layout")); + } + + /** + * Sets the selected color and updates the UI and settings. + * + * @param colorString The color in hexadecimal format (e.g., "#RRGGBB"). + * @throws IllegalArgumentException If the color string is invalid. + */ + @Override + public final void setText(String colorString) { + try { + Logger.printDebug(() -> "setText: " + colorString); + super.setText(colorString); + + currentColor = Color.parseColor(colorString) & 0x00FFFFFF; + if (colorSetting != null) { + colorSetting.save(getColorString(currentColor)); + } + updateColorPreview(); + updateWidgetColorDot(); + } catch (IllegalArgumentException ex) { + // This code is reached if the user pastes settings json with an invalid color + // since this preference is updated with the new setting text. + Logger.printDebug(() -> "Parse color error: " + colorString, ex); + Utils.showToastShort(str("revanced_settings_color_invalid")); + setText(colorSetting.resetToDefault()); + } catch (Exception ex) { + Logger.printException(() -> "setText failure: " + colorString, ex); + } + } + + @Override + protected void onBindView(View view) { + super.onBindView(view); + + widgetColorDot = view.findViewById(getResourceIdentifier( + "revanced_color_dot_widget", "id")); + widgetColorDot.setBackgroundResource(getResourceIdentifier( + "revanced_settings_circle_background", "drawable")); + widgetColorDot.getBackground().setTint(currentColor | 0xFF000000); + widgetColorDot.setAlpha(isEnabled() ? 1.0f : DISABLED_ALPHA); + } + + /** + * Creates a layout with a color preview and EditText for hex color input. + * + * @param context The context for creating the layout. + * @return A LinearLayout containing the color preview and EditText. + */ + private LinearLayout createDialogLayout(Context context) { + LinearLayout layout = new LinearLayout(context); + layout.setOrientation(LinearLayout.VERTICAL); + layout.setPadding(70, 0, 70, 0); + + // Inflate color picker. + View colorPicker = LayoutInflater.from(context).inflate( + getResourceIdentifier("revanced_color_picker", "layout"), null); + dialogColorPickerView = colorPicker.findViewById( + getResourceIdentifier("color_picker_view", "id")); + dialogColorPickerView.setColor(currentColor); + layout.addView(colorPicker); + + // Horizontal layout for preview and EditText. + LinearLayout inputLayout = new LinearLayout(context); + inputLayout.setOrientation(LinearLayout.HORIZONTAL); + inputLayout.setPadding(0, 20, 0, 0); + + dialogColorPreview = new TextView(context); + inputLayout.addView(dialogColorPreview); + updateColorPreview(); + + EditText editText = getEditText(); + ViewParent parent = editText.getParent(); + if (parent instanceof ViewGroup parentViewGroup) { + parentViewGroup.removeView(editText); + } + editText.setLayoutParams(new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT + )); + String currentColorString = getColorString(currentColor); + editText.setText(currentColorString); + editText.setSelection(currentColorString.length()); + editText.setTypeface(Typeface.MONOSPACE); + colorTextWatcher = createColorTextWatcher(dialogColorPickerView); + editText.addTextChangedListener(colorTextWatcher); + inputLayout.addView(editText); + + // Add a dummy view to take up remaining horizontal space, + // otherwise it will show an oversize underlined text view. + View paddingView = new View(context); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( + 0, + LinearLayout.LayoutParams.MATCH_PARENT, + 1f + ); + paddingView.setLayoutParams(params); + inputLayout.addView(paddingView); + + layout.addView(inputLayout); + + // Set up color picker listener with debouncing. + // Add listener last to prevent callbacks from set calls above. + dialogColorPickerView.setOnColorChangedListener(color -> { + // Check if it actually changed, since this callback + // can be caused by updates in afterTextChanged(). + if (currentColor == color) { + return; + } + + String updatedColorString = getColorString(color); + Logger.printDebug(() -> "onColorChanged: " + updatedColorString); + currentColor = color; + editText.setText(updatedColorString); + editText.setSelection(updatedColorString.length()); + + updateColorPreview(); + updateWidgetColorDot(); + }); + + return layout; + } + + /** + * Updates the color preview TextView with a colored dot. + */ + private void updateColorPreview() { + if (dialogColorPreview != null) { + dialogColorPreview.setText(getColorDot(currentColor)); + } + } + + private void updateWidgetColorDot() { + if (widgetColorDot != null) { + widgetColorDot.getBackground().setTint(currentColor | 0xFF000000); + widgetColorDot.setAlpha(isEnabled() ? 1.0f : DISABLED_ALPHA); + } + } + + /** + * Creates a TextWatcher to monitor changes in the EditText for color input. + * + * @return A TextWatcher that updates the color preview on valid input. + */ + private TextWatcher createColorTextWatcher(ColorPickerView colorPickerView) { + return new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable edit) { + try { + String colorString = edit.toString(); + + String sanitizedColorString = cleanupColorCodeString(colorString); + if (!sanitizedColorString.equals(colorString)) { + edit.replace(0, colorString.length(), sanitizedColorString); + return; + } + + if (sanitizedColorString.length() != COLOR_STRING_LENGTH) { + // User is still typing out the color. + return; + } + + final int newColor = Color.parseColor(colorString); + if (currentColor != newColor) { + Logger.printDebug(() -> "afterTextChanged: " + sanitizedColorString); + currentColor = newColor; + updateColorPreview(); + updateWidgetColorDot(); + colorPickerView.setColor(newColor); + } + } catch (Exception ex) { + // Should never be reached since input is validated before using. + Logger.printException(() -> "afterTextChanged failure", ex); + } + } + }; + } + + /** + * Prepares the dialog builder with a custom view and reset button. + * + * @param builder The AlertDialog.Builder to configure. + */ + @Override + protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { + Utils.setEditTextDialogTheme(builder); + LinearLayout dialogLayout = createDialogLayout(builder.getContext()); + builder.setView(dialogLayout); + final int originalColor = currentColor; + + builder.setNeutralButton(str("revanced_settings_reset_color"), null); + + builder.setPositiveButton(android.R.string.ok, (dialog, which) -> { + try { + String colorString = getEditText().getText().toString(); + + if (colorString.length() != COLOR_STRING_LENGTH) { + Utils.showToastShort(str("revanced_settings_color_invalid")); + setText(getColorString(originalColor)); + return; + } + + setText(colorString); + } catch (Exception ex) { + // Should never happen due to a bad color string, + // since the text is validated and fixed while the user types. + Logger.printException(() -> "setPositiveButton failure", ex); + } + }); + + builder.setNegativeButton(android.R.string.cancel, (dialog, which) -> { + try { + // Restore the original color. + setText(getColorString(originalColor)); + } catch (Exception ex) { + Logger.printException(() -> "setNegativeButton failure", ex); + } + }); + } + + @Override + protected void showDialog(Bundle state) { + super.showDialog(state); + + AlertDialog dialog = (AlertDialog) getDialog(); + dialog.setCanceledOnTouchOutside(false); + + // Do not close dialog when reset is pressed. + Button button = dialog.getButton(AlertDialog.BUTTON_NEUTRAL); + button.setOnClickListener(view -> { + try { + final int defaultColor = Color.parseColor(colorSetting.defaultValue) & 0x00FFFFFF; + // Setting view color causes listener callback into this class. + dialogColorPickerView.setColor(defaultColor); + } catch (Exception ex) { + Logger.printException(() -> "setOnClickListener failure", ex); + } + }); + } + + @Override + protected void onDialogClosed(boolean positiveResult) { + super.onDialogClosed(positiveResult); + + if (colorTextWatcher != null) { + getEditText().removeTextChangedListener(colorTextWatcher); + colorTextWatcher = null; + } + + dialogColorPreview = null; + dialogColorPickerView = null; + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + updateWidgetColorDot(); + } +} diff --git a/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ColorPickerView.java b/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ColorPickerView.java new file mode 100644 index 000000000..cbec3349c --- /dev/null +++ b/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ColorPickerView.java @@ -0,0 +1,500 @@ +package app.revanced.extension.shared.settings.preference; + +import static app.revanced.extension.shared.Utils.dipToPixels; +import static app.revanced.extension.shared.settings.preference.ColorPickerPreference.getColorString; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ComposeShader; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.RectF; +import android.graphics.Shader; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; + +import androidx.annotation.ColorInt; + +import app.revanced.extension.shared.Logger; +import app.revanced.extension.shared.Utils; + +/** + * A custom color picker view that allows the user to select a color using a hue slider and a saturation-value selector. + * This implementation is density-independent and responsive across different screen sizes and DPIs. + * + *

+ * This view displays two main components for color selection: + *

+ * + *

+ * The view uses {@link LinearGradient} and {@link ComposeShader} to create the color gradients for the hue bar and the + * saturation-value selector. It also uses {@link Paint} to draw the selectors (draggable handles). + * + *

+ * The selected color can be retrieved using {@link #getColor()} and can be set using {@link #setColor(int)}. + * An {@link OnColorChangedListener} can be registered to receive notifications when the selected color changes. + */ +public class ColorPickerView extends View { + + /** + * Interface definition for a callback to be invoked when the selected color changes. + */ + public interface OnColorChangedListener { + /** + * Called when the selected color has changed. + * + * Important: Callback color uses RGB format with zero alpha channel. + * + * @param color The new selected color. + */ + void onColorChanged(@ColorInt int color); + } + + /** Expanded touch area for the hue bar to increase the touch-sensitive area. */ + public static final float TOUCH_EXPANSION = dipToPixels(20f); + + private static final float MARGIN_BETWEEN_AREAS = dipToPixels(24); + private static final float VIEW_PADDING = dipToPixels(16); + private static final float HUE_BAR_WIDTH = dipToPixels(12); + private static final float HUE_CORNER_RADIUS = dipToPixels(6); + private static final float SELECTOR_RADIUS = dipToPixels(12); + private static final float SELECTOR_STROKE_WIDTH = 8; + /** + * Hue fill radius. Use slightly smaller radius for the selector handle fill, + * otherwise the anti-aliasing causes the fill color to bleed past the selector outline. + */ + private static final float SELECTOR_FILL_RADIUS = SELECTOR_RADIUS - SELECTOR_STROKE_WIDTH / 2; + /** Thin dark outline stroke width for the selector rings. */ + private static final float SELECTOR_EDGE_STROKE_WIDTH = 1; + public static final float SELECTOR_EDGE_RADIUS = + SELECTOR_RADIUS + SELECTOR_STROKE_WIDTH / 2 + SELECTOR_EDGE_STROKE_WIDTH / 2; + + /** Selector outline inner color. */ + @ColorInt + private static final int SELECTOR_OUTLINE_COLOR = Color.WHITE; + + /** Dark edge color for the selector rings. */ + @ColorInt + private static final int SELECTOR_EDGE_COLOR = Color.parseColor("#CFCFCF"); + + private static final int[] HUE_COLORS = new int[361]; + static { + for (int i = 0; i < 361; i++) { + HUE_COLORS[i] = Color.HSVToColor(new float[]{i, 1, 1}); + } + } + + /** Hue bar. */ + private final Paint huePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + /** Saturation-value selector. */ + private final Paint saturationValuePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + /** Draggable selector. */ + private final Paint selectorPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + { + selectorPaint.setStrokeWidth(SELECTOR_STROKE_WIDTH); + } + + /** Bounds of the hue bar. */ + private final RectF hueRect = new RectF(); + /** Bounds of the saturation-value selector. */ + private final RectF saturationValueRect = new RectF(); + + /** HSV color calculations to avoid allocations during drawing. */ + private final float[] hsvArray = {1, 1, 1}; + + /** Current hue value (0-360). */ + private float hue = 0f; + /** Current saturation value (0-1). */ + private float saturation = 1f; + /** Current value (brightness) value (0-1). */ + private float value = 1f; + + /** The currently selected color in RGB format with no alpha channel. */ + @ColorInt + private int selectedColor; + + private OnColorChangedListener colorChangedListener; + + /** Track if we're currently dragging the hue or saturation handle. */ + private boolean isDraggingHue; + private boolean isDraggingSaturation; + + public ColorPickerView(Context context) { + super(context); + } + + public ColorPickerView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public ColorPickerView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + final float DESIRED_ASPECT_RATIO = 0.8f; // height = width * 0.8 + + final int minWidth = Utils.dipToPixels(250); + final int minHeight = (int) (minWidth * DESIRED_ASPECT_RATIO); + + int width = resolveSize(minWidth, widthMeasureSpec); + int height = resolveSize(minHeight, heightMeasureSpec); + + // Ensure minimum dimensions for usability + width = Math.max(width, minWidth); + height = Math.max(height, minHeight); + + // Adjust height to maintain desired aspect ratio if possible + final int desiredHeight = (int) (width * DESIRED_ASPECT_RATIO); + if (MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY) { + height = desiredHeight; + } + + setMeasuredDimension(width, height); + } + + /** + * Called when the size of the view changes. + * This method calculates and sets the bounds of the hue bar and saturation-value selector. + * It also creates the necessary shaders for the gradients. + */ + @Override + protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) { + super.onSizeChanged(width, height, oldWidth, oldHeight); + + // Calculate bounds with hue bar on the right + final float effectiveWidth = width - (2 * VIEW_PADDING); + final float selectorWidth = effectiveWidth - HUE_BAR_WIDTH - MARGIN_BETWEEN_AREAS; + + // Adjust rectangles to account for padding and density-independent dimensions + saturationValueRect.set( + VIEW_PADDING, + VIEW_PADDING, + VIEW_PADDING + selectorWidth, + height - VIEW_PADDING + ); + + hueRect.set( + width - VIEW_PADDING - HUE_BAR_WIDTH, + VIEW_PADDING, + width - VIEW_PADDING, + height - VIEW_PADDING + ); + + // Update the shaders. + updateHueShader(); + updateSaturationValueShader(); + } + + /** + * Updates the hue full spectrum (0-360 degrees). + */ + private void updateHueShader() { + LinearGradient hueShader = new LinearGradient( + hueRect.left, hueRect.top, + hueRect.left, hueRect.bottom, + HUE_COLORS, + null, + Shader.TileMode.CLAMP + ); + + huePaint.setShader(hueShader); + } + + /** + * Updates the shader for the saturation-value selector based on the currently selected hue. + * This method creates a combined shader that blends a saturation gradient with a value gradient. + */ + private void updateSaturationValueShader() { + // Create a saturation-value gradient based on the current hue. + // Calculate the start color (white with the selected hue) for the saturation gradient. + final int startColor = Color.HSVToColor(new float[]{hue, 0f, 1f}); + + // Calculate the middle color (fully saturated color with the selected hue) for the saturation gradient. + final int midColor = Color.HSVToColor(new float[]{hue, 1f, 1f}); + + // Create a linear gradient for the saturation from startColor to midColor (horizontal). + LinearGradient satShader = new LinearGradient( + saturationValueRect.left, saturationValueRect.top, + saturationValueRect.right, saturationValueRect.top, + startColor, + midColor, + Shader.TileMode.CLAMP + ); + + // Create a linear gradient for the value (brightness) from white to black (vertical). + //noinspection ExtractMethodRecommender + LinearGradient valShader = new LinearGradient( + saturationValueRect.left, saturationValueRect.top, + saturationValueRect.left, saturationValueRect.bottom, + Color.WHITE, + Color.BLACK, + Shader.TileMode.CLAMP + ); + + // Combine the saturation and value shaders using PorterDuff.Mode.MULTIPLY to create the final color. + ComposeShader combinedShader = new ComposeShader(satShader, valShader, PorterDuff.Mode.MULTIPLY); + + // Set the combined shader for the saturation-value paint. + saturationValuePaint.setShader(combinedShader); + } + + /** + * Draws the color picker view on the canvas. + * This method draws the saturation-value selector, the hue bar with rounded corners, + * and the draggable handles. + * + * @param canvas The canvas on which to draw. + */ + @Override + protected void onDraw(Canvas canvas) { + // Draw the saturation-value selector rectangle. + canvas.drawRect(saturationValueRect, saturationValuePaint); + + // Draw the hue bar. + canvas.drawRoundRect(hueRect, HUE_CORNER_RADIUS, HUE_CORNER_RADIUS, huePaint); + + final float hueSelectorX = hueRect.centerX(); + final float hueSelectorY = hueRect.top + (hue / 360f) * hueRect.height(); + + final float satSelectorX = saturationValueRect.left + saturation * saturationValueRect.width(); + final float satSelectorY = saturationValueRect.top + (1 - value) * saturationValueRect.height(); + + // Draw the saturation and hue selector handle filled with the selected color. + hsvArray[0] = hue; + final int hueHandleColor = Color.HSVToColor(0xFF, hsvArray); + selectorPaint.setStyle(Paint.Style.FILL_AND_STROKE); + + selectorPaint.setColor(hueHandleColor); + canvas.drawCircle(hueSelectorX, hueSelectorY, SELECTOR_FILL_RADIUS, selectorPaint); + + selectorPaint.setColor(selectedColor | 0xFF000000); + canvas.drawCircle(satSelectorX, satSelectorY, SELECTOR_FILL_RADIUS, selectorPaint); + + // Draw white outlines for the handles. + selectorPaint.setColor(SELECTOR_OUTLINE_COLOR); + selectorPaint.setStyle(Paint.Style.STROKE); + selectorPaint.setStrokeWidth(SELECTOR_STROKE_WIDTH); + canvas.drawCircle(hueSelectorX, hueSelectorY, SELECTOR_RADIUS, selectorPaint); + canvas.drawCircle(satSelectorX, satSelectorY, SELECTOR_RADIUS, selectorPaint); + + // Draw thin dark outlines for the handles at the outer edge of the white outline. + selectorPaint.setColor(SELECTOR_EDGE_COLOR); + selectorPaint.setStrokeWidth(SELECTOR_EDGE_STROKE_WIDTH); + canvas.drawCircle(hueSelectorX, hueSelectorY, SELECTOR_EDGE_RADIUS, selectorPaint); + canvas.drawCircle(satSelectorX, satSelectorY, SELECTOR_EDGE_RADIUS, selectorPaint); + } + + /** + * Handles touch events on the view. + * This method determines whether the touch event occurred within the hue bar or the saturation-value selector, + * updates the corresponding values (hue, saturation, value), and invalidates the view to trigger a redraw. + *

+ * In addition to testing if the touch is within the strict rectangles, an expanded hit area (by selectorRadius) + * is used so that the draggable handles remain active even when half of the handle is outside the drawn bounds. + * + * @param event The motion event. + * @return True if the event was handled, false otherwise. + */ + @SuppressLint("ClickableViewAccessibility") // performClick is not overridden, but not needed in this case. + @Override + public boolean onTouchEvent(MotionEvent event) { + try { + final float x = event.getX(); + final float y = event.getY(); + final int action = event.getAction(); + Logger.printDebug(() -> "onTouchEvent action: " + action + " x: " + x + " y: " + y); + + // Define touch expansion for the hue bar. + RectF expandedHueRect = new RectF( + hueRect.left - TOUCH_EXPANSION, + hueRect.top, + hueRect.right + TOUCH_EXPANSION, + hueRect.bottom + ); + + switch (action) { + case MotionEvent.ACTION_DOWN: + // Calculate current handle positions. + final float hueSelectorX = hueRect.centerX(); + final float hueSelectorY = hueRect.top + (hue / 360f) * hueRect.height(); + + final float satSelectorX = saturationValueRect.left + saturation * saturationValueRect.width(); + final float valSelectorY = saturationValueRect.top + (1 - value) * saturationValueRect.height(); + + // Create hit areas for both handles. + RectF hueHitRect = new RectF( + hueSelectorX - SELECTOR_RADIUS, + hueSelectorY - SELECTOR_RADIUS, + hueSelectorX + SELECTOR_RADIUS, + hueSelectorY + SELECTOR_RADIUS + ); + RectF satValHitRect = new RectF( + satSelectorX - SELECTOR_RADIUS, + valSelectorY - SELECTOR_RADIUS, + satSelectorX + SELECTOR_RADIUS, + valSelectorY + SELECTOR_RADIUS + ); + + // Check if the touch started on a handle or within the expanded hue bar area. + if (hueHitRect.contains(x, y)) { + isDraggingHue = true; + updateHueFromTouch(y); + } else if (satValHitRect.contains(x, y)) { + isDraggingSaturation = true; + updateSaturationValueFromTouch(x, y); + } else if (expandedHueRect.contains(x, y)) { + // Handle touch within the expanded hue bar area. + isDraggingHue = true; + updateHueFromTouch(y); + } else if (saturationValueRect.contains(x, y)) { + isDraggingSaturation = true; + updateSaturationValueFromTouch(x, y); + } + break; + + case MotionEvent.ACTION_MOVE: + // Continue updating values even if touch moves outside the view. + if (isDraggingHue) { + updateHueFromTouch(y); + } else if (isDraggingSaturation) { + updateSaturationValueFromTouch(x, y); + } + break; + + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + isDraggingHue = false; + isDraggingSaturation = false; + break; + } + } catch (Exception ex) { + Logger.printException(() -> "onTouchEvent failure", ex); + } + + return true; + } + + /** + * Updates the hue value based on touch position, clamping to valid range. + * + * @param y The y-coordinate of the touch position. + */ + private void updateHueFromTouch(float y) { + // Clamp y to the hue rectangle bounds. + final float clampedY = Utils.clamp(y, hueRect.top, hueRect.bottom); + final float updatedHue = ((clampedY - hueRect.top) / hueRect.height()) * 360f; + if (hue == updatedHue) { + return; + } + + hue = updatedHue; + updateSaturationValueShader(); + updateSelectedColor(); + } + + /** + * Updates saturation and value based on touch position, clamping to valid range. + * + * @param x The x-coordinate of the touch position. + * @param y The y-coordinate of the touch position. + */ + private void updateSaturationValueFromTouch(float x, float y) { + // Clamp x and y to the saturation-value rectangle bounds. + final float clampedX = Utils.clamp(x, saturationValueRect.left, saturationValueRect.right); + final float clampedY = Utils.clamp(y, saturationValueRect.top, saturationValueRect.bottom); + + final float updatedSaturation = (clampedX - saturationValueRect.left) / saturationValueRect.width(); + final float updatedValue = 1 - ((clampedY - saturationValueRect.top) / saturationValueRect.height()); + + if (saturation == updatedSaturation && value == updatedValue) { + return; + } + saturation = updatedSaturation; + value = updatedValue; + updateSelectedColor(); + } + + /** + * Updates the selected color and notifies listeners. + */ + private void updateSelectedColor() { + final int updatedColor = Color.HSVToColor(0, new float[]{hue, saturation, value}); + + if (selectedColor != updatedColor) { + selectedColor = updatedColor; + + if (colorChangedListener != null) { + colorChangedListener.onColorChanged(updatedColor); + } + } + + // Must always redraw, otherwise if saturation is pure grey or black + // then the hue slider cannot be changed. + invalidate(); + } + + /** + * Sets the currently selected color. + * + * @param color The color to set in either ARGB or RGB format. + */ + public void setColor(@ColorInt int color) { + color &= 0x00FFFFFF; + if (selectedColor == color) { + return; + } + + // Update the selected color. + selectedColor = color; + Logger.printDebug(() -> "setColor: " + getColorString(selectedColor)); + + // Convert the ARGB color to HSV values. + float[] hsv = new float[3]; + Color.colorToHSV(color, hsv); + + // Update the hue, saturation, and value. + hue = hsv[0]; + saturation = hsv[1]; + value = hsv[2]; + + // Update the saturation-value shader based on the new hue. + updateSaturationValueShader(); + + // Notify the listener if it's set. + if (colorChangedListener != null) { + colorChangedListener.onColorChanged(selectedColor); + } + + // Invalidate the view to trigger a redraw. + invalidate(); + } + + /** + * Gets the currently selected color. + * + * @return The selected color in RGB format with no alpha channel. + */ + @ColorInt + public int getColor() { + return selectedColor; + } + + /** + * Sets the listener to be notified when the selected color changes. + * + * @param listener The listener to set. + */ + public void setOnColorChangedListener(OnColorChangedListener listener) { + colorChangedListener = listener; + } +} diff --git a/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ImportExportPreference.java b/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ImportExportPreference.java index a1d051c2b..20d2510e2 100644 --- a/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ImportExportPreference.java +++ b/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ImportExportPreference.java @@ -70,7 +70,7 @@ public class ImportExportPreference extends EditTextPreference implements Prefer // Show the user the settings in JSON format. builder.setNeutralButton(str("revanced_settings_import_copy"), (dialog, which) -> { - Utils.setClipboard(getEditText().getText().toString()); + Utils.setClipboard(getEditText().getText()); }).setPositiveButton(str("revanced_settings_import"), (dialog, which) -> { importSettings(builder.getContext(), getEditText().getText().toString()); }); diff --git a/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/LogBufferManager.java b/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/LogBufferManager.java new file mode 100644 index 000000000..4bd54c65b --- /dev/null +++ b/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/LogBufferManager.java @@ -0,0 +1,113 @@ +package app.revanced.extension.shared.settings.preference; + +import static app.revanced.extension.shared.StringRef.str; + +import java.util.Deque; +import java.util.Objects; +import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.concurrent.atomic.AtomicInteger; + +import app.revanced.extension.shared.Logger; +import app.revanced.extension.shared.Utils; +import app.revanced.extension.shared.settings.BaseSettings; + +/** + * Manages a buffer for storing debug logs from {@link Logger}. + * Stores just under 1MB of the most recent log data. + * + * All methods are thread-safe. + */ +public final class LogBufferManager { + /** Maximum byte size of all buffer entries. Must be less than Android's 1 MB Binder transaction limit. */ + private static final int BUFFER_MAX_BYTES = 900_000; + /** Limit number of log lines. */ + private static final int BUFFER_MAX_SIZE = 10_000; + + private static final Deque logBuffer = new ConcurrentLinkedDeque<>(); + private static final AtomicInteger logBufferByteSize = new AtomicInteger(); + + /** + * Appends a log message to the internal buffer if debugging is enabled. + * The buffer is limited to approximately {@link #BUFFER_MAX_BYTES} or {@link #BUFFER_MAX_SIZE} + * to prevent excessive memory usage. + * + * @param message The log message to append. + */ + public static void appendToLogBuffer(String message) { + Objects.requireNonNull(message); + + // It's very important that no Settings are used in this method, + // as this code is used when a context is not set and thus referencing + // a setting will crash the app. + logBuffer.addLast(message); + int newSize = logBufferByteSize.addAndGet(message.length()); + + // Remove oldest entries if over the log size limits. + while (newSize > BUFFER_MAX_BYTES || logBuffer.size() > BUFFER_MAX_SIZE) { + String removed = logBuffer.pollFirst(); + if (removed == null) { + // Thread race of two different calls to this method, and the other thread won. + return; + } + + newSize = logBufferByteSize.addAndGet(-removed.length()); + } + } + + /** + * Exports all logs from the internal buffer to the clipboard. + * Displays a toast with the result. + */ + public static void exportToClipboard() { + try { + if (!BaseSettings.DEBUG.get()) { + Utils.showToastShort(str("revanced_debug_logs_disabled")); + return; + } + + if (logBuffer.isEmpty()) { + Utils.showToastShort(str("revanced_debug_logs_none_found")); + clearLogBufferData(); // Clear toast log entry that was just created. + return; + } + + // Most (but not all) Android 13+ devices always show a "copied to clipboard" toast + // and there is no way to programmatically detect if a toast will show or not. + // Show a toast even if using Android 13+, but show ReVanced toast first (before copying to clipboard). + Utils.showToastShort(str("revanced_debug_logs_copied_to_clipboard")); + + Utils.setClipboard(String.join("\n", logBuffer)); + } catch (Exception ex) { + // Handle security exception if clipboard access is denied. + String errorMessage = String.format(str("revanced_debug_logs_failed_to_export"), ex.getMessage()); + Utils.showToastLong(errorMessage); + Logger.printDebug(() -> errorMessage, ex); + } + } + + private static void clearLogBufferData() { + // Cannot simply clear the log buffer because there is no + // write lock for both the deque and the atomic int. + // Instead pop off log entries and decrement the size one by one. + while (!logBuffer.isEmpty()) { + String removed = logBuffer.pollFirst(); + if (removed != null) { + logBufferByteSize.addAndGet(-removed.length()); + } + } + } + + /** + * Clears the internal log buffer and displays a toast with the result. + */ + public static void clearLogBuffer() { + if (!BaseSettings.DEBUG.get()) { + Utils.showToastShort(str("revanced_debug_logs_disabled")); + return; + } + + // Show toast before clearing, otherwise toast log will still remain. + Utils.showToastShort(str("revanced_debug_logs_clear_toast")); + clearLogBufferData(); + } +} diff --git a/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ReVancedAboutPreference.java b/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ReVancedAboutPreference.java index ba2facccb..161711737 100644 --- a/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ReVancedAboutPreference.java +++ b/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ReVancedAboutPreference.java @@ -8,7 +8,6 @@ import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; -import android.content.res.Configuration; import android.graphics.Color; import android.net.Uri; import android.os.Bundle; @@ -54,7 +53,7 @@ public class ReVancedAboutPreference extends Preference { } protected boolean isDarkModeEnabled() { - return Utils.isDarkModeEnabled(getContext()); + return Utils.isDarkModeEnabled(); } /** diff --git a/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/SortedListPreference.java b/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/SortedListPreference.java index c5d166a7f..b1de29ee2 100644 --- a/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/SortedListPreference.java +++ b/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/SortedListPreference.java @@ -6,9 +6,8 @@ import android.util.AttributeSet; import android.util.Pair; import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import java.util.SortedMap; -import java.util.TreeMap; import app.revanced.extension.shared.Utils; @@ -46,17 +45,25 @@ public class SortedListPreference extends ListPreference { } List> firstEntries = new ArrayList<>(firstEntriesToPreserve); - SortedMap> lastEntries = new TreeMap<>(); + + // Android does not have a triple class like Kotlin, So instead use a nested pair. + // Cannot easily use a SortedMap, because if two entries incorrectly have + // identical names then the duplicates entries are not preserved. + List>> lastEntries = new ArrayList<>(); for (int i = 0; i < entrySize; i++) { Pair pair = new Pair<>(entries[i], entryValues[i]); if (i < firstEntriesToPreserve) { firstEntries.add(pair); } else { - lastEntries.put(Utils.removePunctuationToLowercase(pair.first), pair); + lastEntries.add(new Pair<>(Utils.removePunctuationToLowercase(pair.first), pair)); } } + //noinspection ComparatorCombinators + Collections.sort(lastEntries, (pair1, pair2) + -> pair1.first.compareTo(pair2.first)); + CharSequence[] sortedEntries = new CharSequence[entrySize]; CharSequence[] sortedEntryValues = new CharSequence[entrySize]; @@ -67,9 +74,10 @@ public class SortedListPreference extends ListPreference { i++; } - for (Pair pair : lastEntries.values()) { - sortedEntries[i] = pair.first; - sortedEntryValues[i] = pair.second; + for (Pair> outer : lastEntries) { + Pair inner = outer.second; + sortedEntries[i] = inner.first; + sortedEntryValues[i] = inner.second; i++; } diff --git a/extensions/shared/library/src/main/java/app/revanced/extension/shared/spoof/requests/PlayerRoutes.java b/extensions/shared/library/src/main/java/app/revanced/extension/shared/spoof/requests/PlayerRoutes.java index f45e890d5..5179b3e5f 100644 --- a/extensions/shared/library/src/main/java/app/revanced/extension/shared/spoof/requests/PlayerRoutes.java +++ b/extensions/shared/library/src/main/java/app/revanced/extension/shared/spoof/requests/PlayerRoutes.java @@ -71,9 +71,7 @@ final class PlayerRoutes { return innerTubeBody.toString(); } - /** - * @noinspection SameParameterValue - */ + @SuppressWarnings("SameParameterValue") static HttpURLConnection getPlayerResponseConnectionFromRoute(Route.CompiledRoute route, ClientType clientType) throws IOException { var connection = Requester.getConnectionFromCompiledRoute(YT_API_URL, route); diff --git a/extensions/spotify/build.gradle.kts b/extensions/spotify/build.gradle.kts index 4a5ce935d..f4da3ba6f 100644 --- a/extensions/spotify/build.gradle.kts +++ b/extensions/spotify/build.gradle.kts @@ -10,7 +10,7 @@ android { } compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 } } diff --git a/extensions/spotify/src/main/java/app/revanced/extension/spotify/layout/hide/createbutton/HideCreateButtonPatch.java b/extensions/spotify/src/main/java/app/revanced/extension/spotify/layout/hide/createbutton/HideCreateButtonPatch.java new file mode 100644 index 000000000..f3003bb31 --- /dev/null +++ b/extensions/spotify/src/main/java/app/revanced/extension/spotify/layout/hide/createbutton/HideCreateButtonPatch.java @@ -0,0 +1,51 @@ +package app.revanced.extension.spotify.layout.hide.createbutton; + +import java.util.List; + +import app.revanced.extension.shared.Utils; + +@SuppressWarnings("unused") +public final class HideCreateButtonPatch { + + /** + * A list of ids of resources which contain the Create button title. + */ + private static final List CREATE_BUTTON_TITLE_RES_ID_LIST = List.of( + Integer.toString(Utils.getResourceIdentifier("navigationbar_musicappitems_create_title", "string")) + ); + + /** + * The old id of the resource which contained the Create button title. Used in older versions of the app. + */ + private static final int OLD_CREATE_BUTTON_TITLE_RES_ID = + Utils.getResourceIdentifier("bottom_navigation_bar_create_tab_title", "string"); + + /** + * Injection point. This method is called on every navigation bar item to check whether it is the Create button. + * If the navigation bar item is the Create button, it returns null to erase it. + * The method fingerprint used to patch ensures we can safely return null here. + */ + public static Object returnNullIfIsCreateButton(Object navigationBarItem) { + if (navigationBarItem == null) { + return null; + } + + String stringifiedNavigationBarItem = navigationBarItem.toString(); + boolean isCreateButton = CREATE_BUTTON_TITLE_RES_ID_LIST.stream() + .anyMatch(stringifiedNavigationBarItem::contains); + + if (isCreateButton) { + return null; + } + + return navigationBarItem; + } + + /** + * Injection point. Called in older versions of the app. Returns whether the old navigation bar item is the old + * Create button. + */ + public static boolean isOldCreateButton(int oldNavigationBarItemTitleResId) { + return oldNavigationBarItemTitleResId == OLD_CREATE_BUTTON_TITLE_RES_ID; + } +} diff --git a/extensions/spotify/src/main/java/app/revanced/extension/spotify/layout/theme/CustomThemePatch.java b/extensions/spotify/src/main/java/app/revanced/extension/spotify/layout/theme/CustomThemePatch.java index 8949b9b2d..ef3932501 100644 --- a/extensions/spotify/src/main/java/app/revanced/extension/spotify/layout/theme/CustomThemePatch.java +++ b/extensions/spotify/src/main/java/app/revanced/extension/spotify/layout/theme/CustomThemePatch.java @@ -8,15 +8,54 @@ import app.revanced.extension.shared.Utils; @SuppressWarnings("unused") public final class CustomThemePatch { + private static final int BACKGROUND_COLOR = getColorFromString("@color/gray_7"); + private static final int BACKGROUND_COLOR_SECONDARY = getColorFromString("@color/gray_15"); + private static final int ACCENT_COLOR = getColorFromString("@color/spotify_green_157"); + private static final int ACCENT_PRESSED_COLOR = + getColorFromString("@color/dark_brightaccent_background_press"); + /** - * Injection point. + * Returns an int representation of the color resource or hex code. */ - public static long getThemeColor(String colorString) { + private static int getColorFromString(String colorString) { try { return Utils.getColorFromString(colorString); } catch (Exception ex) { - Logger.printException(() -> "Invalid custom color: " + colorString, ex); + Logger.printException(() -> "Invalid color string: " + colorString, ex); return Color.BLACK; } } + + /** + * Injection point. Returns an int representation of the replaced color from the original color. + */ + public static int replaceColor(int originalColor) { + switch (originalColor) { + // Playlist background color. + case 0xFF121212: + return BACKGROUND_COLOR; + + // Share menu background color. + case 0xFF1F1F1F: + // Home category pills background color. + case 0xFF333333: + // Settings header background color. + case 0xFF282828: + // Spotify Connect device list background color. + case 0xFF2A2A2A: + return BACKGROUND_COLOR_SECONDARY; + + // Some Lottie animations have a color that's slightly off due to rounding errors. + case 0xFF1ED760: case 0xFF1ED75F: + // Intermediate color used in some animations, same rounding issue. + case 0xFF1DB954: case 0xFF1CB854: + return ACCENT_COLOR; + + case 0xFF1ABC54: + return ACCENT_PRESSED_COLOR; + + default: + return originalColor; + } + } } diff --git a/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/UnlockPremiumPatch.java b/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/UnlockPremiumPatch.java index f9371db44..f01fee831 100644 --- a/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/UnlockPremiumPatch.java +++ b/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/UnlockPremiumPatch.java @@ -10,6 +10,7 @@ import java.util.Map; import java.util.Objects; import app.revanced.extension.shared.Logger; +import app.revanced.extension.shared.Utils; @SuppressWarnings("unused") public final class UnlockPremiumPatch { @@ -22,15 +23,15 @@ public final class UnlockPremiumPatch { private static final boolean IS_SPOTIFY_LEGACY_APP_TARGET; static { - boolean legacy; + boolean isLegacy; try { Class.forName(SPOTIFY_MAIN_ACTIVITY_LEGACY); - legacy = true; + isLegacy = true; } catch (ClassNotFoundException ex) { - legacy = false; + isLegacy = false; } - IS_SPOTIFY_LEGACY_APP_TARGET = legacy; + IS_SPOTIFY_LEGACY_APP_TARGET = isLegacy; } private static class OverrideAttribute { @@ -61,11 +62,12 @@ public final class UnlockPremiumPatch { } } - private static final List OVERRIDES = List.of( + private static final List PREMIUM_OVERRIDES = List.of( // Disables player and app ads. new OverrideAttribute("ads", FALSE), // Works along on-demand, allows playing any song without restriction. new OverrideAttribute("player-license", "premium"), + new OverrideAttribute("player-license-v2", "premium", !IS_SPOTIFY_LEGACY_APP_TARGET), // Disables shuffle being initially enabled when first playing a playlist. new OverrideAttribute("shuffle", FALSE), // Allows playing any song on-demand, without a shuffled order. @@ -91,18 +93,46 @@ public final class UnlockPremiumPatch { new OverrideAttribute("tablet-free", FALSE, false) ); + /** + * A list of home sections feature types ids which should be removed. These ids match the ones from the protobuf + * response which delivers home sections. + */ private static final List REMOVED_HOME_SECTIONS = List.of( Section.VIDEO_BRAND_AD_FIELD_NUMBER, Section.IMAGE_BRAND_AD_FIELD_NUMBER ); + /** + * A list of lists which contain strings that match whether a context menu item should be filtered out. + * The main approach used is matching context menu items by the id of their text resource. + */ + private static final List> FILTERED_CONTEXT_MENU_ITEMS_BY_STRINGS = List.of( + // "Listen to music ad-free" upsell on playlists. + List.of(getResourceIdentifier("context_menu_remove_ads")), + // "Listen to music ad-free" upsell on albums. + List.of(getResourceIdentifier("playlist_entity_reinventfree_adsfree_context_menu_item")), + // "Start a Jam" context menu item, but only filtered if the user does not have premium and the item is + // being used as a Premium upsell (ad). + List.of( + getResourceIdentifier("group_session_context_menu_start"), + "isPremiumUpsell=true" + ) + ); + + /** + * Utility method for returning resources ids as strings. + */ + private static String getResourceIdentifier(String resourceIdentifierName) { + return Integer.toString(Utils.getResourceIdentifier(resourceIdentifierName, "id")); + } + /** * Injection point. Override account attributes. */ - public static void overrideAttribute(Map attributes) { + public static void overrideAttributes(Map attributes) { try { - for (var override : OVERRIDES) { - var attribute = attributes.get(override.key); + for (OverrideAttribute override : PREMIUM_OVERRIDES) { + Object attribute = attributes.get(override.key); if (attribute == null) { if (override.isExpected) { Logger.printException(() -> "'" + override.key + "' expected but not found"); @@ -117,12 +147,12 @@ public final class UnlockPremiumPatch { } } } catch (Exception ex) { - Logger.printException(() -> "overrideAttribute failure", ex); + Logger.printException(() -> "overrideAttributes failure", ex); } } /** - * Injection point. Remove station data from Google assistant URI. + * Injection point. Remove station data from Google Assistant URI. */ public static String removeStationString(String spotifyUriOrUrl) { return spotifyUriOrUrl.replace("spotify:station:", "spotify:"); @@ -130,7 +160,7 @@ public final class UnlockPremiumPatch { /** * Injection point. Remove ads sections from home. - * Depends on patching protobuffer list remove method. + * Depends on patching abstract protobuf list ensureIsMutable method. */ public static void removeHomeSections(List

sections) { try { @@ -139,4 +169,17 @@ public final class UnlockPremiumPatch { Logger.printException(() -> "Remove home sections failure", ex); } } + + /** + * Injection point. Returns whether the context menu item is a Premium ad. + */ + public static boolean isFilteredContextMenuItem(Object contextMenuItem) { + if (contextMenuItem == null) { + return false; + } + + String stringifiedContextMenuItem = contextMenuItem.toString(); + return FILTERED_CONTEXT_MENU_ITEMS_BY_STRINGS.stream() + .anyMatch(filters -> filters.stream().allMatch(stringifiedContextMenuItem::contains)); + } } diff --git a/extensions/spotify/stub/build.gradle.kts b/extensions/spotify/stub/build.gradle.kts index a8da923ed..61a9e204a 100644 --- a/extensions/spotify/stub/build.gradle.kts +++ b/extensions/spotify/stub/build.gradle.kts @@ -7,11 +7,11 @@ android { compileSdk = 34 defaultConfig { - minSdk = 26 + minSdk = 24 } compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 } } diff --git a/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/Utils.java b/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/Utils.java index 63f4b0127..d1d0f089f 100644 --- a/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/Utils.java +++ b/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/Utils.java @@ -2,7 +2,6 @@ package app.revanced.extension.tiktok; import static app.revanced.extension.shared.Utils.isDarkModeEnabled; -import android.content.Context; import android.graphics.Color; import android.view.View; import android.widget.TextView; @@ -43,8 +42,8 @@ public class Utils { private static final @ColorInt int TEXT_LIGHT_MODE_SUMMARY = Color.argb(255, 80, 80, 80); - public static void setTitleAndSummaryColor(Context context, View view) { - final boolean darkModeEnabled = isDarkModeEnabled(context); + public static void setTitleAndSummaryColor(View view) { + final boolean darkModeEnabled = isDarkModeEnabled(); TextView title = view.findViewById(android.R.id.title); title.setTextColor(darkModeEnabled diff --git a/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/DownloadPathPreference.java b/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/DownloadPathPreference.java index fb4e27121..f387c68f5 100644 --- a/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/DownloadPathPreference.java +++ b/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/DownloadPathPreference.java @@ -101,7 +101,7 @@ public class DownloadPathPreference extends DialogPreference { protected void onBindView(View view) { super.onBindView(view); - Utils.setTitleAndSummaryColor(getContext(), view); + Utils.setTitleAndSummaryColor(view); } @Override diff --git a/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/InputTextPreference.java b/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/InputTextPreference.java index d2df31462..a4785c955 100644 --- a/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/InputTextPreference.java +++ b/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/InputTextPreference.java @@ -22,6 +22,6 @@ public class InputTextPreference extends EditTextPreference { protected void onBindView(View view) { super.onBindView(view); - Utils.setTitleAndSummaryColor(getContext(), view); + Utils.setTitleAndSummaryColor(view); } } diff --git a/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/RangeValuePreference.java b/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/RangeValuePreference.java index 012d334f0..a13438a90 100644 --- a/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/RangeValuePreference.java +++ b/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/RangeValuePreference.java @@ -127,7 +127,7 @@ public class RangeValuePreference extends DialogPreference { protected void onBindView(View view) { super.onBindView(view); - Utils.setTitleAndSummaryColor(getContext(), view); + Utils.setTitleAndSummaryColor(view); } @Override diff --git a/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/ReVancedTikTokAboutPreference.java b/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/ReVancedTikTokAboutPreference.java index 408bab6c0..7348ccc70 100644 --- a/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/ReVancedTikTokAboutPreference.java +++ b/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/ReVancedTikTokAboutPreference.java @@ -48,6 +48,6 @@ public class ReVancedTikTokAboutPreference extends ReVancedAboutPreference { protected void onBindView(View view) { super.onBindView(view); - Utils.setTitleAndSummaryColor(getContext(), view); + Utils.setTitleAndSummaryColor(view); } } diff --git a/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/TogglePreference.java b/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/TogglePreference.java index f0e8085f0..7a78d504d 100644 --- a/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/TogglePreference.java +++ b/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/settings/preference/TogglePreference.java @@ -22,6 +22,6 @@ public class TogglePreference extends SwitchPreference { protected void onBindView(View view) { super.onBindView(view); - Utils.setTitleAndSummaryColor(getContext(), view); + Utils.setTitleAndSummaryColor(view); } } diff --git a/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/spoof/sim/SpoofSimPatch.java b/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/spoof/sim/SpoofSimPatch.java index d2557e05c..d3e1baf7b 100644 --- a/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/spoof/sim/SpoofSimPatch.java +++ b/extensions/tiktok/src/main/java/app/revanced/extension/tiktok/spoof/sim/SpoofSimPatch.java @@ -16,9 +16,7 @@ public class SpoofSimPatch { return false; } - Logger.initializationException(SpoofSimPatch.class, - "Context is not yet set, cannot spoof: " + fieldSpoofed, null); - + Logger.initializationException(() -> "Context is not yet set, cannot spoof: " + fieldSpoofed, null); return true; } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/ThemeHelper.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/ThemeHelper.java index 0177c9cbc..d6594f20d 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/ThemeHelper.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/ThemeHelper.java @@ -105,6 +105,14 @@ public class ThemeHelper { return isDarkTheme() ? getLightThemeColor() : getDarkThemeColor(); } + public static int getDialogBackgroundColor() { + final String colorName = isDarkTheme() + ? "yt_black1" + : "yt_white1"; + + return Utils.getColorFromString(colorName); + } + public static int getToolbarBackgroundColor() { final String colorName = isDarkTheme() ? "yt_black3" diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/AlternativeThumbnailsPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/AlternativeThumbnailsPatch.java index c670a79de..a4dd50fcc 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/AlternativeThumbnailsPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/AlternativeThumbnailsPatch.java @@ -686,7 +686,7 @@ public final class AlternativeThumbnailsPatch { ? "" : fullUrl.substring(imageExtensionEndIndex); } - /** @noinspection SameParameterValue */ + @SuppressWarnings("SameParameterValue") String createStillsUrl(@NonNull ThumbnailQuality qualityToUse, boolean includeViewTracking) { // Images could be upgraded to webp if they are not already, but this fails quite often, // especially for new videos uploaded in the last hour. diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/DisableHapticFeedbackPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/DisableHapticFeedbackPatch.java new file mode 100644 index 000000000..6ae49427a --- /dev/null +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/DisableHapticFeedbackPatch.java @@ -0,0 +1,35 @@ +package app.revanced.extension.youtube.patches; + +import app.revanced.extension.youtube.settings.Settings; + +@SuppressWarnings("unused") +public class DisableHapticFeedbackPatch { + + /** + * Injection point. + */ + public static boolean disableChapterVibrate() { + return Settings.DISABLE_HAPTIC_FEEDBACK_CHAPTERS.get(); + } + + /** + * Injection point. + */ + public static boolean disableSeekUndoVibrate() { + return Settings.DISABLE_HAPTIC_FEEDBACK_SEEK_UNDO.get(); + } + + /** + * Injection point. + */ + public static boolean disablePreciseSeekingVibrate() { + return Settings.DISABLE_HAPTIC_FEEDBACK_PRECISE_SEEKING.get(); + } + + /** + * Injection point. + */ + public static boolean disableZoomVibrate() { + return Settings.DISABLE_HAPTIC_FEEDBACK_ZOOM.get(); + } +} diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/NavigationButtonsPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/NavigationButtonsPatch.java index d2e1d5f8b..7021cc6f9 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/NavigationButtonsPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/NavigationButtonsPatch.java @@ -95,7 +95,7 @@ public final class NavigationButtonsPatch { return false; } - return Utils.isDarkModeEnabled(Utils.getContext()) + return Utils.isDarkModeEnabled() ? !DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK : !DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT; } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/OpenShortsInRegularPlayerPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/OpenShortsInRegularPlayerPatch.java index abe3b0cfd..e0a1e3c70 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/OpenShortsInRegularPlayerPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/OpenShortsInRegularPlayerPatch.java @@ -31,6 +31,8 @@ public class OpenShortsInRegularPlayerPatch { private static WeakReference mainActivityRef = new WeakReference<>(null); + private static volatile boolean overrideBackPressToExit; + /** * Injection point. */ @@ -38,6 +40,18 @@ public class OpenShortsInRegularPlayerPatch { mainActivityRef = new WeakReference<>(activity); } + /** + * Injection point. + */ + public static boolean overrideBackPressToExit(boolean original) { + if (overrideBackPressToExit) { + Logger.printDebug(() -> "Overriding back press to exit activity"); + return false; + } + + return original; + } + /** * Injection point. */ @@ -45,6 +59,7 @@ public class OpenShortsInRegularPlayerPatch { try { ShortsPlayerType type = Settings.SHORTS_PLAYER_TYPE.get(); if (type == ShortsPlayerType.SHORTS_PLAYER) { + overrideBackPressToExit = false; return false; // Default unpatched behavior. } @@ -61,13 +76,17 @@ public class OpenShortsInRegularPlayerPatch { // set to open in the regular player, so it's ignored as // checking the map makes the patch more complicated. Logger.printDebug(() -> "Ignoring Short with no videoId"); + overrideBackPressToExit = false; return false; } if (NavigationButton.getSelectedNavigationButton() == NavigationButton.SHORTS) { + overrideBackPressToExit = false; return false; // Always use Shorts player for the Shorts nav button. } + overrideBackPressToExit = true; + final boolean forceFullScreen = (type == ShortsPlayerType.REGULAR_PLAYER_FULLSCREEN); OpenVideosFullscreenHookPatch.setOpenNextVideoFullscreen(forceFullScreen); diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/OpenVideosFullscreenHookPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/OpenVideosFullscreenHookPatch.java index 62f9bbff9..ff2d77874 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/OpenVideosFullscreenHookPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/OpenVideosFullscreenHookPatch.java @@ -33,7 +33,7 @@ public class OpenVideosFullscreenHookPatch { } if (!isFullScreenPatchIncluded()) { - return false; + return original; } return Settings.OPEN_VIDEOS_FULLSCREEN_PORTRAIT.get(); diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/ReturnYouTubeDislikePatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/ReturnYouTubeDislikePatch.java index 2db744ae6..bb351b66b 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/ReturnYouTubeDislikePatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/ReturnYouTubeDislikePatch.java @@ -152,11 +152,13 @@ public class ReturnYouTubeDislikePatch { return original; // No need to check for Shorts in the context. } - if (conversionContextString.contains("|shorts_dislike_button.eml")) { + if (Utils.containsAny(conversionContextString, + "|shorts_dislike_button.eml", "|reel_dislike_button.eml")) { return getShortsSpan(original, true); } - if (conversionContextString.contains("|shorts_like_button.eml")) { + if (Utils.containsAny(conversionContextString, + "|shorts_like_button.eml", "|reel_like_button.eml")) { if (!Utils.containsNumber(original)) { Logger.printDebug(() -> "Replacing hidden likes count"); return getShortsSpan(original, false); @@ -361,6 +363,11 @@ public class ReturnYouTubeDislikePatch { if (videoId.equals(lastPrefetchedVideoId)) { return; } + if (!Utils.isNetworkConnected()) { + Logger.printDebug(() -> "Cannot pre-fetch RYD, network is not connected"); + lastPrefetchedVideoId = null; + return; + } final boolean videoIdIsShort = VideoInformation.lastPlayerResponseIsShort(); // Shorts shelf in home and subscription feed causes player response hook to be called, @@ -415,6 +422,12 @@ public class ReturnYouTubeDislikePatch { } Logger.printDebug(() -> "New video id: " + videoId + " playerType: " + currentPlayerType); + if (!Utils.isNetworkConnected()) { + Logger.printDebug(() -> "Cannot fetch RYD, network is not connected"); + currentVideoData = null; + return; + } + ReturnYouTubeDislike data = ReturnYouTubeDislike.getFetchForVideoId(videoId); // Pre-emptively set the data to short status. // Required to prevent Shorts data from being used on a minimized video in incognito mode. diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/VideoInformation.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/VideoInformation.java index 6df9a9095..99d8a5b6a 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/VideoInformation.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/VideoInformation.java @@ -354,4 +354,23 @@ public final class VideoInformation { return videoTime >= videoLength && videoLength > 0; } + /** + * Overrides the current playback speed. + * Rest of the implementation added by patch. + */ + public static void overridePlaybackSpeed(float speedOverride) { + Logger.printDebug(() -> "Overriding playback speed to: " + speedOverride); + } + + /** + * Injection point. + * + * @param newlyLoadedPlaybackSpeed The current playback speed. + */ + public static void setPlaybackSpeed(float newlyLoadedPlaybackSpeed) { + if (playbackSpeed != newlyLoadedPlaybackSpeed) { + Logger.printDebug(() -> "Video speed changed: " + newlyLoadedPlaybackSpeed); + playbackSpeed = newlyLoadedPlaybackSpeed; + } + } } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/WideSearchbarPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/WideSearchbarPatch.java index 90f18a6c2..2b07a2f73 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/WideSearchbarPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/WideSearchbarPatch.java @@ -1,7 +1,5 @@ package app.revanced.extension.youtube.patches; -import android.content.res.Resources; -import android.util.TypedValue; import android.view.View; import app.revanced.extension.shared.Logger; @@ -33,8 +31,7 @@ public final class WideSearchbarPatch { final int paddingRight = searchBarView.getPaddingRight(); final int paddingTop = searchBarView.getPaddingTop(); final int paddingBottom = searchBarView.getPaddingBottom(); - final int paddingStart = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, - 8, Resources.getSystem().getDisplayMetrics()); + final int paddingStart = Utils.dipToPixels(8); if (Utils.isRightToLeftLocale()) { searchBarView.setPadding(paddingLeft, paddingTop, paddingStart, paddingBottom); diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/ZoomHapticsPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/ZoomHapticsPatch.java deleted file mode 100644 index 0367eb868..000000000 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/ZoomHapticsPatch.java +++ /dev/null @@ -1,10 +0,0 @@ -package app.revanced.extension.youtube.patches; - -import app.revanced.extension.youtube.settings.Settings; - -@SuppressWarnings("unused") -public class ZoomHapticsPatch { - public static boolean shouldVibrate() { - return !Settings.DISABLE_ZOOM_HAPTICS.get(); - } -} diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/AdsFilter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/AdsFilter.java index 78015ea79..1572c4b72 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/AdsFilter.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/AdsFilter.java @@ -64,48 +64,45 @@ public final class AdsFilter extends Filter { "_interstitial" ); - final var buttonedAd = new StringFilterGroup( - Settings.HIDE_BUTTONED_ADS, - "_ad_with", - "_buttoned_layout", - // text_image_button_group_layout, landscape_image_button_group_layout, full_width_square_image_button_group_layout - "image_button_group_layout", - "full_width_square_image_layout", - "video_display_button_group_layout", - "landscape_image_wide_button_layout", - "video_display_carousel_button_group_layout", - "video_display_full_buttoned_short_dr_layout", - "compact_landscape_image_layout", // Tablet layout search results. - "text_image_no_button_layout" // Tablet layout search results. - ); - final var generalAds = new StringFilterGroup( Settings.HIDE_GENERAL_ADS, + "_ad_with", + "_buttoned_layout", "ads_video_with_context", "banner_text_icon", - "square_image_layout", - "watch_metadata_app_promo", - "video_display_full_layout", - "hero_promo_image", - "statement_banner", + "brand_video_shelf", + "brand_video_singleton", "carousel_footered_layout", - "text_image_button_layout", + "carousel_headered_layout", + "compact_landscape_image_layout", // Tablet layout search results. + "composite_concurrent_carousel_layout", + "full_width_portrait_image_layout", + "full_width_square_image_carousel_layout", + "full_width_square_image_layout", + "hero_promo_image", + // text_image_button_group_layout, landscape_image_button_group_layout, full_width_square_image_button_group_layout + "image_button_group_layout", + "landscape_image_wide_button_layout", "primetime_promo", "product_details", - "composite_concurrent_carousel_layout", - "carousel_headered_layout", - "full_width_portrait_image_layout", - "brand_video_shelf", - "brand_video_singleton" + "square_image_layout", + "statement_banner", + "text_image_button_layout", + "text_image_no_button_layout", // Tablet layout search results. + "video_display_button_group_layout", + "video_display_carousel_button_group_layout", + "video_display_full_buttoned_short_dr_layout", + "video_display_full_layout", + "watch_metadata_app_promo" ); final var movieAds = new StringFilterGroup( Settings.HIDE_MOVIES_SECTION, "browsy_bar", "compact_movie", + "compact_tvfilm_item", "horizontal_movie_shelf", "movie_and_show_upsell_card", - "compact_tvfilm_item", "offer_module_root" ); @@ -160,7 +157,6 @@ public final class AdsFilter extends Filter { addPathCallbacks( generalAds, - buttonedAd, merchandise, viewProducts, selfSponsor, @@ -181,17 +177,19 @@ public final class AdsFilter extends Filter { } // Check for the index because of likelihood of false positives. - if (matchedGroup == shoppingLinks && contentIndex != 0) { + if (contentIndex != 0 && matchedGroup == shoppingLinks) { return false; } - if (exceptions.matches(path)) + if (exceptions.matches(path)) { return false; + } if (matchedGroup == fullscreenAd) { if (path.contains("|ImageType|")) closeFullscreenAd(); - return false; // Do not actually filter the fullscreen ad otherwise it will leave a dimmed screen. + // Do not actually filter the fullscreen ad otherwise it will leave a dimmed screen. + return false; } if (matchedGroup == channelProfile) { diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilterPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilterPatch.java index d630ee9ed..531578a8b 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilterPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilterPatch.java @@ -10,18 +10,11 @@ import app.revanced.extension.youtube.settings.Settings; */ public final class PlaybackSpeedMenuFilterPatch extends Filter { - /** - * Old litho based speed selection menu. - */ - public static volatile boolean isOldPlaybackSpeedMenuVisible; - /** * 0.05x speed selection menu. */ public static volatile boolean isPlaybackRateSelectorMenuVisible; - private final StringFilterGroup oldPlaybackMenuGroup; - public PlaybackSpeedMenuFilterPatch() { // 0.05x litho speed menu. var playbackRateSelectorGroup = new StringFilterGroup( @@ -29,22 +22,13 @@ public final class PlaybackSpeedMenuFilterPatch extends Filter { "playback_rate_selector_menu_sheet.eml-js" ); - // Old litho based speed menu. - oldPlaybackMenuGroup = new StringFilterGroup( - Settings.CUSTOM_SPEED_MENU, - "playback_speed_sheet_content.eml-js"); - - addPathCallbacks(playbackRateSelectorGroup, oldPlaybackMenuGroup); + addPathCallbacks(playbackRateSelectorGroup); } @Override boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { - if (matchedGroup == oldPlaybackMenuGroup) { - isOldPlaybackSpeedMenuVisible = true; - } else { - isPlaybackRateSelectorMenuVisible = true; - } + isPlaybackRateSelectorMenuVisible = true; return false; } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ShortsFilter.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ShortsFilter.java index ef1cd5bb5..752cca7cb 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ShortsFilter.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/ShortsFilter.java @@ -143,12 +143,14 @@ public final class ShortsFilter extends Filter { StringFilterGroup likeButton = new StringFilterGroup( Settings.HIDE_SHORTS_LIKE_BUTTON, - "shorts_like_button.eml" + "shorts_like_button.eml", + "reel_like_button.eml" ); StringFilterGroup dislikeButton = new StringFilterGroup( Settings.HIDE_SHORTS_DISLIKE_BUTTON, - "shorts_dislike_button.eml" + "shorts_dislike_button.eml", + "reel_dislike_button.eml" ); joinButton = new StringFilterGroup( @@ -168,12 +170,13 @@ public final class ShortsFilter extends Filter { shortsActionBar = new StringFilterGroup( null, - "shorts_action_bar.eml" + "shorts_action_bar.eml", + "reel_action_bar.eml" ); actionButton = new StringFilterGroup( null, - // Can be simply 'button.eml' or 'shorts_video_action_button.eml' + // Can be simply 'button.eml', 'shorts_video_action_button.eml' or 'reel_action_button.eml' "button.eml" ); @@ -195,15 +198,18 @@ public final class ShortsFilter extends Filter { videoActionButtonGroupList.addAll( new ByteArrayFilterGroup( Settings.HIDE_SHORTS_COMMENTS_BUTTON, - "reel_comment_button" + "reel_comment_button", + "youtube_shorts_comment_outline" ), new ByteArrayFilterGroup( Settings.HIDE_SHORTS_SHARE_BUTTON, - "reel_share_button" + "reel_share_button", + "youtube_shorts_share_outline" ), new ByteArrayFilterGroup( Settings.HIDE_SHORTS_REMIX_BUTTON, - "reel_remix_button" + "reel_remix_button", + "youtube_shorts_remix_outline" ) ); @@ -211,6 +217,12 @@ public final class ShortsFilter extends Filter { // Suggested actions. // suggestedActionsGroupList.addAll( + new ByteArrayFilterGroup( + Settings.HIDE_SHORTS_COMMENT_PANEL, + // 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_" diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java index 9b6224106..4c509bccb 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java @@ -1,24 +1,57 @@ package app.revanced.extension.youtube.patches.playback.speed; import static app.revanced.extension.shared.StringRef.str; +import static app.revanced.extension.shared.Utils.dipToPixels; +import android.annotation.SuppressLint; +import android.app.Dialog; +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.graphics.Rect; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.shapes.RoundRectShape; +import android.icu.text.NumberFormat; import android.support.v7.widget.RecyclerView; +import android.view.animation.Animation; +import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; +import android.view.Window; +import android.view.WindowManager; +import android.widget.Button; +import android.widget.FrameLayout; +import android.widget.GridLayout; +import android.widget.LinearLayout; +import android.widget.SeekBar; +import android.widget.TextView; +import java.lang.ref.WeakReference; import java.util.Arrays; +import java.util.function.Function; import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Utils; +import app.revanced.extension.youtube.ThemeHelper; +import app.revanced.extension.youtube.patches.VideoInformation; import app.revanced.extension.youtube.patches.components.PlaybackSpeedMenuFilterPatch; import app.revanced.extension.youtube.settings.Settings; +import app.revanced.extension.youtube.shared.PlayerType; +import kotlin.Unit; +import kotlin.jvm.functions.Function1; @SuppressWarnings("unused") public class CustomPlaybackSpeedPatch { /** - * Maximum playback speed, exclusive value. Custom speeds must be less than this value. + * Maximum playback speed, inclusive. Custom speeds must be this or less. *

* Going over 8x does not increase the actual playback speed any higher, * and the UI selector starts flickering and acting weird. @@ -26,6 +59,11 @@ public class CustomPlaybackSpeedPatch { */ public static final float PLAYBACK_SPEED_MAXIMUM = 8; + /** + * Scale used to convert user speed to {@link android.widget.ProgressBar#setProgress(int)}. + */ + private static final float PROGRESS_BAR_VALUE_SCALE = 100; + /** * Tap and hold speed. */ @@ -34,16 +72,28 @@ public class CustomPlaybackSpeedPatch { /** * Custom playback speeds. */ - public static float[] customPlaybackSpeeds; + public static final float[] customPlaybackSpeeds; /** - * The last time the old playback menu was forcefully called. + * Formats speeds to UI strings. */ - private static long lastTimeOldPlaybackMenuInvoked; + private static final NumberFormat speedFormatter = NumberFormat.getNumberInstance(); + + /** + * Weak reference to the currently open dialog. + */ + private static WeakReference

currentDialog = new WeakReference<>(null); + + /** + * Minimum and maximum custom playback speeds of {@link #customPlaybackSpeeds}. + */ + private static final float customPlaybackSpeedsMin, customPlaybackSpeedsMax; static { - final float holdSpeed = Settings.SPEED_TAP_AND_HOLD.get(); + // Cap at 2 decimals (rounds automatically). + speedFormatter.setMaximumFractionDigits(2); + final float holdSpeed = Settings.SPEED_TAP_AND_HOLD.get(); if (holdSpeed > 0 && holdSpeed <= PLAYBACK_SPEED_MAXIMUM) { TAP_AND_HOLD_SPEED = holdSpeed; } else { @@ -51,7 +101,9 @@ public class CustomPlaybackSpeedPatch { TAP_AND_HOLD_SPEED = Settings.SPEED_TAP_AND_HOLD.resetToDefault(); } - loadCustomSpeeds(); + customPlaybackSpeeds = loadCustomSpeeds(); + customPlaybackSpeedsMin = customPlaybackSpeeds[0]; + customPlaybackSpeedsMax = customPlaybackSpeeds[customPlaybackSpeeds.length - 1]; } /** @@ -65,37 +117,41 @@ public class CustomPlaybackSpeedPatch { Utils.showToastLong(str("revanced_custom_playback_speeds_invalid", PLAYBACK_SPEED_MAXIMUM)); } - private static void loadCustomSpeeds() { + private static float[] loadCustomSpeeds() { try { - String[] speedStrings = Settings.CUSTOM_PLAYBACK_SPEEDS.get().split("\\s+"); + // Automatically replace commas with periods, + // if the user added speeds in a localized format. + String[] speedStrings = Settings.CUSTOM_PLAYBACK_SPEEDS.get() + .replace(',', '.').split("\\s+"); Arrays.sort(speedStrings); if (speedStrings.length == 0) { throw new IllegalArgumentException(); } - customPlaybackSpeeds = new float[speedStrings.length]; + float[] speeds = new float[speedStrings.length]; int i = 0; for (String speedString : speedStrings) { final float speedFloat = Float.parseFloat(speedString); - if (speedFloat <= 0 || arrayContains(customPlaybackSpeeds, speedFloat)) { + if (speedFloat <= 0 || arrayContains(speeds, speedFloat)) { throw new IllegalArgumentException(); } - if (speedFloat >= PLAYBACK_SPEED_MAXIMUM) { + if (speedFloat > PLAYBACK_SPEED_MAXIMUM) { showInvalidCustomSpeedToast(); Settings.CUSTOM_PLAYBACK_SPEEDS.resetToDefault(); - loadCustomSpeeds(); - return; + return loadCustomSpeeds(); } - customPlaybackSpeeds[i++] = speedFloat; + speeds[i++] = speedFloat; } + + return speeds; } catch (Exception ex) { - Logger.printInfo(() -> "parse error", ex); - Utils.showToastLong(str("revanced_custom_playback_speeds_parse_exception")); + Logger.printInfo(() -> "Parse error", ex); + Utils.showToastShort(str("revanced_custom_playback_speeds_parse_exception")); Settings.CUSTOM_PLAYBACK_SPEEDS.resetToDefault(); - loadCustomSpeeds(); + return loadCustomSpeeds(); } } @@ -113,38 +169,28 @@ public class CustomPlaybackSpeedPatch { recyclerView.getViewTreeObserver().addOnDrawListener(() -> { try { if (PlaybackSpeedMenuFilterPatch.isPlaybackRateSelectorMenuVisible) { - if (hideLithoMenuAndShowOldSpeedMenu(recyclerView, 5)) { + if (hideLithoMenuAndShowCustomSpeedMenu(recyclerView, 5)) { PlaybackSpeedMenuFilterPatch.isPlaybackRateSelectorMenuVisible = false; } - return; } } catch (Exception ex) { - Logger.printException(() -> "isPlaybackRateSelectorMenuVisible failure", ex); - } - - try { - if (PlaybackSpeedMenuFilterPatch.isOldPlaybackSpeedMenuVisible) { - if (hideLithoMenuAndShowOldSpeedMenu(recyclerView, 8)) { - PlaybackSpeedMenuFilterPatch.isOldPlaybackSpeedMenuVisible = false; - } - } - } catch (Exception ex) { - Logger.printException(() -> "isOldPlaybackSpeedMenuVisible failure", ex); + Logger.printException(() -> "onFlyoutMenuCreate failure", ex); } }); } - private static boolean hideLithoMenuAndShowOldSpeedMenu(RecyclerView recyclerView, int expectedChildCount) { + @SuppressWarnings("SameParameterValue") + private static boolean hideLithoMenuAndShowCustomSpeedMenu(RecyclerView recyclerView, int expectedChildCount) { if (recyclerView.getChildCount() == 0) { return false; } View firstChild = recyclerView.getChildAt(0); - if (!(firstChild instanceof ViewGroup PlaybackSpeedParentView)) { + if (!(firstChild instanceof ViewGroup playbackSpeedParentView)) { return false; } - if (PlaybackSpeedParentView.getChildCount() != expectedChildCount) { + if (playbackSpeedParentView.getChildCount() != expectedChildCount) { return false; } @@ -168,23 +214,418 @@ public class CustomPlaybackSpeedPatch { ((ViewGroup) parentView3rd).setVisibility(View.GONE); ((ViewGroup) parentView4th).setVisibility(View.GONE); - // Close the litho speed menu and show the old one. - showOldPlaybackSpeedMenu(); + // Close the litho speed menu and show the modern custom speed dialog. + showModernCustomPlaybackSpeedDialog(recyclerView.getContext()); + Logger.printDebug(() -> "Modern playback speed dialog shown"); return true; } - public static void showOldPlaybackSpeedMenu() { - // This method is sometimes used multiple times. - // To prevent this, ignore method reuse within 1 second. - final long now = System.currentTimeMillis(); - if (now - lastTimeOldPlaybackMenuInvoked < 1000) { - Logger.printDebug(() -> "Ignoring call to showOldPlaybackSpeedMenu"); - return; - } - lastTimeOldPlaybackMenuInvoked = now; - Logger.printDebug(() -> "Old video quality menu shown"); + /** + * Displays a modern custom dialog for adjusting video playback speed. + *

+ * This method creates a dialog with a slider, plus/minus buttons, and preset speed buttons + * to allow the user to modify the video playback speed. The dialog is styled with rounded + * corners and themed colors, positioned at the bottom of the screen. The playback speed + * can be adjusted in 0.05 increments using the slider or buttons, or set directly to preset + * values. The dialog updates the displayed speed in real-time and applies changes to the + * video playback. The dialog is dismissed if the player enters Picture-in-Picture (PiP) mode. + */ + @SuppressLint("SetTextI18n") + public static void showModernCustomPlaybackSpeedDialog(Context context) { + // Create a dialog without a theme for custom appearance. + Dialog dialog = new Dialog(context); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); // Remove default title bar. - // Rest of the implementation added by patch. + // Store the dialog reference. + currentDialog = new WeakReference<>(dialog); + + // Create main vertical LinearLayout for dialog content. + LinearLayout mainLayout = new LinearLayout(context); + mainLayout.setOrientation(LinearLayout.VERTICAL); + + // Preset size constants. + final int dip4 = dipToPixels(4); // Height for handle bar. + final int dip5 = dipToPixels(5); + final int dip6 = dipToPixels(6); // Padding for mainLayout from bottom. + final int dip8 = dipToPixels(8); // Padding for mainLayout from left and right. + final int dip20 = dipToPixels(20); + final int dip32 = dipToPixels(32); // Height for in-rows speed buttons. + final int dip36 = dipToPixels(36); // Height for minus and plus buttons. + final int dip40 = dipToPixels(40); // Width for handle bar. + final int dip60 = dipToPixels(60); // Height for speed button container. + + mainLayout.setPadding(dip5, dip8, dip5, dip8); + + // Set rounded rectangle background for the main layout. + RoundRectShape roundRectShape = new RoundRectShape( + createCornerRadii(12), null, null); + ShapeDrawable background = new ShapeDrawable(roundRectShape); + background.getPaint().setColor(ThemeHelper.getDialogBackgroundColor()); + mainLayout.setBackground(background); + + // Add handle bar at the top. + View handleBar = new View(context); + ShapeDrawable handleBackground = new ShapeDrawable(new RoundRectShape( + createCornerRadii(4), null, null)); + handleBackground.getPaint().setColor(getAdjustedBackgroundColor(true)); + handleBar.setBackground(handleBackground); + LinearLayout.LayoutParams handleParams = new LinearLayout.LayoutParams( + dip40, // handle bar width. + dip4 // handle bar height. + ); + handleParams.gravity = Gravity.CENTER_HORIZONTAL; // Center horizontally. + handleParams.setMargins(0, 0, 0, dip20); // 20dp bottom margins. + handleBar.setLayoutParams(handleParams); + // Add handle bar view to main layout. + mainLayout.addView(handleBar); + + // Display current playback speed. + TextView currentSpeedText = new TextView(context); + float currentSpeed = VideoInformation.getPlaybackSpeed(); + // Initially show with only 0 minimum digits, so 1.0 shows as 1x + currentSpeedText.setText(formatSpeedStringX(currentSpeed, 0)); + currentSpeedText.setTextColor(ThemeHelper.getForegroundColor()); + currentSpeedText.setTextSize(16); + currentSpeedText.setTypeface(Typeface.DEFAULT_BOLD); + currentSpeedText.setGravity(Gravity.CENTER); + LinearLayout.LayoutParams textParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); + textParams.setMargins(0, 0, 0, 0); + currentSpeedText.setLayoutParams(textParams); + // Add current speed text view to main layout. + mainLayout.addView(currentSpeedText); + + // Create horizontal layout for slider and +/- buttons. + LinearLayout sliderLayout = new LinearLayout(context); + sliderLayout.setOrientation(LinearLayout.HORIZONTAL); + sliderLayout.setGravity(Gravity.CENTER_VERTICAL); + sliderLayout.setPadding(dip5, dip5, dip5, dip5); // 5dp padding. + + // Create minus button. + Button minusButton = new Button(context, null, 0); // Disable default theme style. + minusButton.setText(""); // No text on button. + ShapeDrawable minusBackground = new ShapeDrawable(new RoundRectShape(createCornerRadii(20), null, null)); + minusBackground.getPaint().setColor(getAdjustedBackgroundColor(false)); + minusButton.setBackground(minusBackground); + OutlineSymbolDrawable minusDrawable = new OutlineSymbolDrawable(false); // Minus symbol. + minusButton.setForeground(minusDrawable); + LinearLayout.LayoutParams minusParams = new LinearLayout.LayoutParams(dip36, dip36); + minusParams.setMargins(0, 0, dip5, 0); // 5dp to slider. + minusButton.setLayoutParams(minusParams); + + // Create slider for speed adjustment. + SeekBar speedSlider = new SeekBar(context); + speedSlider.setMax(speedToProgressValue(customPlaybackSpeedsMax)); + speedSlider.setProgress(speedToProgressValue(currentSpeed)); + speedSlider.getProgressDrawable().setColorFilter( + ThemeHelper.getForegroundColor(), PorterDuff.Mode.SRC_IN); // Theme progress bar. + speedSlider.getThumb().setColorFilter( + ThemeHelper.getForegroundColor(), PorterDuff.Mode.SRC_IN); // Theme slider thumb. + LinearLayout.LayoutParams sliderParams = new LinearLayout.LayoutParams( + 0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f); + sliderParams.setMargins(dip5, 0, dip5, 0); // 5dp to -/+ buttons. + speedSlider.setLayoutParams(sliderParams); + + // Create plus button. + Button plusButton = new Button(context, null, 0); // Disable default theme style. + plusButton.setText(""); // No text on button. + ShapeDrawable plusBackground = new ShapeDrawable(new RoundRectShape( + createCornerRadii(20), null, null)); + plusBackground.getPaint().setColor(getAdjustedBackgroundColor(false)); + plusButton.setBackground(plusBackground); + OutlineSymbolDrawable plusDrawable = new OutlineSymbolDrawable(true); // Plus symbol. + plusButton.setForeground(plusDrawable); + LinearLayout.LayoutParams plusParams = new LinearLayout.LayoutParams(dip36, dip36); + plusParams.setMargins(dip5, 0, 0, 0); // 5dp to slider. + plusButton.setLayoutParams(plusParams); + + // Add -/+ and slider views to slider layout. + sliderLayout.addView(minusButton); + sliderLayout.addView(speedSlider); + sliderLayout.addView(plusButton); + + LinearLayout.LayoutParams sliderLayoutParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); + sliderLayoutParams.setMargins(0, 0, 0, dip5); // 5dp bottom margin. + sliderLayout.setLayoutParams(sliderLayoutParams); + + // Add slider layout to main layout. + mainLayout.addView(sliderLayout); + + Function userSelectedSpeed = newSpeed -> { + final float roundedSpeed = roundSpeedToNearestIncrement(newSpeed); + if (VideoInformation.getPlaybackSpeed() == roundedSpeed) { + // Nothing has changed. New speed rounds to the current speed. + return null; + } + + VideoInformation.overridePlaybackSpeed(roundedSpeed); + RememberPlaybackSpeedPatch.userSelectedPlaybackSpeed(roundedSpeed); + currentSpeedText.setText(formatSpeedStringX(roundedSpeed, 2)); // Update display. + speedSlider.setProgress(speedToProgressValue(roundedSpeed)); // Update slider. + return null; + }; + + // Set listener for slider to update playback speed. + speedSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (fromUser) { + // Convert from progress value to video playback speed. + userSelectedSpeed.apply(customPlaybackSpeedsMin + (progress / PROGRESS_BAR_VALUE_SCALE)); + } + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) {} + + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} + }); + + minusButton.setOnClickListener(v -> userSelectedSpeed.apply( + VideoInformation.getPlaybackSpeed() - 0.05f)); + plusButton.setOnClickListener(v -> userSelectedSpeed.apply( + VideoInformation.getPlaybackSpeed() + 0.05f)); + + // Create GridLayout for preset speed buttons. + GridLayout gridLayout = new GridLayout(context); + gridLayout.setColumnCount(5); // 5 columns for speed buttons. + gridLayout.setAlignmentMode(GridLayout.ALIGN_BOUNDS); + gridLayout.setRowCount((int) Math.ceil(customPlaybackSpeeds.length / 5.0)); + LinearLayout.LayoutParams gridParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); + gridParams.setMargins(0, 0, 0, 0); // No margins around GridLayout. + gridLayout.setLayoutParams(gridParams); + + // For all buttons show at least 1 zero in decimal (2 -> "2.0"). + speedFormatter.setMinimumFractionDigits(1); + + // Add buttons for each preset playback speed. + for (float speed : customPlaybackSpeeds) { + // Container for button and optional label. + FrameLayout buttonContainer = new FrameLayout(context); + + // Set layout parameters for each grid cell. + GridLayout.LayoutParams containerParams = new GridLayout.LayoutParams(); + containerParams.width = 0; // Equal width for columns. + containerParams.columnSpec = GridLayout.spec(GridLayout.UNDEFINED, 1, 1f); + containerParams.setMargins(dip5, 0, dip5, 0); // Button margins. + containerParams.height = dip60; // Fixed height for button and label. + buttonContainer.setLayoutParams(containerParams); + + // Create speed button. + Button speedButton = new Button(context, null, 0); + speedButton.setText(speedFormatter.format(speed)); // Do not use 'x' speed format. + speedButton.setTextColor(ThemeHelper.getForegroundColor()); + speedButton.setTextSize(12); + speedButton.setAllCaps(false); + speedButton.setGravity(Gravity.CENTER); + + ShapeDrawable buttonBackground = new ShapeDrawable(new RoundRectShape( + createCornerRadii(20), null, null)); + buttonBackground.getPaint().setColor(getAdjustedBackgroundColor(false)); + speedButton.setBackground(buttonBackground); + speedButton.setPadding(dip5, dip5, dip5, dip5); + + // Center button vertically and stretch horizontally in container. + FrameLayout.LayoutParams buttonParams = new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, dip32, Gravity.CENTER); + speedButton.setLayoutParams(buttonParams); + + // Add speed buttons view to buttons container layout. + buttonContainer.addView(speedButton); + + // Add "Normal" label for 1.0x speed. + if (speed == 1.0f) { + TextView normalLabel = new TextView(context); + // Use same 'Normal' string as stock YouTube. + normalLabel.setText(str("normal_playback_rate_label")); + normalLabel.setTextColor(ThemeHelper.getForegroundColor()); + normalLabel.setTextSize(10); + normalLabel.setGravity(Gravity.CENTER); + + FrameLayout.LayoutParams labelParams = new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT, + Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL); + labelParams.bottomMargin = 0; // Position label below button. + normalLabel.setLayoutParams(labelParams); + + buttonContainer.addView(normalLabel); + } + + speedButton.setOnClickListener(v -> userSelectedSpeed.apply(speed)); + + gridLayout.addView(buttonContainer); + } + + // Add in-rows speed buttons layout to main layout. + mainLayout.addView(gridLayout); + + // Wrap mainLayout in another LinearLayout for side margins. + LinearLayout wrapperLayout = new LinearLayout(context); + wrapperLayout.setOrientation(LinearLayout.VERTICAL); + wrapperLayout.setPadding(dip8, 0, dip8, 0); // 8dp side margins. + wrapperLayout.addView(mainLayout); + dialog.setContentView(wrapperLayout); + + // Configure dialog window to appear at the bottom. + Window window = dialog.getWindow(); + if (window != null) { + WindowManager.LayoutParams params = window.getAttributes(); + params.gravity = Gravity.BOTTOM; // Position at bottom of screen. + params.y = dip6; // 6dp margin from bottom. + // In landscape, use the smaller dimension (height) as portrait width. + int portraitWidth = context.getResources().getDisplayMetrics().widthPixels; + if (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { + portraitWidth = Math.min( + portraitWidth, + context.getResources().getDisplayMetrics().heightPixels); + } + params.width = portraitWidth; // Use portrait width. + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + window.setAttributes(params); + window.setBackgroundDrawable(null); // Remove default dialog background. + } + + // Create observer for PlayerType changes. + Function1 playerTypeObserver = new Function1<>() { + @Override + public Unit invoke(PlayerType type) { + Dialog current = currentDialog.get(); + if (current == null || !current.isShowing()) { + // Should never happen. + PlayerType.getOnChange().removeObserver(this); + Logger.printException(() -> "Removing player type listener as dialog is null or closed"); + } else if (type == PlayerType.WATCH_WHILE_PICTURE_IN_PICTURE) { + current.dismiss(); + Logger.printDebug(() -> "Playback speed dialog dismissed due to PiP mode"); + } + return Unit.INSTANCE; + } + }; + + // Add observer to dismiss dialog when entering PiP mode. + PlayerType.getOnChange().addObserver(playerTypeObserver); + + // Remove observer when dialog is dismissed. + dialog.setOnDismissListener(d -> { + PlayerType.getOnChange().removeObserver(playerTypeObserver); + Logger.printDebug(() -> "PlayerType observer removed on dialog dismiss"); + }); + + // Apply slide-in animation when showing the dialog. + final int fadeDurationFast = Utils.getResourceInteger("fade_duration_fast"); + Animation slideInABottomAnimation = Utils.getResourceAnimation("slide_in_bottom"); + slideInABottomAnimation.setDuration(fadeDurationFast); + mainLayout.startAnimation(slideInABottomAnimation); + + dialog.show(); // Display the dialog. + } + + /** + * Creates an array of corner radii for a rounded rectangle shape. + * + * @param dp The radius in density-independent pixels (dp) to apply to all corners. + * @return An array of eight float values representing the corner radii + * (top-left, top-right, bottom-right, bottom-left). + */ + private static float[] createCornerRadii(float dp) { + final float radius = dipToPixels(dp); + return new float[]{radius, radius, radius, radius, radius, radius, radius, radius}; + } + + /** + * @param speed The playback speed value to format. + * @return A string representation of the speed with 'x' (e.g. "1.25x" or "1.00x"). + */ + private static String formatSpeedStringX(float speed, int minimumFractionDigits) { + speedFormatter.setMinimumFractionDigits(minimumFractionDigits); + return speedFormatter.format(speed) + 'x'; + } + + /** + * @return user speed converted to a value for {@link SeekBar#setProgress(int)}. + */ + private static int speedToProgressValue(float speed) { + return (int) ((speed - customPlaybackSpeedsMin) * PROGRESS_BAR_VALUE_SCALE); + } + + /** + * Rounds the given playback speed to the nearest 0.05 increment and ensures it is within valid bounds. + * + * @param speed The playback speed to round. + * @return The rounded speed, constrained to the specified bounds. + */ + private static float roundSpeedToNearestIncrement(float speed) { + // Round to nearest 0.05 speed. + final float roundedSpeed = Math.round(speed / 0.05f) * 0.05f; + return Utils.clamp(roundedSpeed, 0.05f, PLAYBACK_SPEED_MAXIMUM); + } + + /** + * Adjusts the background color based on the current theme. + * + * @param isHandleBar If true, applies a stronger darkening factor (0.9) for the handle bar in light theme; + * if false, applies a standard darkening factor (0.95) for other elements in light theme. + * @return A modified background color, lightened by 20% for dark themes or darkened by 5% (or 10% for handle bar) + * for light themes to ensure visual contrast. + */ + public static int getAdjustedBackgroundColor(boolean isHandleBar) { + final int baseColor = ThemeHelper.getDialogBackgroundColor(); + float darkThemeFactor = isHandleBar ? 1.25f : 1.115f; // 1.25f for handleBar, 1.115f for others in dark theme. + float lightThemeFactor = isHandleBar ? 0.9f : 0.95f; // 0.9f for handleBar, 0.95f for others in light theme. + return ThemeHelper.isDarkTheme() + ? ThemeHelper.adjustColorBrightness(baseColor, darkThemeFactor) // Lighten for dark theme. + : ThemeHelper.adjustColorBrightness(baseColor, lightThemeFactor); // Darken for light theme. + } +} + +/** + * Custom Drawable for rendering outlined plus and minus symbols on buttons. + */ +class OutlineSymbolDrawable extends Drawable { + private final boolean isPlus; // Determines if the symbol is a plus or minus. + private final Paint paint; + + OutlineSymbolDrawable(boolean isPlus) { + this.isPlus = isPlus; + paint = new Paint(Paint.ANTI_ALIAS_FLAG); // Enable anti-aliasing for smooth rendering. + paint.setColor(ThemeHelper.getForegroundColor()); + paint.setStyle(Paint.Style.STROKE); // Use stroke style for outline. + paint.setStrokeWidth(dipToPixels(1)); // 1dp stroke width. + } + + @Override + public void draw(Canvas canvas) { + Rect bounds = getBounds(); + final int width = bounds.width(); + final int height = bounds.height(); + final float centerX = width / 2f; // Center X coordinate. + final float centerY = height / 2f; // Center Y coordinate. + final float size = Math.min(width, height) * 0.25f; // Symbol size is 25% of button dimensions. + + // Draw horizontal line for both plus and minus symbols. + canvas.drawLine(centerX - size, centerY, centerX + size, centerY, paint); + if (isPlus) { + // Draw vertical line for plus symbol. + canvas.drawLine(centerX, centerY - size, centerX, centerY + size, paint); + } + } + + @Override + public void setAlpha(int alpha) { + paint.setAlpha(alpha); + } + + @Override + public void setColorFilter(ColorFilter colorFilter) { + paint.setColorFilter(colorFilter); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; } } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/RememberPlaybackSpeedPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/RememberPlaybackSpeedPatch.java index a6c86477c..04840c761 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/RememberPlaybackSpeedPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/RememberPlaybackSpeedPatch.java @@ -33,10 +33,10 @@ public final class RememberPlaybackSpeedPatch { public static void userSelectedPlaybackSpeed(float playbackSpeed) { try { if (Settings.REMEMBER_PLAYBACK_SPEED_LAST_SELECTED.get()) { - // With the 0.05x menu, if the speed is set by integrations to higher than 2.0x + // With the 0.05x menu, if the speed is set by a patch to higher than 2.0x // then the menu will allow increasing without bounds but the max speed is - // still capped to under 8.0x. - playbackSpeed = Math.min(playbackSpeed, CustomPlaybackSpeedPatch.PLAYBACK_SPEED_MAXIMUM - 0.05f); + // still capped to 8.0x. + playbackSpeed = Math.min(playbackSpeed, CustomPlaybackSpeedPatch.PLAYBACK_SPEED_MAXIMUM); // Prevent toast spamming if using the 0.05x adjustments. // Show exactly one toast after the user stops interacting with the speed menu. @@ -57,7 +57,7 @@ public final class RememberPlaybackSpeedPatch { } Settings.PLAYBACK_SPEED_DEFAULT.save(finalPlaybackSpeed); - Utils.showToastLong(str("revanced_remember_playback_speed_toast", (finalPlaybackSpeed + "x"))); + Utils.showToastShort(str("revanced_remember_playback_speed_toast", (finalPlaybackSpeed + "x"))); }, TOAST_DELAY_MILLISECONDS); } } catch (Exception ex) { diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/theme/ProgressBarDrawable.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/theme/ProgressBarDrawable.java index bf0284f79..93d53c9a5 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/theme/ProgressBarDrawable.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/theme/ProgressBarDrawable.java @@ -20,13 +20,16 @@ import app.revanced.extension.youtube.settings.Settings; public class ProgressBarDrawable extends Drawable { private final Paint paint = new Paint(); + { + paint.setColor(SeekbarColorPatch.getSeekbarColor()); + } @Override public void draw(@NonNull Canvas canvas) { if (Settings.HIDE_SEEKBAR_THUMBNAIL.get()) { return; } - paint.setColor(SeekbarColorPatch.getSeekbarColor()); + canvas.drawRect(getBounds(), paint); } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/theme/SeekbarColorPatch.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/theme/SeekbarColorPatch.java index 4d036509e..2156bc693 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/theme/SeekbarColorPatch.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/theme/SeekbarColorPatch.java @@ -60,7 +60,7 @@ public final class SeekbarColorPatch { * this is the color value of {@link Settings#SEEKBAR_CUSTOM_COLOR_PRIMARY}. * Otherwise this is {@link #ORIGINAL_SEEKBAR_COLOR}. */ - private static int customSeekbarColor = ORIGINAL_SEEKBAR_COLOR; + private static final int customSeekbarColor; /** * Custom seekbar hue, saturation, and brightness values. @@ -77,24 +77,25 @@ public final class SeekbarColorPatch { Color.colorToHSV(ORIGINAL_SEEKBAR_COLOR, hsv); ORIGINAL_SEEKBAR_COLOR_BRIGHTNESS = hsv[2]; - if (SEEKBAR_CUSTOM_COLOR_ENABLED) { - loadCustomSeekbarColor(); - } + customSeekbarColor = SEEKBAR_CUSTOM_COLOR_ENABLED + ? loadCustomSeekbarColor() + : ORIGINAL_SEEKBAR_COLOR; } - private static void loadCustomSeekbarColor() { + private static int loadCustomSeekbarColor() { try { - customSeekbarColor = Color.parseColor(Settings.SEEKBAR_CUSTOM_COLOR_PRIMARY.get()); - Color.colorToHSV(customSeekbarColor, customSeekbarColorHSV); - - customSeekbarColorGradient[0] = customSeekbarColor; + final int color = Color.parseColor(Settings.SEEKBAR_CUSTOM_COLOR_PRIMARY.get()); + Color.colorToHSV(color, customSeekbarColorHSV); + customSeekbarColorGradient[0] = color; customSeekbarColorGradient[1] = Color.parseColor(Settings.SEEKBAR_CUSTOM_COLOR_ACCENT.get()); + + return color; } catch (Exception ex) { Utils.showToastShort(str("revanced_seekbar_custom_color_invalid")); Settings.SEEKBAR_CUSTOM_COLOR_PRIMARY.resetToDefault(); Settings.SEEKBAR_CUSTOM_COLOR_ACCENT.resetToDefault(); - loadCustomSeekbarColor(); + return loadCustomSeekbarColor(); } } @@ -114,6 +115,7 @@ public final class SeekbarColorPatch { : (int) channel3Bits; } + @SuppressWarnings("SameParameterValue") private static String get9BitStyleIdentifier(int color24Bit) { final int r3 = colorChannelTo3Bits(Color.red(color24Bit)); final int g3 = colorChannelTo3Bits(Color.green(color24Bit)); @@ -179,7 +181,7 @@ public final class SeekbarColorPatch { //noinspection ConstantConditions if (false) { // Set true to force slow animation for development. final int longAnimation = Utils.getResourceIdentifier( - Utils.isDarkModeEnabled(Utils.getContext()) + Utils.isDarkModeEnabled() ? "startup_animation_5s_30fps_dark" : "startup_animation_5s_30fps_light", "raw"); diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/returnyoutubedislike/ReturnYouTubeDislike.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/returnyoutubedislike/ReturnYouTubeDislike.java index a0730c055..2a3c5a07c 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/returnyoutubedislike/ReturnYouTubeDislike.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/returnyoutubedislike/ReturnYouTubeDislike.java @@ -21,8 +21,6 @@ import android.text.Spanned; import android.text.style.ForegroundColorSpan; import android.text.style.ImageSpan; import android.text.style.ReplacementSpan; -import android.util.DisplayMetrics; -import android.util.TypedValue; import androidx.annotation.GuardedBy; import androidx.annotation.NonNull; @@ -120,16 +118,13 @@ public class ReturnYouTubeDislike { private static final ShapeDrawable leftSeparatorShape; static { - DisplayMetrics dp = Objects.requireNonNull(Utils.getContext()).getResources().getDisplayMetrics(); - leftSeparatorBounds = new Rect(0, 0, - (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1.2f, dp), - (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14, dp)); - final int middleSeparatorSize = - (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3.7f, dp); + Utils.dipToPixels(1.2f), + Utils.dipToPixels(14f)); + final int middleSeparatorSize = Utils.dipToPixels(3.7f); middleSeparatorBounds = new Rect(0, 0, middleSeparatorSize, middleSeparatorSize); - leftSeparatorShapePaddingPixels = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8.4f, dp); + leftSeparatorShapePaddingPixels = Utils.dipToPixels(8.4f); leftSeparatorShape = new ShapeDrawable(new RectShape()); leftSeparatorShape.setBounds(leftSeparatorBounds); diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/LicenseActivityHook.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/LicenseActivityHook.java index 5a14ca39c..a6335a5e3 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/LicenseActivityHook.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/LicenseActivityHook.java @@ -6,7 +6,6 @@ import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.preference.PreferenceFragment; -import android.util.TypedValue; import android.view.ViewGroup; import android.widget.TextView; import android.widget.Toolbar; @@ -119,8 +118,7 @@ public class LicenseActivityHook { toolbar.setNavigationIcon(ReVancedPreferenceFragment.getBackButtonDrawable()); toolbar.setTitle(getResourceIdentifier("revanced_settings_title", "string")); - final int margin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, - Utils.getContext().getResources().getDisplayMetrics()); + final int margin = Utils.dipToPixels(16); toolbar.setTitleMarginStart(margin); toolbar.setTitleMarginEnd(margin); TextView toolbarTextView = Utils.getChildView(toolbar, false, diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java index 4a36e6458..f52865799 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java @@ -63,12 +63,11 @@ public class Settings extends BaseSettings { public static final BooleanSetting CUSTOM_SPEED_MENU = new BooleanSetting("revanced_custom_speed_menu", TRUE); public static final FloatSetting PLAYBACK_SPEED_DEFAULT = new FloatSetting("revanced_playback_speed_default", -2.0f); public static final StringSetting CUSTOM_PLAYBACK_SPEEDS = new StringSetting("revanced_custom_playback_speeds", - "0.25\n0.5\n0.75\n0.9\n0.95\n1.0\n1.05\n1.1\n1.25\n1.5\n1.75\n2.0\n3.0\n4.0\n5.0", true); + "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, new ForceOriginalAudioAvailability()); // Ads - public static final BooleanSetting HIDE_BUTTONED_ADS = new BooleanSetting("revanced_hide_buttoned_ads", TRUE); public static final BooleanSetting HIDE_END_SCREEN_STORE_BANNER = new BooleanSetting("revanced_hide_end_screen_store_banner", TRUE, true); public static final BooleanSetting HIDE_FULLSCREEN_ADS = new BooleanSetting("revanced_hide_fullscreen_ads", TRUE); public static final BooleanSetting HIDE_GENERAL_ADS = new BooleanSetting("revanced_hide_general_ads", TRUE); @@ -276,6 +275,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting HIDE_SHORTS_SEARCH = new BooleanSetting("revanced_hide_shorts_search", FALSE); public static final BooleanSetting HIDE_SHORTS_SEARCH_SUGGESTIONS = new BooleanSetting("revanced_hide_shorts_search_suggestions", TRUE); public static final BooleanSetting HIDE_SHORTS_SHARE_BUTTON = new BooleanSetting("revanced_hide_shorts_share_button", FALSE); + public static final BooleanSetting HIDE_SHORTS_COMMENT_PANEL = new BooleanSetting("revanced_hide_shorts_comment_panel", TRUE); public static final BooleanSetting HIDE_SHORTS_SHOP_BUTTON = new BooleanSetting("revanced_hide_shorts_shop_button", TRUE); public static final BooleanSetting HIDE_SHORTS_SOUND_BUTTON = new BooleanSetting("revanced_hide_shorts_sound_button", FALSE); public static final BooleanSetting HIDE_SHORTS_SOUND_METADATA_LABEL = new BooleanSetting("revanced_hide_shorts_sound_metadata_label", FALSE); @@ -310,16 +310,16 @@ public class Settings extends BaseSettings { public static final BooleanSetting AUTO_REPEAT = new BooleanSetting("revanced_auto_repeat", FALSE); public static final BooleanSetting BYPASS_URL_REDIRECTS = new BooleanSetting("revanced_bypass_url_redirects", TRUE); public static final BooleanSetting CHECK_WATCH_HISTORY_DOMAIN_NAME = new BooleanSetting("revanced_check_watch_history_domain_name", TRUE, false, false); - public static final BooleanSetting DISABLE_ZOOM_HAPTICS = new BooleanSetting("revanced_disable_zoom_haptics", TRUE); + public static final BooleanSetting DISABLE_HAPTIC_FEEDBACK_CHAPTERS = new BooleanSetting("revanced_disable_haptic_feedback_chapters", FALSE); + public static final BooleanSetting DISABLE_HAPTIC_FEEDBACK_PRECISE_SEEKING = new BooleanSetting("revanced_disable_haptic_feedback_precise_seeking", FALSE); + public static final BooleanSetting DISABLE_HAPTIC_FEEDBACK_SEEK_UNDO = new BooleanSetting("revanced_disable_haptic_feedback_seek_undo", FALSE); + public static final BooleanSetting DISABLE_HAPTIC_FEEDBACK_ZOOM = new BooleanSetting("revanced_disable_haptic_feedback_zoom", FALSE); public static final BooleanSetting EXTERNAL_BROWSER = new BooleanSetting("revanced_external_browser", TRUE, true); public static final BooleanSetting REMOVE_TRACKING_QUERY_PARAMETER = new BooleanSetting("revanced_remove_tracking_query_parameter", TRUE); public static final BooleanSetting SPOOF_DEVICE_DIMENSIONS = new BooleanSetting("revanced_spoof_device_dimensions", FALSE, true, "revanced_spoof_device_dimensions_user_dialog_message"); - /** - * When enabled, share the debug logs with care. - * The buffer contains select user data, including the client ip address and information that could identify the end user. - */ - public static final BooleanSetting DEBUG_PROTOBUFFER = new BooleanSetting("revanced_debug_protobuffer", FALSE, parent(BaseSettings.DEBUG)); + public static final BooleanSetting DEBUG_PROTOBUFFER = new BooleanSetting("revanced_debug_protobuffer", FALSE, false, + "revanced_debug_protobuffer_user_dialog_message", parent(BaseSettings.DEBUG)); // Swipe controls public static final BooleanSetting SWIPE_CHANGE_VIDEO = new BooleanSetting("revanced_swipe_change_video", FALSE, true); @@ -338,13 +338,17 @@ public class Settings extends BaseSettings { parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME)); public static final IntegerSetting SWIPE_OVERLAY_OPACITY = new IntegerSetting("revanced_swipe_overlay_background_opacity", 60, true, parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME)); - public static final StringSetting SWIPE_OVERLAY_PROGRESS_COLOR = new StringSetting("revanced_swipe_overlay_progress_color", "#FFFFFF", true, - parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME)); + public static final StringSetting SWIPE_OVERLAY_BRIGHTNESS_COLOR = new StringSetting("revanced_swipe_overlay_progress_brightness_color", "#FFFFFF", true, + parent(SWIPE_BRIGHTNESS)); + public static final StringSetting SWIPE_OVERLAY_VOLUME_COLOR = new StringSetting("revanced_swipe_overlay_progress_volume_color", "#FFFFFF", true, + parent(SWIPE_VOLUME)); public static final LongSetting SWIPE_OVERLAY_TIMEOUT = new LongSetting("revanced_swipe_overlay_timeout", 500L, true, parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME)); - public static final BooleanSetting SWIPE_SAVE_AND_RESTORE_BRIGHTNESS = new BooleanSetting("revanced_swipe_save_and_restore_brightness", TRUE, true, parent(SWIPE_BRIGHTNESS)); + public static final BooleanSetting SWIPE_SAVE_AND_RESTORE_BRIGHTNESS = new BooleanSetting("revanced_swipe_save_and_restore_brightness", TRUE, true, + parent(SWIPE_BRIGHTNESS)); public static final FloatSetting SWIPE_BRIGHTNESS_VALUE = new FloatSetting("revanced_swipe_brightness_value", -1f); - public static final BooleanSetting SWIPE_LOWEST_VALUE_ENABLE_AUTO_BRIGHTNESS = new BooleanSetting("revanced_swipe_lowest_value_enable_auto_brightness", FALSE, true, parent(SWIPE_BRIGHTNESS)); + public static final BooleanSetting SWIPE_LOWEST_VALUE_ENABLE_AUTO_BRIGHTNESS = new BooleanSetting("revanced_swipe_lowest_value_enable_auto_brightness", FALSE, true, + parent(SWIPE_BRIGHTNESS)); // ReturnYoutubeDislike public static final BooleanSetting RYD_ENABLED = new BooleanSetting("revanced_ryd_enabled", TRUE); diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ClearLogBufferPreference.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ClearLogBufferPreference.java new file mode 100644 index 000000000..109c6c8e7 --- /dev/null +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ClearLogBufferPreference.java @@ -0,0 +1,34 @@ +package app.revanced.extension.youtube.settings.preference; + +import android.content.Context; +import android.util.AttributeSet; +import android.preference.Preference; +import app.revanced.extension.shared.settings.preference.LogBufferManager; + +/** + * A custom preference that clears the ReVanced debug log buffer when clicked. + * Invokes the {@link LogBufferManager#clearLogBuffer} method. + */ +@SuppressWarnings("unused") +public class ClearLogBufferPreference extends Preference { + + { + setOnPreferenceClickListener(pref -> { + LogBufferManager.clearLogBuffer(); + return true; + }); + } + + public ClearLogBufferPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + public ClearLogBufferPreference(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + public ClearLogBufferPreference(Context context, AttributeSet attrs) { + super(context, attrs); + } + public ClearLogBufferPreference(Context context) { + super(context); + } +} diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ExportLogToClipboardPreference.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ExportLogToClipboardPreference.java new file mode 100644 index 000000000..fac1cfa79 --- /dev/null +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ExportLogToClipboardPreference.java @@ -0,0 +1,34 @@ +package app.revanced.extension.youtube.settings.preference; + +import android.content.Context; +import android.util.AttributeSet; +import android.preference.Preference; +import app.revanced.extension.shared.settings.preference.LogBufferManager; + +/** + * A custom preference that triggers exporting ReVanced debug logs to the clipboard when clicked. + * Invokes the {@link LogBufferManager#exportToClipboard} method. + */ +@SuppressWarnings({"deprecation", "unused"}) +public class ExportLogToClipboardPreference extends Preference { + + { + setOnPreferenceClickListener(pref -> { + LogBufferManager.exportToClipboard(); + return true; + }); + } + + public ExportLogToClipboardPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + public ExportLogToClipboardPreference(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + public ExportLogToClipboardPreference(Context context, AttributeSet attrs) { + super(context, attrs); + } + public ExportLogToClipboardPreference(Context context) { + super(context); + } +} diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ReVancedPreferenceFragment.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ReVancedPreferenceFragment.java index 916378bf5..1257bb190 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ReVancedPreferenceFragment.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ReVancedPreferenceFragment.java @@ -17,7 +17,6 @@ import android.preference.SwitchPreference; import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.style.BackgroundColorSpan; -import android.util.TypedValue; import android.view.ViewGroup; import android.view.WindowInsets; import android.widget.TextView; @@ -245,9 +244,7 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment { toolbar.setNavigationIcon(getBackButtonDrawable()); toolbar.setNavigationOnClickListener(view -> preferenceScreenDialog.dismiss()); - final int margin = (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, 16, getResources().getDisplayMetrics() - ); + final int margin = Utils.dipToPixels(16); toolbar.setTitleMargin(margin, 0, margin, 0); TextView toolbarTextView = Utils.getChildView(toolbar, diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/SegmentPlaybackController.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/SegmentPlaybackController.java index 3f48930e3..22259d571 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/SegmentPlaybackController.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/SegmentPlaybackController.java @@ -5,7 +5,6 @@ import static app.revanced.extension.shared.StringRef.str; import android.graphics.Canvas; import android.graphics.Rect; import android.text.TextUtils; -import android.util.TypedValue; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -727,15 +726,11 @@ public class SegmentPlaybackController { } } - private static int highlightSegmentTimeBarScreenWidth = -1; // actual pixel width to use - private static int getHighlightSegmentTimeBarScreenWidth() { - if (highlightSegmentTimeBarScreenWidth == -1) { - highlightSegmentTimeBarScreenWidth = (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, HIGHLIGHT_SEGMENT_DRAW_BAR_WIDTH, - Objects.requireNonNull(Utils.getContext()).getResources().getDisplayMetrics()); - } - return highlightSegmentTimeBarScreenWidth; - } + /** + * Actual screen pixel width to use for the highlight segment time bar. + */ + private static final int highlightSegmentTimeBarScreenWidth + = Utils.dipToPixels(HIGHLIGHT_SEGMENT_DRAW_BAR_WIDTH); /** * Injection point. @@ -757,7 +752,7 @@ public class SegmentPlaybackController { final float left = leftPadding + segment.start * videoMillisecondsToPixels; final float right; if (segment.category == SegmentCategory.HIGHLIGHT) { - right = left + getHighlightSegmentTimeBarScreenWidth(); + right = left + highlightSegmentTimeBarScreenWidth; } else { right = leftPadding + segment.end * videoMillisecondsToPixels; } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SegmentCategory.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SegmentCategory.java index ec1b1fca5..ae6900330 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SegmentCategory.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SegmentCategory.java @@ -1,6 +1,7 @@ package app.revanced.extension.youtube.sponsorblock.objects; import static app.revanced.extension.shared.StringRef.sf; +import static app.revanced.extension.shared.settings.preference.ColorPickerPreference.COLOR_DOT_STRING; import static app.revanced.extension.youtube.settings.Settings.*; import android.graphics.Color; @@ -9,7 +10,9 @@ 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; @@ -134,7 +137,8 @@ public enum SegmentCategory { updateEnabledCategories(); } - public static int applyOpacityToColor(int color, float opacity) { + @ColorInt + public static int applyOpacityToColor(@ColorInt int color, float opacity) { if (opacity < 0 || opacity > 1.0f) { throw new IllegalArgumentException("Invalid opacity: " + opacity); } @@ -165,29 +169,28 @@ public enum SegmentCategory { /** * Skipped segment toast, if the skip occurred in the first quarter of the video */ - @NonNull public final StringRef skippedToastBeginning; /** * Skipped segment toast, if the skip occurred in the middle half of the video */ - @NonNull public final StringRef skippedToastMiddle; /** * Skipped segment toast, if the skip occurred in the last quarter of the video */ - @NonNull public final StringRef skippedToastEnd; - @NonNull public final Paint paint; + /** + * Category color with opacity applied. + */ + @ColorInt private int color; /** * Value must be changed using {@link #setBehaviour(CategoryBehaviour)}. * Caller must also {@link #updateEnabledCategories()}. */ - @NonNull public CategoryBehaviour behaviour = CategoryBehaviour.IGNORE; SegmentCategory(String keyValue, StringRef title, StringRef description, @@ -247,7 +250,7 @@ public enum SegmentCategory { } } - public void setBehaviour(@NonNull CategoryBehaviour behaviour) { + public void setBehaviour(CategoryBehaviour behaviour) { this.behaviour = Objects.requireNonNull(behaviour); this.behaviorSetting.save(behaviour.reVancedKeyValue); } @@ -273,6 +276,10 @@ public enum SegmentCategory { return opacitySetting.get(); } + public float getOpacityDefault() { + return opacitySetting.defaultValue; + } + public void resetColorAndOpacity() { setColor(colorSetting.defaultValue); setOpacity(opacitySetting.defaultValue); @@ -291,10 +298,19 @@ public enum SegmentCategory { /** * @return Integer color of #RRGGBB format. */ + @ColorInt public int getColorNoOpacity() { return color & 0x00FFFFFF; } + /** + * @return Integer color of #RRGGBB format. + */ + @ColorInt + public int getColorNoOpacityDefault() { + return Color.parseColor(colorSetting.defaultValue) & 0x00FFFFFF; + } + /** * @return Hex color string of #RRGGBB format with no opacity level. */ @@ -302,22 +318,27 @@ public enum SegmentCategory { return String.format(Locale.US, "#%06X", getColorNoOpacity()); } - private static SpannableString getCategoryColorDotSpan(String text, int color) { - SpannableString dotSpan = new SpannableString('⬤' + 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); return dotSpan; } - public static SpannableString getCategoryColorDot(int color) { - return getCategoryColorDotSpan("", color); + public static SpannableString getCategoryColorDot(@ColorInt int color) { + SpannableString dotSpan = new SpannableString(COLOR_DOT_STRING); + 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; } public SpannableString getCategoryColorDot() { return getCategoryColorDot(color); } - public SpannableString getTitleWithColorDot(int categoryColor) { + public SpannableString getTitleWithColorDot(@ColorInt int categoryColor) { return getCategoryColorDotSpan(" " + title, categoryColor); } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SegmentCategoryListPreference.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SegmentCategoryListPreference.java index 36204319c..8c2a98757 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SegmentCategoryListPreference.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SegmentCategoryListPreference.java @@ -1,35 +1,46 @@ package app.revanced.extension.youtube.sponsorblock.objects; import static app.revanced.extension.shared.StringRef.str; +import static app.revanced.extension.shared.Utils.getResourceIdentifier; +import static app.revanced.extension.shared.settings.preference.ColorPickerPreference.getColorString; import static app.revanced.extension.youtube.sponsorblock.objects.SegmentCategory.applyOpacityToColor; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; import android.preference.ListPreference; import android.text.Editable; import android.text.InputType; import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.Button; import android.widget.EditText; import android.widget.GridLayout; +import android.widget.LinearLayout; import android.widget.TextView; +import androidx.annotation.ColorInt; + import java.util.Locale; import java.util.Objects; import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Utils; +import app.revanced.extension.shared.settings.preference.ColorPickerPreference; +import app.revanced.extension.shared.settings.preference.ColorPickerView; @SuppressWarnings("deprecation") public class SegmentCategoryListPreference extends ListPreference { private final SegmentCategory category; - private TextView colorDotView; - private EditText colorEditText; - private EditText opacityEditText; + /** - * #RRGGBB + * RGB format (no alpha). */ + @ColorInt private int categoryColor; /** * [0, 1] @@ -37,6 +48,11 @@ public class SegmentCategoryListPreference extends ListPreference { private float categoryOpacity; private int selectedDialogEntryIndex; + private TextView dialogColorDotView; + private EditText dialogColorEditText; + private EditText dialogOpacityEditText; + private ColorPickerView dialogColorPickerView; + public SegmentCategoryListPreference(Context context, SegmentCategory category) { super(context); this.category = Objects.requireNonNull(category); @@ -67,8 +83,20 @@ public class SegmentCategoryListPreference extends ListPreference { categoryOpacity = category.getOpacity(); Context context = builder.getContext(); + LinearLayout mainLayout = new LinearLayout(context); + mainLayout.setOrientation(LinearLayout.VERTICAL); + mainLayout.setPadding(70, 0, 70, 0); + + // Inflate the color picker view. + View colorPickerContainer = LayoutInflater.from(context) + .inflate(getResourceIdentifier("revanced_color_picker", "layout"), null); + dialogColorPickerView = colorPickerContainer.findViewById( + getResourceIdentifier("color_picker_view", "id")); + dialogColorPickerView.setColor(categoryColor); + mainLayout.addView(colorPickerContainer); + + // Grid layout for color and opacity inputs. GridLayout gridLayout = new GridLayout(context); - gridLayout.setPadding(70, 0, 150, 0); // Padding for the entire layout. gridLayout.setColumnCount(3); gridLayout.setRowCount(2); @@ -84,19 +112,22 @@ public class SegmentCategoryListPreference extends ListPreference { gridParams.rowSpec = GridLayout.spec(0); // First row. gridParams.columnSpec = GridLayout.spec(1); // Second column. gridParams.setMargins(0, 0, 10, 0); - colorDotView = new TextView(context); - colorDotView.setLayoutParams(gridParams); - gridLayout.addView(colorDotView); + dialogColorDotView = new TextView(context); + dialogColorDotView.setLayoutParams(gridParams); + gridLayout.addView(dialogColorDotView); updateCategoryColorDot(); gridParams = new GridLayout.LayoutParams(); gridParams.rowSpec = GridLayout.spec(0); // First row. gridParams.columnSpec = GridLayout.spec(2); // Third column. - colorEditText = new EditText(context); - colorEditText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS); - colorEditText.setTextLocale(Locale.US); - colorEditText.setText(category.getColorString()); - colorEditText.addTextChangedListener(new TextWatcher() { + dialogColorEditText = new EditText(context); + dialogColorEditText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS + | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); + dialogColorEditText.setAutofillHints((String) null); + dialogColorEditText.setTypeface(Typeface.MONOSPACE); + dialogColorEditText.setTextLocale(Locale.US); + dialogColorEditText.setText(getColorString(categoryColor)); + dialogColorEditText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @@ -109,28 +140,30 @@ public class SegmentCategoryListPreference extends ListPreference { public void afterTextChanged(Editable edit) { try { String colorString = edit.toString(); - final int colorStringLength = colorString.length(); + String normalizedColorString = ColorPickerPreference.cleanupColorCodeString(colorString); - if (!colorString.startsWith("#")) { - edit.insert(0, "#"); // Recursively calls back into this method. + if (!normalizedColorString.equals(colorString)) { + edit.replace(0, colorString.length(), normalizedColorString); return; } - final int maxColorStringLength = 7; // #RRGGBB - if (colorStringLength > maxColorStringLength) { - edit.delete(maxColorStringLength, colorStringLength); + if (normalizedColorString.length() != ColorPickerPreference.COLOR_STRING_LENGTH) { + // User is still typing out the color. return; } - categoryColor = Color.parseColor(colorString); - updateCategoryColorDot(); - } catch (IllegalArgumentException ex) { - // Ignore. + // Remove the alpha channel. + final int newColor = Color.parseColor(colorString) & 0x00FFFFFF; + // Changing view color causes callback into this class. + dialogColorPickerView.setColor(newColor); + } catch (Exception ex) { + // Should never be reached since input is validated before using. + Logger.printException(() -> "colorEditText afterTextChanged failure", ex); } } }); - colorEditText.setLayoutParams(gridParams); - gridLayout.addView(colorEditText); + dialogColorEditText.setLayoutParams(gridParams); + gridLayout.addView(dialogColorEditText); gridParams = new GridLayout.LayoutParams(); gridParams.rowSpec = GridLayout.spec(1); // Second row. @@ -143,9 +176,13 @@ public class SegmentCategoryListPreference extends ListPreference { gridParams = new GridLayout.LayoutParams(); gridParams.rowSpec = GridLayout.spec(1); // Second row. gridParams.columnSpec = GridLayout.spec(2); // Third column. - opacityEditText = new EditText(context); - opacityEditText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL); - opacityEditText.addTextChangedListener(new TextWatcher() { + dialogOpacityEditText = new EditText(context); + dialogOpacityEditText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL + | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); + dialogOpacityEditText.setAutofillHints((String) null); + dialogOpacityEditText.setTypeface(Typeface.MONOSPACE); + dialogOpacityEditText.setTextLocale(Locale.US); + dialogOpacityEditText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @@ -183,31 +220,40 @@ public class SegmentCategoryListPreference extends ListPreference { } updateCategoryColorDot(); - } catch (NumberFormatException ex) { + } catch (Exception ex) { // Should never happen. - Logger.printException(() -> "Could not parse opacity string", ex); + Logger.printException(() -> "opacityEditText afterTextChanged failure", ex); } } }); - opacityEditText.setLayoutParams(gridParams); - gridLayout.addView(opacityEditText); + dialogOpacityEditText.setLayoutParams(gridParams); + gridLayout.addView(dialogOpacityEditText); updateOpacityText(); - builder.setView(gridLayout); + mainLayout.addView(gridLayout); + + // Set up color picker listener. + // Do last to prevent listener callbacks while setting up view. + dialogColorPickerView.setOnColorChangedListener(color -> { + if (categoryColor == color) { + return; + } + categoryColor = color; + String hexColor = getColorString(color); + Logger.printDebug(() -> "onColorChanged: " + hexColor); + + updateCategoryColorDot(); + dialogColorEditText.setText(hexColor); + dialogColorEditText.setSelection(hexColor.length()); + }); + + builder.setView(mainLayout); builder.setTitle(category.title.toString()); builder.setPositiveButton(android.R.string.ok, (dialog, which) -> { onClick(dialog, DialogInterface.BUTTON_POSITIVE); }); - builder.setNeutralButton(str("revanced_sb_reset_color"), (dialog, which) -> { - try { - category.resetColorAndOpacity(); - updateUI(); - Utils.showToastShort(str("revanced_sb_color_reset")); - } catch (Exception ex) { - Logger.printException(() -> "setNeutralButton failure", ex); - } - }); + builder.setNeutralButton(str("revanced_settings_reset_color"), null); builder.setNegativeButton(android.R.string.cancel, null); selectedDialogEntryIndex = findIndexOfValue(getValue()); @@ -218,6 +264,25 @@ public class SegmentCategoryListPreference extends ListPreference { } } + @Override + protected void showDialog(Bundle state) { + super.showDialog(state); + + // Do not close dialog when reset is pressed. + Button button = ((AlertDialog) getDialog()).getButton(AlertDialog.BUTTON_NEUTRAL); + button.setOnClickListener(view -> { + try { + // Setting view color causes callback to update the UI. + dialogColorPickerView.setColor(category.getColorNoOpacityDefault()); + + categoryOpacity = category.getOpacityDefault(); + updateOpacityText(); + } catch (Exception ex) { + Logger.printException(() -> "setOnClickListener failure", ex); + } + }); + } + @Override protected void onDialogClosed(boolean positiveResult) { try { @@ -230,43 +295,42 @@ public class SegmentCategoryListPreference extends ListPreference { } try { - String colorString = colorEditText.getText().toString(); - if (!colorString.equals(category.getColorString()) || categoryOpacity != category.getOpacity()) { - category.setColor(colorString); - category.setOpacity(categoryOpacity); - Utils.showToastShort(str("revanced_sb_color_changed")); - } + category.setColor(dialogColorEditText.getText().toString()); + category.setOpacity(categoryOpacity); } catch (IllegalArgumentException ex) { - Utils.showToastShort(str("revanced_sb_color_invalid")); + Utils.showToastShort(str("revanced_settings_color_invalid")); } updateUI(); } } catch (Exception ex) { Logger.printException(() -> "onDialogClosed failure", ex); + } finally { + dialogColorDotView = null; + dialogColorEditText = null; + dialogOpacityEditText = null; + dialogColorPickerView = null; } } - private void applyOpacityToCategoryColor() { - categoryColor = applyOpacityToColor(categoryColor, categoryOpacity); + @ColorInt + private int applyOpacityToCategoryColor() { + return applyOpacityToColor(categoryColor, categoryOpacity); } public void updateUI() { categoryColor = category.getColorNoOpacity(); categoryOpacity = category.getOpacity(); - applyOpacityToCategoryColor(); - setTitle(category.getTitleWithColorDot(categoryColor)); + setTitle(category.getTitleWithColorDot(applyOpacityToCategoryColor())); } private void updateCategoryColorDot() { - applyOpacityToCategoryColor(); - - colorDotView.setText(SegmentCategory.getCategoryColorDot(categoryColor)); + dialogColorDotView.setText(SegmentCategory.getCategoryColorDot(applyOpacityToCategoryColor())); } private void updateOpacityText() { - opacityEditText.setText(String.format(Locale.US, "%.2f", categoryOpacity)); + dialogOpacityEditText.setText(String.format(Locale.US, "%.2f", categoryOpacity)); } @Override @@ -277,4 +341,4 @@ public class SegmentCategoryListPreference extends ListPreference { // This is required otherwise the ReVanced preference fragment // sets all ListPreference summaries to show the current selection. } -} \ No newline at end of file +} diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/ui/SponsorBlockPreferenceGroup.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/ui/SponsorBlockPreferenceGroup.java index 4ed3bf238..1b5e0aae5 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/ui/SponsorBlockPreferenceGroup.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/ui/SponsorBlockPreferenceGroup.java @@ -376,7 +376,11 @@ public class SponsorBlockPreferenceGroup extends PreferenceGroup { Utils.setEditTextDialogTheme(builder); builder.setNeutralButton(str("revanced_sb_settings_copy"), (dialog, which) -> { - Utils.setClipboard(getEditText().getText().toString()); + try { + Utils.setClipboard(getEditText().getText()); + } catch (Exception ex) { + Logger.printException(() -> "Copy settings failure", ex); + } }); } }; @@ -421,7 +425,7 @@ public class SponsorBlockPreferenceGroup extends PreferenceGroup { .setTitle(apiUrl.getTitle()) .setView(editText) .setNegativeButton(android.R.string.cancel, null) - .setNeutralButton(str("revanced_sb_reset"), urlChangeListener) + .setNeutralButton(str("revanced_settings_reset"), urlChangeListener) .setPositiveButton(android.R.string.ok, urlChangeListener) .show(); return true; @@ -433,7 +437,11 @@ public class SponsorBlockPreferenceGroup extends PreferenceGroup { Utils.setEditTextDialogTheme(builder); builder.setNeutralButton(str("revanced_sb_settings_copy"), (dialog, which) -> { - Utils.setClipboard(getEditText().getText().toString()); + try { + Utils.setClipboard(getEditText().getText()); + } catch (Exception ex) { + Logger.printException(() -> "Copy settings failure", ex); + } }); } }; diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/swipecontrols/SwipeControlsConfigurationProvider.kt b/extensions/youtube/src/main/java/app/revanced/extension/youtube/swipecontrols/SwipeControlsConfigurationProvider.kt index e8f181936..c5854fd2f 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/swipecontrols/SwipeControlsConfigurationProvider.kt +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/swipecontrols/SwipeControlsConfigurationProvider.kt @@ -1,10 +1,10 @@ package app.revanced.extension.youtube.swipecontrols -import android.annotation.SuppressLint import android.graphics.Color import app.revanced.extension.shared.Logger import app.revanced.extension.shared.StringRef.str import app.revanced.extension.shared.Utils +import app.revanced.extension.shared.settings.StringSetting import app.revanced.extension.youtube.settings.Settings import app.revanced.extension.youtube.shared.PlayerType @@ -51,105 +51,112 @@ class SwipeControlsConfigurationProvider { /** * Indicates whether press-to-swipe mode is enabled, requiring a press before swiping to activate controls. */ - val shouldEnablePressToSwipe: Boolean - get() = Settings.SWIPE_PRESS_TO_ENGAGE.get() + val shouldEnablePressToSwipe = Settings.SWIPE_PRESS_TO_ENGAGE.get() /** * The threshold for detecting swipe gestures, in pixels. * Loaded once to ensure consistent behavior during rapid scroll events. */ - val swipeMagnitudeThreshold: Int - get() = Settings.SWIPE_MAGNITUDE_THRESHOLD.get() + val swipeMagnitudeThreshold = Settings.SWIPE_MAGNITUDE_THRESHOLD.get() /** * The sensitivity of volume swipe gestures, determining how much volume changes per swipe. * Resets to default if set to 0, as it would disable swiping. */ - val volumeSwipeSensitivity: Int - get() { - val sensitivity = Settings.SWIPE_VOLUME_SENSITIVITY.get() + val volumeSwipeSensitivity: Int by lazy { + val sensitivity = Settings.SWIPE_VOLUME_SENSITIVITY.get() - if (sensitivity < 1) { - return Settings.SWIPE_VOLUME_SENSITIVITY.resetToDefault() - } - - return sensitivity + if (sensitivity < 1) { + return@lazy Settings.SWIPE_VOLUME_SENSITIVITY.resetToDefault() } + + sensitivity + } //endregion //region overlay adjustments /** * Indicates whether haptic feedback should be enabled for swipe control interactions. */ - val shouldEnableHapticFeedback: Boolean - get() = Settings.SWIPE_HAPTIC_FEEDBACK.get() + val shouldEnableHapticFeedback = Settings.SWIPE_HAPTIC_FEEDBACK.get() /** * The duration in milliseconds that the overlay should remain visible after a change. */ - val overlayShowTimeoutMillis: Long - get() = Settings.SWIPE_OVERLAY_TIMEOUT.get() + val overlayShowTimeoutMillis = Settings.SWIPE_OVERLAY_TIMEOUT.get() /** * The background opacity of the overlay, converted from a percentage (0-100) to an alpha value (0-255). * Resets to default and shows a toast if the value is out of range. */ - val overlayBackgroundOpacity: Int - get() { - var opacity = Settings.SWIPE_OVERLAY_OPACITY.get() + val overlayBackgroundOpacity: Int by lazy { + var opacity = Settings.SWIPE_OVERLAY_OPACITY.get() - if (opacity < 0 || opacity > 100) { - Utils.showToastLong(str("revanced_swipe_overlay_background_opacity_invalid_toast")) - opacity = Settings.SWIPE_OVERLAY_OPACITY.resetToDefault() - } - - opacity = opacity * 255 / 100 - return Color.argb(opacity, 0, 0, 0) + if (opacity < 0 || opacity > 100) { + Utils.showToastLong(str("revanced_swipe_overlay_background_opacity_invalid_toast")) + opacity = Settings.SWIPE_OVERLAY_OPACITY.resetToDefault() } + opacity = opacity * 255 / 100 + Color.argb(opacity, 0, 0, 0) + } + /** - * The color of the progress bar in the overlay. + * The color of the progress bar in the overlay for brightness. * Resets to default and shows a toast if the color string is invalid or empty. */ - val overlayProgressColor: Int - get() { - try { - @SuppressLint("UseKtx") - val color = Color.parseColor(Settings.SWIPE_OVERLAY_PROGRESS_COLOR.get()) - return (0xBF000000.toInt() or (color and 0xFFFFFF)) - } catch (ex: IllegalArgumentException) { - Logger.printDebug({ "Could not parse color" }, ex) - Utils.showToastLong(str("revanced_swipe_overlay_progress_color_invalid_toast")) - Settings.SWIPE_OVERLAY_PROGRESS_COLOR.resetToDefault() - return overlayProgressColor // Recursively return. - } + val overlayBrightnessProgressColor: Int by lazy { + // Use lazy to avoid repeat parsing. Changing color requires app restart. + getSettingColor(Settings.SWIPE_OVERLAY_BRIGHTNESS_COLOR) + } + + /** + * The color of the progress bar in the overlay for volume. + * Resets to default and shows a toast if the color string is invalid or empty. + */ + val overlayVolumeProgressColor: Int by lazy { + getSettingColor(Settings.SWIPE_OVERLAY_VOLUME_COLOR) + } + + private fun getSettingColor(setting: StringSetting): Int { + try { + //noinspection UseKtx + val color = Color.parseColor(setting.get()) + return (0xBF000000.toInt() or (color and 0x00FFFFFF)) + } catch (ex: IllegalArgumentException) { + // This code should never be reached. + // Color picker rejects and will not save bad colors to a setting. + // If a user imports bad data, the color picker preference resets the + // bad color before this method can be called. + Logger.printDebug({ "Could not parse color: $setting" }, ex) + Utils.showToastLong(str("revanced_settings_color_invalid")) + setting.resetToDefault() + return getSettingColor(setting) // Recursively return. } + } /** * The background color used for the filled portion of the progress bar in the overlay. */ - val overlayFillBackgroundPaint: Int - get() = 0x80D3D3D3.toInt() + val overlayFillBackgroundPaint = 0x80D3D3D3.toInt() /** * The color used for text and icons in the overlay. */ - val overlayTextColor: Int - get() = Color.WHITE + val overlayTextColor = Color.WHITE /** * The text size in the overlay, in density-independent pixels (dp). * Must be between 1 and 30 dp; resets to default and shows a toast if invalid. */ - val overlayTextSize: Int - get() { - val size = Settings.SWIPE_OVERLAY_TEXT_SIZE.get() - if (size < 1 || size > 30) { - Utils.showToastLong(str("revanced_swipe_text_overlay_size_invalid_toast")) - return Settings.SWIPE_OVERLAY_TEXT_SIZE.resetToDefault() - } - return size + val overlayTextSize: Int by lazy { + val size = Settings.SWIPE_OVERLAY_TEXT_SIZE.get() + if (size < 1 || size > 30) { + Utils.showToastLong(str("revanced_swipe_text_overlay_size_invalid_toast")) + return@lazy Settings.SWIPE_OVERLAY_TEXT_SIZE.resetToDefault() } + size + } /** * Defines the style of the swipe controls overlay, determining its layout and appearance. @@ -199,28 +206,25 @@ class SwipeControlsConfigurationProvider { /** * A minimal vertical progress bar. */ - VERTICAL_MINIMAL(isMinimal = true, isVertical = true) + VERTICAL_MINIMAL(isMinimal = true, isVertical = true) } /** * The current style of the overlay, determining its layout and appearance. */ - val overlayStyle: SwipeOverlayStyle - get() = Settings.SWIPE_OVERLAY_STYLE.get() + val overlayStyle = Settings.SWIPE_OVERLAY_STYLE.get() //endregion //region behaviour /** * Indicates whether the brightness level should be saved and restored when entering or exiting fullscreen mode. */ - val shouldSaveAndRestoreBrightness: Boolean - get() = Settings.SWIPE_SAVE_AND_RESTORE_BRIGHTNESS.get() + val shouldSaveAndRestoreBrightness = Settings.SWIPE_SAVE_AND_RESTORE_BRIGHTNESS.get() /** * Indicates whether auto-brightness should be enabled when the brightness gesture reaches its lowest value. */ - val shouldLowestValueEnableAutoBrightness: Boolean - get() = Settings.SWIPE_LOWEST_VALUE_ENABLE_AUTO_BRIGHTNESS.get() + val shouldLowestValueEnableAutoBrightness = Settings.SWIPE_LOWEST_VALUE_ENABLE_AUTO_BRIGHTNESS.get() /** * The saved brightness value for the swipe gesture, used to restore brightness in fullscreen mode. @@ -229,4 +233,4 @@ class SwipeControlsConfigurationProvider { get() = Settings.SWIPE_BRIGHTNESS_VALUE.get() set(value) = Settings.SWIPE_BRIGHTNESS_VALUE.save(value) //endregion -} \ No newline at end of file +} diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/swipecontrols/views/SwipeControlsOverlayLayout.kt b/extensions/youtube/src/main/java/app/revanced/extension/youtube/swipecontrols/views/SwipeControlsOverlayLayout.kt index 6a9044e85..71226c082 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/swipecontrols/views/SwipeControlsOverlayLayout.kt +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/swipecontrols/views/SwipeControlsOverlayLayout.kt @@ -39,7 +39,7 @@ class SwipeControlsOverlayLayout( constructor(context: Context) : this(context, SwipeControlsConfigurationProvider()) - // Drawable icons for brightness and volume + // Drawable icons for brightness and volume. private val autoBrightnessIcon: Drawable = getDrawable("revanced_ic_sc_brightness_auto") private val lowBrightnessIcon: Drawable = getDrawable("revanced_ic_sc_brightness_low") private val mediumBrightnessIcon: Drawable = getDrawable("revanced_ic_sc_brightness_medium") @@ -50,7 +50,7 @@ class SwipeControlsOverlayLayout( private val normalVolumeIcon: Drawable = getDrawable("revanced_ic_sc_volume_normal") private val fullVolumeIcon: Drawable = getDrawable("revanced_ic_sc_volume_high") - // Function to retrieve drawable resources by name + // Function to retrieve drawable resources by name. private fun getDrawable(name: String): Drawable { val drawable = resources.getDrawable( Utils.getResourceIdentifier(context, name, "drawable"), @@ -60,19 +60,19 @@ class SwipeControlsOverlayLayout( return drawable } - // Initialize progress bars + // Initialize progress bars. private val circularProgressView: CircularProgressView private val horizontalProgressView: HorizontalProgressView private val verticalBrightnessProgressView: VerticalProgressView private val verticalVolumeProgressView: VerticalProgressView init { - // Initialize circular progress bar + // Initialize circular progress bar. circularProgressView = CircularProgressView( context, config.overlayBackgroundOpacity, config.overlayStyle.isMinimal, - config.overlayProgressColor, + config.overlayBrightnessProgressColor, // Placeholder, updated in showFeedbackView. config.overlayFillBackgroundPaint, config.overlayTextColor, config.overlayTextSize @@ -80,18 +80,18 @@ class SwipeControlsOverlayLayout( layoutParams = LayoutParams(100f.toDisplayPixels().toInt(), 100f.toDisplayPixels().toInt()).apply { addRule(CENTER_IN_PARENT, TRUE) } - visibility = GONE // Initially hidden + visibility = GONE // Initially hidden. } addView(circularProgressView) - // Initialize horizontal progress bar + // Initialize horizontal progress bar. val screenWidth = resources.displayMetrics.widthPixels - val layoutWidth = (screenWidth * 4 / 5).toInt() // Cap at ~360dp + val layoutWidth = (screenWidth * 4 / 5).toInt() // Cap at ~360dp. horizontalProgressView = HorizontalProgressView( context, config.overlayBackgroundOpacity, config.overlayStyle.isMinimal, - config.overlayProgressColor, + config.overlayBrightnessProgressColor, // Placeholder, updated in showFeedbackView. config.overlayFillBackgroundPaint, config.overlayTextColor, config.overlayTextSize @@ -104,16 +104,16 @@ class SwipeControlsOverlayLayout( topMargin = 20f.toDisplayPixels().toInt() } } - visibility = GONE // Initially hidden + visibility = GONE // Initially hidden. } addView(horizontalProgressView) - // Initialize vertical progress bar for brightness (right side) + // Initialize vertical progress bar for brightness (right side). verticalBrightnessProgressView = VerticalProgressView( context, config.overlayBackgroundOpacity, config.overlayStyle.isMinimal, - config.overlayProgressColor, + config.overlayBrightnessProgressColor, config.overlayFillBackgroundPaint, config.overlayTextColor, config.overlayTextSize @@ -123,16 +123,16 @@ class SwipeControlsOverlayLayout( rightMargin = 40f.toDisplayPixels().toInt() addRule(CENTER_VERTICAL) } - visibility = GONE // Initially hidden + visibility = GONE // Initially hidden. } addView(verticalBrightnessProgressView) - // Initialize vertical progress bar for volume (left side) + // Initialize vertical progress bar for volume (left side). verticalVolumeProgressView = VerticalProgressView( context, config.overlayBackgroundOpacity, config.overlayStyle.isMinimal, - config.overlayProgressColor, + config.overlayVolumeProgressColor, config.overlayFillBackgroundPaint, config.overlayTextColor, config.overlayTextSize @@ -142,12 +142,12 @@ class SwipeControlsOverlayLayout( leftMargin = 40f.toDisplayPixels().toInt() addRule(CENTER_VERTICAL) } - visibility = GONE // Initially hidden + visibility = GONE // Initially hidden. } addView(verticalVolumeProgressView) } - // Handler and callback for hiding progress bars + // Handler and callback for hiding progress bars. private val feedbackHideHandler = Handler(Looper.getMainLooper()) private val feedbackHideCallback = Runnable { circularProgressView.visibility = GONE @@ -165,29 +165,42 @@ class SwipeControlsOverlayLayout( val viewToShow = when { config.overlayStyle.isCircular -> circularProgressView - config.overlayStyle.isVertical -> if (isBrightness) verticalBrightnessProgressView else verticalVolumeProgressView + config.overlayStyle.isVertical -> + if (isBrightness) + verticalBrightnessProgressView + else + verticalVolumeProgressView else -> horizontalProgressView } viewToShow.apply { + // Set the appropriate progress color. + if (this is CircularProgressView || this is HorizontalProgressView) { + setProgressColor( + if (isBrightness) + config.overlayBrightnessProgressColor + else + config.overlayVolumeProgressColor + ) + } setProgress(progress, max, value, isBrightness) this.icon = icon visibility = VISIBLE } } - // Handle volume change + // Handle volume change. override fun onVolumeChanged(newVolume: Int, maximumVolume: Int) { val volumePercentage = (newVolume.toFloat() / maximumVolume) * 100 val icon = when { newVolume == 0 -> mutedVolumeIcon - volumePercentage < 33 -> lowVolumeIcon - volumePercentage < 66 -> normalVolumeIcon + volumePercentage < 25 -> lowVolumeIcon + volumePercentage < 50 -> normalVolumeIcon else -> fullVolumeIcon } showFeedbackView("$newVolume", newVolume, maximumVolume, icon, isBrightness = false) } - // Handle brightness change + // Handle brightness change. override fun onBrightnessChanged(brightness: Double) { if (config.shouldLowestValueEnableAutoBrightness && brightness <= 0) { val displayText = if (config.overlayStyle.isVertical) "А" @@ -195,18 +208,19 @@ class SwipeControlsOverlayLayout( showFeedbackView(displayText, 0, 100, autoBrightnessIcon, isBrightness = true) } else { val brightnessValue = round(brightness).toInt() + val clampedProgress = max(0, brightnessValue) val icon = when { - brightnessValue < 25 -> lowBrightnessIcon - brightnessValue < 50 -> mediumBrightnessIcon - brightnessValue < 75 -> highBrightnessIcon + clampedProgress < 25 -> lowBrightnessIcon + clampedProgress < 50 -> mediumBrightnessIcon + clampedProgress < 75 -> highBrightnessIcon else -> fullBrightnessIcon } - val displayText = if (config.overlayStyle.isVertical) "$brightnessValue" else "$brightnessValue%" - showFeedbackView(displayText, brightnessValue, 100, icon, isBrightness = true) + val displayText = if (config.overlayStyle.isVertical) "$clampedProgress" else "$clampedProgress%" + showFeedbackView(displayText, clampedProgress, 100, icon, isBrightness = true) } } - // Begin swipe session + // Begin swipe session. override fun onEnterSwipeSession() { if (config.shouldEnableHapticFeedback) { @Suppress("DEPRECATION") @@ -233,25 +247,41 @@ abstract class AbstractProgressView( defStyleAttr: Int = 0 ) : View(context, attrs, defStyleAttr) { - // Combined paint creation function for both fill and stroke styles - private fun createPaint(color: Int, style: Paint.Style = Paint.Style.FILL, strokeCap: Paint.Cap = Paint.Cap.BUTT, strokeWidth: Float = 0f) = Paint(Paint.ANTI_ALIAS_FLAG).apply { + // Combined paint creation function for both fill and stroke styles. + private fun createPaint( + color: Int, + style: Paint.Style = Paint.Style.FILL, + strokeCap: Paint.Cap = Paint.Cap.BUTT, + strokeWidth: Float = 0f + ) = Paint(Paint.ANTI_ALIAS_FLAG).apply { this.style = style this.color = color this.strokeCap = strokeCap this.strokeWidth = strokeWidth } - // Initialize paints - val backgroundPaint = createPaint(overlayBackgroundOpacity, style = Paint.Style.FILL) - val progressPaint = createPaint(overlayProgressColor, style = Paint.Style.STROKE, strokeCap = Paint.Cap.ROUND, strokeWidth = 6f.toDisplayPixels()) - val fillBackgroundPaint = createPaint(overlayFillBackgroundPaint, style = Paint.Style.FILL) - val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { - color = overlayTextColor + // Initialize paints. + val backgroundPaint = createPaint( + overlayBackgroundOpacity, + style = Paint.Style.FILL + ) + val progressPaint = createPaint( + overlayProgressColor, + style = Paint.Style.STROKE, + strokeCap = Paint.Cap.ROUND, + strokeWidth = 6f.toDisplayPixels() + ) + val fillBackgroundPaint = createPaint( + overlayFillBackgroundPaint, + style = Paint.Style.FILL + ) + val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { + color = overlayTextColor textAlign = Paint.Align.CENTER - textSize = overlayTextSize.toFloat().toDisplayPixels() + textSize = overlayTextSize.toFloat().toDisplayPixels() } - // Rect for text measurement + // Rect for text measurement. protected val textBounds = Rect() protected var progress = 0 @@ -268,13 +298,18 @@ abstract class AbstractProgressView( invalidate() } + fun setProgressColor(color: Int) { + progressPaint.color = color + invalidate() + } + protected fun measureTextWidth(text: String, paint: Paint): Int { paint.getTextBounds(text, 0, text.length, textBounds) return textBounds.width() } override fun onDraw(canvas: Canvas) { - // Base class implementation can be empty + // Base class implementation can be empty. } } @@ -393,8 +428,8 @@ class HorizontalProgressView( } /** - * Calculate required width based on content - * @return Required width to display all elements + * Calculate required width based on content. + * @return Required width to display all elements. */ private fun calculateRequiredWidth(): Float { textWidth = measureTextWidth(displayText, textPaint).toFloat() @@ -537,8 +572,8 @@ class VerticalProgressView( } /** - * Calculate required height based on content - * @return Required height to display all elements + * Calculate required height based on content. + * @return Required height to display all elements. */ private fun calculateRequiredHeight(): Float { return if (!isMinimalStyle) { @@ -633,4 +668,4 @@ class VerticalProgressView( super.setProgress(value, max, text, isBrightnessMode) requestLayout() } -} \ No newline at end of file +} diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/PlaybackSpeedDialogButton.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/PlaybackSpeedDialogButton.java index 3ac387061..a61ed679c 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/PlaybackSpeedDialogButton.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/videoplayer/PlaybackSpeedDialogButton.java @@ -5,9 +5,13 @@ import android.view.View; import androidx.annotation.Nullable; import app.revanced.extension.shared.Logger; +import app.revanced.extension.youtube.patches.VideoInformation; import app.revanced.extension.youtube.patches.playback.speed.CustomPlaybackSpeedPatch; import app.revanced.extension.youtube.settings.Settings; +import static app.revanced.extension.shared.StringRef.str; +import static app.revanced.extension.shared.Utils.showToastShort; + @SuppressWarnings("unused") public class PlaybackSpeedDialogButton { @Nullable @@ -23,8 +27,27 @@ public class PlaybackSpeedDialogButton { "revanced_playback_speed_dialog_button", "revanced_playback_speed_dialog_button_placeholder", Settings.PLAYBACK_SPEED_DIALOG_BUTTON::get, - view -> CustomPlaybackSpeedPatch.showOldPlaybackSpeedMenu(), - null + view -> { + try { + CustomPlaybackSpeedPatch.showModernCustomPlaybackSpeedDialog(view.getContext()); + } catch (Exception ex) { + Logger.printException(() -> "speed button onClick failure", ex); + } + }, + view -> { + try { + final float speed = (!Settings.REMEMBER_PLAYBACK_SPEED_LAST_SELECTED.get() || + VideoInformation.getPlaybackSpeed() == Settings.PLAYBACK_SPEED_DEFAULT.get()) + ? 1.0f + : Settings.PLAYBACK_SPEED_DEFAULT.get(); + + VideoInformation.overridePlaybackSpeed(speed); + showToastShort(str("revanced_custom_playback_speeds_reset_toast", (speed + "x"))); + } catch (Exception ex) { + Logger.printException(() -> "speed button reset failure", ex); + } + return true; + } ); } catch (Exception ex) { Logger.printException(() -> "initializeButton failure", ex); diff --git a/gradle.properties b/gradle.properties index d18a538e2..34552e85f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M org.gradle.parallel = true android.useAndroidX = true kotlin.code.style = official -version = 5.24.0 +version = 5.26.0 diff --git a/package-lock.json b/package-lock.json index f758b6bde..80bae02a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "@semantic-release/changelog": "^6.0.3", "@semantic-release/git": "^10.0.1", "gradle-semantic-release-plugin": "^1.10.1", - "semantic-release": "^24.2.1" + "semantic-release": "^24.2.5" } }, "node_modules/@babel/code-frame": { @@ -1964,9 +1964,9 @@ } }, "node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", "dev": true, "license": "MIT", "engines": { @@ -3460,9 +3460,9 @@ "license": "ISC" }, "node_modules/marked": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", - "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==", + "version": "15.0.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.12.tgz", + "integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==", "dev": true, "license": "MIT", "bin": { @@ -3473,24 +3473,38 @@ } }, "node_modules/marked-terminal": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-7.1.0.tgz", - "integrity": "sha512-+pvwa14KZL74MVXjYdPR3nSInhGhNvPce/3mqLVZT2oUvt654sL1XImFuLZ1pkA866IYZ3ikDTOFUIC7XzpZZg==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-7.3.0.tgz", + "integrity": "sha512-t4rBvPsHc57uE/2nJOLmMbZCQ4tgAccAED3ngXQqW6g+TxA488JzJ+FK3lQkzBQOI1mRV/r/Kq+1ZlJ4D0owQw==", "dev": true, "license": "MIT", "dependencies": { "ansi-escapes": "^7.0.0", - "chalk": "^5.3.0", + "ansi-regex": "^6.1.0", + "chalk": "^5.4.1", "cli-highlight": "^2.1.11", "cli-table3": "^0.6.5", - "node-emoji": "^2.1.3", - "supports-hyperlinks": "^3.0.0" + "node-emoji": "^2.2.0", + "supports-hyperlinks": "^3.1.0" }, "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "marked": ">=1 <14" + "marked": ">=1 <16" + } + }, + "node_modules/marked-terminal/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/meow": { @@ -3607,9 +3621,9 @@ "license": "MIT" }, "node_modules/node-emoji": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz", - "integrity": "sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.2.0.tgz", + "integrity": "sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw==", "dev": true, "license": "MIT", "dependencies": { @@ -6760,9 +6774,9 @@ "license": "MIT" }, "node_modules/semantic-release": { - "version": "24.2.1", - "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.2.1.tgz", - "integrity": "sha512-z0/3cutKNkLQ4Oy0HTi3lubnjTsdjjgOqmxdPjeYWe6lhFqUPfwslZxRHv3HDZlN4MhnZitb9SLihDkZNxOXfQ==", + "version": "24.2.5", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.2.5.tgz", + "integrity": "sha512-9xV49HNY8C0/WmPWxTlaNleiXhWb//qfMzG2c5X8/k7tuWcu8RssbuS+sujb/h7PiWSXv53mrQvV9hrO9b7vuQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6784,8 +6798,8 @@ "hosted-git-info": "^8.0.0", "import-from-esm": "^2.0.0", "lodash-es": "^4.17.21", - "marked": "^12.0.0", - "marked-terminal": "^7.0.0", + "marked": "^15.0.0", + "marked-terminal": "^7.3.0", "micromatch": "^4.0.2", "p-each-series": "^3.0.0", "p-reduce": "^3.0.0", diff --git a/package.json b/package.json index 789e20fc8..5c21bb60c 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,6 @@ "@semantic-release/changelog": "^6.0.3", "@semantic-release/git": "^10.0.1", "gradle-semantic-release-plugin": "^1.10.1", - "semantic-release": "^24.2.1" + "semantic-release": "^24.2.5" } } diff --git a/patches/api/patches.api b/patches/api/patches.api index a42224881..ac535ded7 100644 --- a/patches/api/patches.api +++ b/patches/api/patches.api @@ -361,10 +361,22 @@ public final class app/revanced/patches/messenger/inputfield/DisableTypingIndica public static final fun getDisableTypingIndicatorPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } +public final class app/revanced/patches/messenger/metaai/RemoveMetaAIPatchKt { + public static final fun getRemoveMetaAIPatch ()Lapp/revanced/patcher/patch/BytecodePatch; +} + +public final class app/revanced/patches/messenger/misc/extension/ExtensionPatchKt { + public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch; +} + public final class app/revanced/patches/messenger/navbar/RemoveMetaAITabPatchKt { public static final fun getRemoveMetaAITabPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } +public final class app/revanced/patches/meta/ads/HideAdsPatchKt { + public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; +} + public final class app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatchKt { public static final fun getForceEnglishLocalePatch ()Lapp/revanced/patcher/patch/BytecodePatch; } @@ -509,6 +521,14 @@ public final class app/revanced/patches/primevideo/misc/extension/ExtensionPatch public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } +public final class app/revanced/patches/primevideo/misc/permissions/RenamePermissionsPatchKt { + public static final fun getRenamePermissionsPatch ()Lapp/revanced/patcher/patch/ResourcePatch; +} + +public final class app/revanced/patches/protonmail/account/RemoveFreeAccountsLimitPatchKt { + public static final fun getRemoveFreeAccountsLimitPatch ()Lapp/revanced/patcher/patch/ResourcePatch; +} + public final class app/revanced/patches/protonmail/signature/RemoveSentFromSignaturePatchKt { public static final fun getRemoveSentFromSignaturePatch ()Lapp/revanced/patcher/patch/ResourcePatch; } @@ -632,6 +652,10 @@ public final class app/revanced/patches/reddit/customclients/sync/syncforreddit/ public static final fun getFixSLinksPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } +public final class app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/thumbnail/FixPostThumbnailsPatchKt { + public static final fun getFixPostThumbnailsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; +} + public final class app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/user/UseUserEndpointPatchKt { public static final fun getUseUserEndpointPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } @@ -650,6 +674,7 @@ public final class app/revanced/patches/reddit/layout/disablescreenshotpopup/Dis public final class app/revanced/patches/reddit/layout/premiumicon/UnlockPremiumIconPatchKt { public static final fun getUnlockPremiumIconPatch ()Lapp/revanced/patcher/patch/BytecodePatch; + public static final fun getUnlockPremiumIconsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } public final class app/revanced/patches/reddit/misc/extension/ExtensionPatchKt { @@ -729,6 +754,10 @@ public final class app/revanced/patches/shared/misc/mapping/ResourceMappingPatch public static final fun getResourceMappings ()Ljava/util/List; } +public final class app/revanced/patches/shared/misc/pairip/license/DisableLicenseCheckPatchKt { + public static final fun getDisableLicenseCheckPatch ()Lapp/revanced/patcher/patch/BytecodePatch; +} + public final class app/revanced/patches/shared/misc/settings/SettingsPatchKt { public static final fun settingsPatch (Ljava/util/List;Ljava/util/Set;)Lapp/revanced/patcher/patch/ResourcePatch; public static final fun settingsPatch (Lkotlin/Pair;Ljava/util/Set;)Lapp/revanced/patcher/patch/ResourcePatch; @@ -925,6 +954,10 @@ public final class app/revanced/patches/soundcloud/offlinesync/EnableOfflineSync public static final fun getEnableOfflineSync ()Lapp/revanced/patcher/patch/BytecodePatch; } +public final class app/revanced/patches/spotify/layout/hide/createbutton/HideCreateButtonPatchKt { + public static final fun getHideCreateButtonPatch ()Lapp/revanced/patcher/patch/BytecodePatch; +} + public final class app/revanced/patches/spotify/layout/theme/CustomThemePatchKt { public static final fun getCustomThemePatch ()Lapp/revanced/patcher/patch/ResourcePatch; } @@ -949,6 +982,10 @@ public final class app/revanced/patches/spotify/misc/fix/SpoofSignaturePatchKt { public static final fun getSpoofSignaturePatch ()Lapp/revanced/patcher/patch/BytecodePatch; } +public final class app/revanced/patches/spotify/misc/fix/login/FixFacebookLoginPatchKt { + public static final fun getFixFacebookLoginPatch ()Lapp/revanced/patcher/patch/BytecodePatch; +} + public final class app/revanced/patches/spotify/misc/privacy/SanitizeSharingLinksPatchKt { public static final fun getSanitizeSharingLinksPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } @@ -1460,6 +1497,10 @@ public final class app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatchKt { public static final fun getGmsCoreSupportPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } +public final class app/revanced/patches/youtube/misc/hapticfeedback/DisableHapticFeedbackPatchKt { + public static final fun getDisableHapticFeedbackPatch ()Lapp/revanced/patcher/patch/BytecodePatch; +} + public final class app/revanced/patches/youtube/misc/imageurlhook/CronetImageUrlHookKt { public static final fun addImageUrlErrorCallbackHook (Ljava/lang/String;)V public static final fun addImageUrlHook (Ljava/lang/String;Z)V @@ -1692,8 +1733,23 @@ public final class app/revanced/util/BytecodeUtilsKt { public static final fun indexOfFirstResourceIdOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I public static final fun injectHideViewCall (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;IILjava/lang/String;Ljava/lang/String;)V public static final fun literal (Lapp/revanced/patcher/FingerprintBuilder;Lkotlin/jvm/functions/Function0;)V + public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;B)V + public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;C)V + public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;D)V + public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;F)V + public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;I)V + public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;J)V + public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;S)V public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Z)V public static synthetic fun returnEarly$default (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ZILjava/lang/Object;)V + public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;B)V + public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;C)V + public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;D)V + public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;F)V + public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;I)V + public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;J)V + public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;S)V + public static final fun returnLate (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Z)V public static final fun transformMethods (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lkotlin/jvm/functions/Function1;)V public static final fun traverseClassHierarchy (Lapp/revanced/patcher/patch/BytecodePatchContext;Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lkotlin/jvm/functions/Function1;)V } diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/adb/HideAdbPatch.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/adb/HideAdbPatch.kt index 7e05318df..28653638b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/all/misc/adb/HideAdbPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/all/misc/adb/HideAdbPatch.kt @@ -47,7 +47,7 @@ val hideAdbStatusPatch = bytecodePatch( .takeIf { it.opcode == Opcode.INVOKE_STATIC } ?.getReference() ?.takeIf { - it.anyMethodSignatureMatches(it, + it.anyMethodSignatureMatches( SETTINGS_GLOBAL_GET_INT_OR_THROW_METHOD_REFERENCE, SETTINGS_GLOBAL_GET_INT_OR_DEFAULT_METHOD_REFERENCE ) diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/build/SpoofBuildInfoPatch.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/build/SpoofBuildInfoPatch.kt index 7cfd385c6..aa4fbf3f8 100644 --- a/patches/src/main/kotlin/app/revanced/patches/all/misc/build/SpoofBuildInfoPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/all/misc/build/SpoofBuildInfoPatch.kt @@ -7,7 +7,7 @@ import app.revanced.patcher.patch.stringOption @Suppress("unused") val spoofBuildInfoPatch = bytecodePatch( name = "Spoof build info", - description = "Spoof the information about the current build.", + description = "Spoofs the information about the current build.", use = false, ) { val board by stringOption( @@ -141,14 +141,14 @@ val spoofBuildInfoPatch = bytecodePatch( val socManufacturer by stringOption( key = "soc-manufacturer", default = null, - title = "SOC Manufacturer", + title = "SOC manufacturer", description = "The manufacturer of the device's primary system-on-chip.", ) val socModel by stringOption( key = "soc-model", default = null, - title = "SOC Model", + title = "SOC model", description = "The model name of the device's primary system-on-chip.", ) diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/connectivity/telephony/sim/spoof/SpoofSimCountryPatch.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/connectivity/telephony/sim/spoof/SpoofSimCountryPatch.kt index b50ccfc88..2f90b5ec3 100644 --- a/patches/src/main/kotlin/app/revanced/patches/all/misc/connectivity/telephony/sim/spoof/SpoofSimCountryPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/all/misc/connectivity/telephony/sim/spoof/SpoofSimCountryPatch.kt @@ -36,12 +36,12 @@ val spoofSimCountryPatch = bytecodePatch( val networkCountryIso by isoCountryPatchOption( "networkCountryIso", - "Network ISO Country Code", + "Network ISO country code", ) val simCountryIso by isoCountryPatchOption( "simCountryIso", - "Sim ISO Country Code", + "SIM ISO country code", ) dependsOn( diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/shortcut/sharetargets/RemoveShareTargetsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/shortcut/sharetargets/RemoveShareTargetsPatch.kt index 6b07c7dc6..4ec7651fe 100644 --- a/patches/src/main/kotlin/app/revanced/patches/all/misc/shortcut/sharetargets/RemoveShareTargetsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/all/misc/shortcut/sharetargets/RemoveShareTargetsPatch.kt @@ -17,7 +17,8 @@ val removeShareTargetsPatch = resourcePatch( try { document("res/xml/shortcuts.xml") } catch (_: FileNotFoundException) { - return@execute Logger.getLogger(this::class.java.name).warning("The app has no shortcuts") + return@execute Logger.getLogger(this::class.java.name).warning( + "The app has no shortcuts. No changes applied.") }.use { document -> val rootNode = document.getNode("shortcuts") as? Element ?: return@use diff --git a/patches/src/main/kotlin/app/revanced/patches/angulus/ads/RemoveAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/angulus/ads/RemoveAdsPatch.kt index 5eb585cf5..c1f3acb8e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/angulus/ads/RemoveAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/angulus/ads/RemoveAdsPatch.kt @@ -1,14 +1,17 @@ package app.revanced.patches.angulus.ads import app.revanced.patcher.patch.bytecodePatch +import app.revanced.patches.shared.misc.pairip.license.disableLicenseCheckPatch import app.revanced.util.returnEarly @Suppress("unused") val angulusPatch = bytecodePatch(name = "Hide ads") { compatibleWith("com.drinkplusplus.angulus") + dependsOn(disableLicenseCheckPatch) + execute { // Always return 0 as the daily measurement count. - getDailyMeasurementCountFingerprint.method.returnEarly() + getDailyMeasurementCountFingerprint.method.returnEarly(0) } } diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/ads/HideAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/ads/HideAdsPatch.kt index 29aeccc1b..9e80fe416 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/ads/HideAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/ads/HideAdsPatch.kt @@ -1,23 +1,9 @@ package app.revanced.patches.instagram.ads -import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.patch.bytecodePatch +@Deprecated("Patch was moved to different package: app.revanced.patches.meta.ads.hideAdsPatch") @Suppress("unused") -val hideAdsPatch = bytecodePatch( - name = "Hide ads", - description = "Hides ads in stories, discover, profile, etc. " + - "An ad can still appear once when refreshing the home feed.", -) { - compatibleWith("com.instagram.android") - - execute { - adInjectorFingerprint.method.addInstructions( - 0, - """ - const/4 v0, 0x0 - return v0 - """, - ) - } +val hideAdsPatch = bytecodePatch { + dependsOn(app.revanced.patches.meta.ads.hideAdsPatch) } diff --git a/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/UnlockPremiumPatch.kt b/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/UnlockPremiumPatch.kt index 4561cee41..8dc963a49 100644 --- a/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/UnlockPremiumPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/premium/UnlockPremiumPatch.kt @@ -5,7 +5,7 @@ import app.revanced.patcher.patch.bytecodePatch @Suppress("unused") val unlockPremiumPatch = bytecodePatch( - name = "Unlock premium", + name = "Unlock Premium", ) { compatibleWith("com.adobe.lrmobile"("10.0.2")) diff --git a/patches/src/main/kotlin/app/revanced/patches/messenger/inputfield/DisableSwitchingEmojiToStickerPatch.kt b/patches/src/main/kotlin/app/revanced/patches/messenger/inputfield/DisableSwitchingEmojiToStickerPatch.kt index 19f5c1251..b9e301725 100644 --- a/patches/src/main/kotlin/app/revanced/patches/messenger/inputfield/DisableSwitchingEmojiToStickerPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/messenger/inputfield/DisableSwitchingEmojiToStickerPatch.kt @@ -5,9 +5,14 @@ import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.bytecodePatch import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +/** + * This patch will be deleted soon. + * + * Pull requests to update this patch to the latest app target are invited. + */ +@Deprecated("This patch only works with an outdated app target that is no longer fully supported by Facebook.") @Suppress("unused") val disableSwitchingEmojiToStickerPatch = bytecodePatch( - name = "Disable switching emoji to sticker", description = "Disables switching from emoji to sticker search mode in message input field.", ) { compatibleWith("com.facebook.orca"("439.0.0.29.119")) diff --git a/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/Fingerprints.kt new file mode 100644 index 000000000..80b94bf1a --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/Fingerprints.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.messenger.metaai + +import com.android.tools.smali.dexlib2.Opcode +import app.revanced.patcher.fingerprint + +internal val getMobileConfigBoolFingerprint = fingerprint { + parameters("J") + returns("Z") + opcodes(Opcode.RETURN) + custom { method, classDef -> + method.implementation ?: return@custom false // unsure if this is necessary + classDef.interfaces.contains("Lcom/facebook/mobileconfig/factory/MobileConfigUnsafeContext;") + } +} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/RemoveMetaAIPatch.kt b/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/RemoveMetaAIPatch.kt new file mode 100644 index 000000000..e669ca2d8 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/RemoveMetaAIPatch.kt @@ -0,0 +1,34 @@ +package app.revanced.patches.messenger.metaai + +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.patch.bytecodePatch +import app.revanced.patches.messenger.misc.extension.sharedExtensionPatch +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction + +private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/messenger/metaai/RemoveMetaAIPatch;" + +@Suppress("unused") +val removeMetaAIPatch = bytecodePatch( + name = "Remove Meta AI", + description = "Removes UI elements related to Meta AI." +) { + compatibleWith("com.facebook.orca") + + dependsOn(sharedExtensionPatch) + + execute { + getMobileConfigBoolFingerprint.method.apply { + val returnIndex = getMobileConfigBoolFingerprint.patternMatch!!.startIndex + val returnRegister = getInstruction(returnIndex).registerA + + addInstructions( + returnIndex, + """ + invoke-static { p1, p2, v$returnRegister }, $EXTENSION_CLASS_DESCRIPTOR->overrideConfigBool(JZ)Z + move-result v$returnRegister + """ + ) + } + } +} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/messenger/misc/extension/ExtensionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/messenger/misc/extension/ExtensionPatch.kt new file mode 100644 index 000000000..0de5210ee --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/messenger/misc/extension/ExtensionPatch.kt @@ -0,0 +1,5 @@ +package app.revanced.patches.messenger.misc.extension + +import app.revanced.patches.shared.misc.extension.sharedExtensionPatch + +val sharedExtensionPatch = sharedExtensionPatch("messenger", mainActivityOnCreateHook) \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/messenger/misc/extension/Hooks.kt b/patches/src/main/kotlin/app/revanced/patches/messenger/misc/extension/Hooks.kt new file mode 100644 index 000000000..0700c3209 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/messenger/misc/extension/Hooks.kt @@ -0,0 +1,7 @@ +package app.revanced.patches.messenger.misc.extension + +import app.revanced.patches.shared.misc.extension.extensionHook + +internal val mainActivityOnCreateHook = extensionHook { + strings("MainActivity_onCreate_begin") +} diff --git a/patches/src/main/kotlin/app/revanced/patches/messenger/navbar/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/messenger/navbar/Fingerprints.kt deleted file mode 100644 index 766e20209..000000000 --- a/patches/src/main/kotlin/app/revanced/patches/messenger/navbar/Fingerprints.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.messenger.navbar - -import app.revanced.patcher.fingerprint -import com.android.tools.smali.dexlib2.Opcode - -internal val createTabConfigurationFingerprint = fingerprint { - strings("MessengerTabConfigurationCreator.createTabConfiguration") - opcodes( - Opcode.INVOKE_DIRECT, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.INVOKE_DIRECT, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - ) -} diff --git a/patches/src/main/kotlin/app/revanced/patches/messenger/navbar/RemoveMetaAITabPatch.kt b/patches/src/main/kotlin/app/revanced/patches/messenger/navbar/RemoveMetaAITabPatch.kt index 75fb98577..280f448b3 100644 --- a/patches/src/main/kotlin/app/revanced/patches/messenger/navbar/RemoveMetaAITabPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/messenger/navbar/RemoveMetaAITabPatch.kt @@ -1,25 +1,12 @@ package app.revanced.patches.messenger.navbar import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import app.revanced.patches.messenger.metaai.removeMetaAIPatch +@Deprecated("Superseded by removeMetaAIPatch", ReplaceWith("removeMetaAIPatch")) @Suppress("unused") val removeMetaAITabPatch = bytecodePatch( - name = "Remove Meta AI tab", description = "Removes the 'Meta AI' tab from the navbar.", ) { - compatibleWith("com.facebook.orca") - - execute { - createTabConfigurationFingerprint.let { - val moveResultIndex = it.patternMatch!!.startIndex + 1 - val enabledRegister = it.method.getInstruction(moveResultIndex).registerA - it.method.replaceInstruction( - moveResultIndex, - "const/4 v$enabledRegister, 0x0" - ) - } - } + dependsOn(removeMetaAIPatch) } diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/meta/ads/Fingerprints.kt similarity index 85% rename from patches/src/main/kotlin/app/revanced/patches/instagram/ads/Fingerprints.kt rename to patches/src/main/kotlin/app/revanced/patches/meta/ads/Fingerprints.kt index 1e5eb6d04..d9e1d9e0b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/meta/ads/Fingerprints.kt @@ -1,13 +1,13 @@ -package app.revanced.patches.instagram.ads - -import app.revanced.patcher.fingerprint -import com.android.tools.smali.dexlib2.AccessFlags - -internal val adInjectorFingerprint = fingerprint { - accessFlags(AccessFlags.PRIVATE) - returns("Z") - parameters("L", "L") - strings( - "SponsoredContentController.insertItem", - ) -} +package app.revanced.patches.meta.ads + +import app.revanced.patcher.fingerprint +import com.android.tools.smali.dexlib2.AccessFlags + +internal val adInjectorFingerprint = fingerprint { + accessFlags(AccessFlags.PRIVATE) + returns("Z") + parameters("L", "L") + strings( + "SponsoredContentController.insertItem", + ) +} diff --git a/patches/src/main/kotlin/app/revanced/patches/meta/ads/HideAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/meta/ads/HideAdsPatch.kt new file mode 100644 index 000000000..f1fb3d791 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/meta/ads/HideAdsPatch.kt @@ -0,0 +1,21 @@ +package app.revanced.patches.meta.ads + +import app.revanced.patcher.patch.bytecodePatch +import app.revanced.util.returnEarly + +@Suppress("unused") +val hideAdsPatch = bytecodePatch( + name = "Hide ads", +) { + /** + * Patch is identical for both Instagram and Threads app. + */ + compatibleWith( + "com.instagram.android", + "com.instagram.barcelona", + ) + + execute { + adInjectorFingerprint.method.returnEarly(false) + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/primevideo/misc/permissions/RenamePermissionsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/primevideo/misc/permissions/RenamePermissionsPatch.kt new file mode 100644 index 000000000..9a671879f --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/primevideo/misc/permissions/RenamePermissionsPatch.kt @@ -0,0 +1,44 @@ +package app.revanced.patches.primevideo.misc.permissions + +import app.revanced.patcher.patch.PatchException +import app.revanced.patcher.patch.resourcePatch +import app.revanced.util.asSequence +import app.revanced.util.getNode +import org.w3c.dom.Element + +@Suppress("unused") +val renamePermissionsPatch = resourcePatch( + name = "Rename shared permissions", + description = "Rename certain permissions shared across Amazon apps. " + + "Applying this patch can fix installation errors, but can also break features in certain apps.", + use = false +) { + compatibleWith("com.amazon.avod.thirdpartyclient") + + val permissionNames = setOf( + "com.amazon.identity.permission.CAN_CALL_MAP_INFORMATION_PROVIDER", + "com.amazon.identity.auth.device.perm.AUTH_SDK", + "com.amazon.dcp.sso.permission.account.changed", + "com.amazon.dcp.sso.permission.AmazonAccountPropertyService.property.changed", + "com.amazon.identity.permission.CALL_AMAZON_DEVICE_INFORMATION_PROVIDER", + "com.amazon.appmanager.preload.permission.READ_PRELOAD_DEVICE_INFO_PROVIDER" + ) + + execute { + document("AndroidManifest.xml").use { document -> + val manifest = document.getNode("manifest") as Element + + val permissions = manifest + .getElementsByTagName("permission") + .asSequence() + .map { Pair(it as Element, it.getAttribute("android:name")) } + .filter { (_, name) -> name in permissionNames } + + if (permissions.none()) throw PatchException("Could not find any permissions to rename") + + permissions.forEach { (element, name) -> + element.setAttribute("android:name", "revanced.$name") + } + } + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/protonmail/account/RemoveFreeAccountsLimitPatch.kt b/patches/src/main/kotlin/app/revanced/patches/protonmail/account/RemoveFreeAccountsLimitPatch.kt new file mode 100644 index 000000000..473d8d400 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/protonmail/account/RemoveFreeAccountsLimitPatch.kt @@ -0,0 +1,21 @@ +package app.revanced.patches.protonmail.account + +import app.revanced.patcher.patch.resourcePatch +import app.revanced.util.findElementByAttributeValueOrThrow + +@Suppress("unused") +val removeFreeAccountsLimitPatch = resourcePatch( + name = "Remove free accounts limit", + description = "Removes the limit for maximum free accounts logged in.", +) { + compatibleWith("ch.protonmail.android") + + execute { + document("res/values/integers.xml").use { document -> + document.documentElement.childNodes.findElementByAttributeValueOrThrow( + "name", + "core_feature_auth_user_check_max_free_user_count", + ).textContent = Int.MAX_VALUE.toString() + } + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/protonmail/signature/RemoveSentFromSignaturePatch.kt b/patches/src/main/kotlin/app/revanced/patches/protonmail/signature/RemoveSentFromSignaturePatch.kt index f3d2b2dd2..a59b8e7dd 100644 --- a/patches/src/main/kotlin/app/revanced/patches/protonmail/signature/RemoveSentFromSignaturePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/protonmail/signature/RemoveSentFromSignaturePatch.kt @@ -39,4 +39,4 @@ val removeSentFromSignaturePatch = resourcePatch( if (!foundString) throw PatchException("Could not find 'sent from' string in resources") } -} \ No newline at end of file +} diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/thumbnail/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/thumbnail/Fingerprints.kt new file mode 100644 index 000000000..7a64031f1 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/thumbnail/Fingerprints.kt @@ -0,0 +1,12 @@ +package app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.thumbnail + +import app.revanced.patcher.fingerprint +import com.android.tools.smali.dexlib2.AccessFlags + +internal val customImageViewLoadFingerprint = fingerprint { + accessFlags(AccessFlags.PUBLIC) + parameters("Ljava/lang/String;", "Z", "Z", "I", "I") + custom { _, classDef -> + classDef.endsWith("CustomImageView;") + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/thumbnail/FixPostThumbnailsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/thumbnail/FixPostThumbnailsPatch.kt new file mode 100644 index 000000000..4ac2fc3d0 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/thumbnail/FixPostThumbnailsPatch.kt @@ -0,0 +1,31 @@ +package app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.thumbnail + +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.patch.bytecodePatch + +@Suppress("unused") +val fixPostThumbnailsPatch = bytecodePatch( + name = "Fix post thumbnails", + description = "Fixes loading post thumbnails by correcting their URLs.", +) { + + compatibleWith( + "com.laurencedawson.reddit_sync", + "com.laurencedawson.reddit_sync.pro", + "com.laurencedawson.reddit_sync.dev" + ) + + // Image URLs contain escaped ampersands (&), let's replace these with unescaped ones (&). + execute { + customImageViewLoadFingerprint.method.addInstructions( + 0, + """ + # url = url.replace("&", "&"); + const-string v0, "&" + const-string v1, "&" + invoke-virtual { p1, v0, v1 }, Ljava/lang/String;->replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String; + move-result-object p1 + """ + ) + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/UnlockPremiumIconPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/UnlockPremiumIconPatch.kt index bde2b52b9..992ff27e5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/UnlockPremiumIconPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/UnlockPremiumIconPatch.kt @@ -4,9 +4,9 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.patch.bytecodePatch @Suppress("unused") -val unlockPremiumIconPatch = bytecodePatch( - name = "Unlock premium Reddit icons", - description = "Unlocks the premium Reddit icons.", +val unlockPremiumIconsPatch = bytecodePatch( + name = "Unlock Premium icons", + description = "Unlocks the Reddit Premium icons.", ) { compatibleWith("com.reddit.frontpage") @@ -20,3 +20,9 @@ val unlockPremiumIconPatch = bytecodePatch( ) } } + +@Deprecated("Patch was renamed", ReplaceWith("unlockPremiumIconsPatch")) +@Suppress("unused") +val unlockPremiumIconPatch = bytecodePatch{ + dependsOn(unlockPremiumIconsPatch) +} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt index 19e1bad96..d5260653a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt @@ -198,7 +198,7 @@ fun gmsCoreSupportPatch( // Google Play Utility is not present in all apps, so we need to check if it's present. if (googlePlayUtilityFingerprint.methodOrNull != null) { - googlePlayUtilityFingerprint.method.returnEarly() + googlePlayUtilityFingerprint.method.returnEarly(0) } // Verify GmsCore is installed and whitelisted for power optimizations and background usage. diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/pairip/license/DisableLicenseCheckPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/pairip/license/DisableLicenseCheckPatch.kt new file mode 100644 index 000000000..36a99f728 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/pairip/license/DisableLicenseCheckPatch.kt @@ -0,0 +1,27 @@ +package app.revanced.patches.shared.misc.pairip.license + +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.patch.bytecodePatch +import app.revanced.util.returnEarly +import java.util.logging.Logger + +@Suppress("unused") +val disableLicenseCheckPatch = bytecodePatch( + name = "Disable Pairip license check", + description = "Disables Play Integrity API (Pairip) client-side license check.", + use = false +) { + + execute { + if (processLicenseResponseFingerprint.methodOrNull == null || validateLicenseResponseFingerprint.methodOrNull == null) { + return@execute Logger.getLogger(this::class.java.name) + .warning("Could not find Pairip licensing check. No changes applied.") + } + + // Set first parameter (responseCode) to 0 (success status). + processLicenseResponseFingerprint.method.addInstruction(0, "const/4 p1, 0x0") + + // Short-circuit the license response validation. + validateLicenseResponseFingerprint.method.returnEarly() + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/pairip/license/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/pairip/license/Fingerprints.kt new file mode 100644 index 000000000..344fd02da --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/pairip/license/Fingerprints.kt @@ -0,0 +1,17 @@ +package app.revanced.patches.shared.misc.pairip.license + +import app.revanced.patcher.fingerprint + +internal val processLicenseResponseFingerprint = fingerprint { + custom { method, classDef -> + classDef.type == "Lcom/pairip/licensecheck/LicenseClient;" && + method.name == "processResponse" + } +} + +internal val validateLicenseResponseFingerprint = fingerprint { + custom { method, classDef -> + classDef.type == "Lcom/pairip/licensecheck/ResponseValidator;" && + method.name == "validateResponse" + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/layout/hide/createbutton/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/layout/hide/createbutton/Fingerprints.kt new file mode 100644 index 000000000..5d555b187 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/layout/hide/createbutton/Fingerprints.kt @@ -0,0 +1,28 @@ +package app.revanced.patches.spotify.layout.hide.createbutton + +import app.revanced.patcher.fingerprint +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.reference.MethodReference + +internal val navigationBarItemSetClassFingerprint = fingerprint { + strings("NavigationBarItemSet(") +} + +internal val navigationBarItemSetConstructorFingerprint = fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) + // Make sure the method checks whether navigation bar items are null before adding them. + // If this is not true, then we cannot patch the method and potentially transform the parameters into null. + opcodes(Opcode.IF_EQZ, Opcode.INVOKE_VIRTUAL) + custom { method, _ -> + method.indexOfFirstInstruction { + getReference()?.name == "add" + } >= 0 + } +} + +internal val oldNavigationBarAddItemFingerprint = fingerprint { + strings("Bottom navigation tabs exceeds maximum of 5 tabs") +} diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/layout/hide/createbutton/HideCreateButtonPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/layout/hide/createbutton/HideCreateButtonPatch.kt new file mode 100644 index 000000000..9685f0463 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/layout/hide/createbutton/HideCreateButtonPatch.kt @@ -0,0 +1,110 @@ +package app.revanced.patches.spotify.layout.hide.createbutton + +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.smali.ExternalLabel +import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch +import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference +import java.util.logging.Logger + +private const val EXTENSION_CLASS_DESCRIPTOR = + "Lapp/revanced/extension/spotify/layout/hide/createbutton/HideCreateButtonPatch;" + +@Suppress("unused") +val hideCreateButtonPatch = bytecodePatch( + name = "Hide Create button", + description = "Hides the \"Create\" button in the navigation bar." +) { + compatibleWith("com.spotify.music") + + dependsOn(sharedExtensionPatch) + + execute { + if (IS_SPOTIFY_LEGACY_APP_TARGET) { + Logger.getLogger(this::class.java.name).warning( + "Create button does not exist in legacy app target. No changes applied." + ) + return@execute + } + + val oldNavigationBarAddItemMethod = oldNavigationBarAddItemFingerprint.originalMethodOrNull + // Only throw the fingerprint error when oldNavigationBarAddItemMethod does not exist. + val navigationBarItemSetClassDef = if (oldNavigationBarAddItemMethod == null) { + navigationBarItemSetClassFingerprint.originalClassDef + } else { + navigationBarItemSetClassFingerprint.originalClassDefOrNull + } + + if (navigationBarItemSetClassDef != null) { + // Main patch for newest and most versions. + // The NavigationBarItemSet constructor accepts multiple parameters which represent each navigation bar item. + // Each item is manually checked whether it is not null and then added to a LinkedHashSet. + // Since the order of the items can differ, we are required to check every parameter to see whether it is the + // Create button. So, for every parameter passed to the method, invoke our extension method and overwrite it + // to null in case it is the Create button. + navigationBarItemSetConstructorFingerprint.match(navigationBarItemSetClassDef).method.apply { + // Add 1 to the index because the first parameter register is `this`. + val parameterTypesWithRegister = parameterTypes.mapIndexed { index, parameterType -> + parameterType to (index + 1) + } + + val returnNullIfIsCreateButtonDescriptor = + "$EXTENSION_CLASS_DESCRIPTOR->returnNullIfIsCreateButton(Ljava/lang/Object;)Ljava/lang/Object;" + + parameterTypesWithRegister.reversed().forEach { (parameterType, parameterRegister) -> + addInstructions( + 0, + """ + invoke-static { p$parameterRegister }, $returnNullIfIsCreateButtonDescriptor + move-result-object p$parameterRegister + check-cast p$parameterRegister, $parameterType + """ + ) + } + } + } + + if (oldNavigationBarAddItemMethod != null) { + // In case an older version of the app is being patched, hook the old method which adds navigation bar items. + // Return null early if the navigation bar item title resource id is old Create button title resource id. + oldNavigationBarAddItemFingerprint.methodOrNull?.apply { + val getNavigationBarItemTitleStringIndex = indexOfFirstInstructionOrThrow { + val reference = getReference() + reference?.definingClass == "Landroid/content/res/Resources;" && reference.name == "getString" + } + // This register is a parameter register, so it can be used at the start of the method when adding + // the new instructions. + val oldNavigationBarItemTitleResIdRegister = + getInstruction(getNavigationBarItemTitleStringIndex).registerD + + // The instruction where the normal method logic starts. + val firstInstruction = getInstruction(0) + + val isOldCreateButtonDescriptor = + "$EXTENSION_CLASS_DESCRIPTOR->isOldCreateButton(I)Z" + + addInstructionsWithLabels( + 0, + """ + invoke-static { v$oldNavigationBarItemTitleResIdRegister }, $isOldCreateButtonDescriptor + move-result v0 + + # If this navigation bar item is not the Create button, jump to the normal method logic. + if-eqz v0, :normal-method-logic + + # Return null early because this method return value is a BottomNavigationItemView. + const/4 v0, 0 + return-object v0 + """, + ExternalLabel("normal-method-logic", firstInstruction) + ) + } + } + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/layout/theme/CustomThemePatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/layout/theme/CustomThemePatch.kt index da0d8482d..738db4dec 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/layout/theme/CustomThemePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/layout/theme/CustomThemePatch.kt @@ -2,65 +2,19 @@ package app.revanced.patches.spotify.layout.theme import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.fingerprint import app.revanced.patcher.patch.booleanOption import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.patch.stringOption -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.spotify.misc.extension.IS_SPOTIFY_LEGACY_APP_TARGET import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch +import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET import app.revanced.util.* -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction -import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference import org.w3c.dom.Element private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/spotify/layout/theme/CustomThemePatch;" -internal val spotifyBackgroundColor = stringOption( - key = "backgroundColor", - default = "@android:color/black", - title = "Primary background color", - description = "The background color. Can be a hex color or a resource reference.", - required = true, -) - -internal val overridePlayerGradientColor = booleanOption( - key = "overridePlayerGradientColor", - default = false, - title = "Override player gradient color", - description = "Apply primary background color to the player gradient color, which changes dynamically with the song.", - required = false -) - -internal val spotifyBackgroundColorSecondary = stringOption( - key = "backgroundColorSecondary", - default = "#FF121212", - title = "Secondary background color", - description = - "The secondary background color. (e.g. playlist list in home, player artist, song credits). Can be a hex color or a resource reference.", - required = true, -) - -internal val spotifyAccentColor = stringOption( - key = "accentColor", - default = "#FF1ED760", - title = "Accent color", - description = "The accent color ('Spotify green' by default). Can be a hex color or a resource reference.", - required = true, -) - -internal val spotifyAccentColorPressed = stringOption( - key = "accentColorPressed", - default = "#FF169C46", - title = "Pressed dark theme accent color", - description = - "The color when accented buttons are pressed, by default slightly darker than accent. Can be a hex color or a resource reference.", - required = true, -) - private val customThemeBytecodePatch = bytecodePatch { dependsOn(sharedExtensionPatch) @@ -71,60 +25,60 @@ private val customThemeBytecodePatch = bytecodePatch { return@execute } - fun MutableMethod.addColorChangeInstructions(literal: Long, colorString: String) { - val index = indexOfFirstLiteralInstructionOrThrow(literal) - val register = getInstruction(index).registerA + val colorSpaceUtilsClassDef = colorSpaceUtilsClassFingerprint.originalClassDef + + // Hook a util method that converts ARGB to RGBA in the sRGB color space to replace hardcoded accent colors. + convertArgbToRgbaFingerprint.match(colorSpaceUtilsClassDef).method.apply { + addInstructions( + 0, + """ + long-to-int p0, p0 + invoke-static { p0 }, $EXTENSION_CLASS_DESCRIPTOR->replaceColor(I)I + move-result p0 + int-to-long p0, p0 + """ + ) + } + + // Lottie JSON parser method. It parses the JSON Lottie animation into its own class, + // including the solid color of it. + parseLottieJsonFingerprint.method.apply { + val invokeParseColorIndex = indexOfFirstInstructionOrThrow { + val reference = getReference() + reference?.definingClass == "Landroid/graphics/Color;" + && reference.name == "parseColor" + } + val parsedColorRegister = getInstruction(invokeParseColorIndex + 1).registerA + + val replaceColorDescriptor = "$EXTENSION_CLASS_DESCRIPTOR->replaceColor(I)I" addInstructions( - index + 1, + invokeParseColorIndex + 2, """ - const-string v$register, "$colorString" - invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getThemeColor(Ljava/lang/String;)J - move-result-wide v$register + # Use invoke-static/range because the register number is too large. + invoke-static/range { v$parsedColorRegister .. v$parsedColorRegister }, $replaceColorDescriptor + move-result v$parsedColorRegister """ ) } - val encoreColorsClassName = with(encoreThemeFingerprint.originalMethod) { - // "Encore" colors are referenced right before the value of POSITIVE_INFINITY is returned. - // Begin the instruction find using the index of where POSITIVE_INFINITY is set into the register. - val positiveInfinityIndex = indexOfFirstLiteralInstructionOrThrow( - Float.POSITIVE_INFINITY - ) - val encoreColorsFieldReferenceIndex = indexOfFirstInstructionReversedOrThrow( - positiveInfinityIndex, - Opcode.SGET_OBJECT - ) - - getInstruction(encoreColorsFieldReferenceIndex) - .getReference()!!.definingClass - } - - val encoreColorsConstructorFingerprint = fingerprint { - accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR) - custom { method, classDef -> - classDef.type == encoreColorsClassName && - method.containsLiteralInstruction(PLAYLIST_BACKGROUND_COLOR_LITERAL) + // Lottie animated color parser. + parseAnimatedColorFingerprint.method.apply { + val invokeArgbIndex = indexOfFirstInstructionOrThrow { + val reference = getReference() + reference?.definingClass == "Landroid/graphics/Color;" + && reference.name == "argb" } + val argbColorRegister = getInstruction(invokeArgbIndex + 1).registerA + + addInstructions( + invokeArgbIndex + 2, + """ + invoke-static { v$argbColorRegister }, $EXTENSION_CLASS_DESCRIPTOR->replaceColor(I)I + move-result v$argbColorRegister + """ + ) } - - val backgroundColor by spotifyBackgroundColor - val backgroundColorSecondary by spotifyBackgroundColorSecondary - - encoreColorsConstructorFingerprint.method.apply { - addColorChangeInstructions(PLAYLIST_BACKGROUND_COLOR_LITERAL, backgroundColor!!) - addColorChangeInstructions(SHARE_MENU_BACKGROUND_COLOR_LITERAL, backgroundColorSecondary!!) - } - - homeCategoryPillColorsFingerprint.method.addColorChangeInstructions( - HOME_CATEGORY_PILL_COLOR_LITERAL, - backgroundColorSecondary!! - ) - - settingsHeaderColorFingerprint.method.addColorChangeInstructions( - SETTINGS_HEADER_COLOR_LITERAL, - backgroundColorSecondary!! - ) } } @@ -138,11 +92,48 @@ val customThemePatch = resourcePatch( dependsOn(customThemeBytecodePatch) - val backgroundColor by spotifyBackgroundColor() - val overridePlayerGradientColor by overridePlayerGradientColor() - val backgroundColorSecondary by spotifyBackgroundColorSecondary() - val accentColor by spotifyAccentColor() - val accentColorPressed by spotifyAccentColorPressed() + val backgroundColor by stringOption( + key = "backgroundColor", + default = "@android:color/black", + title = "Primary background color", + description = "The background color. Can be a hex color or a resource reference.", + required = true, + ) + + val overridePlayerGradientColor by booleanOption( + key = "overridePlayerGradientColor", + default = false, + title = "Override player gradient color", + description = + "Apply primary background color to the player gradient color, which changes dynamically with the song.", + required = false, + ) + + val backgroundColorSecondary by stringOption( + key = "backgroundColorSecondary", + default = "#FF121212", + title = "Secondary background color", + description = "The secondary background color. (e.g. playlist list in home, player artist, song credits). " + + "Can be a hex color or a resource reference.\",", + required = true, + ) + + val accentColor by stringOption( + key = "accentColor", + default = "#FF1ED760", + title = "Accent color", + description = "The accent color ('Spotify green' by default). Can be a hex color or a resource reference.", + required = true, + ) + + val accentColorPressed by stringOption( + key = "accentColorPressed", + default = "#FF1ABC54", + title = "Pressed dark theme accent color", + description = "The color when accented buttons are pressed, by default slightly darker than accent. " + + "Can be a hex color or a resource reference.", + required = true, + ) execute { document("res/values/colors.xml").use { document -> @@ -161,34 +152,41 @@ val customThemePatch = resourcePatch( } node.textContent = when (name) { + // Main background color. + "gray_7", + // Left sidebar background color in tablet mode. + "gray_10", // Gradient next to user photo and "All" in home page. "dark_base_background_base", - // Main background. - "gray_7", - // Left sidebar background in tablet mode. - "gray_10", - // "Add account", "Settings and privacy", "View Profile" left sidebar background. + // "Add account", "Settings and privacy", "View Profile" left sidebar background color. "dark_base_background_elevated_base", // Song/player gradient start/end color. "bg_gradient_start_color", "bg_gradient_end_color", - // Login screen background and gradient start. + // Login screen background color and gradient start. "sthlm_blk", "sthlm_blk_grad_start", // Misc. "image_placeholder_color", -> backgroundColor - // Track credits, merch background in song player. + // "About the artist" background color in song player. + "gray_15", + // Track credits, merch background color in song player. "track_credits_card_bg", "benefit_list_default_color", "merch_card_background", // Playlist list background in home page. "opacity_white_10", - // "About the artist" background in song player. - "gray_15", // "What's New" pills background. "dark_base_background_tinted_highlight" -> backgroundColorSecondary - "dark_brightaccent_background_base", "dark_base_text_brightaccent", "green_light" -> accentColor - "dark_brightaccent_background_press" -> accentColorPressed + "dark_brightaccent_background_base", + "dark_base_text_brightaccent", + "green_light", + "spotify_green_157" + -> accentColor + + "dark_brightaccent_background_press" + -> accentColorPressed + else -> continue } } @@ -198,8 +196,8 @@ val customThemePatch = resourcePatch( document("res/drawable/start_screen_gradient.xml").use { document -> val gradientNode = document.getElementsByTagName("gradient").item(0) as Element - gradientNode.setAttribute("android:startColor", backgroundColor) - gradientNode.setAttribute("android:endColor", backgroundColor) + gradientNode.setAttribute("android:startColor", "@color/gray_7") + gradientNode.setAttribute("android:endColor", "@color/gray_7") } } } diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/layout/theme/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/layout/theme/Fingerprints.kt index 355422477..eb3ab7839 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/layout/theme/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/layout/theme/Fingerprints.kt @@ -4,30 +4,25 @@ import app.revanced.patcher.fingerprint import app.revanced.util.containsLiteralInstruction import com.android.tools.smali.dexlib2.AccessFlags -internal val encoreThemeFingerprint = fingerprint { - strings("Encore theme was not provided.") // Partial string match. - custom { method, _ -> - method.name == "invoke" - } +internal val colorSpaceUtilsClassFingerprint = fingerprint { + strings("The specified color must be encoded in an RGB color space.") // Partial string match. } -internal const val PLAYLIST_BACKGROUND_COLOR_LITERAL = 0xFF121212 -internal const val SHARE_MENU_BACKGROUND_COLOR_LITERAL = 0xFF1F1F1F -internal const val HOME_CATEGORY_PILL_COLOR_LITERAL = 0xFF333333 -internal const val SETTINGS_HEADER_COLOR_LITERAL = 0xFF282828 - -internal val homeCategoryPillColorsFingerprint = fingerprint{ - accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR) - custom { method, _ -> - method.containsLiteralInstruction(HOME_CATEGORY_PILL_COLOR_LITERAL) && - method.containsLiteralInstruction(0x33000000) - } +internal val convertArgbToRgbaFingerprint = fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC, AccessFlags.FINAL) + returns("J") + parameters("J") } -internal val settingsHeaderColorFingerprint = fingerprint { - accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR) +internal val parseLottieJsonFingerprint = fingerprint { + strings("Unsupported matte type: ") +} + +internal val parseAnimatedColorFingerprint = fingerprint { + parameters("L", "F") + returns("Ljava/lang/Object;") custom { method, _ -> - method.containsLiteralInstruction(SETTINGS_HEADER_COLOR_LITERAL) && - method.containsLiteralInstruction(0) + method.containsLiteralInstruction(255.0) && + method.containsLiteralInstruction(1.0) } } diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/OnDemandPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/OnDemandPatch.kt index 6444ff7fb..a624b42fd 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/OnDemandPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/OnDemandPatch.kt @@ -3,9 +3,9 @@ package app.revanced.patches.spotify.lite.ondemand import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.patch.bytecodePatch +@Deprecated("Patch no longer works and will be deleted soon") @Suppress("unused") val onDemandPatch = bytecodePatch( - name = "Enable on demand", description = "Enables listening to songs on-demand, allowing to play any song from playlists, albums or artists without limitations. This does not remove ads.", ) { compatibleWith("com.spotify.lite") diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/Fingerprints.kt index daddd2841..a797763a0 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/Fingerprints.kt @@ -1,15 +1,18 @@ package app.revanced.patches.spotify.misc import app.revanced.patcher.fingerprint -import app.revanced.patches.spotify.misc.extension.IS_SPOTIFY_LEGACY_APP_TARGET +import app.revanced.patcher.patch.BytecodePatchContext +import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.TypeReference -internal val accountAttributeFingerprint = fingerprint { +context(BytecodePatchContext) +internal val accountAttributeFingerprint get() = fingerprint { custom { _, classDef -> classDef.type == if (IS_SPOTIFY_LEGACY_APP_TARGET) { "Lcom/spotify/useraccount/v1/AccountAttribute;" @@ -19,7 +22,8 @@ internal val accountAttributeFingerprint = fingerprint { } } -internal val productStateProtoGetMapFingerprint = fingerprint { +context(BytecodePatchContext) +internal val productStateProtoGetMapFingerprint get() = fingerprint { returns("Ljava/util/Map;") custom { _, classDef -> classDef.type == if (IS_SPOTIFY_LEGACY_APP_TARGET) { @@ -34,9 +38,22 @@ internal val buildQueryParametersFingerprint = fingerprint { strings("trackRows", "device_type:tablet") } -internal val contextMenuExperimentsFingerprint = fingerprint { +internal val contextMenuViewModelClassFingerprint = fingerprint { + strings("ContextMenuViewModel(header=") +} + +internal val contextMenuViewModelAddItemFingerprint = fingerprint { parameters("L") - strings("remove_ads_upsell_enabled") + returns("V") + custom { method, _ -> + method.indexOfFirstInstruction { + getReference()?.name == "add" + } >= 0 + } +} + +internal val getViewModelFingerprint = fingerprint { + custom { method, _ -> method.name == "getViewModel" } } internal val contextFromJsonFingerprint = fingerprint { @@ -47,15 +64,15 @@ internal val contextFromJsonFingerprint = fingerprint { Opcode.MOVE_RESULT_OBJECT, Opcode.INVOKE_STATIC ) - custom { methodDef, classDef -> - methodDef.name == "fromJson" && + custom { method, classDef -> + method.name == "fromJson" && classDef.endsWith("voiceassistants/playermodels/ContextJsonAdapter;") } } internal val readPlayerOptionOverridesFingerprint = fingerprint { - custom { methodDef, classDef -> - methodDef.name == "readPlayerOptionOverrides" && + custom { method, classDef -> + method.name == "readPlayerOptionOverrides" && classDef.endsWith("voiceassistants/playermodels/PreparePlayOptionsJsonAdapter;") } } @@ -65,8 +82,15 @@ internal val protobufListsFingerprint = fingerprint { custom { method, _ -> method.name == "emptyProtobufList" } } -internal val protobufListRemoveFingerprint = fingerprint { - custom { method, _ -> method.name == "remove" } +internal val abstractProtobufListEnsureIsMutableFingerprint = fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + parameters() + returns("V") + custom { method, _ -> + method.indexOfFirstInstruction { + getReference()?.type == "Ljava/lang/UnsupportedOperationException;" + } >= 0 + } } internal val homeSectionFingerprint = fingerprint { @@ -84,7 +108,8 @@ internal val homeStructureGetSectionsFingerprint = fingerprint { internal fun reactivexFunctionApplyWithClassInitFingerprint(className: String) = fingerprint { returns("Ljava/lang/Object;") parameters("Ljava/lang/Object;") - custom { method, _ -> method.name == "apply" && method.indexOfFirstInstruction { + custom { method, _ -> + method.name == "apply" && method.indexOfFirstInstruction { opcode == Opcode.NEW_INSTANCE && getReference()?.type?.endsWith(className) == true } >= 0 } diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/UnlockPremiumPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/UnlockPremiumPatch.kt index 90bfc1694..d32ce24b3 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/UnlockPremiumPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/UnlockPremiumPatch.kt @@ -2,23 +2,21 @@ package app.revanced.patches.spotify.misc 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.extensions.InstructionExtensions.removeInstruction import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions -import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableClass import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.spotify.misc.extension.IS_SPOTIFY_LEGACY_APP_TARGET +import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET +import app.revanced.util.* import app.revanced.util.toPublicAccessFlags import com.android.tools.smali.dexlib2.Opcode 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.FieldReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference @@ -29,7 +27,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/spotify/ @Suppress("unused") val unlockPremiumPatch = bytecodePatch( - name = "Unlock Spotify Premium", + name = "Unlock Premium", description = "Unlocks Spotify Premium features. Server-sided features like downloading songs are still locked.", ) { compatibleWith("com.spotify.music") @@ -63,7 +61,7 @@ val unlockPremiumPatch = bytecodePatch( addInstruction( getAttributesMapIndex + 1, "invoke-static { v$attributesMapRegister }, " + - "$EXTENSION_CLASS_DESCRIPTOR->overrideAttribute(Ljava/util/Map;)V" + "$EXTENSION_CLASS_DESCRIPTOR->overrideAttributes(Ljava/util/Map;)V" ) } @@ -74,7 +72,7 @@ val unlockPremiumPatch = bytecodePatch( buildQueryParametersFingerprint.stringMatches!!.first().index, Opcode.IF_EQZ ) - replaceInstruction(addQueryParameterConditionIndex, "nop") + removeInstruction(addQueryParameterConditionIndex) } @@ -122,40 +120,63 @@ val unlockPremiumPatch = bytecodePatch( } - // Disable the "Spotify Premium" upsell experiment in context menus. - contextMenuExperimentsFingerprint.method.apply { - val moveIsEnabledIndex = indexOfFirstInstructionOrThrow( - contextMenuExperimentsFingerprint.stringMatches!!.first().index, Opcode.MOVE_RESULT - ) - val isUpsellEnabledRegister = getInstruction(moveIsEnabledIndex).registerA + val contextMenuViewModelClassDef = contextMenuViewModelClassFingerprint.originalClassDef - replaceInstruction(moveIsEnabledIndex, "const/4 v$isUpsellEnabledRegister, 0") + // Hook the method which adds context menu items and return before adding if the item is a Premium ad. + contextMenuViewModelAddItemFingerprint.match(contextMenuViewModelClassDef).method.apply { + val contextMenuItemClassType = parameterTypes.first() + val contextMenuItemClassDef = classes.find { + it.type == contextMenuItemClassType + } ?: throw PatchException("Could not find context menu item class.") + + // The class returned by ContextMenuItem->getViewModel, which represents the actual context menu item. + val viewModelClassType = getViewModelFingerprint.match(contextMenuItemClassDef).originalMethod.returnType + + // The instruction where the normal method logic starts. + val firstInstruction = getInstruction(0) + + val isFilteredContextMenuItemDescriptor = + "$EXTENSION_CLASS_DESCRIPTOR->isFilteredContextMenuItem(Ljava/lang/Object;)Z" + + addInstructionsWithLabels( + 0, + """ + # The first parameter is the context menu item being added. + # Invoke getViewModel to get the actual context menu item. + invoke-interface { p1 }, $contextMenuItemClassType->getViewModel()$viewModelClassType + move-result-object v0 + + # Check if this context menu item should be filtered out. + invoke-static { v0 }, $isFilteredContextMenuItemDescriptor + move-result v0 + + # If this context menu item should not be filtered out, jump to the normal method logic. + if-eqz v0, :normal-method-logic + return-void + """, + ExternalLabel("normal-method-logic", firstInstruction) + ) } - val protobufListClassDef = with(protobufListsFingerprint.originalMethod) { + val protobufArrayListClassDef = with(protobufListsFingerprint.originalMethod) { val emptyProtobufListGetIndex = indexOfFirstInstructionOrThrow(Opcode.SGET_OBJECT) - // Find the protobuffer list class using the definingClass which contains the empty list static value. + // Find the protobuf array list class using the definingClass which contains the empty list static value. val classType = getInstruction(emptyProtobufListGetIndex).getReference()!!.definingClass - classes.find { it.type == classType } ?: throw PatchException("Could not find protobuffer list class.") + classes.find { it.type == classType } ?: throw PatchException("Could not find protobuf array list class.") } + val abstractProtobufListClassDef = classes.find { + it.type == protobufArrayListClassDef.superclass + } ?: throw PatchException("Could not find abstract protobuf list class.") + // Need to allow mutation of the list so the home ads sections can be removed. - // Protobuffer list has an 'isMutable' boolean parameter that sets the mutability. + // Protobuf array list has an 'isMutable' boolean parameter that sets the mutability. // Forcing that always on breaks unrelated code in strange ways. - // Instead, remove the method call that checks if the list is unmodifiable. - protobufListRemoveFingerprint.match(protobufListClassDef).method.apply { - val invokeThrowUnmodifiableIndex = indexOfFirstInstructionOrThrow { - val reference = getReference() - opcode == Opcode.INVOKE_VIRTUAL && - reference?.returnType == "V" && reference.parameterTypes.isEmpty() - } - - // Remove the method call that throws an exception if the list is not mutable. - removeInstruction(invokeThrowUnmodifiableIndex) - } - + // Instead, return early in the method that throws an error if the list is unmutable. + abstractProtobufListEnsureIsMutableFingerprint.match(abstractProtobufListClassDef) + .method.returnEarly() // Make featureTypeCase_ accessible so we can check the home section type in the extension. homeSectionFingerprint.classDef.publicizeField("featureTypeCase_") diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/extension/ExtensionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/extension/ExtensionPatch.kt index 438fe49df..048228871 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/extension/ExtensionPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/extension/ExtensionPatch.kt @@ -1,21 +1,5 @@ package app.revanced.patches.spotify.misc.extension -import app.revanced.patcher.patch.bytecodePatch import app.revanced.patches.shared.misc.extension.sharedExtensionPatch -import app.revanced.patches.spotify.shared.SPOTIFY_MAIN_ACTIVITY_LEGACY -/** - * If patching a legacy 8.x target. This may also be set if patching slightly older/newer app targets, - * but the only legacy target of interest is 8.6.98.900 as it's the last version that - * supports Spotify integration on Kenwood/Pioneer car stereos. - */ -internal var IS_SPOTIFY_LEGACY_APP_TARGET = false - -val sharedExtensionPatch = bytecodePatch { - dependsOn(sharedExtensionPatch("spotify", mainActivityOnCreateHook)) - - execute { - IS_SPOTIFY_LEGACY_APP_TARGET = mainActivityOnCreateHook.fingerprint - .originalClassDef.type == SPOTIFY_MAIN_ACTIVITY_LEGACY - } -} +val sharedExtensionPatch = sharedExtensionPatch("spotify", mainActivityOnCreateHook) diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/SpoofSignaturePatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/SpoofSignaturePatch.kt index 7ac278ff3..d59969c6c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/SpoofSignaturePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/SpoofSignaturePatch.kt @@ -7,7 +7,5 @@ import app.revanced.patcher.patch.bytecodePatch val spoofSignaturePatch = bytecodePatch( description = "Spoofs the signature of the app fix various functions of the app.", ) { - compatibleWith("com.spotify.music") - dependsOn(spoofPackageInfoPatch) } diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/login/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/login/Fingerprints.kt new file mode 100644 index 000000000..b9edaaeac --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/login/Fingerprints.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.spotify.misc.fix.login + +import app.revanced.patcher.fingerprint +import app.revanced.util.literal + +internal val katanaProxyLoginMethodHandlerClassFingerprint = fingerprint { + strings("katana_proxy_auth") +} + +internal val katanaProxyLoginMethodTryAuthorizeFingerprint = fingerprint { + strings("e2e") + literal { 0 } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/login/FixFacebookLoginPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/login/FixFacebookLoginPatch.kt new file mode 100644 index 000000000..dc9179854 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/fix/login/FixFacebookLoginPatch.kt @@ -0,0 +1,29 @@ +package app.revanced.patches.spotify.misc.fix.login + +import app.revanced.patcher.patch.bytecodePatch +import app.revanced.util.returnEarly + +@Suppress("unused") +val fixFacebookLoginPatch = bytecodePatch( + name = "Fix Facebook login", + description = + "Fix logging in with Facebook when the app is patched by always opening the login in a web browser window.", +) { + compatibleWith("com.spotify.music") + + execute { + // The Facebook SDK tries to handle the login using the Facebook app in case it is installed. + // However, the Facebook app does signature checks with the app that is requesting the authentication, + // which ends up making the Facebook server reject with an invalid key hash for the app signature. + // Override the Faceboook SDK to always handle the login using the web browser, which does not perform + // signature checks. + + val katanaProxyLoginMethodHandlerClass = katanaProxyLoginMethodHandlerClassFingerprint.originalClassDef + // Always return 0 (no Intent was launched) as the result of trying to authorize with the Facebook app to + // make the login fallback to a web browser window. + katanaProxyLoginMethodTryAuthorizeFingerprint + .match(katanaProxyLoginMethodHandlerClass) + .method + .returnEarly(0) + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/Fingerprints.kt index 3d60abf9b..a2d65561d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/Fingerprints.kt @@ -1,41 +1,41 @@ -package app.revanced.patches.spotify.misc.privacy - -import app.revanced.patcher.fingerprint -import app.revanced.util.literal -import com.android.tools.smali.dexlib2.AccessFlags - -internal val shareCopyUrlFingerprint = fingerprint { - returns("Ljava/lang/Object;") - parameters("Ljava/lang/Object;") - strings("clipboard", "Spotify Link") - custom { method, _ -> - method.name == "invokeSuspend" - } -} - -internal val shareCopyUrlLegacyFingerprint = fingerprint { - returns("Ljava/lang/Object;") - parameters("Ljava/lang/Object;") - strings("clipboard", "createNewSession failed") - custom { method, _ -> - method.name == "apply" - } -} - -internal val formatAndroidShareSheetUrlFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) - returns("Ljava/lang/String;") - parameters("L", "Ljava/lang/String;") - literal { - '\n'.code.toLong() - } -} - -internal val formatAndroidShareSheetUrlLegacyFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC) - returns("Ljava/lang/String;") - parameters("Lcom/spotify/share/social/sharedata/ShareData;", "Ljava/lang/String;") - literal { - '\n'.code.toLong() - } -} +package app.revanced.patches.spotify.misc.privacy + +import app.revanced.patcher.fingerprint +import app.revanced.util.literal +import com.android.tools.smali.dexlib2.AccessFlags + +internal val shareCopyUrlFingerprint = fingerprint { + returns("Ljava/lang/Object;") + parameters("Ljava/lang/Object;") + strings("clipboard", "Spotify Link") + custom { method, _ -> + method.name == "invokeSuspend" + } +} + +internal val shareCopyUrlLegacyFingerprint = fingerprint { + returns("Ljava/lang/Object;") + parameters("Ljava/lang/Object;") + strings("clipboard", "createNewSession failed") + custom { method, _ -> + method.name == "apply" + } +} + +internal val formatAndroidShareSheetUrlFingerprint = fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) + returns("Ljava/lang/String;") + parameters("L", "Ljava/lang/String;") + literal { + '\n'.code.toLong() + } +} + +internal val formatAndroidShareSheetUrlLegacyFingerprint = fingerprint { + accessFlags(AccessFlags.PUBLIC) + returns("Ljava/lang/String;") + parameters("Lcom/spotify/share/social/sharedata/ShareData;", "Ljava/lang/String;") + literal { + '\n'.code.toLong() + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/SanitizeSharingLinksPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/SanitizeSharingLinksPatch.kt index 8df4c7720..7fe59394d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/SanitizeSharingLinksPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/SanitizeSharingLinksPatch.kt @@ -1,70 +1,70 @@ -package app.revanced.patches.spotify.misc.privacy - -import app.revanced.patcher.Fingerprint -import app.revanced.patcher.extensions.InstructionExtensions.addInstructions -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patches.spotify.misc.extension.IS_SPOTIFY_LEGACY_APP_TARGET -import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstructionOrThrow -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/spotify/misc/privacy/SanitizeSharingLinksPatch;" - -@Suppress("unused") -val sanitizeSharingLinksPatch = bytecodePatch( - name = "Sanitize sharing links", - description = "Removes the tracking query parameters from links before they are shared.", -) { - compatibleWith("com.spotify.music") - - dependsOn(sharedExtensionPatch) - - execute { - val extensionMethodDescriptor = "$EXTENSION_CLASS_DESCRIPTOR->" + - "sanitizeUrl(Ljava/lang/String;)Ljava/lang/String;" - - val copyFingerprint = if (IS_SPOTIFY_LEGACY_APP_TARGET) { - shareCopyUrlLegacyFingerprint - } else { - shareCopyUrlFingerprint - } - - copyFingerprint.method.apply { - val newPlainTextInvokeIndex = indexOfFirstInstructionOrThrow { - getReference()?.name == "newPlainText" - } - val register = getInstruction(newPlainTextInvokeIndex).registerD - - addInstructions( - newPlainTextInvokeIndex, - """ - invoke-static { v$register }, $extensionMethodDescriptor - move-result-object v$register - """ - ) - } - - // Android native share sheet is used for all other quick share types (X, WhatsApp, etc). - val shareUrlParameter : String - val shareSheetFingerprint : Fingerprint - if (IS_SPOTIFY_LEGACY_APP_TARGET) { - shareSheetFingerprint = formatAndroidShareSheetUrlLegacyFingerprint - shareUrlParameter = "p2" - } else { - shareSheetFingerprint = formatAndroidShareSheetUrlFingerprint - shareUrlParameter = "p1" - } - - shareSheetFingerprint.method.addInstructions( - 0, - """ - invoke-static { $shareUrlParameter }, $extensionMethodDescriptor - move-result-object $shareUrlParameter - """ - ) - } -} +package app.revanced.patches.spotify.misc.privacy + +import app.revanced.patcher.Fingerprint +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.patch.bytecodePatch +import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch +import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +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/spotify/misc/privacy/SanitizeSharingLinksPatch;" + +@Suppress("unused") +val sanitizeSharingLinksPatch = bytecodePatch( + name = "Sanitize sharing links", + description = "Removes the tracking query parameters from links before they are shared.", +) { + compatibleWith("com.spotify.music") + + dependsOn(sharedExtensionPatch) + + execute { + val extensionMethodDescriptor = "$EXTENSION_CLASS_DESCRIPTOR->" + + "sanitizeUrl(Ljava/lang/String;)Ljava/lang/String;" + + val copyFingerprint = if (IS_SPOTIFY_LEGACY_APP_TARGET) { + shareCopyUrlLegacyFingerprint + } else { + shareCopyUrlFingerprint + } + + copyFingerprint.method.apply { + val newPlainTextInvokeIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "newPlainText" + } + val urlRegister = getInstruction(newPlainTextInvokeIndex).registerD + + addInstructions( + newPlainTextInvokeIndex, + """ + invoke-static { v$urlRegister }, $extensionMethodDescriptor + move-result-object v$urlRegister + """ + ) + } + + // Android native share sheet is used for all other quick share types (X, WhatsApp, etc). + val shareUrlParameter : String + val shareSheetFingerprint : Fingerprint + if (IS_SPOTIFY_LEGACY_APP_TARGET) { + shareSheetFingerprint = formatAndroidShareSheetUrlLegacyFingerprint + shareUrlParameter = "p2" + } else { + shareSheetFingerprint = formatAndroidShareSheetUrlFingerprint + shareUrlParameter = "p1" + } + + shareSheetFingerprint.method.addInstructions( + 0, + """ + invoke-static { $shareUrlParameter }, $extensionMethodDescriptor + move-result-object $shareUrlParameter + """ + ) + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/widgets/FixThirdPartyLaunchersWidgets.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/widgets/FixThirdPartyLaunchersWidgets.kt index ad40f24e2..c84b43f71 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/widgets/FixThirdPartyLaunchersWidgets.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/widgets/FixThirdPartyLaunchersWidgets.kt @@ -1,7 +1,9 @@ package app.revanced.patches.spotify.misc.widgets import app.revanced.patcher.patch.bytecodePatch +import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET import app.revanced.util.returnEarly +import java.util.logging.Logger @Suppress("unused") val fixThirdPartyLaunchersWidgets = bytecodePatch( @@ -11,6 +13,14 @@ val fixThirdPartyLaunchersWidgets = bytecodePatch( compatibleWith("com.spotify.music") execute { + if (IS_SPOTIFY_LEGACY_APP_TARGET) { + // The permission check does not exist in legacy versions. + Logger.getLogger(this::class.java.name).warning( + "Legacy app target does not have any third party launcher restrictions. No changes applied." + ) + return@execute + } + // Only system app launchers are granted the BIND_APPWIDGET permission. // Override the method that checks for it to always return true, as this permission is not actually required // for the widgets to work. diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/shared/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/shared/Fingerprints.kt index 1afbcde45..b107fd267 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/shared/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/shared/Fingerprints.kt @@ -1,6 +1,8 @@ package app.revanced.patches.spotify.shared import app.revanced.patcher.fingerprint +import app.revanced.patcher.patch.BytecodePatchContext +import app.revanced.patches.spotify.misc.extension.mainActivityOnCreateHook private const val SPOTIFY_MAIN_ACTIVITY = "Lcom/spotify/music/SpotifyMainActivity;" @@ -15,3 +17,18 @@ internal val mainActivityOnCreateFingerprint = fingerprint { || classDef.type == SPOTIFY_MAIN_ACTIVITY_LEGACY) } } + +private var isLegacyAppTarget: Boolean? = null + +/** + * If patching a legacy 8.x target. This may also be set if patching slightly older/newer app targets, + * but the only legacy target of interest is 8.6.98.900 as it's the last version that + * supports Spotify integration on Kenwood/Pioneer car stereos. + */ +context(BytecodePatchContext) +internal val IS_SPOTIFY_LEGACY_APP_TARGET get(): Boolean { + if (isLegacyAppTarget == null) { + isLegacyAppTarget = mainActivityOnCreateHook.fingerprint.originalClassDef.type == SPOTIFY_MAIN_ACTIVITY_LEGACY + } + return isLegacyAppTarget!! +} diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/ad/general/HideAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/ad/general/HideAdsPatch.kt index dc66e4bfe..351e8ec2a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/ad/general/HideAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/ad/general/HideAdsPatch.kt @@ -46,7 +46,6 @@ private val hideAdsResourcePatch = resourcePatch { SwitchPreference("revanced_hide_general_ads"), SwitchPreference("revanced_hide_end_screen_store_banner"), SwitchPreference("revanced_hide_fullscreen_ads"), - SwitchPreference("revanced_hide_buttoned_ads"), SwitchPreference("revanced_hide_paid_promotion_label"), SwitchPreference("revanced_hide_player_store_shelf"), SwitchPreference("revanced_hide_self_sponsor_ads"), diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsPatch.kt index 2c55658fb..fc9c3dc83 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsPatch.kt @@ -48,7 +48,12 @@ private val swipeControlsResourcePatch = resourcePatch { summaryKey = null, ), TextPreference("revanced_swipe_overlay_background_opacity", inputType = InputType.NUMBER), - TextPreference("revanced_swipe_overlay_progress_color", inputType = InputType.TEXT_CAP_CHARACTERS), + TextPreference("revanced_swipe_overlay_progress_brightness_color", + tag = "app.revanced.extension.shared.settings.preference.ColorPickerPreference", + inputType = InputType.TEXT_CAP_CHARACTERS), + TextPreference("revanced_swipe_overlay_progress_volume_color", + tag = "app.revanced.extension.shared.settings.preference.ColorPickerPreference", + inputType = InputType.TEXT_CAP_CHARACTERS), TextPreference("revanced_swipe_text_overlay_size", inputType = InputType.NUMBER), TextPreference("revanced_swipe_overlay_timeout", inputType = InputType.NUMBER), TextPreference("revanced_swipe_threshold", inputType = InputType.NUMBER), diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/Fingerprints.kt index f3a6244c3..cc883425b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/Fingerprints.kt @@ -74,3 +74,21 @@ internal val setPivotBarVisibilityParentFingerprint = fingerprint { parameters("Z") strings("FEnotifications_inbox") } + +internal val shortsExperimentalPlayerFeatureFlagFingerprint = fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + returns("Z") + parameters() + literal { + 45677719L + } +} + +internal val renderNextUIFeatureFlagFingerprint = fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + returns("Z") + parameters() + literal { + 45649743L + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt index 49e119357..551a109f7 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt @@ -18,6 +18,7 @@ import app.revanced.patches.youtube.misc.litho.filter.addLithoFilter import app.revanced.patches.youtube.misc.litho.filter.lithoFilterPatch import app.revanced.patches.youtube.misc.navigation.navigationBarHookPatch import app.revanced.patches.youtube.misc.playservice.is_19_41_or_greater +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 @@ -26,6 +27,7 @@ import app.revanced.util.forEachLiteralValueInstruction import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstLiteralInstruction +import app.revanced.util.returnLate import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.MethodReference @@ -90,6 +92,7 @@ private val hideShortsComponentsResourcePatch = resourcePatch { SwitchPreference("revanced_hide_shorts_paused_overlay_buttons"), // Suggested actions. + SwitchPreference("revanced_hide_shorts_comment_panel"), SwitchPreference("revanced_hide_shorts_save_sound_button"), SwitchPreference("revanced_hide_shorts_use_template_button"), SwitchPreference("revanced_hide_shorts_upcoming_button"), @@ -251,5 +254,27 @@ val hideShortsComponentsPatch = bytecodePatch( } // endregion + + // region Disable experimental Shorts flags. + + // Flags might be present in earlier targets, but they are not found in 19.47.53. + // If these flags are forced on, the experimental layout is still not used and + // it appears the features requires additional server side data to fully use. + if (is_20_07_or_greater) { + // Experimental Shorts player uses Android native buttons and not Litho, + // and the layout is provided by the server. + // + // Since the buttons are native components and not Litho, it should be possible to + // fix the RYD Shorts loading delay by asynchronously loading RYD and updating + // the button text after RYD has loaded. + shortsExperimentalPlayerFeatureFlagFingerprint.method.returnLate(true) + + // Experimental UI renderer must also be disabled since it requires the + // experimental Shorts player. If this is enabled but Shorts player + // is disabled then the app crashes when the Shorts player is opened. + renderNextUIFeatureFlagFingerprint.method.returnLate(true) + } + + // endregion } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/Fingerprints.kt index 096ed695d..a8aef3734 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/Fingerprints.kt @@ -15,9 +15,6 @@ internal val openVideosFullscreenPortraitFingerprint = fingerprint { } } -/** - * Used to enable opening regular videos fullscreen. - */ internal val openVideosFullscreenHookPatchExtensionFingerprint = fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC) returns("Z") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/Fingerprints.kt index 961ddef02..abd7f10ce 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/Fingerprints.kt @@ -53,4 +53,12 @@ internal val shortsPlaybackIntentFingerprint = fingerprint { "ReelWatchFragmentArgs", "reels_fragment_descriptor" ) +} + +internal val exitVideoPlayerFingerprint = fingerprint { + returns("V") + parameters() + literal { + mdx_drawer_layout_id + } } \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/OpenShortsInRegularPlayerPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/OpenShortsInRegularPlayerPatch.kt index 1198c4ce2..c932f4a03 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/OpenShortsInRegularPlayerPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/OpenShortsInRegularPlayerPatch.kt @@ -1,11 +1,16 @@ package app.revanced.patches.youtube.layout.shortsplayer 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.patch.resourcePatch import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch +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.ListPreference import app.revanced.patches.youtube.layout.player.fullscreen.openVideosFullscreenHookPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch @@ -19,12 +24,29 @@ import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint import app.revanced.util.findFreeRegister import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.MethodReference private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/OpenShortsInRegularPlayerPatch;" +internal var mdx_drawer_layout_id = -1L + private set + +private val openShortsInRegularPlayerResourcePatch = resourcePatch { + dependsOn(resourceMappingPatch) + + execute { + mdx_drawer_layout_id = resourceMappings[ + "id", + "mdx_drawer_layout", + ] + + } +} + @Suppress("unused") val openShortsInRegularPlayerPatch = bytecodePatch( name = "Open Shorts in regular player", @@ -36,7 +58,8 @@ val openShortsInRegularPlayerPatch = bytecodePatch( addResourcesPatch, openVideosFullscreenHookPatch, navigationBarHookPatch, - versionCheckPatch + versionCheckPatch, + openShortsInRegularPlayerResourcePatch ) compatibleWith( @@ -127,5 +150,28 @@ val openShortsInRegularPlayerPatch = bytecodePatch( ${extensionInstructions(0, 1)} """ ) + + // Fix issue with back button exiting the app instead of minimizing the player. + // Without this change this issue can be difficult to reproduce, but seems to occur + // most often with 'open video in regular player' and not open in fullscreen player. + exitVideoPlayerFingerprint.method.apply { + // Method call for Activity.finish() + val finishIndex = indexOfFirstInstructionOrThrow { + val reference = getReference() + reference?.name == "finish" + } + + // Index of PlayerType.isWatchWhileMaximizedOrFullscreen() + val index = indexOfFirstInstructionReversedOrThrow(finishIndex, Opcode.MOVE_RESULT) + val register = getInstruction(index).registerA + + addInstructions( + index + 1, + """ + invoke-static { v$register }, ${EXTENSION_CLASS_DESCRIPTOR}->overrideBackPressToExit(Z)Z + move-result v$register + """ + ) + } } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt index 73e84d659..514eae710 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt @@ -89,14 +89,15 @@ val themePatch = bytecodePatch( execute { val preferences = mutableSetOf( SwitchPreference("revanced_seekbar_custom_color"), - TextPreference("revanced_seekbar_custom_color_primary", inputType = InputType.TEXT_CAP_CHARACTERS), + TextPreference("revanced_seekbar_custom_color_primary", + tag = "app.revanced.extension.shared.settings.preference.ColorPickerPreference", + inputType = InputType.TEXT_CAP_CHARACTERS), ) if (is_19_25_or_greater) { - preferences += TextPreference( - "revanced_seekbar_custom_color_accent", - inputType = InputType.TEXT_CAP_CHARACTERS - ) + preferences += TextPreference("revanced_seekbar_custom_color_accent", + tag = "app.revanced.extension.shared.settings.preference.ColorPickerPreference", + inputType = InputType.TEXT_CAP_CHARACTERS) } PreferenceScreen.SEEKBAR.addPreferences( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/EnableDebuggingPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/EnableDebuggingPatch.kt index f4facb097..d991b2d4b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/EnableDebuggingPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/EnableDebuggingPatch.kt @@ -5,6 +5,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction 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.shared.misc.settings.preference.NonInteractivePreference import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting import app.revanced.patches.shared.misc.settings.preference.SwitchPreference @@ -23,7 +24,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR = val enableDebuggingPatch = bytecodePatch( name = "Enable debugging", - description = "Adds options for debugging.", + description = "Adds options for debugging and exporting ReVanced logs to the clipboard.", ) { dependsOn( sharedExtensionPatch, @@ -56,6 +57,16 @@ val enableDebuggingPatch = bytecodePatch( SwitchPreference("revanced_debug_protobuffer"), SwitchPreference("revanced_debug_stacktrace"), SwitchPreference("revanced_debug_toast_on_error"), + NonInteractivePreference( + "revanced_debug_export_logs_to_clipboard", + tag = "app.revanced.extension.youtube.settings.preference.ExportLogToClipboardPreference", + selectable = true, + ), + NonInteractivePreference( + "revanced_debug_logs_clear_buffer", + tag = "app.revanced.extension.youtube.settings.preference.ClearLogBufferPreference", + selectable = true, + ), ), ), ) @@ -107,7 +118,6 @@ val enableDebuggingPatch = bytecodePatch( return-wide v0 """ ) - } experimentalStringFeatureFlagFingerprint.match( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/hapticfeedback/DisableHapticFeedbackPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/hapticfeedback/DisableHapticFeedbackPatch.kt new file mode 100644 index 000000000..977226560 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/hapticfeedback/DisableHapticFeedbackPatch.kt @@ -0,0 +1,74 @@ +package app.revanced.patches.youtube.misc.hapticfeedback + +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.all.misc.resources.addResources +import app.revanced.patches.all.misc.resources.addResourcesPatch +import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference +import app.revanced.patches.shared.misc.settings.preference.SwitchPreference +import app.revanced.patches.youtube.misc.settings.PreferenceScreen +import app.revanced.patches.youtube.misc.settings.settingsPatch + +private const val EXTENSION_CLASS_DESCRIPTOR = + "Lapp/revanced/extension/youtube/patches/DisableHapticFeedbackPatch;" + +@Suppress("unused") +val disableHapticFeedbackPatch = bytecodePatch( + name = "Disable haptic feedback", + description = "Adds an option to disable haptic feedback in the player for various actions.", +) { + dependsOn( + settingsPatch, + addResourcesPatch, + ) + + compatibleWith( + "com.google.android.youtube"( + "19.16.39", + "19.25.37", + "19.34.42", + "19.43.41", + "19.47.53", + "20.07.39", + "20.12.46", + ) + ) + + execute { + addResources("youtube", "misc.hapticfeedback.disableHapticFeedbackPatch") + + PreferenceScreen.PLAYER.addPreferences( + PreferenceScreenPreference( + "revanced_disable_haptic_feedback", + preferences = setOf( + SwitchPreference("revanced_disable_haptic_feedback_chapters"), + SwitchPreference("revanced_disable_haptic_feedback_precise_seeking"), + SwitchPreference("revanced_disable_haptic_feedback_seek_undo"), + SwitchPreference("revanced_disable_haptic_feedback_zoom"), + ) + ) + ) + + arrayOf( + markerHapticsFingerprint to "disableChapterVibrate", + scrubbingHapticsFingerprint to "disablePreciseSeekingVibrate", + seekUndoHapticsFingerprint to "disableSeekUndoVibrate", + zoomHapticsFingerprint to "disableZoomVibrate" + ).forEach { (fingerprint, methodName) -> + fingerprint.method.apply { + addInstructionsWithLabels( + 0, + """ + invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->$methodName()Z + move-result v0 + if-eqz v0, :vibrate + return-void + """, + ExternalLabel("vibrate", getInstruction(0)) + ) + } + } + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/hapticfeedback/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/hapticfeedback/Fingerprints.kt new file mode 100644 index 000000000..13efc4693 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/hapticfeedback/Fingerprints.kt @@ -0,0 +1,23 @@ +package app.revanced.patches.youtube.misc.hapticfeedback + +import app.revanced.patcher.fingerprint + +internal val markerHapticsFingerprint = fingerprint { + returns("V") + strings("Failed to execute markers haptics vibrate.") +} + +internal val scrubbingHapticsFingerprint = fingerprint { + returns("V") + strings("Failed to haptics vibrate for fine scrubbing.") +} + +internal val seekUndoHapticsFingerprint = fingerprint { + returns("V") + strings("Failed to execute seek undo haptics vibrate.") +} + +internal val zoomHapticsFingerprint = fingerprint { + returns("V") + strings("Failed to haptics vibrate for video zoom") +} diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt index 06a28e7f3..1cd74f52c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt @@ -74,6 +74,7 @@ private val settingsResourcePatch = resourcePatch { arrayOf( ResourceGroup("drawable", + "revanced_settings_circle_background.xml", "revanced_settings_cursor.xml", "revanced_settings_icon.xml", "revanced_settings_screen_00_about.xml", @@ -91,6 +92,8 @@ private val settingsResourcePatch = resourcePatch { "revanced_settings_screen_12_video.xml", ), ResourceGroup("layout", + "revanced_color_dot_widget.xml", + "revanced_color_picker.xml", "revanced_preference_with_icon_no_search_result.xml", "revanced_search_suggestion_item.xml", "revanced_settings_with_toolbar.xml"), diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/Fingerprints.kt deleted file mode 100644 index 65cb70769..000000000 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/Fingerprints.kt +++ /dev/null @@ -1,7 +0,0 @@ -package app.revanced.patches.youtube.misc.zoomhaptics - -import app.revanced.patcher.fingerprint - -internal val zoomHapticsFingerprint = fingerprint { - strings("Failed to haptics vibrate for video zoom") -} diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/ZoomHapticsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/ZoomHapticsPatch.kt index 0e961dfeb..44cde6002 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/ZoomHapticsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/zoomhaptics/ZoomHapticsPatch.kt @@ -1,54 +1,11 @@ package app.revanced.patches.youtube.misc.zoomhaptics -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.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.youtube.misc.settings.PreferenceScreen -import app.revanced.patches.youtube.misc.settings.settingsPatch +import app.revanced.patches.youtube.misc.hapticfeedback.disableHapticFeedbackPatch +@Deprecated("Superseded by disableHapticFeedbackPatch", ReplaceWith("disableHapticFeedbackPatch")) val zoomHapticsPatch = bytecodePatch( - name = "Disable zoom haptics", description = "Adds an option to disable haptics when zooming.", ) { - dependsOn( - settingsPatch, - addResourcesPatch, - ) - - compatibleWith( - "com.google.android.youtube"( - "19.16.39", - "19.25.37", - "19.34.42", - "19.43.41", - "19.47.53", - "20.07.39", - "20.12.46", - ) - ) - - execute { - addResources("youtube", "misc.zoomhaptics.zoomHapticsPatch") - - PreferenceScreen.MISC.addPreferences( - SwitchPreference("revanced_disable_zoom_haptics"), - ) - - zoomHapticsFingerprint.method.apply { - addInstructionsWithLabels( - 0, - """ - invoke-static { }, Lapp/revanced/extension/youtube/patches/ZoomHapticsPatch;->shouldVibrate()Z - move-result v0 - if-nez v0, :vibrate - return-void - """, - ExternalLabel("vibrate", getInstruction(0)), - ) - } - } -} + dependsOn(disableHapticFeedbackPatch) +} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/Fingerprints.kt index 349f7300b..5157f9823 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/Fingerprints.kt @@ -123,3 +123,13 @@ internal val playbackSpeedMenuSpeedChangedFingerprint = fingerprint { Opcode.RETURN_OBJECT, ) } + +internal val playbackSpeedClassFingerprint = fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) + returns("L") + parameters("L") + opcodes( + Opcode.RETURN_OBJECT + ) + strings("PLAYBACK_RATE_MENU_BOTTOM_SHEET_FRAGMENT") +} diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt index a22934d1c..5a9c5e740 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt @@ -7,6 +7,7 @@ import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableClass import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable +import app.revanced.patcher.util.smali.toInstructions import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.shared.newVideoQualityChangedFingerprint import app.revanced.patches.youtube.video.playerresponse.Hook @@ -16,6 +17,8 @@ import app.revanced.patches.youtube.video.videoid.hookBackgroundPlayVideoId import app.revanced.patches.youtube.video.videoid.hookPlayerResponseVideoId import app.revanced.patches.youtube.video.videoid.hookVideoId import app.revanced.patches.youtube.video.videoid.videoIdPatch +import app.revanced.util.addInstructionsAtControlFlowLabel +import app.revanced.util.addStaticFieldToExtension import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import com.android.tools.smali.dexlib2.AccessFlags @@ -29,6 +32,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.immutable.ImmutableMethod +import com.android.tools.smali.dexlib2.immutable.ImmutableMethodImplementation import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter import com.android.tools.smali.dexlib2.util.MethodUtil @@ -189,6 +193,72 @@ val videoInformationPatch = bytecodePatch( proxy(classes.first { it.type == setPlaybackSpeedMethodReference.definingClass }) .mutableClass.methods.first { it.name == setPlaybackSpeedMethodReference.name } setPlaybackSpeedMethodIndex = 0 + + // Add override playback speed method. + onPlaybackSpeedItemClickFingerprint.classDef.methods.add( + ImmutableMethod( + definingClass, + "overridePlaybackSpeed", + listOf(ImmutableMethodParameter("F", annotations, null)), + "V", + AccessFlags.PUBLIC.value or AccessFlags.PUBLIC.value, + annotations, + null, + ImmutableMethodImplementation( + 4, + """ + # Check if the playback speed is not auto (-2.0f) + const/4 v0, 0x0 + cmpg-float v0, v3, v0 + if-lez v0, :ignore + + # Get the container class field. + iget-object v0, v2, $setPlaybackSpeedContainerClassFieldReference + + # For some reason, in YouTube 19.44.39 this value is sometimes null. + if-eqz v0, :ignore + + # Get the field from its class. + iget-object v1, v0, $setPlaybackSpeedClassFieldReference + + # Invoke setPlaybackSpeed on that class. + invoke-virtual {v1, v3}, $setPlaybackSpeedMethodReference + + :ignore + return-void + """.toInstructions(), null, null + ) + ).toMutable() + ) + } + + playbackSpeedClassFingerprint.method.apply { + val index = indexOfFirstInstructionOrThrow(Opcode.RETURN_OBJECT) + val register = getInstruction(index).registerA + val playbackSpeedClass = this.returnType + + // Set playback speed class. + addInstructionsAtControlFlowLabel( + index, + "sput-object v$register, $EXTENSION_CLASS_DESCRIPTOR->playbackSpeedClass:$playbackSpeedClass" + ) + + val smaliInstructions = + """ + if-eqz v0, :ignore + invoke-virtual {v0, p0}, $playbackSpeedClass->overridePlaybackSpeed(F)V + return-void + :ignore + nop + """ + + addStaticFieldToExtension( + EXTENSION_CLASS_DESCRIPTOR, + "overridePlaybackSpeed", + "playbackSpeedClass", + playbackSpeedClass, + smaliInstructions + ) } // Handle new playback speed menu. diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt index d6a7fb561..027be3a1b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt @@ -1,19 +1,11 @@ package app.revanced.patches.youtube.video.speed.custom -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.extensions.InstructionExtensions.instructions import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patcher.patch.resourcePatch -import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch -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.InputType import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.shared.misc.settings.preference.TextPreference @@ -27,27 +19,11 @@ import app.revanced.patches.youtube.misc.recyclerviewtree.hook.addRecyclerViewTr import app.revanced.patches.youtube.misc.recyclerviewtree.hook.recyclerViewTreeHookPatch import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.video.speed.settingsMenuVideoSpeedGroup -import app.revanced.util.* -import com.android.tools.smali.dexlib2.AccessFlags +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstLiteralInstruction +import app.revanced.util.indexOfFirstLiteralInstructionOrThrow import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction -import com.android.tools.smali.dexlib2.iface.reference.FieldReference -import com.android.tools.smali.dexlib2.iface.reference.MethodReference -import com.android.tools.smali.dexlib2.immutable.ImmutableField - -internal var speedUnavailableId = -1L - private set - -private val customPlaybackSpeedResourcePatch = resourcePatch { - dependsOn(resourceMappingPatch) - - execute { - speedUnavailableId = resourceMappings[ - "string", - "varispeed_unavailable_message", - ] - } -} private const val FILTER_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilterPatch;" @@ -64,8 +40,7 @@ internal val customPlaybackSpeedPatch = bytecodePatch( addResourcesPatch, lithoFilterPatch, versionCheckPatch, - recyclerViewTreeHookPatch, - customPlaybackSpeedResourcePatch + recyclerViewTreeHookPatch ) execute { @@ -87,38 +62,6 @@ internal val customPlaybackSpeedPatch = bytecodePatch( ) } - // Replace the speeds float array with custom speeds. - speedArrayGeneratorFingerprint.method.apply { - val sizeCallIndex = indexOfFirstInstructionOrThrow { getReference()?.name == "size" } - val sizeCallResultRegister = getInstruction(sizeCallIndex + 1).registerA - - replaceInstruction(sizeCallIndex + 1, "const/4 v$sizeCallResultRegister, 0x0") - - val arrayLengthConstIndex = indexOfFirstLiteralInstructionOrThrow(7) - val arrayLengthConstDestination = getInstruction(arrayLengthConstIndex).registerA - val playbackSpeedsArrayType = "$EXTENSION_CLASS_DESCRIPTOR->customPlaybackSpeeds:[F" - - addInstructions( - arrayLengthConstIndex + 1, - """ - sget-object v$arrayLengthConstDestination, $playbackSpeedsArrayType - array-length v$arrayLengthConstDestination, v$arrayLengthConstDestination - """, - ) - - val originalArrayFetchIndex = indexOfFirstInstructionOrThrow { - val reference = getReference() - reference?.type == "[F" && reference.definingClass.endsWith("/PlayerConfigModel;") - } - val originalArrayFetchDestination = - getInstruction(originalArrayFetchIndex).registerA - - replaceInstruction( - originalArrayFetchIndex, - "sget-object v$originalArrayFetchDestination, $playbackSpeedsArrayType", - ) - } - // Override the min/max speeds that can be used. speedLimiterFingerprint.method.apply { val limitMinIndex = indexOfFirstLiteralInstructionOrThrow(0.25f) @@ -135,47 +78,7 @@ internal val customPlaybackSpeedPatch = bytecodePatch( replaceInstruction(limitMaxIndex, "const/high16 v$limitMaxRegister, 8.0f") } - // Add a static INSTANCE field to the class. - // This is later used to call "showOldPlaybackSpeedMenu" on the instance. - - val instanceField = ImmutableField( - getOldPlaybackSpeedsFingerprint.originalClassDef.type, - "INSTANCE", - getOldPlaybackSpeedsFingerprint.originalClassDef.type, - AccessFlags.PUBLIC.value or AccessFlags.STATIC.value, - null, - null, - null, - ).toMutable() - - getOldPlaybackSpeedsFingerprint.classDef.staticFields.add(instanceField) - // Set the INSTANCE field to the instance of the class. - // In order to prevent a conflict with another patch, add the instruction at index 1. - getOldPlaybackSpeedsFingerprint.method.addInstruction(1, "sput-object p0, $instanceField") - - // Get the "showOldPlaybackSpeedMenu" method. - // This is later called on the field INSTANCE. - val showOldPlaybackSpeedMenuMethod = showOldPlaybackSpeedMenuFingerprint.match( - getOldPlaybackSpeedsFingerprint.classDef, - ).method.toString() - - // Insert the call to the "showOldPlaybackSpeedMenu" method on the field INSTANCE. - showOldPlaybackSpeedMenuExtensionFingerprint.method.apply { - addInstructionsWithLabels( - instructions.lastIndex, - """ - sget-object v0, $instanceField - if-nez v0, :not_null - return-void - :not_null - invoke-virtual { v0 }, $showOldPlaybackSpeedMenuMethod - """, - ) - } - - // region Force old video quality menu. - // This is necessary, because there is no known way of adding custom playback speeds to the new menu. - + // Close the unpatched playback dialog and show the modern custom dialog. addRecyclerViewTreeHook(EXTENSION_CLASS_DESCRIPTOR) // Required to check if the playback speed menu is currently shown. diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/Fingerprints.kt index 7d4b23ba4..120bb1df3 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/Fingerprints.kt @@ -1,30 +1,9 @@ package app.revanced.patches.youtube.video.speed.custom import app.revanced.patcher.fingerprint -import app.revanced.util.literal import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val getOldPlaybackSpeedsFingerprint = fingerprint { - parameters("[L", "I") - strings("menu_item_playback_speed") -} - -internal val showOldPlaybackSpeedMenuFingerprint = fingerprint { - literal { speedUnavailableId } -} - -internal val showOldPlaybackSpeedMenuExtensionFingerprint = fingerprint { - custom { method, _ -> method.name == "showOldPlaybackSpeedMenu" } -} - -internal val speedArrayGeneratorFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) - returns("[L") - parameters("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;") - strings("0.0#") -} - internal val speedLimiterFingerprint = fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") diff --git a/patches/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/UnlockPremiumPatch.kt b/patches/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/UnlockPremiumPatch.kt index c6689540d..c4cedd092 100644 --- a/patches/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/UnlockPremiumPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/yuka/misc/unlockpremium/UnlockPremiumPatch.kt @@ -3,10 +3,10 @@ package app.revanced.patches.yuka.misc.unlockpremium import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.patch.bytecodePatch +@Deprecated("This patch no longer works and will be removed in the future.") @Suppress("unused") -val unlockPremiumPatch = bytecodePatch( - name = "Unlock premium", -) { +val unlockPremiumPatch = bytecodePatch { + compatibleWith("io.yuka.android"("4.29")) execute { diff --git a/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt b/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt index 0ca022201..afcae5f71 100644 --- a/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt +++ b/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt @@ -10,6 +10,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.PatchException import app.revanced.patcher.util.proxy.mutableTypes.MutableClass +import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.shared.misc.mapping.get @@ -31,6 +32,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.ThreeRegisterInstructio import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction import com.android.tools.smali.dexlib2.iface.reference.Reference +import com.android.tools.smali.dexlib2.immutable.ImmutableField import com.android.tools.smali.dexlib2.util.MethodUtil import java.util.EnumSet @@ -133,6 +135,7 @@ internal val Instruction.registersUsed: List else -> listOf(registerC, registerD, registerE, registerF, registerG) } } + is ThreeRegisterInstruction -> listOf(registerA, registerB, registerC) is TwoRegisterInstruction -> listOf(registerA, registerB) is OneRegisterInstruction -> listOf(registerA) @@ -170,7 +173,7 @@ internal val Instruction.isReturnInstruction: Boolean /** * Adds public [AccessFlags] and removes private and protected flags (if present). */ -internal fun Int.toPublicAccessFlags() : Int { +internal fun Int.toPublicAccessFlags(): Int { return this.or(AccessFlags.PUBLIC.value) .and(AccessFlags.PROTECTED.value.inv()) .and(AccessFlags.PRIVATE.value.inv()) @@ -489,9 +492,10 @@ fun Method.indexOfFirstInstruction(targetOpcode: Opcode): Int = indexOfFirstInst * @return The index of the first opcode specified, or -1 if not found. * @see indexOfFirstInstructionOrThrow */ -fun Method.indexOfFirstInstruction(startIndex: Int = 0, targetOpcode: Opcode): Int = indexOfFirstInstruction(startIndex) { - opcode == targetOpcode -} +fun Method.indexOfFirstInstruction(startIndex: Int = 0, targetOpcode: Opcode): Int = + indexOfFirstInstruction(startIndex) { + opcode == targetOpcode + } /** * Get the index of the first [Instruction] that matches the predicate, starting from [startIndex]. @@ -526,9 +530,10 @@ fun Method.indexOfFirstInstructionOrThrow(targetOpcode: Opcode): Int = indexOfFi * @throws PatchException * @see indexOfFirstInstruction */ -fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, targetOpcode: Opcode): Int = indexOfFirstInstructionOrThrow(startIndex) { - opcode == targetOpcode -} +fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, targetOpcode: Opcode): Int = + indexOfFirstInstructionOrThrow(startIndex) { + opcode == targetOpcode + } /** * Get the index of the first [Instruction] that matches the predicate, starting from [startIndex]. @@ -554,9 +559,10 @@ fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, filter: Instructi * @return -1 if the instruction is not found. * @see indexOfFirstInstructionReversedOrThrow */ -fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, targetOpcode: Opcode): Int = indexOfFirstInstructionReversed(startIndex) { - opcode == targetOpcode -} +fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, targetOpcode: Opcode): Int = + indexOfFirstInstructionReversed(startIndex) { + opcode == targetOpcode + } /** * Get the index of matching instruction, @@ -593,9 +599,10 @@ fun Method.indexOfFirstInstructionReversed(targetOpcode: Opcode): Int = indexOfF * @return The index of the instruction. * @see indexOfFirstInstructionReversed */ -fun Method.indexOfFirstInstructionReversedOrThrow(startIndex: Int? = null, targetOpcode: Opcode): Int = indexOfFirstInstructionReversedOrThrow(startIndex) { - opcode == targetOpcode -} +fun Method.indexOfFirstInstructionReversedOrThrow(startIndex: Int? = null, targetOpcode: Opcode): Int = + indexOfFirstInstructionReversedOrThrow(startIndex) { + opcode == targetOpcode + } /** * Get the index of matching instruction, @@ -652,7 +659,8 @@ fun Method.findInstructionIndicesReversedOrThrow(filter: Instruction.() -> Boole * _Returns an empty list if no indices are found_ * @see findInstructionIndicesReversedOrThrow */ -fun Method.findInstructionIndicesReversed(opcode: Opcode): List = findInstructionIndicesReversed { this.opcode == opcode } +fun Method.findInstructionIndicesReversed(opcode: Opcode): List = + findInstructionIndicesReversed { this.opcode == opcode } /** * @return An immutable list of indices of the opcode in reverse order. @@ -726,43 +734,222 @@ fun BytecodePatchContext.forEachLiteralValueInstruction( } } -/** - * Overrides the first instruction of a method with a constant return value. - * None of the method code will ever execute. - */ -fun MutableMethod.returnEarly(overrideValue: Boolean = false) = overrideReturnValue(overrideValue, false) +private const val RETURN_TYPE_MISMATCH = "Mismatch between override type and Method return type" /** - * Overrides all return statements with a constant value. + * Overrides the first instruction of a method with a constant `Boolean` return value. + * None of the method code will ever execute. + * + * For methods that return an object or any array type, calling this method with `false` + * will force the method to return a `null` value. + */ +fun MutableMethod.returnEarly(value: Boolean = false) { + val returnType = returnType.first() + check(returnType == 'Z' || (!value && (returnType in setOf('V', 'L', '[')))) { RETURN_TYPE_MISMATCH } + overrideReturnValue(value.toHexString(), false) +} + +/** + * Overrides the first instruction of a method with a constant `Byte` return value. + * None of the method code will ever execute. + */ +fun MutableMethod.returnEarly(value: Byte) { + check(returnType.first() == 'B') { RETURN_TYPE_MISMATCH } + overrideReturnValue(value.toString(), false) +} + +/** + * Overrides the first instruction of a method with a constant `Short` return value. + * None of the method code will ever execute. + */ +fun MutableMethod.returnEarly(value: Short) { + check(returnType.first() == 'S') { RETURN_TYPE_MISMATCH } + overrideReturnValue(value.toString(), false) +} + +/** + * Overrides the first instruction of a method with a constant `Char` return value. + * None of the method code will ever execute. + */ +fun MutableMethod.returnEarly(value: Char) { + check(returnType.first() == 'C') { RETURN_TYPE_MISMATCH } + overrideReturnValue(value.code.toString(), false) +} + +/** + * Overrides the first instruction of a method with a constant `Int` return value. + * None of the method code will ever execute. + */ +fun MutableMethod.returnEarly(value: Int) { + check(returnType.first() == 'I') { RETURN_TYPE_MISMATCH } + overrideReturnValue(value.toString(), false) +} + +/** + * Overrides the first instruction of a method with a constant `Long` return value. + * None of the method code will ever execute. + */ +fun MutableMethod.returnEarly(value: Long) { + check(returnType.first() == 'J') { RETURN_TYPE_MISMATCH } + overrideReturnValue(value.toString(), false) +} + +/** + * Overrides the first instruction of a method with a constant `Float` return value. + * None of the method code will ever execute. + */ +fun MutableMethod.returnEarly(value: Float) { + check(returnType.first() == 'F') { RETURN_TYPE_MISMATCH } + overrideReturnValue(value.toString(), false) +} + +/** + * Overrides the first instruction of a method with a constant `Double` return value. + * None of the method code will ever execute. + */ +fun MutableMethod.returnEarly(value: Double) { + check(returnType.first() == 'J') { RETURN_TYPE_MISMATCH } + overrideReturnValue(value.toString(), false) +} + +/** + * Overrides all return statements with a constant `Boolean` value. + * All method code is executed the same as unpatched. + * + * For methods that return an object or any array type, calling this method with `false` + * will force the method to return a `null` value. + * + * @see returnEarly + */ +fun MutableMethod.returnLate(value: Boolean) { + val returnType = returnType.first() + if (returnType == 'V') { + error("Cannot return late for Method of void type") + } + check(returnType == 'Z' || (!value && returnType in setOf('L', '['))) { RETURN_TYPE_MISMATCH } + + overrideReturnValue(value.toHexString(), true) +} + +/** + * Overrides all return statements with a constant `Byte` value. * All method code is executed the same as unpatched. * * @see returnEarly */ -internal fun MutableMethod.returnLate(overrideValue: Boolean = false) = overrideReturnValue(overrideValue, true) +fun MutableMethod.returnLate(value: Byte) { + check(returnType.first() == 'B') { RETURN_TYPE_MISMATCH } + overrideReturnValue(value.toString(), true) +} -private fun MutableMethod.overrideReturnValue(bool: Boolean, returnLate: Boolean) { - val const = if (bool) "0x1" else "0x0" +/** + * Overrides all return statements with a constant `Short` value. + * All method code is executed the same as unpatched. + * + * @see returnEarly + */ +fun MutableMethod.returnLate(value: Short) { + check(returnType.first() == 'S') { RETURN_TYPE_MISMATCH } + overrideReturnValue(value.toString(), true) +} +/** + * Overrides all return statements with a constant `Char` value. + * All method code is executed the same as unpatched. + * + * @see returnEarly + */ +fun MutableMethod.returnLate(value: Char) { + check(returnType.first() == 'C') { RETURN_TYPE_MISMATCH } + overrideReturnValue(value.code.toString(), true) +} + +/** + * Overrides all return statements with a constant `Int` value. + * All method code is executed the same as unpatched. + * + * @see returnEarly + */ +fun MutableMethod.returnLate(value: Int) { + check(returnType.first() == 'I') { RETURN_TYPE_MISMATCH } + overrideReturnValue(value.toString(), true) +} + +/** + * Overrides all return statements with a constant `Long` value. + * All method code is executed the same as unpatched. + * + * @see returnEarly + */ +fun MutableMethod.returnLate(value: Long) { + check(returnType.first() == 'J') { RETURN_TYPE_MISMATCH } + overrideReturnValue(value.toString(), true) +} + +/** + * Overrides all return statements with a constant `Float` value. + * All method code is executed the same as unpatched. + * + * @see returnEarly + */ +fun MutableMethod.returnLate(value: Float) { + check(returnType.first() == 'F') { RETURN_TYPE_MISMATCH } + overrideReturnValue(value.toString(), true) +} + +/** + * Overrides all return statements with a constant `Double` value. + * All method code is executed the same as unpatched. + * + * @see returnEarly + */ +fun MutableMethod.returnLate(value: Double) { + check(returnType.first() == 'D') { RETURN_TYPE_MISMATCH } + overrideReturnValue(value.toString(), true) +} + +private fun MutableMethod.overrideReturnValue(value: String, returnLate: Boolean) { val instructions = when (returnType.first()) { - 'L' -> { + // If return type is an object, always return null. + 'L', '[' -> { """ - const/4 v0, $const + const/4 v0, 0x0 return-object v0 """ } 'V' -> { - if (returnLate) throw IllegalArgumentException("Cannot return late for method of void type") "return-void" } - 'I', 'Z' -> { + 'B', 'Z' -> { """ - const/4 v0, $const + const/4 v0, $value return v0 """ } + 'S', 'C' -> { + """ + const/16 v0, $value + return v0 + """ + } + + 'I', 'F' -> { + """ + const v0, $value + return v0 + """ + } + + 'J', 'D' -> { + """ + const-wide v0, $value + return-wide v0 + """ + } + else -> throw Exception("Return type is not supported: $this") } @@ -777,6 +964,43 @@ private fun MutableMethod.overrideReturnValue(bool: Boolean, returnLate: Boolean } } +internal fun BytecodePatchContext.addStaticFieldToExtension( + className: String, + methodName: String, + fieldName: String, + objectClass: String, + smaliInstructions: String +) { + val classDef = classes.find { classDef -> classDef.type == className } + ?: throw PatchException("No matching methods found in: $className") + val mutableClass = proxy(classDef).mutableClass + + val objectCall = "$mutableClass->$fieldName:$objectClass" + + mutableClass.apply { + methods.first { method -> method.name == methodName }.apply { + staticFields.add( + ImmutableField( + definingClass, + fieldName, + objectClass, + AccessFlags.PUBLIC.value or AccessFlags.STATIC.value, + null, + annotations, + null + ).toMutable() + ) + + addInstructionsWithLabels( + 0, + """ + sget-object v0, $objectCall + """ + smaliInstructions + ) + } + } +} + /** * Set the custom condition for this fingerprint to check for a literal value. * diff --git a/patches/src/main/kotlin/app/revanced/util/Utils.kt b/patches/src/main/kotlin/app/revanced/util/Utils.kt index 57f0edf03..ef7d0ef1a 100644 --- a/patches/src/main/kotlin/app/revanced/util/Utils.kt +++ b/patches/src/main/kotlin/app/revanced/util/Utils.kt @@ -6,3 +6,5 @@ internal object Utils { .joinToString("\n") { it.trimIndent() } // Remove the leading whitespace from each line. .trimIndent() // Remove the leading newline. } + +internal fun Boolean.toHexString(): String = if (this) "0x1" else "0x0" \ No newline at end of file diff --git a/patches/src/main/resources/addresources/values-af-rZA/strings.xml b/patches/src/main/resources/addresources/values-af-rZA/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-af-rZA/strings.xml +++ b/patches/src/main/resources/addresources/values-af-rZA/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-am-rET/strings.xml b/patches/src/main/resources/addresources/values-am-rET/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-am-rET/strings.xml +++ b/patches/src/main/resources/addresources/values-am-rET/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-ar-rSA/strings.xml b/patches/src/main/resources/addresources/values-ar-rSA/strings.xml index 3dbb255ad..0495f230e 100644 --- a/patches/src/main/resources/addresources/values-ar-rSA/strings.xml +++ b/patches/src/main/resources/addresources/values-ar-rSA/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" الإعدادات هل ترغب في المتابعة؟ إعادة التعيين + Reset color + لون غير صالح تحديث وإعادة التشغيل إعادة التشغيل استيراد @@ -42,7 +44,7 @@ Second \"item\" text" إعادة تعيين إعدادات ReVanced إلى الوضع الافتراضي تم استيراد %d إعدادات فشل الاستيراد: %s - إعدادات البحث + بحث الإعدادات لم يتم العثور على نتائج لـ \".%s\" جرّب كلمة مفتاحية أخرى إزالة من سجل البحث؟ @@ -97,9 +99,9 @@ Second \"item\" text" استعادة قوائم الإعدادات القديمة يتم عرض قوائم الإعدادات القديمة لا يتم عرض قوائم الإعدادات القديمة - إظهار سجل البحث في الإعدادات - سجل البحث في الإعدادات معروض - لم يتم عرض سجل البحث في الإعدادات + عرض سجل بحث الإعدادات + يتم عرض سجل البحث في الإعدادات + لا يتم عرض سجل البحث في الإعدادات تعطيل تشغيل فيديوهات Shorts في الخلفية @@ -115,6 +117,11 @@ Second \"item\" text" سجل بروتوكول التخزين المؤقت تتضمن سجلات التصحيح التخزين المؤقت لا تتضمن سجلات التصحيح التخزين المؤقت + "سيؤدي تمكين هذا الإعداد إلى تسجيل بيانات تخطيط إضافية، بما في ذلك النص المعروض على الشاشة لبعض مكونات واجهة المستخدم. + +يمكن أن يساعد هذا في تحديد المكونات عند إنشاء عوامل تصفية مخصصة. + +ومع ذلك، سيؤدي تمكين هذا أيضًا إلى تسجيل بعض بيانات المستخدم مثل عنوان IP الخاص بك." سجل تتبع المكدس تتضمن سجلات التصحيح سجل تتبع المكدس لا تتضمن سجلات التصحيح سجل تتبع المكدس @@ -124,6 +131,15 @@ Second \"item\" text" "يؤدي إيقاف تشغيل ملاحظات الأخطاء إلى إخفاء كافة إشعارات أخطاء ReVanced. لن يتم إعلامك بأي أخطاء غير متوقعة." + تصدير سجلات تصحيح الأخطاء + نسخ سجلات تصحيح أخطاء ReVanced إلى الحافظة + تم تعطيل تسجيلات تصحيح الأخطاء + لم يتم العثور على سجلات + تم نسخ السجلات + فشل تصدير السجلات: $s + مسح سجلات تصحيح الأخطاء + يمسح جميع سجلات تصحيح أخطاء ReVanced المخزنة + تم مسح السجلات إخفاء بطاقات الألبوم @@ -365,9 +381,6 @@ Second \"item\" text" هذه الميزة متاحة فقط للأجهزة القديمة" يتم عرض إعلانات ملء الشاشة - إخفاء الإعلانات الزرية - تم إخفاء الإعلانات الزرية - يتم عرض الإعلانات الزرية إخفاء تسمية الترقية المدفوعة تم إخفاء تسمية الترقية المدفوعة يتم عرض تسمية الترقية المدفوعة @@ -478,9 +491,10 @@ Second \"item\" text" تعتيم خلفية واجهة التمرير السريع قيمة التعتيم بين 0-100 يجب أن يكون تعتيم التمرير السريع بين 0-100 - لون شريط تقدم واجهة التمرير - لون شريط التقدم لعناصر التحكم في مستوى الصوت والسطوع - لون شريط التقدم غير صالح + لون سطوع واجهة التمرير + لون شريط التقدم لعناصر التحكم في السطوع + لون مستوى صوت واجهة التمرير + لون شريط التقدم لعناصر التحكم في مستوى الصوت حجم نص واجهة التمرير حجم النص لواجهة التمرير بين 1-30 يجب أن يكون حجم النص بين 1-30 @@ -736,6 +750,9 @@ Second \"item\" text" إخفاء تسمية الموقع تم إخفاء تسمية الموقع يتم عرض تسمية الموقع + إخفاء لوحة التعليقات + تم إخفاء لوحة التعليقات + يتم عرض لوحة التعليقات إخفاء زر حفظ الموسيقى تم إخفاء زر حفظ الموسيقى يتم عرض زر حفظ الموسيقى @@ -1099,11 +1116,6 @@ Second \"item\" text" %s ثانية الشفافية: اللون: - تم تغيير اللون - إعادة ضبط اللون - رمز اللون غير صالح - إعادة تعيين اللون - إعادة التعيين لمحة يتم توفير البيانات بواسطة SponsorBlock API. انقر هنا لمعرفة المزيد ومشاهدة التنزيلات لمنصات أخرى @@ -1328,6 +1340,22 @@ Second \"item\" text" إعدادات GmsCore إعدادات لـ GmsCore + + الاهتزاز عند الضغط + تغيير الاهتزاز عند الضغط + تعطيل الاهتزاز للفصول + تم تعطيل الاهتزاز للفصول + تم تفعيل الاهتزاز للفصول + تعطيل الاهتزاز عند التمرير الدقيق + تم تعطيل الاهتزاز الدقيق عند البحث + تم تفعيل الاهتزاز عند التمرير الدقيق + تعطيل الاهتزاز عند التراجع عن البحث + تم تعطيل الاهتزاز عند التراجع عن البحث + تم تمكين الاهتزاز عند التراجع عن البحث + تعطيل الاهتزاز عند التكبير + تم تعطيل الاهتزاز عند التكبير + تم تمكين الاهتزاز عند التكبير + إذا قمت مؤخرًا بتغيير تفاصيل تسجيل الدخول إلى حسابك، فأزل تثبيت MicroG ثم أعد تثبيته. @@ -1346,11 +1374,6 @@ Second \"item\" text" يتم إزالة معلمة استعلام التتبع من الروابط لا يتم إزالة معلمة استعلام التتبع من الروابط - - تعطيل الاهتزاز عند التكبير - تم تعطيل الاهتزاز - تم تمكين الاهتزاز - فرض لغة الصوت الأصلية استخدام لغة الصوت الأصلية @@ -1378,7 +1401,7 @@ Second \"item\" text" عرض زر مربع حوار السرعة - يتم عرض الزر + الزر معروض. انقر مع الاستمرار لإعادة ضبط سرعة التشغيل إلى الوضع الافتراضي لا يتم عرض الزر @@ -1390,6 +1413,7 @@ Second \"item\" text" يجب أن تكون سرعات التشغيل المخصصة أقل من %s سرعة التشغيل المخصصة غير صالحة تلقائي + تمت إعادة ضبط سرعة التشغيل إلى: %s سرعة النقر مع الاستمرار المخصصة سرعة التشغيل بين 0-8 diff --git a/patches/src/main/resources/addresources/values-as-rIN/strings.xml b/patches/src/main/resources/addresources/values-as-rIN/strings.xml index fec4d1148..5b92e537e 100644 --- a/patches/src/main/resources/addresources/values-as-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-as-rIN/strings.xml @@ -201,6 +201,8 @@ Second \"item\" text" + + @@ -209,8 +211,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-az-rAZ/strings.xml b/patches/src/main/resources/addresources/values-az-rAZ/strings.xml index 5cb5334c3..ef91a4e08 100644 --- a/patches/src/main/resources/addresources/values-az-rAZ/strings.xml +++ b/patches/src/main/resources/addresources/values-az-rAZ/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Tənzimləmələr Davam etmək istəyirsiniz? Sıfırla + Rəngi sıfırla + Yanlış rəng Yenilə və yenidən başlat Yenidən başlat İdxal et @@ -42,7 +44,7 @@ Second \"item\" text" ReVanced tənzimləmələr standarta təyin edildi %d tənzimləmə idxal edildi Uğursuz idxal prosesi: %s - Axtarış tənzimləmələri + Tənzimləmələri axtar ‘%s’ üçün nəticə tapılmadı Başqa açar sözü yoxla Axtarış tarixçəsindən silinsin? @@ -115,6 +117,11 @@ Davam et düyməsinə toxun və optimallaşdırma dəyişikliklərin qəbul et." Bufer protokol jurnalı Sazlama jurnallarına protokol buferi daxildir Sazlama jurnallarına protokol buferi daxil deyil + "Bu seçimi aktivləşdirmə bəzi UI quruluşları üçün ekran mətni də olmaqla əlavə tərtibat bazasını daxil edəcək. + +Bu, xüsusi filtrlər yaradarkən quruluşları müəyyən etməyə kömək edə bilər. + +Hər halda, bunu aktivləşdirmə IP ünvanınız kimi bəzi istifadəçi məlumatın da daxil edəcək." Yığın izləri jurnalı Sazlama jurnalına yığın izləri daxildir Sazlama jurnalına yığın izləri daxil deyil @@ -124,6 +131,15 @@ Davam et düyməsinə toxun və optimallaşdırma dəyişikliklərin qəbul et." "Xəta ani bildirişlərin qapatmaq, bütün ReVanced xəta bildirişlərin gizlədir. Gözlənilməz hallardan xəbərdar olmayacaqsınız." + Sazlama qeydlərini ixrac edin + ReVanced sazlama qeydlərini buferə köçürür + Sazlama qeydi qapalıdır + Qeydlər tapılmadı + Qeydlər köçürüldü + Qeydləri ixrac etmək alınmadı: $s + Sazlama qeydlərini təmizlə + Saxlanılan bütün ReVanced sazlama qeydlərini təmizləyir + Qeydlər silindi Albom kartlarını gizlət @@ -365,9 +381,6 @@ Məhdudiyyətlər Bu xüsusiyyət yalnız köhnə cihazlar üçün mövcuddur" Tam ekran reklamları göstərilir - Düyməli reklamları gizlət - Düyməli reklamlar gizlədilir - Düyməli reklamlar göstərilir Ödənişli tanıtım etiketini gizlət Ödənişli reklam etiketi gizlədilib Ödənişli reklam etiketi göstərilir @@ -478,9 +491,10 @@ Ekranın sağ tərəfində düzünə sürüşdürərək səs səviyyəsini tənz Sürüşdürmə cildi arxa plan qeyri-şəffaflığı 0-100 arası qeyri-şəffaflıq dəyəri Sürüşmə qeyri-şəffaflığı 0-100 arası olmalıdır - Sürüşdürmə örtüyü irəliləyiş cizgisi rəngi - Səs səviyyəsinə və parlaqlığa nəzarət üçün irəliləyiş cizgisi rəngi - Yanlış irəliləyiş cizgisi rəngi + Sürüşdürmə örtüyü parlaqlıq rəngi + Parlaqlığa nəzarət üçün irəliləyiş zolağının rəngi + Sürüşdürmə örtüyü səs səviyyəsi rəngi + Səs səviyyəsinə nəzarət üçün irəliləyiş zolağının rəngi Sürüşdürmə örtüyü mətn ölçüsü Sürüşmə üçün mətn ölçüsü 1-30 arasındadır Mətn ölçüsü 1-30 arası olmalıdır @@ -1098,11 +1112,6 @@ Təqdim etməyə hazırdır?" %s saniyə Qeyri-şəffaflıq: Rəng: - Rəng dəyişdirildi - Rəngi sıfırla - Etibarsız rəng kodu - Rəngi sıfırla - Sıfırlayın Haqqında Məlumat SponsorBlock API tərəfindən təqdim edilir. Daha ətraflı öyrənmək və digər platformalar üzrə yükləmələrə baxmaq üçün bura toxunun @@ -1327,6 +1336,22 @@ Bunu aktivləşdirmə daha yüksək video keyfiyyətləri əngəlin silə bilər GmsCore Tənzimləmələri GmsCore üçün Tənzimləmələr + + Əks-əlaqə reaksiyası + Əks-əlaqə reaksiyasını dəyişdir + Fəsillər reaksiyasın qapat + Fəsillər reaksiyası qapalıdır + Fəsillər reaksiyası aktivdir + Dəqiq axtarış reaksiyasın qapat + Dəqiq axtarış reaksiyası qapalıdır + Dəqiq axtarış reaksiyası aktivdir + Axtarış geriyə reaksiyasın qapat + Axtarış geri reaksiyası qapalıdır + Axtarış geri reaksiyası aktivdir + Yaxınlaşdırma reaksiyasın qapat + Yaxınlaşdırma reaksiyası qapalıdır + Yaxınlaşdırma reaksiyası aktivdir + Bu yaxınlarda hesabınıza giriş məlumatlarınızı dəyişmisinizsə, MicroG-ni silin və təkrar quraşdırın. @@ -1345,11 +1370,6 @@ Bunu aktivləşdirmə daha yüksək video keyfiyyətləri əngəlin silə bilər İzləmə sorğusu faktoru bağlantılardan silinir İzləmə sorğusu faktoru bağlantılardan silinmir - - Yaxınlaşdırma reaksiyasın qapat - Reaksiya qapalıdır - Reaksiya aktivdir - Orijinal səs dilini zorla Orijinal səs dilini istifadə @@ -1377,7 +1397,7 @@ Bunu aktivləşdirmə daha yüksək video keyfiyyətləri əngəlin silə bilər Sürət dialoq düyməsini göstər - Düymə göstərilir + Düymə göstərilir. Oynatma sürətin standart olaraq qaytarmaq üçün toxunub saxla Düymə göstərilmir @@ -1389,6 +1409,7 @@ Bunu aktivləşdirmə daha yüksək video keyfiyyətləri əngəlin silə bilər Fərdi sürətlər %s dəyərindən az olmalıdır Fərdi oynatma sürətləri etibarsızdır Avtomatik + Oynatma sürəti sıfırlandı: %s Xüsusi toxunma və saxlanılma sürəti 0-8 arası oynatma sürəti diff --git a/patches/src/main/resources/addresources/values-be-rBY/strings.xml b/patches/src/main/resources/addresources/values-be-rBY/strings.xml index 63d92c4d5..65bdc15b8 100644 --- a/patches/src/main/resources/addresources/values-be-rBY/strings.xml +++ b/patches/src/main/resources/addresources/values-be-rBY/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Налады Вы хочаце працягнуць? Скінуць + Скінуць колер + Несапраўдны колер Абнавіце і перазагрузіце Перазапуск Імпарт @@ -115,6 +117,11 @@ Second \"item\" text" Буфер пратаколу часопіса Журналы адладкі ўключаюць пратабуфер Журналы адладкі не ўключаюць пратабуфер + "Уключэнне гэтага параметра будзе запісваць дадатковыя даныя макета, у тым ліку тэкст на экране для некаторых кампанентаў інтэрфейсу. + +Гэта можа дапамагчы ідэнтыфікаваць кампаненты пры стварэнні карыстацкіх фільтраў. + +Аднак уключэнне гэтага параметра таксама будзе запісваць некаторыя даныя карыстальніка, такія як ваш IP-адрас." Сляды стэка журнала Журналы адладкі ўключаюць трасіроўку стэка Журналы адладкі не ўключаюць трасіроўку стэка @@ -124,6 +131,15 @@ Second \"item\" text" "Адключэнне паведамленняў пра памылкі схавае ўсе апавяшчэнні ReVanced пра памылкі. Вы не будзеце атрымліваць апавяшчэнні пра нечаканыя падзеі." + Экспартаваць адладачныя лагі + Капіруе адладачныя лагі ReVanced у буфер абмену + Адладачнае лагаванне адключана + Лагі не знойдзены + Лагі скапіяваны + Не атрымалася экспартаваць лагі: $s + Ачысціць адладачныя лагі + Ачышчае ўсе захаваныя адладачныя лагі ReVanced + Лагі ачышчаны Схаваць карты альбома @@ -365,9 +381,6 @@ Second \"item\" text" Гэтая функцыя даступная толькі для старых прылад" Адлюстроўваецца поўнаэкранная рэклама - Схаваць рэкламу на кнопках - Аб\"явы на кнопках схаваныя - Паказваюцца аб\"явы на кнопках Схаваць метку аплачанай акцыі Пазнака платнай акцыі схавана Адлюстроўваецца ярлык платнай акцыі @@ -478,9 +491,10 @@ Second \"item\" text" Непразрыстасць фону накладкі пракруткі Значэнне непразрыстасці паміж 0-100 Непразрыстасць пракруткі павінна быць паміж 0-100 - Колер слупка прагрэсу накладкі правядзення - Колер слупка прагрэсу для рэгулявання гучнасці і яркасці - Несапраўдны колер слупка прагрэсу + Колер яркасці накладкі правядзення + Колер шкалы прагрэсу для элементаў кіравання яркасцю + Колер гучнасці накладкі правядзення + Колер шкалы прагрэсу для элементаў кіравання гучнасцю Памер тэксту накладкі правядзення Памер тэксту для накладкі правядзення ад 1 да 30 Памер тэксту павінен быць у межах ад 1 да 30 @@ -736,6 +750,9 @@ Second \"item\" text" Схаваць метку месцазнаходжання Метка месцазнаходжання схавана Паказана метка месцазнаходжання + Схаваць панэль каментарыяў + Панель каментарыяў схаваная + Панэль каментарыяў паказана Схаваць кнопку «Захаваць музыку» Кнопка захавання музыкі схавана Кнопка захавання музыкі паказана @@ -1100,11 +1117,6 @@ Second \"item\" text" %s секунд Непразрыстасць: колер: - Колер змяніўся - Скід колеру - Няправільны код колеру - Скінуць колер - Скінуць Пра праграму Дадзеныя прадастаўляюцца API SponsorBlock. Націсніце тут, каб даведацца больш і паглядзець спампоўкі для іншых платформаў @@ -1329,6 +1341,22 @@ Second \"item\" text" Налады GmsCore Налады для GmsCore + + Тактыльная зваротная сувязь + Змяніць тактыльную зваротную сувязь + Адключыць тактыльныя эфекты раздзелаў + Тактыльныя эфекты раздзелаў адключаны + Тактыльныя эфекты раздзелаў уключаны + Адключыць тактыльны эфект дакладнага пошуку + Дакладны тактыльны эфект пошуку адключаны + Тактыльны эфект дакладнага пошуку ўключаны + Адключыць тактыльны эфект адмены пошуку + Тактыльны эфект адмены пошуку адключаны + Тактыльны эфект адмены пошуку ўключаны + Адключыць тактыльны эфект маштабавання + Тактыльны эфект маштабавання адключаны + Тактыльны эфект маштабавання ўключаны + Калі вы нядаўна змянілі даныя для ўваходу ў свой уліковы запіс, выдаліце і пераўсталюйце MicroG. @@ -1347,11 +1375,6 @@ Second \"item\" text" Параметр запыту адсочвання выдалены са спасылак Параметр адсочвання запыту не выдаляецца са спасылак - - Адключыць тактыльны эфект маштабавання - Тактыльныя функцыі адключаны - Тактыльныя сігналы ўключаны - Вымушаная арыгінальная мова аўдыё Выкарыстоўваць арыгінальную мову аўдыя @@ -1379,7 +1402,7 @@ Second \"item\" text" Паказаць дыялогавую кнопку хуткасці - Паказана кнопка + Кнопка паказана. Націсніце і ўтрымлівайце, каб скінуць хуткасць прайгравання да стандартнай Кнопка не паказваецца @@ -1391,6 +1414,7 @@ Second \"item\" text" Нестандартныя хуткасці павінны быць менш за %s Несапраўдныя нестандартныя хуткасці прайгравання Аўто + Хуткасць прайгравання скінута да: %s Уласны хуткасць націску і ўтрымання Хуткасць прайгравання між 0-8 diff --git a/patches/src/main/resources/addresources/values-bg-rBG/strings.xml b/patches/src/main/resources/addresources/values-bg-rBG/strings.xml index 9f83dc52a..07d38ad75 100644 --- a/patches/src/main/resources/addresources/values-bg-rBG/strings.xml +++ b/patches/src/main/resources/addresources/values-bg-rBG/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Настройки Искате ли да продължите? Възстанови + Нулиране на цвета + Невалиден цвят Рестартирай и опресни Рестартиране Импортиране @@ -88,7 +90,7 @@ Second \"item\" text" Реклами Алтернативни миниатюри Поток - Общ + Общи Плеър Лента за прогрес на видеото Контроли с плъзгане @@ -115,6 +117,11 @@ Second \"item\" text" Буфер на протокола за дневника Файлове с дневници за грешки включват буфера Файлове с дневници за грешки не включват буфера + "Активирането на тази настройка ще регистрира допълнителни данни за оформлението, включително текст на екрана за някои компоненти на потребителския интерфейс. + +Това може да помогне за идентифициране на компоненти при създаване на персонализирани филтри. + +Активирането на тази настройка обаче ще регистрира и някои потребителски данни, като например вашия IP адрес." Следи от стека на дневника Дневникът за отстраняване на грешки съдържа следи от стека Дневникът за отстраняване на грешки не съдържа следи от стека @@ -124,6 +131,15 @@ Second \"item\" text" "Изключването на изскачащи съобщения за грешки крие всички известия за грешки на ReVanced. Няма да бъдете уведомени за неочаквани събития." + Експортиране на логове за отстраняване на грешки + Копира логовете за отстраняване на грешки на ReVanced в клипборда + Отстраняването на грешки е деактивирано + Не са намерени логове + Логовете са копирани + Неуспешно експортиране на логове: $s + Изчистване на логовете за отстраняване на грешки + Изчиства всички съхранени логове за отстраняване на грешки на ReVanced + Логовете са изчистени \"Карти на албумите\" @@ -365,9 +381,6 @@ Second \"item\" text" Тази функция е налична само за по-стари устройства" Рекламите в режим на цял екран са показани - Скриване на рекламни бутони - Бутонираните реклами са скрити - Бутонираните реклами са показани Скриване на платените промоции Промоционалните етикети са скрити Промоционалните етикети се показват @@ -478,9 +491,10 @@ Second \"item\" text" Плъзгане на фона на наслагването непрозрачност Стойност на непрозрачността между 0-100 Непрозрачността на плъзгането трябва да е между 0-100 - Цвят на лентата за напредък при плъзгане - Цветът на лентата за напредък за контролите за сила на звука и яркост - Невалиден цвят на лентата за напредък + Цвят на наслагването за яркост при плъзгане + Цветът на лентата за състояние при контролиране на яркостта + Цвят на наслагването за сила на звука при плъзгане + Цветът на лентата за състояние при контролиране на силата на звука Размер на текста на наслагването при плъзгане Размерът на текста за наслагването при плъзгане между 1-30 Размерът на текста трябва да е между 1-30 @@ -736,6 +750,9 @@ Second \"item\" text" Етикет за местоположение Етикет за местоположение е скрит Етикет за местоположение се показва + Скриване на панела за коментари + Панелът за коментари е скрит + Панелът за коментари е показан Скриване на бутона Save music Бутонът за запазване на музика е скрит Показан е бутонът за запазване на музика @@ -1099,11 +1116,6 @@ Second \"item\" text" %s секунди Непрозрачност: Цвят: - Цветът е променен - Възстанови цвета - Невалидна стойност за цвета - Възстановяване на цвят - Възстанови За програмата Данните са предоставени от SponsorBlock API. Докоснете тук за повече информация и изтеглияния @@ -1328,6 +1340,22 @@ Second \"item\" text" GmsCore Настройки Настройки на GmsCore + + Вибрационна обратна връзка + Промяна на вибрационната обратна връзка + Деактивиране на вибрацията при главите + Вибрацията при главите е деактивирана + Вибрацията при главите е активирана + Деактивиране на вибрацията при прецизното търсене + Прецизната вибрация при търсене е деактивирана + Вибрацията при прецизното търсене е активирана + Деактивиране на вибрация при отмяна на търсене + Вибрацията при отмяна на търсене е деактивирана + Вибрацията при отмяна на търсене е активирана + Деактивиране на вибрация при мащабиране + Вибрацията при мащабиране е деактивирана + Вибрацията при мащабиране е активирана + Ако наскоро сте променили данните си за вход в профила, деинсталирайте и инсталирайте отново MicroG. @@ -1346,11 +1374,6 @@ Second \"item\" text" Параметърът на заявката за проследяване е премахнат от връзките Параметърът на заявката за проследяване не е премахнат от връзките - - Деактивиране на вибрация при мащабиране - Вибрациите са деактивирани - Вибрациите са активирани - Принудително оригинално аудио език Използване на оригиналния език на аудиото @@ -1378,7 +1401,7 @@ Second \"item\" text" Показване бутон за скорост - Бутона \"Уведоми ме\" се показва. + Бутонът е показан. Докоснете и задръжте, за да върнете скоростта на възпроизвеждане към стойността по подразбиране Бутонът не е показан @@ -1390,6 +1413,7 @@ Second \"item\" text" Персонализираните скорости трябва да са по-малки от %s Невалидни персонализирани скорости на възпроизвеждане Авто + Скоростта на възпроизвеждане е нулирана на: %s Персонализирана скорост при докосване и задържане Скорост на възпроизвеждане между 0-8 diff --git a/patches/src/main/resources/addresources/values-bn-rBD/strings.xml b/patches/src/main/resources/addresources/values-bn-rBD/strings.xml index de95e72d4..1485da827 100644 --- a/patches/src/main/resources/addresources/values-bn-rBD/strings.xml +++ b/patches/src/main/resources/addresources/values-bn-rBD/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" সেটিংস আপনি কি এগিয়ে যেতে ইচ্ছুক? আবার সেট করুন + রঙ রিসেট করুন + অবৈধ রঙ রিফ্রেশ করুন এবং আবার চালু করুন আবার চালু করুন আমদানি করুন @@ -115,6 +117,7 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ প্রটোকল বাফার লগ ডিবাগ লগ প্রটোকল বাফার সংযুক্ত করবে ডিবাগ লগ প্রটোকল বাফার সংযুক্ত করবে না + "এই সেটিংস সক্ষম করলে কিছু UI উপাদানের জন্য অন-স্ক্রীন পাঠ্য সহ অতিরিক্ত লেআউট ডেটা লগ করা হবে।\n\nএটি কাস্টম ফিল্টার তৈরি করার সময় উপাদান সনাক্ত করতে সাহায্য করতে পারে।\n\nতবে, এটি সক্রিয় করলে আপনার আইপি ঠিকানার মতো কিছু ব্যবহারকারীর ডেটাও লগ করা হবে।" স্টেক ট্রেস লগ ডিবাগ লগ স্টেক ট্রেস সংযুক্ত করবে ডিবাগ লগ স্টেক ট্রেস সংযুক্ত করবে না @@ -124,6 +127,15 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ "ত্রুটি \"toast\" বন্ধ করে ReVanced ত্রুটি বিজ্ঞপ্তিগুলি লুকানো হয়। আপনি কোনও অপ্রত্যাশিত ঘটনার বিষয়ে অবহিত হবেন না।" + ডিবাগ লগগুলি রফতানি করুন + ক্লিপবোর্ডে ReVanced ডিবাগ লগগুলি অনুলিপি করে + ডিবাগ লগিং নিষ্ক্রিয় করা হয়েছে + কোনো লগ পাওয়া যায়নি + লগ অনুলিপি করা হয়েছে + লগ রপ্তানি করতে ব্যর্থ: $s + ডিবাগ লগগুলি সাফ করুন + সমস্ত সঞ্চিত ReVanced ডিবাগ লগ সাফ করে + লগ সাফ করা হয়েছে অ্যালবাম কার্ড লুকান @@ -365,9 +377,6 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ এই বৈশিষ্ট্যটি কেবল পুরনো ডিভাইসের জন্য উপলব্ধ" পূর্ণ স্ক্রীন বিজ্ঞাপন প্রদর্শিত হয়েছে - বোতামযুক্ত বিজ্ঞাপন লুকান - বোতামযুক্ত বিজ্ঞাপন লুকিয়ে রয়েছে - বোতামযুক্ত বিজ্ঞাপন প্রদর্শিত হয়েছে অর্থের বিনিময়ে প্রচার অন্তর্ভুক্ত রয়েছে ব্যানার লুকান অর্থের বিনিময়ে প্রচার অন্তর্ভুক্ত রয়েছে ব্যানার লুকিয়ে রয়েছে অর্থের বিনিময়ে প্রচার অন্তর্ভুক্ত রয়েছে ব্যানার প্রদর্শিত হয়েছে @@ -478,9 +487,10 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ অস্বচ্ছতা 0-100 এর মধ্যে অস্বচ্ছতার মান সোয়াইপের অস্বচ্ছতা অবশ্যই 0-100 এর মধ্যে হতে হবে - সোয়াইপ ওভারলে প্রগ্রেস বার এর রং - ভলিউম এবং উজ্জ্বলতা নিয়ন্ত্রণের জন্য প্রগ্রেস বার এর রং - অবৈধ প্রগ্রেস বার রং + সোয়াইপ ওভারলে উজ্জ্বলতা রঙ + উজ্জ্বলতা নিয়ন্ত্রণের জন্য প্রগ্রেস বারের রঙ + সোয়াইপ ওভারলে ভলিউম রঙ + ভলিউম নিয়ন্ত্রণের জন্য প্রগ্রেস বারের রঙ সোয়াইপ ওভারলে টেক্সট সাইজ সোয়াইপ ওভারলে-এর জন্য টেক্সট সাইজ ১-৩০ এর মধ্যে টেক্সট সাইজ অবশ্যই ১-৩০ এর মধ্যে হতে হবে @@ -736,6 +746,9 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ অবস্থান লেবেল লুকান অবস্থান লেবেল লুকিয়ে রয়েছে অবস্থান লেবেল প্রদর্শিত হয়েছে + মন্তব্য প্যানেল লুকান + মন্তব্য প্যানেল লুকানো আছে + মন্তব্য প্যানেল দেখানো হয়েছে সেভ মিউজিক বোতামটি লুকান Save music বোতাম লুকানো আছে Save music বোতাম দেখানো হচ্ছে @@ -1099,11 +1112,6 @@ YouTube সেটিংসে অটো প্লে পরিবর্তন %s সেকেন্ড স্বচ্ছতা: রং: - রং পরিবর্তন করা হয়েছে - রং আবার সেট করুন - রংয়ের ভুল কোড - রং আবার সেট করুন - পুনরায় সেট করুন সম্পর্কিত ডেটা SponsorBlock API দ্বারা সরবরাহ করা হয়। আরও জানতে এবং অন্যান্য প্ল্যাটফর্মের ডাউনলোড দেখতে এখানে ট্যাপ করুন @@ -1328,6 +1336,22 @@ DeArrow সম্পর্কে আরও জানতে এখানে ট GmsCore সেটিং GmsCore এর জন্য সেটিং + + কম্পন প্রতিক্রিয়া + কম্পন প্রতিক্রিয়া পরিবর্তন করুন + অধ্যায়গুলোর কম্পন নিষ্ক্রিয় করুন + অধ্যায়গুলোর কম্পন নিষ্ক্রিয় করা হয়েছে + অধ্যায়গুলোর কম্পন সক্রিয় করা হয়েছে + নির্দিষ্ট স্থানে খোঁজার কম্পন নিষ্ক্রিয় করুন + সূক্ষ্ম সিকিং কম্পন নিষ্ক্রিয় করা হয়েছে + নির্দিষ্ট স্থানে খোঁজার কম্পন সক্রিয় করা হয়েছে + সীক আনডু কম্পন নিষ্ক্রিয় করুন + সীক আনডু কম্পন নিষ্ক্রিয় করা হয়েছে + সীক আনডু কম্পন সক্রিয় করা হয়েছে + জুম করার কম্পন নিষ্ক্রিয় করুন + জুম করার কম্পন নিষ্ক্রিয় করা হয়েছে + জুম করার কম্পন সক্রিয় করা হয়েছে + আপনি যদি সম্প্রতি আপনার অ্যাকাউন্ট লগইন বিশদ পরিবর্তন করে থাকেন, তবে MicroG আনইনস্টল করুন এবং পুনরায় ইনস্টল করুন। @@ -1346,11 +1370,6 @@ DeArrow সম্পর্কে আরও জানতে এখানে ট লিংক থেকে ট্র্যাকিং করার প্যারামিটার মুছে ফেলা হয়েছে লিংক থেকে ট্র্যাকিং করার প্যারামিটার মুছে ফেলা হয়নি - - জুম করার কম্পন নিষ্ক্রিয় করুন - কম্পন নিষ্ক্রিয় করা হয়েছে - কম্পন সক্রিয় করা হয়েছে - মূল অডিও ভাষা বলপূর্বক চালু করুন মূল অডিও ভাষা ব্যবহার করা হচ্ছে @@ -1378,7 +1397,7 @@ DeArrow সম্পর্কে আরও জানতে এখানে ট স্পিড ডায়ালগ বোতাম দেখান - বোতাম প্রদর্শিত হয়েছে + বোতামটি দেখানো হয়েছে। প্লেব্যাক স্পীড ডিফল্টে রিসেট করতে ট্যাপ করে ধরে রাখুন। বোতাম প্রদর্শিত হয়নি @@ -1390,6 +1409,7 @@ DeArrow সম্পর্কে আরও জানতে এখানে ট কাস্টম গতি %s এর চেয়ে কম হতে হবে অবৈধ কাস্টম প্লেব্যাক গতি স্বতস্ফূর্তভাবে + প্লেব্যাক গতি রিসেট করা হয়েছে: %s কাস্টম ট্যাপ এন্ড হোল্ড স্পিড ০-৮ এর মধ্যে প্লেব্যাক স্পিড diff --git a/patches/src/main/resources/addresources/values-bs-rBA/strings.xml b/patches/src/main/resources/addresources/values-bs-rBA/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-bs-rBA/strings.xml +++ b/patches/src/main/resources/addresources/values-bs-rBA/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-ca-rES/strings.xml b/patches/src/main/resources/addresources/values-ca-rES/strings.xml index 3ca5abe19..3b03d99fc 100644 --- a/patches/src/main/resources/addresources/values-ca-rES/strings.xml +++ b/patches/src/main/resources/addresources/values-ca-rES/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Configuració Vols continuar? Restablir + Restablir el color + Color no vàlid Actualitza i reinicia Reinicia Importa @@ -115,6 +117,11 @@ Toca el botó Continua i permet els canvis d'optimització." Iniciar sesión en el buffer de protocolo El registro de depuración incluye el búfer de protocolo Els registres de depuració no inclouen l\'amortiment de proto + "Si activeu aquest paràmetre, es registraran dades de disseny addicionals, inclòs el text en pantalla per a alguns components de la IU. + +Això pot ajudar a identificar components quan creeu filtres personalitzats. + +Tot i això, si activeu aquesta opció, també es registraran algunes dades de l'usuari, com ara la vostra adreça IP." Registre dels rastrejos de la pila Els registres de depuració inclouen el rastreig de la pila Els registres de depuració no inclouen el rastreig de la pila @@ -124,6 +131,15 @@ Toca el botó Continua i permet els canvis d'optimització." "Desactivar els missatges d'error d'avis oculta totes les notificacions d'error de ReVanced. No se t'informarà de cap esdeveniment inesperat." + Exporta els registres de depuració + Copia els registres de depuració de ReVanced al porta-retalls + El registre de depuració està desactivat + No s\'ha trobat cap registre + Registres copiats + No s\'han pogut exportar els registres: $s + Esborra els registres de depuració + Esborra tots els registres de depuració de ReVanced emmagatzemats + Registres esborrats Amagar les targetes d\'àlbums @@ -365,9 +381,6 @@ Limitacions Aquesta funció només està disponible per a dispositius antics" Els anuncis de pantalla completa es mostren - Amaga els anuncis amb botó - Els anuncis amb botó estan amagats - Els anuncis amb botó es mostren Amaga l\'etiqueta de promoció de pagament L\'etiqueta de promoció de pagament està amagada Es mostra l\'etiqueta de promoció de pagament @@ -478,9 +491,10 @@ Ajusteu el volum lliscant verticalment a la part dreta de la pantalla" Opacitat del fons de la superposició de lliscament Valor d\'opacitat entre 0 i 100 L\'opacitat de lliscament ha d\'estar entre 0 i 100 - Color de la barra de progrés de la superposició lliscant - El color de la barra de progrés per als controls de volum i brillantor - Color de barra de progrés no vàlid + Color de la lluminositat de la superposició de lliscament + El color de la barra de progrés per als controls de brillantor + Color del volum de la superposició de lliscament + El color de la barra de progrés per als controls de volum Mida del text de la superposició lliscant La mida del text per a la superposició lliscant entre 1 i 30 La mida del text ha d\'estar entre 1 i 30 @@ -736,6 +750,9 @@ Per mostrar el menú de la pista d'àudio, canvieu \"Suplanta els fluxos de víd Amaga l\'etiqueta de ubicació L\'etiqueta de ubicació està oculta L\'etiqueta de ubicació es mostra + Amaga el panell de comentaris + El panell de comentaris està ocult + Es mostra el panell de comentaris Amaga el botó Desa música El botó de desar música està ocult El botó de desar música es mostra @@ -1098,11 +1115,6 @@ Preparat per enviar?" %s segons Opacitat: Color: - Color canviat - Color restablert - Codi de color invàlid - Restableix el color - Restablir Quant a Les dades són proporcionades per l\'API de SponsorBlock. Toca aquí per a saber-ne més i veure les descàrregues per a altres plataformes @@ -1327,6 +1339,22 @@ Si actives aquesta opció, es poden desbloquejar qualitats de vídeo més altes" Configuració de GmsCore Configuració de GmsCore + + Hàptica + Canvia la resposta hàptica + Desactiva els hàptics dels capítols + Els hàptics dels capítols estan desactivats + Els hàptics dels capítols estan activats + Desactiva els hàptics de cerca precisa + Els hàptics de cerca precisa estan desactivats + Els hàptics de cerca precisa estan activats + Desactiva els hàptics de desfer la cerca + Els hàptics de desfer la cerca estan desactivats + Els hàptics de desfer la cerca estan activats + Desactiva els hàptics d\'enfocament + Els hàptics de zoom estan desactivats + Els hàptics de zoom estan habilitats + Si recentment heu canviat les dades d\'inici de sessió del vostre compte, desinstal·leu i torneu a instal·lar MicroG. @@ -1345,11 +1373,6 @@ Si actives aquesta opció, es poden desbloquejar qualitats de vídeo més altes" El paràmetre de consulta de seguiment s\'elimina dels enllaços El paràmetre de consulta de seguiment no s\'elimina dels enllaços - - Desactiva els hàptics d\'enfocament - Els hàptics estan desactivats - Els hàptics estan habilitats - Forçar l\'idioma d\'àudio original S\'utilitza l\'idioma d\'àudio original @@ -1377,7 +1400,7 @@ Si actives aquesta opció, es poden desbloquejar qualitats de vídeo més altes" Mostra el botó del diàleg de velocitat - El botó es mostra + Es mostra el botó. Toqueu i manteniu premut per restablir la velocitat de reproducció per defecte El botó no es mostra @@ -1389,6 +1412,7 @@ Si actives aquesta opció, es poden desbloquejar qualitats de vídeo més altes" Les velocitats personalitzades han de ser inferiors a %s Velocitats de reproducció personalitzades no vàlides Automàtic + Velocitat de reproducció restablerta a: %s Velocitat personalitzada de mantenir premut Velocitat de reproducció entre 0 i 8 diff --git a/patches/src/main/resources/addresources/values-cs-rCZ/strings.xml b/patches/src/main/resources/addresources/values-cs-rCZ/strings.xml index d2eb23f23..188b4c6ab 100644 --- a/patches/src/main/resources/addresources/values-cs-rCZ/strings.xml +++ b/patches/src/main/resources/addresources/values-cs-rCZ/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Nastavení Přejete si pokračovat? Výchozí + Obnovit barvu + Neplatná barva Obnovit a restartovat Restartovat Importovat @@ -115,6 +117,11 @@ Klepněte na tlačítko Pokračovat a povolte změny optimalizace." Záznam bufferu protokolu Debugovací záznamy obsahují proto buffer Debugovací záznamy neobsahují proto buffer + "Povolením tohoto nastavení se bude zaznamenávat další data rozvržení, včetně textu na obrazovce pro některé komponenty uživatelského rozhraní. + +To může pomoci identifikovat komponenty při vytváření vlastních filtrů. + +Povolením této možnosti se však budou zaznamenávat i některá uživatelská data, jako je vaše IP adresa." Protokolovat trasování zásobníku Protokoly ladění obsahují trasování zásobníku Ladící protokoly nezahrnují sledování zásobníku @@ -124,6 +131,15 @@ Klepněte na tlačítko Pokračovat a povolte změny optimalizace." "Vypnutí chybových toastů skryje všechna chybová oznámení ReVanced. Nebudete informováni o žádné neočekávané události." + Exportovat ladicí protokoly + Zkopíruje ladicí protokoly ReVanced do schránky + Ladění je vypnuto + Nebyly nalezeny žádné protokoly + Protokoly zkopírovány + Nepodařilo se exportovat protokoly: $s + Vymazat ladicí protokoly + Vymaže všechny uložené ladicí protokoly ReVanced + Protokoly vymazány Skrýt karty alb @@ -365,9 +381,6 @@ Omezení: Tato funkce je dostupná pouze pro starší zařízení" Celostránkové reklamy jsou zobrazeny - Skrýt reklamy s tlačítky - Reklamy s tlačítky jsou skryty - Reklamy s tlačítky jsou zobrazeny Skrýt štítek placené propagace Štítek placené propagace je skryt Štítek placené propagace je zobrazen @@ -478,9 +491,10 @@ Hlasitost se upravuje svislým přejetím po pravé straně obrazovky" Průsvitnost pozadí překrytí tažením Hodnota průsvitnosti mezi 0-100 Průsvitnost tažení musí být mezi 0-100 - Barva ukazatele průběhu překrytí přejetím - Barva ukazatele průběhu pro ovládání hlasitosti a jasu - Neplatná barva ukazatele průběhu + Barva jasu překryvné vrstvy tažení + Barva ukazatele průběhu pro ovládání jasu + Barva hlasitosti překryvné vrstvy tažení + Barva ukazatele průběhu pro ovládání hlasitosti Velikost textu překrytí přejetím Velikost textu překrytí přejetím mezi 1–30 Velikost textu musí být mezi 1–30 @@ -736,6 +750,9 @@ Chcete-li zobrazit nabídku zvukové stopy, změňte možnost „Zfalšovat stre Skrýt štítek umístění Štítek umístění je skrytý Štítek umístění je zobrazen + Skrýt panel Komentáře + Panel komentářů je skrytý + Panel Komentáře je zobrazen Skrýt tlačítko Uložit hudbu Tlačítko Uložit hudbu je skryté Tlačítko Uložit hudbu je zobrazeno @@ -1098,11 +1115,6 @@ Jste připraveni k odeslání?" %s sekund Průhlednost: Barva: - Barva změněna - Barva resetována - Neplatný kód barvy - Resetovat barvu - Výchozí O aplikaci Data poskytuje rozhraní API SponsorBlock. Klepněte zde, abyste se dozvěděli více a zobrazili si soubory ke stažení pro další platformy @@ -1327,6 +1339,22 @@ Povolením této funkce lze odemknout vyšší kvality videa" Nastavení GmsCore Nastavení pro GmsCore + + Haptická odezva + Změnit haptickou odezvu + Zakázat haptiku kapitol + Haptika kapitol je zakázána + Haptika kapitol je povolena + Zakázat haptiku pro přesné hledání + Haptická odezva při přesném vyhledávání je vypnutá + Haptika pro přesné hledání je povolena + Zakázat haptiku pro vrácení zpět vyhledávání + Haptika pro vrácení zpět vyhledávání je vypnutá + Haptika pro vrácení zpět vyhledávání je zapnutá + Zakázat haptiku pro zoom + Haptika zoomu je vypnutá + Haptika zoomu je zapnutá + Pokud jste nedávno změnili přihlašovací údaje svého účtu, odinstalujte a znovu nainstalujte MicroG. @@ -1345,11 +1373,6 @@ Povolením této funkce lze odemknout vyšší kvality videa" Sledovací parametr dotazu je odstraněn z odkazů Sledovací parametr dotazu není odstraněn z odkazů - - Zakázat haptiku pro zoom - Haptika je zakázána - Haptika je povolena - Vynutit původní jazyk zvuku Použít původní jazyk zvuku @@ -1377,7 +1400,7 @@ Povolením této funkce lze odemknout vyšší kvality videa" Zobrazit tlačítko dialogu rychlosti - Tlačítko je zobrazeno + Tlačítko je zobrazeno. Klepnutím a podržením obnovíte výchozí rychlost přehrávání Tlačítko se nezobrazuje @@ -1389,6 +1412,7 @@ Povolením této funkce lze odemknout vyšší kvality videa" Vlastní rychlosti musí být menší než %s Neplatné vlastní rychlosti přehrávání Automaticky + Rychlost přehrávání obnovena na: %s Vlastní rychlost stisknutí a podržení Rychlost přehrávání 0 až 8 diff --git a/patches/src/main/resources/addresources/values-da-rDK/strings.xml b/patches/src/main/resources/addresources/values-da-rDK/strings.xml index c2945d790..529f2a9f6 100644 --- a/patches/src/main/resources/addresources/values-da-rDK/strings.xml +++ b/patches/src/main/resources/addresources/values-da-rDK/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Indstillinger Ønsker du at fortsætte? Nulstil + Nulstil farve + Ugyldig farve Opdater og genstart Genstart Importer @@ -115,6 +117,11 @@ Tap på knappen Fortsæt, og tillad optimeringsændringer." Logprotokolbuffer Fejlfindingslogge inkluderer protobuffer Fejlfindingslogge inkluderer ikke protobuffer + "Aktivering af denne indstilling logger yderligere layoutdata, inklusive tekst på skærmen for nogle UI-komponenter. + +Dette kan hjælpe med at identificere komponenter, når der oprettes brugerdefinerede filtre. + +Aktivering af dette vil dog også logge nogle brugerdata, såsom din IP-adresse." Logstakspor Fejlfindingslogge inkluderer stakspor Fejlfindingslogge inkluderer ikke stakspor @@ -124,6 +131,15 @@ Tap på knappen Fortsæt, og tillad optimeringsændringer." "Hvis du deaktiverer fejl-toasts, skjules alle ReVanced-fejlmeddelelser. Du modtager ikke notifikationer om uventede hændelser." + Eksportér fejlsøgningslogfiler + Kopierer ReVanced-fejlsøgningslogfiler til udklipsholderen + Fejlsøgningslogning er deaktiveret + Ingen logfiler fundet + Logfiler kopieret + Kunne ikke eksportere logfiler: $s + Ryd fejlsøgningslogfiler + Rydder alle gemte ReVanced-fejlsøgningslogfiler + Logfiler ryddet Skjul albumkort @@ -153,6 +169,8 @@ Du modtager ikke notifikationer om uventede hændelser." Knappen er vist Skjul hylden \"Til dig\" + Hylde på kanalsiden er skjult + Hylde på kanalsiden vises Skjul knappen \'Underret mig\' @@ -180,6 +198,8 @@ Du modtager ikke notifikationer om uventede hændelser." Chips hylde er skjult Chips hylde er vist Skjul udvidelige kort under videoer + Udvidelseskort er skjult + Udvidelseskort vises Skjul fællesskabs indlæg Fællesskabs indlæg er skjult Fællesskabs indlæg er vist @@ -195,6 +215,7 @@ Du modtager ikke notifikationer om uventede hændelser." Skjul fællesskabs retningslinjer Fællesskabets retningslinjer er skjult Der er opstillet EF-retningslinjer + Skjul retningslinjer for abonnenter Abonnenter community retningslinjer er skjult Abonnenter community retningslinjer er vist Skjul kanalmedlems hylde @@ -239,10 +260,25 @@ Du modtager ikke notifikationer om uventede hændelser." Skjul Spørg Spørgsmål sektionen er skjult Spørgsmål sektionen vises + Skjul attributter + Fremhævede steder, spil, musik og sektioner med omtalte personer er skjult + Fremhævede steder, spil, musik og sektioner med omtalte personer vises + Skjul kapitler Kapitler sektion er skjult Kapitel afsnit er vist + Skjul \"Hvordan dette indhold blev lavet\" + Sektionen Sådan blev dette indhold lavet er skjult + Sektionen Sådan blev dette indhold lavet vises + Skjul \"Udforsk podcasten\" + Sektionen Udforsk podcasten er skjult + Sektionen Udforsk podcasten vises + Skjul infokort Info-kort sektion er skjult Info-kort sektion er vist + Skjul \"Nøglebegreber\" + Nøglebegrebssektionen er skjult + Nøglebegrebssektionen vises + Skjul udskrift Afsnittet er skjult Afsnittet er vist Video beskrivelse @@ -267,10 +303,17 @@ Du modtager ikke notifikationer om uventede hændelser." Kommentar-oversigt er skjult Kommentar-oversigt er vist Skjul \'Kommentarer fra medlemmer\' header + Kommentarer fra medlemmers overskrift er skjult + Kommentarer fra medlemmers overskrift vises Skjul kommentarsektion Kommentarer sektion er skjult Kommentarer sektion er vist Skjul knappen \"Opret en Short\" + Opret en Short knap er skjult + Opret en Short knap vises + Skjul emoji- og tidsstempelknapper + Emoji- og tidsstempelknapper er skjult + Emoji- og tidsstempelknapper vises Skjul forhåndsvisning kommentar Forhåndsvisning kommentar er skjult Forhåndsvis kommentar er vist @@ -338,9 +381,6 @@ Begrænsninger Denne funktion er kun tilgængelig for ældre enheder" Fuldskærms annoncer vises - Skjul knapfyldte annoncer - Knappede annoncer er skjult - Knappede annoncer vises Skjul betalt kampagneetiket Betalt reklamemærke er skjult Betalt salgsfremmende mærke er vist @@ -357,8 +397,12 @@ Denne funktion er kun tilgængelig for ældre enheder" Shopping hylde er skjult Shopping hylde er vist Skjul shopping links i video beskrivelse + Shopping links i videobeskrivelsen er skjult + Shopping links i videobeskrivelsen vises Skjul knappen \'Besøg butik\' på kanalsider + Knap på kanalsiden er skjult + Knap på kanalsiden vises Skjul søgeresultater Websøgeresultater er skjult Websøgeresultater vises @@ -398,6 +442,8 @@ Denne funktion er kun tilgængelig for ældre enheder" Eksterne downloads Indstillinger for brug af en ekstern downloader Vis ekstern download-knap + Download-knappen i afspilleren vises + Download-knappen i afspilleren vises ikke Overskriv knappen Download-handling Download-knappen åbner din eksterne downloader @@ -445,9 +491,10 @@ Juster lydstyrken ved at swipe lodret i højre side af skærmen" Baggrundsgennemsigtighed for swipe-overlay Gennemsigtighedsværdi mellem 0-100 Gennemsigtighed for swipe skal være mellem 0-100 - Farve på statuslinje for strygeoverlejring - Farven på statuslinjen for lydstyrke- og lysstyrkeknapper - Ugyldig farve til statuslinjen + Farve på lysstyrke for strygeoverlejring + Farven på statuslinjen for lysstyrkekontroller + Farve på lydstyrke for strygeoverlejring + Farven på statuslinjen for lydstyrkekontroller Tekststørrelse for strygeoverlejring Tekststørrelsen for strygeoverlejring mellem 1-30 Tekststørrelsen skal være mellem 1-30 @@ -475,6 +522,7 @@ Juster lydstyrken ved at swipe lodret i højre side af skærmen" Handlingsknapper Skjul eller vis knapper under videoer + Deaktiver Like og Abonner-knappen glød Lykke- og abonnér-knappen gløder ikke, når den nævnes Lykke- og abonnér-knappen gløder, når den nævnes Skjul Like og Dislike @@ -702,6 +750,9 @@ For at vise lydspormenuen skal du ændre \"Spoof videostream\" til iOS TV"Skjul placeringsetiket Placeringsetiket er skjult Placeringsetiket er vist + Skjul kommentarfeltet + Kommentarfeltet er skjult + Kommentarfeltet vises Skjul knappen Gem musik Gem musik knap er skjult Gem musik knap er vist @@ -809,6 +860,7 @@ Indstillinger → Afspilning → Afspil næste video automatisk" Dislikerer midlertidigt ikke tilgængelig (API-timeout ud) Dislikationer er ikke tilgængelige (status %d) + Synes ikke godt om er ikke tilgængelige (klient API-grænse) Dislikationer ikke tilgængelige (%s) Genindlæs video for at stemme ved hjælp af Return YouTube Dislike @@ -817,7 +869,13 @@ Indstillinger → Afspilning → Afspil næste video automatisk" Dislikationer vises Dislikationer vises ikke Vis ikke på Shorts + "Synes ikke godt om på Shorts vises + +Begrænsning: Synes ikke godt om vises muligvis ikke i inkognitotilstand" + Synes ikke godt om på Shorts vises ikke Synes ikke som procent + Synes ikke godt om vises som en procentdel + Synes ikke godt om vises som et tal Kompakt like-knap Lideknap stylet for mindste bredde @@ -878,15 +936,20 @@ Denne funktion fungerer bedst med en videokvalitet på 720p eller lavere og ved Knapper og kontrolelementer er firkantede Knapper og kontrolelementer er afrundede + Brug kompakt Spring over-knap Skip knap stylet for mindste bredde Skip knap stylet for bedste udseende + Skjul automatisk Spring over-knap Skip knap skjuler efter et par sekunder + Spring over-knappen vises for hele segmentet + Vis en toast ved spring Toast vises, når et segment automatisk springes over. Tryk her for at se et eksempel Toast er ikke vist. Tryk her for at se et eksempel Vis videolængde uden segmenter Videolængde minus alle segmenter, vist i parentes ved siden af den fulde videolængde Fuld videolængde vist Opretter nye segmenter + Vis Opret nyt segment-knap Opret ny segmentknap vises Opret ny segmentknap vises ikke Juster nyt segment trin @@ -980,6 +1043,7 @@ Dit bruger-id er som en adgangskode, og det må aldrig deles. Oversprunget over flere segmenter Spring automatisk over Spring automatisk over én gang + Vis en Spring over-knap Vis i søgelinjen Deaktivér Kan ikke indsende segment: %s @@ -1007,6 +1071,9 @@ Eksisterer allerede" Kategori er deaktiveret i indstillinger. Aktivér kategori for at indsende. Nyt SponsorBlock segment Sæt %s som start eller afslutning af et nyt segment? + Start + Slut + Nu Tidspunkt for segmentet begynder på Tidspunkt for segmentet slutter på Er tiderne korrekte? @@ -1027,6 +1094,7 @@ Er du klar til at indsende?" Ugyldig tid givet Statistik + Statistikker er midlertidigt ikke tilgængelige (API er nede) Indlæser... SponsorBloker er deaktiveret Dit brugernavn: <b>%s</b> @@ -1048,11 +1116,6 @@ Er du klar til at indsende?" %s sekunder Opacitet: Farve: - Farve ændret - Nulstil farve - Ugyldig farvekode - Nulstil farve - Nulstil Om Data leveres af SponsorBlock API. Tryk her for at få flere oplysninger og se downloads til andre platforme @@ -1084,6 +1147,7 @@ Hvis det senere slås fra, anbefales det at rydde app-dataene for at forhindre U This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch --> Spoof app version mål 19.35.36 - Gendan gamle Shorts player ikoner + 19.01.34 - Gendan gamle navigationsikoner Skift startside @@ -1241,9 +1305,13 @@ Tryk her for at lære mere om DeArrow" Midten af video Slut på video + DeArrow er midlertidigt ikke tilgængelig (statuskode: %s) + DeArrow er midlertidigt ikke tilgængelig Vis ReVanced meddelelser + Meddelelser ved opstart vises + Meddelelser ved opstart vises ikke Vis meddelelser ved opstart Kunne ikke forbinde til udbyder af annonceringer Luk @@ -1272,6 +1340,22 @@ Aktivering af dette kan låse op for højere videokvalitet" GmsCore Indstillinger Indstillinger for GmsCore + + Haptisk feedback + Skift haptisk feedback + Deaktivér haptics for kapitler + Haptics for kapitler er deaktiveret + Haptics for kapitler er aktiveret + Deaktivér præcis søge-haptics + Præcis søge-haptik er deaktiveret + Præcis søge-haptics er aktiveret + Deaktivér fortryd søge-haptik + Fortryd søge-haptik er deaktiveret + Fortryd søge-haptik er aktiveret + Deaktivér zoom haptics + Zoom haptics er deaktiveret + Zoom haptics er aktiveret + Hvis du for nylig har ændret dine kontooplysninger, skal du afinstallere og geninstallere MicroG. @@ -1290,11 +1374,6 @@ Aktivering af dette kan låse op for højere videokvalitet" Sporingsparameteren er fjernet fra links Sporingsforespørgselsparameteren er ikke fjernet fra links - - Deaktivér zoom haptics - Haptics er deaktiveret - Haptics er aktiveret - Tving originalt lydsprog Bruger originalt lydsprog @@ -1322,7 +1401,7 @@ Aktivering af dette kan låse op for højere videokvalitet" Vis hastigheds dialogknap - Knap vises + Knappen vises. Tryk og hold for at nulstille afspilningshastigheden til standard. Knap vises ikke @@ -1334,6 +1413,7 @@ Aktivering af dette kan låse op for højere videokvalitet" Brugerdefinerede hastigheder skal være mindre end %s Ugyldige brugerdefinerede afspilningshastigheder Automatisk + Afspilningshastighed nulstillet til: %s Brugerdefineret hastighed, når du holder den nede Afspilningshastighed mellem 0-8 diff --git a/patches/src/main/resources/addresources/values-de-rDE/strings.xml b/patches/src/main/resources/addresources/values-de-rDE/strings.xml index f79a40bdd..4d8b24f29 100644 --- a/patches/src/main/resources/addresources/values-de-rDE/strings.xml +++ b/patches/src/main/resources/addresources/values-de-rDE/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Einstellungen Möchtest du fortfahren? Zurücksetzen + Farbe zurücksetzen + Ungültige Farbe Aktualisieren und neu starten Neustart Importieren @@ -111,6 +113,11 @@ Tippen Sie auf die Schaltfläche \"Fortfahren\" und erlauben Sie die Optimierung Protokollpuffer protokollieren Debug-Protokolle enthalten Protokollpuffer Debug-Protokolle enthalten kein Protokollpuffer + "Wenn Sie diese Einstellung aktivieren, werden zusätzliche Layoutdaten protokolliert, einschließlich Text auf dem Bildschirm für einige UI-Komponenten. + +Dies kann helfen, Komponenten bei der Erstellung benutzerdefinierter Filter zu identifizieren. + +Wenn Sie dies aktivieren, werden jedoch auch einige Benutzerdaten wie Ihre IP-Adresse protokolliert." Stacktraces protokollieren Debug-Protokolle enthalten Stacktrace Debug-Logs enthalten keine Stack-Traces @@ -120,6 +127,15 @@ Tippen Sie auf die Schaltfläche \"Fortfahren\" und erlauben Sie die Optimierung "Das Ausschalten von Fehler-Toasts blendet alle Benachrichtigungen über Fehler in ReVanced aus. Sie werden nicht über unerwartete Ereignisse informiert." + Debug-Protokolle exportieren + Kopiert ReVanced-Debug-Protokolle in die Zwischenablage + Debug-Protokollierung ist deaktiviert + Keine Protokolle gefunden + Protokolle kopiert + Fehler beim Exportieren von Protokollen: $s + Debug-Protokolle löschen + Löscht alle gespeicherten ReVanced-Debug-Protokolle + Protokolle gelöscht Albumkarten ausblenden @@ -360,9 +376,6 @@ Einschränkungen Diese Funktion ist nur für ältere Geräte verfügbar" Vollbild-Anzeigen werden angezeigt - Verknüpfte Werbung ausblenden - Verknüpfte Anzeigen sind ausgeblendet - Verknüpfte Werbung wird angezeigt Bezahltes Werbe-Label ausblenden Bezahltes Werbelabel ist ausgeblendet Bezahltes Werbe-Label wird angezeigt @@ -471,9 +484,10 @@ Passen Sie die Helligkeit an, indem Sie auf der linken Seite des Bildschirms ver Bildschirmüberlagerung Deckkraft Swipe Deckkraftwert zwischen 0-100 Die Wischdeckkraft muss zwischen 0 und 100 liegen - Farbe des Fortschrittsbalkens für die Wischgesten-Überlagerung - Die Farbe des Fortschrittsbalkens für Lautstärke- und Helligkeitsregler - Ungültige Farbe für den Fortschrittsbalken + Farbe der Helligkeit des Wisch-Overlays + Die Farbe der Fortschrittsanzeige für Helligkeitsregler + Farbe der Lautstärke des Wisch-Overlays + Die Farbe der Fortschrittsanzeige für Lautstärkeregler Textgröße der Wischgesten-Überlagerung Die Textgröße für die Wischgesten-Überlagerung zwischen 1 und 30 Die Textgröße muss zwischen 1 und 30 liegen @@ -729,6 +743,9 @@ Um das Audiotrack-Menü anzuzeigen, ändere \"Video-Streams fälschen\" zu iOS T Standortbezeichnung ausblenden Ortsbezeichnung ist ausgeblendet Ortsbezeichnung wird angezeigt + Kommentarbereich ausblenden + Das Kommentarfeld ist ausgeblendet + Kommentarbereich wird angezeigt \'Musik speichern\'-Button ausblenden Musikspeicher Button ist ausgeblendet Musikspeicher Button wird angezeigt @@ -1092,11 +1109,6 @@ Bereit zum Einreichen?" %s Sekunden Deckkraft: Farbe: - Farbe geändert - Farbe zurücksetzen - Ungültiger Farbcode - Farbe zurücksetzen - Zurücksetzen Über Daten werden von der SponsorBlock API bereitgestellt. Tippe hier, um mehr zu erfahren und Downloads für andere Plattformen zu sehen @@ -1321,6 +1333,22 @@ Durch Aktivieren dieser Option können höhere Videoqualitäten freigeschaltet w GmsCore Einstellungen Einstellungen für GmsCore + + Haptisches Feedback + Haptisches Feedback ändern + Kapitelhaptik deaktivieren + Kapitelhaptik ist deaktiviert + Kapitelhaptik ist aktiviert + Präzise Suchhaptik deaktivieren + Die präzise Suchhaptik ist deaktiviert + Präzise Suchhaptik ist aktiviert + Haptik für das Rückgängigmachen der Suche deaktivieren + Die Haptik für das Rückgängigmachen der Suche ist deaktiviert + Die Haptik für das Rückgängigmachen der Suche ist aktiviert + Zoomhaptik deaktivieren + Zoomhaptik ist deaktiviert + Zoomhaptik ist aktiviert + Wenn Sie kürzlich Ihre Kontoanmeldedaten geändert haben, deinstallieren Sie MicroG und installieren Sie es erneut. @@ -1339,11 +1367,6 @@ Durch Aktivieren dieser Option können höhere Videoqualitäten freigeschaltet w Tracking-Abfrageparameter wird von Links entfernt Tracking-Abfrageparameter wird nicht von Links entfernt - - Zoomhaptik deaktivieren - Haptik ist deaktiviert - Haptik ist aktiviert - Original Audio erzwingen Original-Audiosprache verwenden @@ -1371,7 +1394,7 @@ Durch Aktivieren dieser Option können höhere Videoqualitäten freigeschaltet w Zeige Geschwindigkeitsdialog Taste - Button wird angezeigt + Die Schaltfläche wird angezeigt. Tippen und halten, um die Wiedergabegeschwindigkeit auf die Standardeinstellung zurückzusetzen. Button wird nicht angezeigt @@ -1383,6 +1406,7 @@ Durch Aktivieren dieser Option können höhere Videoqualitäten freigeschaltet w Benutzerdefinierte Geschwindigkeiten müssen kleiner als %s sein Ungültige benutzerdefinierte Wiedergabegeschwindigkeiten Autom + Wiedergabegeschwindigkeit zurückgesetzt auf: %s Benutzerdefinierte Geschwindigkeit bei Tippen und Halten Abspielgeschwindigkeit zwischen 0-8x diff --git a/patches/src/main/resources/addresources/values-el-rGR/strings.xml b/patches/src/main/resources/addresources/values-el-rGR/strings.xml index 7a6374031..5f0d4e4da 100644 --- a/patches/src/main/resources/addresources/values-el-rGR/strings.xml +++ b/patches/src/main/resources/addresources/values-el-rGR/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Ρυθμίσεις Θέλετε να συνεχίσετε; Επαναφορά + Επαναφορά χρώματος + Μη έγκυρο χρώμα Ανανέωση και επανεκκίνηση Επανεκκίνηση Εισαγωγή @@ -115,6 +117,11 @@ Second \"item\" text" Καταγραφή του buffer πρωτοκόλλου Τα αρχεία καταγραφής σφαλμάτων περιλαμβάνουν το buffer του πρωτοκόλλου Τα αρχεία καταγραφής σφαλμάτων δεν περιλαμβάνουν τον buffer πρωτοκόλλου + "Η ενεργοποίηση αυτής της ρύθμισης θα καταγράψει επιπλέον δεδομένα διάταξης, συμπεριλαμβανομένου του κειμένου στην οθόνη για ορισμένα στοιχεία διεπαφής χρήστη. + +Αυτό μπορεί να βοηθήσει στον εντοπισμό στοιχείων κατά τη δημιουργία προσαρμοσμένων φίλτρων. + +Ωστόσο, η ενεργοποίηση αυτής της ρύθμισης θα καταγράψει επίσης ορισμένα δεδομένα χρήστη, όπως τη διεύθυνση IP σας." Καταγραφή ιχνών στοίβας Τα αρχεία καταγραφής σφαλμάτων περιλαμβάνουν ίχνη στοίβας Τα αρχεία καταγραφής σφαλμάτων δεν περιλαμβάνουν ίχνη στοίβας @@ -124,6 +131,15 @@ Second \"item\" text" "Η απενεργοποίηση των μηνυμάτων σφαλμάτων κρύβει όλες τις ειδοποιήσεις σφαλμάτων που αφορούν το ReVanced. Δεν θα ειδοποιηθείτε για τυχόν απρόβλεπτα γεγονότα." + Εξαγωγή αρχείων καταγραφής εντοπισμού σφαλμάτων + Αντιγραφή των αρχείων καταγραφής εντοπισμού σφαλμάτων ReVanced στο πρόχειρο + Η καταγραφή εντοπισμού σφαλμάτων είναι απενεργοποιημένη + Δεν βρέθηκαν αρχεία καταγραφής + Τα αρχεία καταγραφής αντιγράφηκαν + Αποτυχία εξαγωγής αρχείων καταγραφής: $s + Εκκαθάριση αρχείων καταγραφής εντοπισμού σφαλμάτων + Εκκαθάριση όλων των αποθηκευμένων αρχειών καταγραφής εντοπισμού σφαλμάτων ReVanced + Τα αρχεία καταγραφής εκκαθαρίστηκαν Κάρτες άλμπουμ @@ -367,9 +383,6 @@ Second \"item\" text" Αυτή η λειτουργία είναι διαθέσιμη μόνο για παλιότερες συσκευές" Οι διαφημίσεις πλήρους οθόνης εμφανίζονται - Διαφημίσεις κουμπιών - Κρυμμένες - Εμφανίζονται Ετικέτες προώθησης επί πληρωμή Κρυμμένες Εμφανίζονται @@ -480,9 +493,10 @@ Second \"item\" text" Αδιαφάνεια φόντου σάρωσης Τιμή αδιαφάνειας μεταξύ 0-100 Η αδιαφάνεια σάρωσης πρέπει να είναι μεταξύ 0-100 - Χρώμα γραμμής προόδου σάρωσης - Το χρώμα της γραμμής προόδου για τα στοιχεία ελέγχου έντασης ήχου και φωτεινότητας - Μη έγκυρο χρώμα γραμμής προόδου + Χρώμα φωτεινότητας σάρωσης + Το χρώμα της γραμμής προόδου για τα στοιχεία ελέγχου φωτεινότητας + Χρώμα έντασης ήχου σάρωσης + Το χρώμα της γραμμής προόδου για τα στοιχεία ελέγχου έντασης ήχου Μέγεθος κειμένου σάρωσης Το μέγεθος κειμένου για τα στοιχεία ελέγχου σάρωσης μεταξύ 1-30 Το μέγεθος κειμένου πρέπει να είναι μεταξύ 1-30 @@ -738,6 +752,9 @@ Second \"item\" text" Ετικέτα τοποθεσίας Κρυμμένη Εμφανίζεται + Απόκρυψη πίνακα σχολίων + Η καρτέλα σχολίων είναι κρυμμένη + Εμφανίζεται ο πίνακας σχολίων Κουμπί «Αποθήκευση μουσικής» Κρυμμένο Εμφανίζεται @@ -1100,11 +1117,6 @@ Second \"item\" text" %s δευτερόλεπτα Αδιαφάνεια: Χρώμα: - Το χρώμα άλλαξε - Το χρώμα επαναφέρθηκε - Μη έγκυρος κωδικός χρώματος - Επαναφορά χρώματος - Επαναφορά Σχετικά με Τα δεδομένα παρέχονται από το SponsorBlock API. Πατήστε για να μάθετε περισσότερα και να δείτε λήψεις για άλλες πλατφόρμες @@ -1327,6 +1339,22 @@ Second \"item\" text" Ρυθμίσεις GmsCore Ρυθμίσεις για το MicroG GmsCore + + Απόκριση δόνησης + Αλλαγή απόκρισης δόνησης + Απενεργοποίηση απόκρισης δόνησης κατά την αλλαγή κεφαλαίων + Η απόκριση δόνησης κατά την αλλαγή κεφαλαίων είναι απενεργοποιημένη + Η απόκριση δόνησης κατά την αλλαγή κεφαλαίων είναι ενεργοποιημένη + Απενεργοποίηση απόκρισης δόνησης κατά τη λειτουργία ακριβής αναζήτησης + Η απόκριση δόνησης κατά τη λειτουργία ακριβής αναζήτησης είναι απενεργοποιημένη + Η απόκριση δόνησης κατά τη λειτουργία ακριβής αναζήτησης είναι ενεργοποιημένη + Απενεργοποίηση απόκρισης δόνησης κατά τη λειτουργία «Αφήστε για ακύρωση» + Η απόκριση δόνησης κατά τη λειτουργία «Αφήστε για ακύρωση» είναι απενεργοποιημένη + Η απόκριση δόνησης κατά τη λειτουργία «Αφήστε για ακύρωση» είναι ενεργοποιημένη + Απενεργοποίηση απόκρισης δόνησης χειρονομίας ζουμ + Η απόκριση δόνησης της χειρονομίας ζουμ είναι απενεργοποιημένη + Η απόκριση δόνησης της χειρονομίας ζουμ είναι ενεργοποιημένη + Εάν αλλάξατε πρόσφατα τα στοιχεία σύνδεσης του λογαριασμού σας, απεγκαταστήστε και εγκαταστήστε ξανά το MicroG. @@ -1345,11 +1373,6 @@ Second \"item\" text" Η παράμετρος παρακολούθησης αφαιρείται από τους συνδέσμους στην κοινοποίηση Η παράμετρος παρακολούθησης δεν αφαιρείται από τους συνδέσμους στην κοινοποίηση - - Απενεργοποίηση απόκρισης δόνησης χειρονομίας ζουμ - Η απόκριση δόνησης είναι απενεργοποιημένη - Η απόκριση δόνησης είναι ενεργοποιημένη - Εξαναγκασμός αρχικής γλώσσας ήχου Χρησιμοποιείται η αρχική γλώσσα ήχου @@ -1377,7 +1400,7 @@ Second \"item\" text" Εμφάνιση κουμπιού αλλαγής ταχύτητας - Το κουμπί εμφανίζεται + Το κουμπί εμφανίζεται. Πατήστε παρατεταμένα για επαναφορά της ταχύτητας αναπαραγωγής στην προεπιλογή Το κουμπί δεν εμφανίζεται @@ -1389,6 +1412,7 @@ Second \"item\" text" Οι ταχύτητες πρέπει να είναι μικρότερες από %sx Μη έγκυρες προσαρμοσμένες ταχύτητες αναπαραγωγής Αυτόματη + Η ταχύτητα αναπαραγωγής επαναφέρθηκε σε: %s Προσαρμοσμένη ταχύτητα παρατεταμένου πατήματος Ταχύτητα αναπαραγωγής μεταξύ 0-8 diff --git a/patches/src/main/resources/addresources/values-es-rES/strings.xml b/patches/src/main/resources/addresources/values-es-rES/strings.xml index e03c5daee..c6f92c14a 100644 --- a/patches/src/main/resources/addresources/values-es-rES/strings.xml +++ b/patches/src/main/resources/addresources/values-es-rES/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Ajustes ¿Desea continuar? Restablecer + Restablecer color + Color no válido Actualizar y reiniciar Reiniciar Importar @@ -114,6 +116,11 @@ Desactivar las optimizaciones de batería para MicroG no afectará negativamente Búfer de protocolo de registro Los registros de depuración incluyen el búfer proto Los registros de depuración no incluyen el búfer proto + "Si activas este ajuste, se registrarán datos de diseño adicionales, incluido el texto en pantalla de algunos componentes de la IU. + +Esto puede ayudar a identificar componentes al crear filtros personalizados. + +Sin embargo, si activas esto, también se registrarán algunos datos del usuario, como tu dirección IP." Registrar stack traces Los registros de depuración incluyen stack trace Los registros de depuración no incluyen stack trace @@ -121,6 +128,15 @@ Desactivar las optimizaciones de batería para MicroG no afectará negativamente Se muestra un toast si se produce un error No se muestra un toast si se produce un error "Desactivar las notificaciones de error oculta todas las notificaciones de error de ReVanced." + Exportar registros de depuración + Copia los registros de depuración de ReVanced al portapapeles + El registro de depuración está desactivado + No se encontraron registros + Registros copiados + Error al exportar los registros: $s + Borrar registros de depuración + Borra todos los registros de depuración de ReVanced almacenados + Registros borrados Ocultar álbumes @@ -362,9 +378,6 @@ Limitaciones Esta función solo está disponible para dispositivos antiguos" Se muestran anuncios a pantalla completa - Ocultar anuncios botonados - Los anuncios botonados están ocultos - Se muestran anuncios botonados Ocultar etiqueta de promoción de pago Etiqueta de promoción pagada está oculta Etiqueta de promoción pagada se muestra @@ -475,9 +488,10 @@ Ajusta el volumen deslizando verticalmente en el lado derecho de la pantalla"Opacidad del fondo de la superposición de deslizamiento Valor de opacidad entre 0-100 La opacidad de la superposición de deslizamiento debe estar entre 0 y 100 - Color de la barra de progreso de la superposición de deslizamiento - El color de la barra de progreso para los controles de volumen y brillo - Color de barra de progreso no válido + Color del brillo de la superposición de deslizamiento + El color de la barra de progreso para los controles de brillo + Color del volumen de la superposición de deslizamiento + El color de la barra de progreso para los controles de volumen Tamaño del texto de la superposición de deslizamiento El tamaño del texto para la superposición de deslizamiento entre 1 y 30 El tamaño del texto debe estar entre 1 y 30 @@ -733,6 +747,9 @@ Para mostrar el menú de la pista de audio, cambia \"Suplantar transmisiones de Ocultar etiqueta de ubicación Etiqueta de ubicación oculta Etiqueta de ubicación mostrada + Ocultar el panel de comentarios + El panel de comentarios est oculto + Se muestra el panel de comentarios Ocultar el botón Guardar música El botón Guardar música está oculto Mostrar el botón de guardar música @@ -1087,11 +1104,6 @@ Ya existe" %s segundos Opacidad: Color: - Color cambiado - Restablecer color - Código de color inválido - Reiniciar color - Restablecer Acerca de Los datos son proporcionados por la API de SponsorBlock. Pulsa aquí para aprender más y ver las descargas para otras plataformas @@ -1316,6 +1328,22 @@ Habilitar esto puede desbloquear calidades de vídeo más altas" Ajustes de GmsCore Configuración de GmsCore + + Vibración háptica + Cambiar la vibración háptica + Desactivar la respuesta háptica de los capítulos + La respuesta háptica de los capítulos está desactivada + La respuesta háptica de los capítulos está activada + Desactivar la respuesta háptica de la búsqueda precisa + La respuesta háptica de búsqueda precisa está desactivada + La respuesta háptica de la búsqueda precisa está activada + Desactivar la respuesta háptica de deshacer la búsqueda + La respuesta háptica de deshacer la búsqueda está desactivada + La respuesta háptica de deshacer la búsqueda está activada + Desactivar la respuesta háptica del zoom + La respuesta háptica del zoom está desactivada + La respuesta háptica del zoom está activada + Si has cambiado recientemente los datos de inicio de sesión de tu cuenta, desinstala y vuelve a instalar MicroG. @@ -1334,11 +1362,6 @@ Habilitar esto puede desbloquear calidades de vídeo más altas" Parámetro de la consulta de seguimiento se elimina de los enlaces Parámetro de la consulta de seguimiento no se elimina de los enlaces - - Desactivar hápticas al hacer zoom - Hápticas desactivadas - Haptics están habilitados - Forzar idioma de audio original Usar el idioma de audio original @@ -1366,7 +1389,7 @@ Habilitar esto puede desbloquear calidades de vídeo más altas" Mostrar botón de diálogo de velocidad - Se muestra el botón + Se muestra el botón. Mantén pulsado para restablecer la velocidad de reproducción predeterminada El botón no se muestra @@ -1378,6 +1401,7 @@ Habilitar esto puede desbloquear calidades de vídeo más altas" Las velocidades personalizadas deben ser menores que %s Velocidades de reproducción personalizadas no válidas Automático + Velocidad de reproducción restablecida a: %s Velocidad personalizada al tocar y mantener Velocidad de reproducción entre 0-8 diff --git a/patches/src/main/resources/addresources/values-et-rEE/strings.xml b/patches/src/main/resources/addresources/values-et-rEE/strings.xml index 3763d8631..8c3725262 100644 --- a/patches/src/main/resources/addresources/values-et-rEE/strings.xml +++ b/patches/src/main/resources/addresources/values-et-rEE/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Seaded Kas soovite jätkata? Lähtesta + Lähtesta värv + Vigane värv Värskenda ja taaskäivita Taaskäivita Impordi @@ -115,6 +117,11 @@ Vajutage jätkamise nuppu ja lubage optimeerimismuutused." Logi protokolipuffari Vea logid sisaldavad protokolipuffari Vea logid ei sisalda protokolipuffari + "Selle sätte lubamine logib täiendavaid paigutuse andmeid, sealhulgas mõne kasutajaliidese komponendi ekraanil kuvatavat teksti. + +See võib aidata komponente tuvastada kohandatud filtrite loomisel. + +Selle lubamine logib aga ka mõningaid kasutajaandmeid, näiteks teie IP-aadressi." Logi stekira jäljed Silumispäevikud sisaldavad virna jäljendamise Silumispäevikud ei sisalda virna jäljendamise @@ -124,6 +131,15 @@ Vajutage jätkamise nuppu ja lubage optimeerimismuutused." "Vea teadete väljalülitamine peidab kõik ReVanced i veateadete märguanded. Teid ei teavitata ühestki ootamatust sündmusest." + Ekspordi silumislogid + Kopeerib ReVanced silumislogid lõikelauale + Silumislogimine on keelatud + Logisid ei leitud + Logid kopeeritud + Logide eksportimine ebaõnnestus: $s + Puhasta silumislogid + Puhastab kõik salvestatud ReVanced silumislogid + Logid puhastatud Peida albumikaardid @@ -365,9 +381,6 @@ Piirangud See funktsioon on saadaval ainult vanemates seadmetes" Täisekraanireklaamid kuvatakse - Peida nuppudega reklaamid - Nuppudega reklaamid on peidetud - Nuked onukleitud reklaamid näidatakse Peida makstud edendamise silt Makstud edendamise silt on peidus Makstud edendamise silt on näidatud @@ -478,9 +491,10 @@ Helitugevuse reguleerimiseks pühkige ekraani paremal küljel vertikaalselt"Pühkiva katte tausta läbipaistvus Läbipaistvuse väärtus vahemikus 0-100 Pühkiva katte läbipaistvus peab olema vahemikus 0-100 - Liigutamise ülekatte edenemisriba värv - Helitugevuse ja heleduse juhtnuppude edenemisriba värv - Vigane edenemisriba värv + Pühkige ekraani heleduse värvi + Heleduse juhtnuppude edenemisriba värv + Pühkige ekraani helitugevuse värvi + Helitugevuse juhtnuppude edenemisriba värv Liigutamise ülekatte teksti suurus Liigutamise ülekatte teksti suurus vahemikus 1–30 Teksti suurus peab olema vahemikus 1–30 @@ -736,6 +750,9 @@ Heliriba menüü kuvamiseks muutke valikut „Võltsitud videovoogedastus“ vä Peida asukoha silt Asukoha silt on peidetud Asukoha silt on nähtav + Peida kommentaaripaneel + Kommentaaripaneel on peidetud + Kommentaaripaneel on nähtaval Peida Salvesta muusika nupp Muusika salvestamise nupp on peidetud Muusika salvestamise nupp on nähtav @@ -1099,11 +1116,6 @@ Kas olete esitamiseks valmis?" %s sekundit Läbipaistmatus: Värv: - Värv muudetud - Värv lähtestatud - Vigane värvikood - Lähtesta värv - Lähtesta Teave Andmed on pärit SponsorBlock API-st. Puudutage siia, et saada lisateavet ja vaadata allalaadimisi teistele platvormidele @@ -1328,6 +1340,22 @@ Selle lubamine võib avada kõrgema video kvaliteedi" GmsCore seaded GmsCore seaded + + Haptiline tagasiside + Muuda haptilist tagasisidet + Keela peatükkide hääled + Peatükkide hääled on keelatud + Peatükkide hääled on lubatud + Keela täpse otsingu hääled + Täpse otsimise haptika on keelatud + Täpse otsingu hääled on lubatud + Keela otsimise tagasivõtmise haptika + Otsimise tagasivõtmise haptika on keelatud + Otsimise tagasivõtmise haptika on lubatud + Keela suumimise hääled + Suumi haptika on keelatud + Suumi haptika on lubatud + Kui sa hiljuti muutsid oma konto sisselogimisandmeid, siis eemalda ja installeeri MicroG uuesti. @@ -1346,11 +1374,6 @@ Selle lubamine võib avada kõrgema video kvaliteedi" Jälgimise päringuparameeter eemaldatakse linkidest Jälgimise päringuparameeter ei eemaldata linkidest - - Keela suumimise hääled - Hääled on keelatud - Hääled on lubatud - Sunni originaalheli keel Algse helikeele kasutamine @@ -1378,7 +1401,7 @@ Selle lubamine võib avada kõrgema video kvaliteedi" Kuva kiiruse dialoogi nupp - Nupp kuvatakse + Nupp on nähtaval. Puudutage ja hoidke all, et taastada taasesituse kiirus vaikeväärtusele Nuppi ei kuvata @@ -1390,6 +1413,7 @@ Selle lubamine võib avada kõrgema video kvaliteedi" Kohandatud kiirused peavad olema alla %s Kehtetud kohandatud video taasesituse kiirused Automaatne + Taasesituse kiirus on lähtestatud: %s Kohandatud puuduta ja hoia kiiruse tase Taasesituse kiirus vahemikus 0-8 diff --git a/patches/src/main/resources/addresources/values-eu-rES/strings.xml b/patches/src/main/resources/addresources/values-eu-rES/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-eu-rES/strings.xml +++ b/patches/src/main/resources/addresources/values-eu-rES/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-fa-rIR/strings.xml b/patches/src/main/resources/addresources/values-fa-rIR/strings.xml index d4c4d8952..92217d21d 100644 --- a/patches/src/main/resources/addresources/values-fa-rIR/strings.xml +++ b/patches/src/main/resources/addresources/values-fa-rIR/strings.xml @@ -42,21 +42,48 @@ Second \"item\" text" بازگرداندن تنظیمات ReVanced به پیش‌فرض %d تنظیمات وارد شدند واردکردن انجام نشد: %s + تنظیمات جستجو + نتایجی برای %s یافت نشد + کلیدواژه دیگری را امتحان کنید + حذف از تاریخچه جستجو؟ + نمایش آیکون تنظیمات ReVanced + نمادهای تنظیمات نشان داده می‌شوند + نمادهای تنظیمات نمایش داده نمی شوند زبان ReVanced + زبان برنامه + وارد کردن/صادر کردن + وارد کردن / صادر کردن تنظیمات ReVanced + شما درحال استفاده از نسخه <i>%s</i> از پچ Revanced هستید + توجه + لینک‌های رسمی + MicroG GmsCore نصب نشده است. آنرا نصب کنید. + اقدام لازم است + باز کردن تارنما + ادامه + درباره + عمومی + اجراکننده + نوار جریان پخش + ويدئو + عیب‌یابی + فعال یا غیرفعال کردن گزینه‌های عیب یابی + گزارش عیب + لاگ عیب فعال است + لاگ عیب غیرفعال است + پنهان سازی دکمه \'نمایش بیشتر\' + دکمه پنهان است + دکمه نمایان است + پنهان سازی قفسه بلیط diff --git a/patches/src/main/resources/addresources/values-fi-rFI/strings.xml b/patches/src/main/resources/addresources/values-fi-rFI/strings.xml index 7757d978a..0f6b96e53 100644 --- a/patches/src/main/resources/addresources/values-fi-rFI/strings.xml +++ b/patches/src/main/resources/addresources/values-fi-rFI/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Asetukset Haluatko jatkaa? Nollaa + Nollaa väri + Virheellinen väri Päivitä ja käynnistä uudelleen Käynnistä uudelleen Tuo @@ -90,7 +92,7 @@ Napauta jatka-painiketta ja salli optimoinnin muutokset." Syöte Yleiset Soitin - Liukusäädin + Etenemispalkki Pyyhkäisyohjaus Sekalaiset Video @@ -115,6 +117,11 @@ Napauta jatka-painiketta ja salli optimoinnin muutokset." Loki protokollan puskuri Virheenkorjauslokit sisältävät proto-puskurin Virheenkorjauslokit eivät sisällä proto-puskuria + "Tämän asetuksen käyttöönotto kirjaa lisätietoja asettelusta, mm. joidenkin käyttöliittymäkomponenttien näyttötekstiä. + +Tämä voi auttaa komponenttien tunnistamisessa, kun luot mukautettuja suodattimia. + +Tämän käyttöönotto kirjaa myös joitakin käyttäjätietoja, kuten IP-osoitteesi." Loki pinojäljet Vianetsintälokit sisältävät pinojäljet Vianetsintälokit eivät sisällä pinojälkiä @@ -124,6 +131,15 @@ Napauta jatka-painiketta ja salli optimoinnin muutokset." "Virheilmoitusten poistaminen käytöstä piilottaa kaikki ReVancedin virheilmoitukset. Et saa ilmoituksia odottamattomista tapahtumista." + Vie virheenkorjauslokit + Kopioi ReVancedin virheenkorjauslokit leikepöydälle + Virheenkorjausloki ei ole käytössä + Lokeja ei löytynyt + Lokit kopioitu + Lokien vienti epäonnistui: $s + Tyhjennä virheenkorjauslokit + Tyhjentää kaikki tallennetut ReVanced-virheenkorjauslokit + Lokit tyhjennetty Piilota albumikortit @@ -162,6 +178,8 @@ Et saa ilmoituksia odottamattomista tapahtumista." Painike näytetään Piilota videosuositusten otsikot + \"Ihmiset katsoivat myös\"- ja \"Saatat pitää myös\" -tunnisteet on piilotettu + \"Ihmiset katsoivat myös\"- ja \"Saatat pitää myös\" -tunnisteet näytetään Piilota \"Näytä lisää\" -painike @@ -239,6 +257,9 @@ Et saa ilmoituksia odottamattomista tapahtumista." Piilota \"tekoälyn luoma videoyhteenveto\" Videon yhteenveto-osio on piilotettu Videon yhteenveto-osio näytetään + Piilota Ask + Ask-osio on piilotettu + Ask-osio näytetään Piilota Määritteet Esitellyt paikat, Pelit, Musiikki ja Mainitut ihmiset -osiot on piilotettu Esitellyt paikat, Pelit, Musiikki ja Mainitut ihmiset -osiot näytetään @@ -360,9 +381,6 @@ Rajoitukset Tämä ominaisuus on käytettävissä vain vanhemmilla laitteilla" Koko näytön mainokset näytetään - Piilota painikkeelliset mainokset - Painikkeelliset mainokset on piilotettu - Painikkeelliset mainokset näytetään Piilota maksetun mainostuksen tunniste Maksetun mainostuksen tunniste on piilotettu Maksetun mainostuksen tunniste näytetään @@ -435,26 +453,26 @@ Tämä ominaisuus on käytettävissä vain vanhemmilla laitteilla" %s ei ole asennettu. Asenna se. - Poista tarkka hakuele käytöstä + Poista tarkka etsintäele käytöstä Ele ei ole käytössä Ele on käytössä - Ota kelaus napauttamalla käyttöön - Kelaus napauttamalla on käytössä - Kelaus napauttamalla ei ole käytössä + Ota etsintä napauttamalla käyttöön + Etsintä napauttamalla on käytössä + Etsintä napauttamalla ei ole käytössä Ota kirkkauden ele käyttöön - "Koko näytön kirkkauden pyyhkäisy on käytössä + "Koko näytön kirkkauspyyhkäisy on käytössä Säädä kirkkautta pyyhkäisemällä pystysuoraan näytön vasemmalla puolella" - Koko näytön kirkkauden pyyhkäisy ei ole käytössä + Koko näytön kirkkauspyyhkäisy ei ole käytössä Ota äänenvoimakkuuden ele käyttöön - "Koko näytön äänenvoimakkuuden pyyhkäisy on käytössä + "Koko näytön äänenvoimakkuuspyyhkäisy on käytössä Säädä äänenvoimakkuutta pyyhkäisemällä pystysuoraan näytön oikealta puolella" - Koko näytön äänenvoimakkuuden pyyhkäisy ei ole käytössä + Koko näytön äänenvoimakkuuspyyhkäisy ei ole käytössä Ota pyyhkäise painamalla -ele käyttöön Pyyhkäise painamalla -ele on käytössä Pyyhkäise painamalla -ele ei ole käytössä @@ -468,22 +486,23 @@ Säädä äänenvoimakkuutta pyyhkäisemällä pystysuoraan näytön oikealta pu Automaattinen kirkkaus otetaan käyttöön pyyhkäisemällä alhaisimpaan arvoon Pienimpään arvoon alas pyyhkäiseminen ei ota käyttöön automaattista kirkkautta Automaattinen - Pyyhkäisypeittokuvan aikakatkaisu + Pyyhkäisyn peittokuvan aikakatkaisu Kuinka monta millisekuntia ikkuna on näkyvissä - Pyyhkäisypeittokuvan taustan läpinäkymättömyys + Pyyhkäisyn peittokuvan taustan läpinäkymättömyys Läpinäkymättömyysarvo 0–100 välillä - Pyyhkäisypeittokuvan läpinäkymättömyyden tulee olla 0–100 välillä - Pyyhkäisypeittokuvan edistymispalkin väri - Äänenvoimakkuuden ja kirkkauden säätimien edistymispalkin väri - Virheellinen edistymispalkin väri - Pyyhkäisypeittokuvan tekstin koko - Pyyhkäisypeittokuvan tekstin koko 1–30 välillä + Pyyhkäisyn peittokuvan läpinäkymättömyyden tulee olla 0–100 välillä + Kirkkauspyyhkäisyn peittokuvan väri + Kirkkauden liukusäätimien väri + Äänenvoimakkuuspyyhkäisyn peittokuvan väri + Äänenvoimakkuuden liukusäätimien väri + Pyyhkäisyn peittokuvan tekstin koko + Pyyhkäisyn peittokuvan tekstin koko 1–30 välillä Tekstin koon tulee olla 1–30 välillä Pyyhkäisyn kynnysraja Pyyhkäisyä varten tarvittavan kynnyksen määrä - Äänenvoimakkuuden pyyhkäisyn herkkyys + Äänenvoimakkuuspyyhkäisyn herkkyys Kuinka paljon äänenvoimakkuus muuttuu pyyhkäisyä kohden - Pyyhkäisypeittokuvan tyyli + Pyyhkäisyn peittokuvan tyyli Vaakasuuntainen peittokuva Vaakasuuntainen peittokuva (minimaalinen – ylhäällä) Vaakasuuntainen peittokuva (minimaalinen – keskellä) @@ -532,6 +551,9 @@ Säädä äänenvoimakkuutta pyyhkäisemällä pystysuoraan näytön oikealta pu Kiitos-painike näytetään + Piilota Ask + Ask-painike on piilotettu + Ask-painike näytetään Piilota Klippi Klippi-painike on piilotettu @@ -681,12 +703,12 @@ Jos haluat nähdä sen, aseta \"Naamioi videovirrat\" iOS TV:ksi" Vierivät numerot animoidaan - Piilota liukusäädin videosoittimessa - Videosoittimen liukusäädin on piilotettu - Videosoittimen liukusäädin näytetään - Piilota liukusäädin videon pikkukuvissa - Pikkukuvan liukusäädin on piilotettu - Pikkukuvan liukusäädin näytetään + Piilota etenemispalkki videosoittimessa + Videosoittimen etenemispalkki on piilotettu + Videosoittimen etenemispalkki näytetään + Piilota etenemispalkki videon pikkukuvissa + Pikkukuvan etenemispalkki on piilotettu + Pikkukuvan etenemispalkki näytetään Shorts-soitin @@ -887,18 +909,18 @@ Rajoitus: Ei-tykkäykset eivät välttämättä näy incognito-tilassa" Ota korkealaatuiset pikkukuvat käyttöön - Liukusäätimen pikkukuvat ovat korkealaatuisia - Liukusäätimen pikkukuvat ovat keskilaatuisia - Koko näytön liukusäätimen pikkukuvat ovat korkealaatuisia - Koko näytön liukusäätimen pikkukuvat ovat keskilaatuisia - "Tämä palauttaa myös pienoiskuvat livestriimeissä, joilla ei ole liukusäätimen pikkukuvia. + Etenemispalkin pikkukuvat ovat korkealaatuisia + Etenemispalkin pikkukuvat ovat keskilaatuisia + Koko näytön etenemispalkin pikkukuvat ovat korkealaatuisia + Koko näytön etenemispalkin pikkukuvat ovat keskilaatuisia + "Tämä palauttaa myös pienoiskuvat livestriimeissä, joilla ei ole etenemispalkin pikkukuvia. -Liukusäätimen pikkukuvat käyttävät samaa laatua kuin nykyinen video. +Etenemispalkin pikkukuvat käyttävät samaa laatua kuin nykyinen video. Tämä ominaisuus toimii parhaiten, kun videon laatu on 720p tai alhaisempi ja kun käytössä on erittäin nopea Internet-yhteys." - Palauta vanhat liukusäätimen pikkukuvat - Liukusäätimen pikkukuvat näkyvät liukusäätimen yläpuolella - Liukusäätimen pikkukuvat näkyvät kokoruututilassa + Palauta vanhat etenemispalkin pikkukuvat + Etenemispalkin pikkukuvat näkyvät etenemispalkin yläpuolella + Etenemispalkin pikkukuvat näkyvät kokoruututilassa Ota SponsorBlock käyttöön @@ -1019,7 +1041,7 @@ UserID on kuin salasana, eikä sitä pidä jakaa kenellekään. Ohita automaattisesti Ohita automaattisesti kerran Näytä Ohita-painike - Näytä liukusäätimessä + Näytä etenemispalkissa Poista käytöstä Osiota ei voitu lähettää: %s SponsorBlock on tilapäisesti poissa käytöstä @@ -1091,11 +1113,6 @@ Oletko valmis lähettämään?" %s sekuntia Läpikuultamattomuus: Väri: - Väri vaihdettu - Väri nollattu - Virheellinen värikoodi - Nollaa väri - Nollaa Tietoja Tiedot tarjoaa SponsorBlock API. Napauta tätä saadaksesi lisätietoja ja nähdäksesi lataukset muille alustoille @@ -1236,14 +1253,14 @@ Pyyhkäise laajentaaksesi tai sulkeaksesi" Ota liukuvärillinen latausruutu käyttöön Latausruudulla on liukuvärillinen tausta Latausruudulla on yksivärinen tausta - Ota oma liukusäätimen väri käyttöön - Oma liukusäätimen väri näytetään - Alkuperäinen liukusäätimen väri näytetään - Oma liukusäätimen väri - Liukusäätimen väri - Oma liukusäätimen korostusväri - Liukusäätimen korostusväri - Virheellinen liukusäätimen väriarvo + Ota oma etenemispalkin väri käyttöön + Oma etenemispalkin väri näytetään + Alkuperäinen etenemispalkin väri näytetään + Oma etenemispalkin väri + Etenemispalkin väri + Oma etenemispalkin korostusväri + Etenemispalkin korostusväri + Virheellinen etenemispalkin väriarvo Ohita kuvien alueelliset rajoitukset @@ -1320,6 +1337,22 @@ Tämä voi avata korkealaatuisemmat videot" GmsCore-asetukset GmsCoren asetukset + + Haptinen palaute + Muuta haptista palautetta + Poista videon osien haptiikka käytöstä + Videon osien haptiikka ei ole käytössä + Videon osien haptiikka on käytössä + Poista tarkan etsintäeleen haptiikka käytöstä + Tarkan etsinnän haptiikka ei ole käytössä + Tarkan etsinnän haptiikka on käytössä + Poista etsinnän kumoamisen haptiikka käytöstä + Etsinnän kumoamisen haptiikka ei ole käytössä + Etsinnän kumoamisen haptiikka on käytössä + Poista zoomaushaptiikka käytöstä + Zoomaushaptiikka ei ole käytössä + Zoomaushaptiikka on käytössä + Jos olet äskettäin muuttanut tilisi kirjautumistietoja, poista ja asenna MicroG uudelleen. @@ -1338,11 +1371,6 @@ Tämä voi avata korkealaatuisemmat videot" Seurantakyselyparametrit poistetaan linkeistä Seurantakyselyparametrejä ei poisteta linkeistä - - Poista zoomaushaptiikka käytöstä - Haptiikka ei ole käytössä - Haptiikka on käytössä - Pakota alkuperäinen äänen kieli Käytetään alkuperäistä ääntä @@ -1370,7 +1398,6 @@ Tämä voi avata korkealaatuisemmat videot" Näytä nopeuden valintapainike - Painike näytetään Painiketta ei näytetä diff --git a/patches/src/main/resources/addresources/values-fil-rPH/strings.xml b/patches/src/main/resources/addresources/values-fil-rPH/strings.xml index a646bdb1c..ff0f2d86c 100644 --- a/patches/src/main/resources/addresources/values-fil-rPH/strings.xml +++ b/patches/src/main/resources/addresources/values-fil-rPH/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Mga Setting Gusto mo bang magpatuloy? I-reset + I-reset ang kulay + Hindi wasto ang kulay I-refresh at i-restart I-restart Angkat @@ -115,6 +117,11 @@ Tapikin ang pindutan ng pagpapatuloy at payagan ang mga pagbabago sa pag-optimiz Mag-log protocol buffer Kasama sa mga debug log ang proto buffer Ang mga debug log ay hindi kasama ang proto buffer + "Ang pagpapagana sa setting na ito ay magtatala ng karagdagang data ng layout, kabilang ang on-screen na teksto para sa ilang bahagi ng UI. + +Maaaring makatulong ito na matukoy ang mga bahagi kapag lumilikha ng mga custom na filter. + +Gayunpaman, ang pagpapagana nito ay magtatala rin ng ilang data ng user gaya ng iyong IP address." Mga bakas ng stack ng log Kasama sa mga debug log ang stack trace Hindi kasama sa mga debug log ang stack trace @@ -124,6 +131,15 @@ Tapikin ang pindutan ng pagpapatuloy at payagan ang mga pagbabago sa pag-optimiz "Ang pag-off ng mga toast ng error ay nagtatago ng lahat ng mga abiso ng error ng ReVanced. Hindi ka aabisuhan ng anumang hindi inaasahang mga kaganapan." + I-export ang mga debug log + Kinokopya ang mga ReVanced debug log sa clipboard + Hindi pinagana ang pag-log ng debug + Walang nakitang mga log + Nakopya ang mga log + Nabigong i-export ang mga log: $s + I-clear ang mga debug log + Iki-clear ang lahat ng nakaimbak na ReVanced debug log + Na-clear ang mga log Itago ang mga album card @@ -365,9 +381,6 @@ Mga limitasyon Ang tampok na ito ay magagamit lamang para sa mga mas lumang device" Ipinapakita ang mga fullscreen na ad - Itago ang mga naka-button na ad - Nakatago ang mga naka-button na ad - Ipinapakita ang mga naka-button na ad Itago ang may bayad na label ng promosyon Nakatago ang label ng bayad na promosyon Ipinapakita ang may bayad na label ng promosyon @@ -478,9 +491,10 @@ Ayusin ang volume sa pamamagitan ng pag-swipe nang patayo sa kanang bahagi ng sc Transparency ng background ng swipe overlay Halaga ng opacity sa pagitan ng 0-100 Ang opacity ng swipe ay dapat nasa pagitan ng 0-100 - Kulay ng progress bar ng swipe overlay - Ang kulay ng progress bar para sa mga kontrol ng volume at brightness - Hindi wasto ang kulay ng progress bar + Kulay ng liwanag ng swipe overlay + Ang kulay ng progress bar para sa mga kontrol ng liwanag + Kulay ng volume ng swipe overlay + Ang kulay ng progress bar para sa mga kontrol ng volume Laki ng teksto ng swipe overlay Ang laki ng teksto para sa swipe overlay sa pagitan ng 1-30 Ang laki ng teksto ay dapat sa pagitan ng 1-30 @@ -734,6 +748,9 @@ Upang ipakita ang menu ng Audio track, baguhin ang 'Spoof video streams' sa iOS Itago ang label ng lokasyon Nakatago ang label ng lokasyon Ipinapakita ang label ng lokasyon + Itago ang panel ng Komento + Nakatago ang panel ng mga komento + Ipinapakita ang panel ng Komento Itago ang Save music button Ang buton ng pag-save ng musika ay nakatago Ang buton ng pag-save ng musika ay ipinapakita @@ -1097,11 +1114,6 @@ Isumite na ba?" %s segundo Opacity: Kulay: - Nagbago ang kulay - Pag-reset ng kulay - Di-wastong code ng kulay - I-reset ang kulay - I-reset Tungkol Ang data ay ibinibigay ng SponsorBlock API. Mag-tap dito para matuto pa at makakita ng mga download para sa iba pang platform @@ -1326,6 +1338,22 @@ Ang pagpapagana nito ay maaaring magbukas ng mas mataas na kalidad ng video"Mga Setting ng GmsCore Mga setting para sa GmsCore + + Haptic feedback + Baguhin ang haptic feedback + Huwag paganahin ang chapters haptics + Hindi pinagana ang Chapters haptics + Pinagana ang Chapters haptics + Huwag paganahin ang tumpak na paghahanap ng haptics + Hindi pinagana ang tumpak na paghahanap ng haptics + Pinagana ang tumpak na paghahanap ng haptics + Huwag paganahin ang seek undo haptics + Hindi pinagana ang seek undo haptics + Pinagana ang seek undo haptics + Huwag paganahin ang zoom haptics + Hindi pinagana ang zoom haptics + Pinagana ang zoom haptics + Kung kamakailan mo lang binago ang mga detalye sa pag-login sa iyong account, i-uninstall at muling i-install ang MicroG. @@ -1344,11 +1372,6 @@ Ang pagpapagana nito ay maaaring magbukas ng mas mataas na kalidad ng video"Ang parameter ng query sa pagsubaybay ay tinanggal mula sa mga link Ang parameter ng query sa pagsubaybay ay hindi inaalis sa mga link - - Huwag paganahin ang zoom haptics - Naka-disable ang Haptics - Pinagana ang Haptics - Pilitin ang orihinal na wika ng audio Ginagamit ang orihinal na wika ng audio @@ -1376,7 +1399,7 @@ Ang pagpapagana nito ay maaaring magbukas ng mas mataas na kalidad ng video" Ipakita ang pindutan ng dialog ng bilis - Ang pindutan ay ipinapakita + Ipinapakita ang button. I-tap at i-hold para i-reset ang bilis ng pag-playback sa default Hindi ipinapakita ang button @@ -1388,6 +1411,7 @@ Ang pagpapagana nito ay maaaring magbukas ng mas mataas na kalidad ng video"Ang mga custom na bilis ay dapat na mas mababa sa %s Hindi wastong custom na bilis ng paglalaro Awtomatik + Na-reset ang bilis ng pag-playback sa: %s Custom speed para sa pag-tap at pag-hold Tugtugin ang bilis ng playback sa pagitan ng 0-8 diff --git a/patches/src/main/resources/addresources/values-fr-rFR/strings.xml b/patches/src/main/resources/addresources/values-fr-rFR/strings.xml index 0a0d32b9d..b59ec851c 100644 --- a/patches/src/main/resources/addresources/values-fr-rFR/strings.xml +++ b/patches/src/main/resources/addresources/values-fr-rFR/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Paramètres Voulez-vous continuer ? Réinitialiser + Réinitialiser la couleur + Couleur invalide Actualiser et redémarrer Redémarrer Importer @@ -115,6 +117,11 @@ Appuyez sur le bouton Continuer et autorisez les modifications." Journaliser les protobufs Les journaux de débogage incluent les protocol buffers Les journaux de débogage n\'incluent pas les protocol buffers + "En activant cette option, des données supplémentaires relatives à la mise en page seront enregistrées, dont le texte à l'écran de certains composants de l'interface utilisateur. + +Cela peut aider à identifier les composants lors de la création de filtres personnalisés. + +Toutefois, l'activation de cette option entraînera également l'enregistrement de certaines données utilisateur, telles que votre adresse IP." Journaliser les stack traces Les journaux de débogage incluent les stack traces Les journaux de débogage n\'incluent pas les stack traces @@ -124,6 +131,15 @@ Appuyez sur le bouton Continuer et autorisez les modifications." "La désactivation des messages toasts d'erreur masque toutes les notifications d'erreur ReVanced. Vous ne serez pas informé des événements inattendus." + Exporter les journaux de débogage + Copie les journaux de débogage ReVanced dans le presse-papiers + La journalisation de débogage est désactivée + Aucun journal trouvé + Journaux copiés + Échec de l\'exportation des journaux : $s + Effacer les journaux de débogage + Efface tous les journaux de débogage ReVanced stockés + Journaux effacés Masquer les fiches d\'album @@ -365,9 +381,6 @@ Limitations Cette fonctionnalité est disponible uniquement pour les appareils anciens" Les annonces plein écran sont affichées - Masquer les annonces au format bouton - Les annonces au format bouton sont masquées - Les annonces au format bouton sont affichées Masquer la bannière de promotion rémunérée La bannière \"Inclut une promotion rémunérée\" est masquée La bannière \"Inclut une promotion rémunérée\" est affichée @@ -478,9 +491,10 @@ Réglez le volume en balayant verticalement sur le côté droit de l'écran"Opacité de l\'arrière-plan de l\'overlay des gestes Valeur de l\'opacité entre 0 et 100 L\'opacité doit être comprise entre 0 et 100 pour les gestes - Couleur de la barre de progression de l\'overlay des gestes - La couleur de la barre de progression pour les commandes de volume et de luminosité - Couleur de barre de progression invalide + Couleur de l\'overlay des gestes de contrôle de la luminosité + La couleur de la barre de progression des commandes de luminosité + Couleur de l\'overlay des gestes de contrôle du volume + La couleur de la barre de progression des commandes de volume Taille du texte de l\'overlay des gestes La taille du texte de l\'overlay des gestes comprise entre 1 et 30 La taille du texte doit être comprise entre 1 et 30 @@ -736,6 +750,9 @@ Pour afficher le menu Piste audio, définissez \"Falsifier les flux vidéo\" sur Masquer le libellé de lieu Le libellé de lieu est masqué Le libellé de lieu est affiché + Masquer le panneau de commentaire + Le panneau de commentaire est masqué + Le panneau de commentaire est affiché Masquer le bouton Enregistrer la musique Le bouton Enregistrer la musique est masqué Le bouton Enregistrer la musique est affiché @@ -1098,11 +1115,6 @@ Prêt à soumettre ?" %s secondes Opacité : Couleur : - Couleur modifiée - Couleur réinitialisée - Code couleur invalide - Réinitialiser la couleur - Réinitialiser À propos Les données sont fournies par l\'API SponsorBlock. Appuyez ici pour en savoir plus et pour voir les téléchargements pour les autres plateformes. @@ -1327,6 +1339,22 @@ Activer cette option peut déverrouiller des qualités vidéo supérieures"Paramètres GmsCore Paramètres relatifs à GmsCore + + Retour haptique + Modifiez les retours haptiques + Désactiver le retour haptique des chapitres + Le retour haptique des chapitres est désactivé + Le retour haptique des chapitres est activé + Désactiver le retour haptique de la recherche précise + Le retour haptique de la recherche précise est désactivé + Le retour haptique de la recherche précise est activé + Désactiver le retour haptique d\'annulation de la recherche + Le retour haptique d\'annulation de la recherche est désactivé + Le retour haptique d\'annulation de la recherche est activé + Désactiver le retour haptique des actions de zoom + Le retour haptique du zoom est désactivé + Le retour haptique du zoom est activé + Si vous avez récemment modifié vos informations de connexion, désinstallez et réinstallez MicroG. @@ -1345,11 +1373,6 @@ Activer cette option peut déverrouiller des qualités vidéo supérieures"Le paramètre de requête destiné au suivi est supprimé des liens Le paramètre de requête destiné au suivi n\'est pas supprimé des liens - - Désactiver le retour haptique des actions de zoom - Le retour haptique est désactivé - Le retour haptique est activé - Forcer la langue audio d\'origine Utilisation de la langue audio d\'origine @@ -1377,7 +1400,7 @@ Activer cette option peut déverrouiller des qualités vidéo supérieures" Afficher un bouton Vitesse - Le bouton est affiché + Le bouton est affiché. Appuyez longuement dessus pour rétablir la vitesse de lecture par défaut. Le bouton n\'est pas affiché @@ -1389,6 +1412,7 @@ Activer cette option peut déverrouiller des qualités vidéo supérieures"Il doit y avoir moins de %s vitesses personnalisées Vitesses de lecture personnalisées invalides Automatique + Vitesse de lecture réinitialisée à : %s Vitesse personnalisée d\'accélération sur appui long Vitesse de lecture comprise entre 0 et 8 diff --git a/patches/src/main/resources/addresources/values-ga-rIE/strings.xml b/patches/src/main/resources/addresources/values-ga-rIE/strings.xml index f2ee4103c..4bbbb061f 100644 --- a/patches/src/main/resources/addresources/values-ga-rIE/strings.xml +++ b/patches/src/main/resources/addresources/values-ga-rIE/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Socruithe Ar mhaith leat dul ar aghaidh? Athshocraigh + Dath a athshocrú + Dath neamhbhailí Athnuachan agus atosaigh Athosaigh Iompórtáil @@ -115,6 +117,11 @@ Brúigh an cnaipe leanúnaí agus ligean athruithe optúimíochta." Maolán prótacal logála Cuimsíonn logaí dífhabhtaithe maolán Ní chuimsíonn logaí dífhabhtaithe maolán proto + "Logálfaidh an socrú seo sonraí breise leagain amach, lena n-áirítear téacs ar an scáileán do chomhpháirteanna UI áirithe. + +Is féidir leis seo cabhrú le comhpháirteanna a aithint agus scagairí saincheaptha á gcruthú. + +Mar sin féin, logálfaidh sé seo roinnt sonraí úsáideora freisin, mar shampla do sheoladh IP." Rianta cruach logála Cuimsíonn logaí dífhabhtaithe rian cruach Ní chuimsíonn logaí dífhabhtaithe rian cruach @@ -124,6 +131,15 @@ Brúigh an cnaipe leanúnaí agus ligean athruithe optúimíochta." "Má mhúchtar tóstaí earráide, folaítear gach fógra earráide ReVanced. Ní chuirfear ar an eolas thú faoi aon imeachtaí gan choinne." + Easpórtáil logaí dífhabhtaithe + Cóipeálann sé logaí dífhabhtaithe ReVanced chuig an gearrthaisce + Tá logáil dífhabhtaithe díchumasaithe + Ní bhfuarthas aon loga + Lógaí cóipeáilte + Theip ar lógaí a easpórtáil: $s + Glan logaí dífhabhtaithe + Glanann sé gach loga dífhabhtaithe ReVanced stóráilte + Lógaí glanta Folaigh cártaí albam @@ -162,8 +178,8 @@ Ní chuirfear ar an eolas thú faoi aon imeachtaí gan choinne." Taispeántar an cnaipe Folaigh lipéid moltaí físeáin - Tá lipéid \",,D’fhéach daoine eile air freisin\",, agus \",,B’fhéidir gur mhaith leat é seo freisin\",, folaithe - Tá lipéid \",,D’fhéach daoine eile air freisin\",, agus \",,B’fhéidir gur mhaith leat é seo freisin\",, ar taispeáint + Tá na lipéid \'Daoine a d\'fhéach orthu freisin\' agus \'B\'fhéidir gur mhaith leat freisin\' i bhfolach + Taispeántar lipéid ‘Daoine a d’fhéach freisin’ agus ‘B’fhéidir gur mhaith leat freisin’ Folaigh cnaipe \'Taispeáin tuilleadh\' @@ -263,8 +279,8 @@ Ní chuirfear ar an eolas thú faoi aon imeachtaí gan choinne." Tá an chuid Príomhchoincheapa i bhfolach Taispeántar an chuid Príomhchoincheapa Folaigh Tras-scríbhinn - Tá an chuid trasscríbhinne i bhfolach - Taispeántar alt an trasscríbhinne + Tá alt an tras-scríbhinn i bhfolach + Taispeántar alt an tras-scríbhinn Cur síos físeán Folaigh nó taispeáint comhpháirteanna tuairisc Barra scagaire @@ -278,8 +294,8 @@ Ní chuirfear ar an eolas thú faoi aon imeachtaí gan choinne." Folaigh i bhfíseáin gaolmhara I bhfolach i bhfíseáin ghaolmhara Taispeántar i bhfíseáin ghaolmhara - Tuairimí - Folaigh nó taispeáin comhpháirteanna na rannóige tuairimí + Tráchtanna + Folaigh nó taispeáin comhpháirteanna na rannóige tráchtanna Folaigh achoimre Comhrá AI Tá achoimre comhrá i bhfolach Taispeántar achoimre comhrá @@ -365,9 +381,6 @@ Teorainneacha Níl an ghné seo ar fáil ach do ghléasanna níos sine" Taispeántar fógraí lánscáileáin - Folaigh fógraí cnaipe - Tá fógraí cnaipe i bhfolach - Taispeántar fógraí cnaipe Folaigh lipéad chun cinn íoctha Tá an lipéad promóisin íoctha i bhfolach Taispeántar lipéad promóisin íoctha @@ -478,9 +491,10 @@ Coigeartaigh an toirt trí haisceartán go hingearach ar thaobh deas an scáile Réabhlóid thrasláiteachta na gcúlra léaráidí Luach léaráidí idir 0-100 Caithfidh léaráidí traslaithe a bheith idir 0-100 - Dath an bharra dul chun cinn forleagain swipe - Dath an bharra dul chun cinn le haghaidh rialuithe toirte agus gile - Dath barra dul chun cinn neamhbhailí + Dath gile forleagan swipe + Dath an bharra dul chun cinn do rialuithe gile + Dath toirte forleagan swipe + Dath an bharra dul chun cinn do rialuithe toirte Méid téacs an fhorleagain swipe Méid téacs an fhorleagain swipe idir 1-30 Caithfidh an méid téacs a bheith idir 1-30 @@ -736,6 +750,9 @@ Chun roghchlár na rian fuaime a thaispeáint, athraigh 'Srutháin físeáin bhr Folaigh lipéad suímh Tá lipéad suímh i bhfolach Taispeántar lipéad suímh + Folaigh painéal na dtuairimí + Tá an painéal tuairimí i bhfolach + Taispeántar painéal na dtuairimí Folaigh cnaipe \'Sábháil ceol\' Tá an cnaipe Sábháil ceoil i bhfolach Taispeántar an cnaipe Sábháil ceoil @@ -1099,11 +1116,6 @@ Maithe chun cur isteach?" %s soicindí Teimhneacht: Dath: - Athraigh dath - Athshocrú dath - Cód dath neamhbhailí - Athshocraigh dath - Athshocraigh Maidir Soláthraíonn an API SponsorBlock sonraí. Tapáil anseo chun níos mó a fhoghlaim agus íoslódálacha a fheiceáil d\'ardáin eile @@ -1328,6 +1340,22 @@ Is féidir le seo caighdeáin físeáin níos airde a dhíghlasáil" Socruithe GmsCore Socruithe le haghaidh GmsCore + + Aiseolas haptach + Athraigh aiseolas haptach + Díchumasaigh haptics caibidlí + Tá haptics caibidlí díchumasaithe + Tá haptics caibidlí cumasaithe + Díchumasaigh haptics beacht cuardaigh + Tá haptics beachtais díchumasaithe + Tá haptics beacht cuardaigh cumasaithe + Díchumasaigh haptics díthurais + Tá haptics díthurais díchumasaithe + Tá haptics díthurais cumasaithe + Díchumasaigh súmáil haptics + Tá súmáil haptics díchumasaithe + Tá súmáil haptics cumasaithe + Má d’athraigh tú sonraí logála isteach do chuntais le déanaí, ansin díshuiteáil agus athshuiteáil MicroG. @@ -1346,11 +1374,6 @@ Is féidir le seo caighdeáin físeáin níos airde a dhíghlasáil" Baintear paraiméadar ceisteanna rianaithe ó naisc Ní bhaintear paraiméadar fiosrúcháin rianaithe ó naisc - - Díchumasaigh súmáil haptics - Tá Haptics díchumasaithe - Tá Haptics cumasaithe - Fórsaigh teanga bhunaidh na fuaime Ag úsáid teanga bhunaidh na fuaime @@ -1378,7 +1401,7 @@ Is féidir le seo caighdeáin físeáin níos airde a dhíghlasáil" Taispeáin cnaipe dialóg luais - Taispeántar an cnaipe + Taispeántar an cnaipe. Tapáil agus coinnigh chun luas athsheinm a athshocrú go réamhshocrú Ní thaispeántar an cnaipe @@ -1390,6 +1413,7 @@ Is féidir le seo caighdeáin físeáin níos airde a dhíghlasáil" Ní mór luas saincheaptha a bheith níos lú ná %s Luasanna athsheinm saincheaptha neamhbhailí Uathoibríoch + Athshocraíodh luas athsheinm go: %s Luas tap is agus greim Luas athsheinm eatarthu 0-8 diff --git a/patches/src/main/resources/addresources/values-gl-rES/strings.xml b/patches/src/main/resources/addresources/values-gl-rES/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-gl-rES/strings.xml +++ b/patches/src/main/resources/addresources/values-gl-rES/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-gu-rIN/strings.xml b/patches/src/main/resources/addresources/values-gu-rIN/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-gu-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-gu-rIN/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-hi-rIN/strings.xml b/patches/src/main/resources/addresources/values-hi-rIN/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-hi-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-hi-rIN/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-hr-rHR/strings.xml b/patches/src/main/resources/addresources/values-hr-rHR/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-hr-rHR/strings.xml +++ b/patches/src/main/resources/addresources/values-hr-rHR/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-hu-rHU/strings.xml b/patches/src/main/resources/addresources/values-hu-rHU/strings.xml index da9bf76a6..a5a084fb3 100644 --- a/patches/src/main/resources/addresources/values-hu-rHU/strings.xml +++ b/patches/src/main/resources/addresources/values-hu-rHU/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Beállítások Szeretné folytatni? Visszaállítás + Szín alaphelyzetbe állítása + Érvénytelen szín Frissítés és újraindítás Újraindítás Importálás @@ -115,6 +117,11 @@ Kattintson a folytatás gombra, és engedélyezze az optimalizálási módosít Napló protokoll puffer A hibakeresési naplók protopuffert tartalmaznak A hibakeresési naplók nem tartalmaznak protopuffert + "Ennek a beállításnak az engedélyezése további elrendezési adatokat fog naplózni, beleértve néhány felhasználói felületi komponens képernyőn megjelenő szövegét. + +Ez segíthet azonosítani az összetevőket egyedi szűrők létrehozásakor. + +Ez a funkció azonban néhány felhasználói adatot is naplóz, például az IP-címét." Naplóverem nyomai A hibakeresési naplók tartalmazzák a verem nyomkövetését A hibakeresési naplók nem tartalmazzák a verem nyomkövetését @@ -124,6 +131,15 @@ Kattintson a folytatás gombra, és engedélyezze az optimalizálási módosít "A hibaüzenetek kikapcsolása elrejti az összes ReVanced hibaértesítést. Nem fog értesülni semmilyen váratlan eseményről." + Hibakeresési naplók exportálása + A ReVanced hibakeresési naplóit a vágólapra másolja + A hibakeresési naplózás ki van kapcsolva + Nem találhatók naplók + Naplók másolva + Nem sikerült exportálni a naplókat: $s + Hibakeresési naplók törlése + Törli az összes tárolt ReVanced hibakeresési naplót + Naplók törölve Album kártyák elrejtése @@ -365,9 +381,6 @@ Korlátozások Ez a funkció csak régebbi eszközökön érhető el" A teljes képernyős hirdetések láthatók - Gomb hirdetések elrejtése - A gomb hirdetések el vannak rejtve - A gomb hirdetések láthatók Fizetett promóció címke elrejtése A fizetett promóciós címke el van rejtve A fizetett promóciós címke meg van jelenítve @@ -478,9 +491,10 @@ A hangerő a képernyő jobb oldalán függőlegesen húzva állítható be"Az áthúzás átfedésének átlátszósága Az átlátszóság értéke 0-100 között legyen A csúsztatás átlátszóságának 0 és 100 között kell lennie - Áthúzás fedvény folyamatjelző sáv színe - A hangerő és fényerő szabályozók folyamatjelző sávjának színe - Érvénytelen folyamatjelző sávszín + A húzással előhívható fedőréteg fényerejének színe + A fényerő-szabályozókhoz tartozó folyamatjelző sáv színe + A húzással előhívható fedőréteg hangerejének színe + A hangerő-szabályozókhoz tartozó folyamatjelző sáv színe Áthúzás fedvény szövegmérete Az áthúzás fedvény szövegmérete 1-30 között A szövegméretnek 1-30 között kell lennie @@ -736,6 +750,9 @@ Az audiosáv menü megjelenítéséhez módosítsa a \"Videófolyamok hamisítá Helycímke elrejtése A helycízke címke el van rejtve A helycízke címke meg van jelenítve + Kommentpanel elrejtése + A megjegyzés panel rejtett + A Kommentpanel látható Zene mentése gomb elrejtése A zene mentés gomb el van rejtve A zene mentés gomb látható @@ -1098,11 +1115,6 @@ Készen állsz a beküldésre?" %s másodperc Áttetszőség: Szín: - A szín megváltoztatva - Szín alaphelyzetbe - Érvénytelen színkód - Színek visszaállítása - Visszaállítás Rólunk Az adatokat a SponsorBlock API biztosítja. Koppintson ide, ha többet szeretne megtudni és megtekintené a letöltéseket más platformokra @@ -1325,6 +1337,22 @@ Ez a beállítás lehetővé teszi a magasabb videóminőségek feloldását"GmsCore beállítások A GmsCore beállításai + + Haptikus visszajelzés + Haptikus visszajelzés módosítása + Fejezetek haptikus visszajelzésének letiltása + A fejezetek haptikus visszajelzése le van tiltva + A fejezetek haptikus visszajelzése engedélyezve van + Pontos keresés haptikus visszajelzésének letiltása + A pontos keresés haptikus visszajelzése ki van kapcsolva + A pontos keresés haptikus visszajelzése engedélyezve van + Keresés visszavonása haptikus visszajelzésének letiltása + A keresés visszavonása haptikus visszajelzése ki van kapcsolva + A keresés visszavonása haptikus visszajelzése be van kapcsolva + Haptikus zoom letiltása + Haptikus zoom le van tiltva + Haptikus zoom be van kapcsolva + Ha nemrég módosította a fiókja bejelentkezési adatait, távolítsa el, majd telepítse újra a MicroG-t. @@ -1343,11 +1371,6 @@ Ez a beállítás lehetővé teszi a magasabb videóminőségek feloldását"A nyomkövetési lekérdezési paraméter eltávolítva a linkekből A nyomkövetési lekérdezési paraméter nincs eltávolítva a linkekből - - Haptikus zoom letiltása - A haptikus zoom letiltva - A haptikus zoom engedélyezve - Eredeti hang kikényszerítése Eredeti hang használata a hang nyelvén @@ -1375,7 +1398,7 @@ Ez a beállítás lehetővé teszi a magasabb videóminőségek feloldását" Sebesség párbeszédpanel megjelenítése - A gomb megjelenik + A gomb látható. Tartsa lenyomva a lejátszási sebesség alapértelmezettre állításához A gomb nem látható @@ -1387,6 +1410,7 @@ Ez a beállítás lehetővé teszi a magasabb videóminőségek feloldását"Az egyéni sebességeknek kevesebbnek kell lenniük, mint %s Érvénytelen egyéni lejátszási sebességek Automatikus + Lejátszási sebesség visszaállítva: %s Egyéni koppintás és tartás sebesség Lejátszási sebesség 0-8 között diff --git a/patches/src/main/resources/addresources/values-hy-rAM/strings.xml b/patches/src/main/resources/addresources/values-hy-rAM/strings.xml index e2bd8317d..092772bda 100644 --- a/patches/src/main/resources/addresources/values-hy-rAM/strings.xml +++ b/patches/src/main/resources/addresources/values-hy-rAM/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Կարգավորումներ Դուք ցանկանում եք շարունակել? Վերականգնել + Գույնը վերականգնել + Անվավեր գույն Թարմացնել և վերագործարկել Վերսկսել Ներմուծել @@ -115,6 +117,11 @@ MicroG-ի համար մարտկոցի օպտիմալացումը անջատել Բուֆերի արձանագրությունը մտնել Մարմնացման առաջնորդման մատնանշումները պարունակում են բուֆերի տարր Մարմնացման առաջնորդման մատնանշումները ներառում են բուֆերի տարր + "Այս կարգավորումը միացնելը կգրանցի լրացուցիչ դասավորության տվյալներ, ներառյալ էկրանի տեքստը որոշ UI բաղադրիչների համար։ + +Սա կարող է օգնել բացահայտել բաղադրիչները՝ հատուկ զտիչներ ստեղծելիս։ + +Այնուամենայնիվ, սա միացնելը կգրանցի նաև օգտատիրոջ որոշ տվյալներ, ինչպիսիք են ձեր IP հասցեն:" Մուտքագրել կուտակային կետերի հետքեր Մարմնացման առաջնորդման մատնանշումները պարունակում են կուտակային կետի հետք Մարմնացման առաջնորդման մատնանշումները չեն պարունակում կուտակային կետի հետք @@ -124,6 +131,15 @@ MicroG-ի համար մարտկոցի օպտիմալացումը անջատել "Սխալների տոաստի անջատումը թաքցնում է ReVanced-ի բոլոր սխալների ծանուցումները։ Դուք չեք ստանա ան予期した出来事ի մասին ծանուցում։" + Արտահանել վրեժխնդրության կարգաբերման մատյանները + Պատճենում է ReVanced-ի կարգաբերման մատյանները սեղմատախտակին + Վրեժխնդրության մատյանների գրանցումն անջատված է + Մատյաններ չեն գտնվել + Մատյանները պատճենված են + Մատյանների արտահանումը ձախողվեց. $s + Մաքրել վրեժխնդրության մատյանները + Մաքրում է բոլոր պահված ReVanced կարգաբերման մատյանները + Մատյանները մաքրվել են Թաքցնել ալբոմի քարտերը @@ -365,9 +381,6 @@ MicroG-ի համար մարտկոցի օպտիմալացումը անջատել Այս հատկությունը հասանելի է միայն հին սարքերի համար" Լի էկրանի գովազդները երևում են - Թաքցնել կոճակավորված գովազդները - Կոճակավորված գովազդները թաքցված են - Կոճակավորված գովազդները երևում են Թաքցնել վճարված խթանման նշանը Վճարված խթանման նշանը թաքցված է Վճարված խթանման նշանը երևում է @@ -478,9 +491,10 @@ MicroG-ի համար մարտկոցի օպտիմալացումը անջատել Սողացման ծածկույթի ֆոնի անթափանցություն Անթափանցության արժեք 0-100 միջակայքում Սողալու անթափանցությունը պետք է լինի 0-100 միջակայքում - Սահեցրեք շերտի առաջընթացի սանդղակի գույնը - Ձայնի և պայծառության կառավարման համար նախատեսված առաջընթացի սանդղակի գույնը - Առաջընթացի սանդղակի անվավեր գույն + Սահեցնել վառության գույնի վրադիրը + Վառության կառավարման առաջընթացի սանդղակի գույնը + Սահեցնել ձայնի գույնի վրադիրը + Ձայնի կառավարման առաջընթացի սանդղակի գույնը Սահեցրեք շերտի տեքստի չափը Սահեցրեք շերտի տեքստի չափը 1-30 միջակայքում Տեքստի չափը պետք է լինի 1-30 միջակայքում @@ -736,6 +750,9 @@ MicroG-ի համար մարտկոցի օպտիմալացումը անջատել Թաքցնել տեղանքի նշումը Տեղանքի նշումը թաքցված է Տեղանքի նշումը ցուցադրվում է + Թաքցնել մեկնաբանության վահանակը + Մեկնաբանությունների վահանակը թաքցված է + Ցուցադրվում է մեկնաբանության վահանակը Թաքցնել երաժշտությունը պահպանել կոճակը «Save music» կոճակը թաքցված է «Save music» կոճակը ցուցադրվում է @@ -1099,11 +1116,6 @@ Seekbar thumbnails-ները կօգտագործեն նույն որակը, ինչ %s վայրկյան Թափանցիկություն․ Գույն։ - Գույնը փոխվել է - Գույնը վերագործարկվել է - Անվավեր գույնի կոդ - Վերագործարկել գույնը - Վերագործարկել Ծրագրի մասին Տվյալները մատուցվում են SponsorBlock API-ի կողմից։ Սեղմեք այստեղ՝ ավելի շատ իմանալու և այլ հարթակների համար ներբեռնումները տեսնելու @@ -1328,6 +1340,22 @@ Mini-player-ը կարող է գրավվել էկրանից դուրս՝ դեպի GmsCore կարգավորումներ GmsCore-ի կարգավորումներ + + Հպումային արձագանք + Փոխել հպումային արձագանքը + Անջատել գլուխների հպումները + Գլուխների հպումներն անջատված են + Գլուխների հպումները միացված են + Անջատել ճշգրիտ փնտրման հպումները + Ճշգրիտ որոնման հպումն անջատված է + Ճշգրիտ փնտրման հպումները միացված են + Անջատել հետարկել որոնման հպումը + Հետարկել որոնման հպումն անջատված է + Հետարկել որոնման հպումը միացված է + Զուումի հպումների ակտիվացումը անջատել + Զուումի հպումն անջատված է + Զուումի հպումը միացված է + Եթե վերջերս փոխել եք ձեր հաշվի մուտքի տվյալները, ապա ջնջեք և նորից տեղադրեք MicroG-ն: @@ -1346,11 +1374,6 @@ Mini-player-ը կարող է գրավվել էկրանից դուրս՝ դեպի Հետևողականության հարցումի պարամետրը հեռացվում է հղումներից Հետևողականության հարցումի պարամետրը չի հեռացվում հղումներից - - Զուումի հպումների ակտիվացումը անջատել - Հպումները անջատված են - Հպումները ակտիվացված են - Բնօրինակ ձայն օգտագործել լեզուն Օգտագործելով ձայնային օրիգինալ լեզուն @@ -1378,7 +1401,7 @@ Mini-player-ը կարող է գրավվել էկրանից դուրս՝ դեպի Ցուցադրել արագության դիալոգի պատուհանի կոճակը - Կոճակը ցուցադրվում է + Կոճակը ցուցադրվում է: Հպեք և պահեք՝ նվագարկման արագությունը լռելյայնի վերականգնելու համար Կոճակը չի ցուցադրվում @@ -1390,6 +1413,7 @@ Mini-player-ը կարող է գրավվել էկրանից դուրս՝ դեպի Պատրաստված արագությունները պետք է լինեն ավելի քիչ քան %s Չի աշխատում պատրաստված վերարտադրման արագությունները։ Ավտո + Նվագարկման արագությունը վերականգնվել է. %s Զգայական վերահսկում՝ անվանափոխման համար Վերարտադրման արագությունը 0-8 միջակայքում diff --git a/patches/src/main/resources/addresources/values-in-rID/strings.xml b/patches/src/main/resources/addresources/values-in-rID/strings.xml index 1adcf77c0..a074f7421 100644 --- a/patches/src/main/resources/addresources/values-in-rID/strings.xml +++ b/patches/src/main/resources/addresources/values-in-rID/strings.xml @@ -35,11 +35,13 @@ Second \"item\" text" Pengaturan Apakah Anda ingin melanjutkan? Setel ulang + Setel ulang warna + Warna tidak sah Segarkan dan mulai ulang Mulai ulang Impor Salin - Pengaturan ReVanced diatur ke setelan awal + Pengaturan ReVanced diatur ke bawaan Mengimpor setelan %d Impor gagal: %s Pengaturan pencarian @@ -53,7 +55,7 @@ Second \"item\" text" "Terjemahan untuk beberapa bahasa mungkin hilang atau tidak lengkap. Untuk menerjemahkan bahasa baru kunjungi translate.revanced.app" - Bahasa Aplikasi + Bahasa aplikasi Impor / Ekspor Impor / Ekspor setelan ReVanced @@ -115,6 +117,11 @@ Ketuk tombol lanjutkan dan izinkan perubahan pengoptimalan." Buffer protokol log Log debug termasuk buffer proto Log debug tidak menyertakan buffer proto + "Mengaktifkan setelan ini akan mencatat data tata letak tambahan, termasuk teks pada layar untuk beberapa komponen UI. + +Ini dapat membantu mengidentifikasi komponen saat membuat filter khusus. + +Namun, mengaktifkan ini juga akan mencatat beberapa data pengguna seperti alamat IP Anda." Jejak log stack Log debug menyertakan jejak stack Log debug tidak menyertakan jejak stack @@ -124,6 +131,15 @@ Ketuk tombol lanjutkan dan izinkan perubahan pengoptimalan." "Mematikan notifikasi kesalahan menyembunyikan semua notifikasi kesalahan ReVanced. Anda tidak akan diberi tahu tentang kejadian yang tidak terduga." + Ekspor catatan debug + Salin catatan debug ReVanced ke papan klip + Pencatatan debug dinonaktifkan + Tidak ditemukan catatan + Catatan disalin + Gagal mengekspor catatan: $s + Bersihkan catatan debug + Menghapus semua catatan debug ReVanced yang tersimpan + Catatan dibersihkan Sembunyikan kartu album @@ -365,9 +381,6 @@ Keterbatasan Fitur ini hanya tersedia untuk perangkat yang lebih lama" Iklan layar penuh ditampilkan - Sembunyikan iklan bertombol - Iklan bertombol disembunyikan - Iklan bertombol ditampilkan Sembunyikan label promosi berbayar Label promosi berbayar disembunyikan Label promosi berbayar ditampilkan @@ -478,9 +491,10 @@ Menyesuaikan volume dengan mengusap secara vertikal di sisi kanan layar"Opasitas latar belakang hamparan geser Nilai opasitas antara 0-100 Opasitas geser harus antara 0-100 - Warna bilah kemajuan lapisan usap - Warna bilah kemajuan untuk kontrol volume dan kecerahan - Warna bilah kemajuan tidak sah + Warna kecerahan lapisan usap + Warna bilah kemajuan untuk kontrol kecerahan + Warna volume lapisan usap + Warna bilah kemajuan untuk kontrol volume Ukuran teks lapisan usap Ukuran teks untuk lapisan usap antara 1-30 Ukuran teks harus antara 1-30 @@ -736,6 +750,9 @@ Untuk menampilkan menu trek Audio, ubah 'Spoof aliran video' ke iOS TV" Sembunyikan label lokasi Label lokasi disembunyikan Label lokasi ditampilkan + Sembunyikan panel Komentar + Panel komentar disembunyikan + Panel komentar ditampilkan Sembunyikan Simpan musik Tombol simpan musik disembunyikan Tombol simpan musik ditampilkan @@ -1098,11 +1115,6 @@ Siap mengirim?" %s detik Opasitas: Warna: - Warna berubah - Reset warna - Kode warna tidak sah - Atur ulang warna - Setel ulang Tentang Data disediakan oleh API SponsorBlock. Tekan di sini untuk mempelajari lebih lanjut dan melihat hasil pengunduhan untuk platform lain @@ -1327,6 +1339,22 @@ Mengaktifkan ini dapat membuka kualitas video yang lebih tinggi" Pengaturan GmsCore Pengaturan untuk GmsCore + + Umpan balik sentuh getar + Ubah umpan balik sentuh getar + Nonaktifkan sentuh getar bab + Sentuh getar bab dinonaktifkan + Sentuh getar bab diaktifkan + Nonaktifkan sentuh getar pencarian presisi + Sentuh getar pencarian presisi dinonaktifkan + Sentuh getar pencarian presisi diaktifkan + Nonaktifkan sentuh getar urungkan pencarian + Sentuh getar urungkan pencarian dinonaktifkan + Sentuh getar urungkan pencarian diaktifkan + Matikan sentuh getar zoom + Sentuh getar zoom dinonaktifkan + Sentuh getar zoom diaktifkan + Jika Anda baru saja mengubah detail login akun Anda, hapus pemasangan dan ulangi memasang MicroG. @@ -1345,11 +1373,6 @@ Mengaktifkan ini dapat membuka kualitas video yang lebih tinggi" Parameter kueri pelacakan dihapus dari tautan Parameter kueri pelacakan tidak dihapus dari tautan - - Matikan sentuh getar zoom - Sentuh getar dinonaktifkan - Sentuh getar diaktifkan - Paksa bahasa audio asli Menggunakan bahasa audio asli @@ -1377,7 +1400,7 @@ Mengaktifkan ini dapat membuka kualitas video yang lebih tinggi" Tampilkan tombol dialog kecepatan - Tombol ditampilkan + Tombol ditampilkan. Ketuk dan tahan untuk mengatur ulang kecepatan pemutaran ke bawaan Tombol tidak ditampilkan @@ -1389,6 +1412,7 @@ Mengaktifkan ini dapat membuka kualitas video yang lebih tinggi" Kecepatan khusus harus kurang dari %s Kecepatan pemutaran khusus tidak valid Otomatis + Kecepatan pemutaran diatur ulang ke: %s Kecepatan ketuk dan tahan khusus Kecepatan pemutaran antara 0-8 diff --git a/patches/src/main/resources/addresources/values-is-rIS/strings.xml b/patches/src/main/resources/addresources/values-is-rIS/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-is-rIS/strings.xml +++ b/patches/src/main/resources/addresources/values-is-rIS/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-it-rIT/strings.xml b/patches/src/main/resources/addresources/values-it-rIT/strings.xml index c51c0994f..37298ba80 100644 --- a/patches/src/main/resources/addresources/values-it-rIT/strings.xml +++ b/patches/src/main/resources/addresources/values-it-rIT/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Impostazioni Sei sicuro di voler continuare? Reimposta + Reimposta colore + Colore non valido Aggiorna e riavvia Riavvia Importa @@ -115,6 +117,11 @@ Tocca il pulsante Continua e consenti le modifiche di ottimizzazione." Buffer di protocollo per log I log di debug includono proto buffer I log di debug non includono proto buffer + "L'abilitazione di questa impostazione registrerà dati di layout aggiuntivi, incluso il testo su schermo per alcuni componenti dell'interfaccia utente. + +Questo può aiutare a identificare i componenti durante la creazione di filtri personalizzati. + +Tuttavia, l'abilitazione di questa opzione registrerà anche alcuni dati dell'utente come il tuo indirizzo IP." Registra stack trace I log di debug includono lo stack trace I log di debug non includono lo stack trace @@ -124,6 +131,15 @@ Tocca il pulsante Continua e consenti le modifiche di ottimizzazione." "Disabilitare i toast di errore nasconde tutte le notifiche di errore di ReVanced. Non sarai notificato di eventi imprevisti." + Esporta i log di debug + Copia i log di debug di ReVanced negli Appunti + La registrazione di debug è disabilitata + Nessun log trovato + Log copiati + Esportazione dei log non riuscita: $s + Cancella i log di debug + Cancella tutti i log di debug di ReVanced memorizzati + Log cancellati Nascondi le schede degli album @@ -365,9 +381,6 @@ Note: Questa funzione è disponibile solo per i dispositivi più vecchi" Le pubblicità a schermo intero sono visibili - Nascondi le pubblicità a pulsante - Le pubblicità a pulsante sono nascoste - Le pubblicità a pulsante sono visibili Nascondi l\'etichetta della promozione a pagamento L\'etichetta della promozione a pagamento è nascosta L\'etichetta della promozione a pagamento è visibile @@ -478,9 +491,10 @@ Regola il volume scorrendo verticalmente sul lato destro dello schermo" Opacità di sfondo della sovrapposizione di scorrimento Valore di opacità tra 0-100 L\'opacità di scorrimento deve essere tra 0-100 - Colore della barra di avanzamento della sovrapposizione a scorrimento - Il colore della barra di avanzamento per i controlli di volume e luminosità - Colore della barra di avanzamento non valido + Colore della luminosit dell\'overlay a scorrimento + Il colore della barra di avanzamento per i controlli della luminosit + Colore del volume dell\'overlay a scorrimento + Il colore della barra di avanzamento per i controlli del volume Dimensione del testo della sovrapposizione a scorrimento La dimensione del testo per la sovrapposizione a scorrimento tra 1 e 30 La dimensione del testo deve essere compresa tra 1 e 30 @@ -736,6 +750,9 @@ Per mostrare il menu della traccia audio, cambia \"Spoof video streams\" in iOS Nascondi etichetta di posizione L\'etichetta di posizione è nascosta L\'etichetta di posizione è visibile + Nascondi pannello dei commenti + Il pannello dei commenti è nascosto + Il pannello dei commenti è visibile Nascondi il pulsante Salva Musica Il pulsante Salva traccia è nascosto Il pulsante Salva traccia è visibile @@ -1098,11 +1115,6 @@ Pronto per l'invio?" %s secondi Opacità: Colore: - Colore modificato - Ripristino colore - Codice colore non valido - Ripristina colore - Reimposta Informazioni I dati sono forniti dall\'API di SponsorBlock. Tocca qui per saperne di più e vedere i download per altre piattaforme @@ -1327,6 +1339,22 @@ Abilitare questa opzione può sbloccare qualità video più elevate" Impostazioni di GmsCore Impostazioni per GmsCore + + Feedback aptico + Modifica feedback aptico + Disabilita aptica capitoli + Aptica capitoli disabilitata + Aptica capitoli abilitata + Disabilita aptica di ricerca precisa + L\'aptica di ricerca precisa è disabilitata + Aptica di ricerca precisa abilitata + Disabilita l\'aptica di annullamento della ricerca + L\'aptica di annullamento della ricerca è disabilitata + L\'aptica di annullamento della ricerca è abilitata + Disabilita zoom aptico + Lo zoom aptico è disabilitato + Lo zoom aptico è abilitato + Se di recente hai modificato i dettagli di accesso al tuo account, disinstalla e reinstalla MicroG. @@ -1345,11 +1373,6 @@ Abilitare questa opzione può sbloccare qualità video più elevate" Il parametro di tracciamento della query viene rimosso dai link Il parametro di tracciamento della query non viene rimosso dai link - - Disabilita zoom aptico - Il feedback aptico è disabilitato - Il feedback aptico è abilitato - Forza la lingua audio originale Utilizza la lingua audio originale @@ -1377,7 +1400,7 @@ Abilitare questa opzione può sbloccare qualità video più elevate" Mostra il pulsante Velocità Video - Il pulsante è visibile + Il pulsante è visualizzato. Tieni premuto per ripristinare la velocità di riproduzione predefinita Il pulsante non è visibile @@ -1389,6 +1412,7 @@ Abilitare questa opzione può sbloccare qualità video più elevate" Le velocità personalizzate devono essere inferiori a %s Velocità di riproduzione personalizzata non valida Automatico + Velocità di riproduzione reimpostata su: %s Velocità personalizzata di tocca e tieni premuto Velocità di riproduzione tra 0-8 diff --git a/patches/src/main/resources/addresources/values-iw-rIL/strings.xml b/patches/src/main/resources/addresources/values-iw-rIL/strings.xml index e16a86143..5332cefcd 100644 --- a/patches/src/main/resources/addresources/values-iw-rIL/strings.xml +++ b/patches/src/main/resources/addresources/values-iw-rIL/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" הגדרות האם ברצונך להמשיך? איפוס + אפס צבע + צבע לא חוקי רענן והפעל מחדש הפעלה מחדש ייבוא @@ -42,6 +44,10 @@ Second \"item\" text" הגדרות ReVanced אופסו לברירת מחדל %d הגדרות יובאו ייבוא נכשל: %s + חפש בהגדרות + לא נמצאו תוצאות עבור \'%s\' + נסה מילת מפתח אחרת + להסיר מהיסטוריית חיפוש? הצג סמלי הגדרות ReVanced סמלי ההגדרות מוצגים סמלי ההגדרות אינם מוצגים @@ -93,6 +99,9 @@ Second \"item\" text" שחזר תפריטי הגדרות ישנים תפריטי הגדרות ישנים מוצגים תפריטי הגדרות ישנים אינם מוצגים + הצג הגדרות היסטוריית חיפוש + הגדרות היסטוריית חיפוש מוצגות + הגדרות היסטוריית חיפוש אינן מוצגות השבת הפעלה ברקע של Shorts @@ -108,6 +117,11 @@ Second \"item\" text" רשום פרוטוקול חוצץ יומני איתור באגים כוללים פרוטוקול חוצץ יומני איתור באגים אינם כוללים פרוטוקול חוצץ + "הפעלת הגדרה זו תתעד נתוני פריסה נוספים, כולל טקסט שעל המסך עבור רכיבי ממשק משתמש מסוימים. + +זה יכול לעזור לזהות רכיבים בעת יצירת מסננים מותאמים אישית. + +עם זאת, הפעלת הגדרה זו תתעד גם כמה נתוני משתמש כמו כתובת ה-IP שלך." רשום עקבות מחסנית יומני איתור באגים כוללים עקבות מחסנית יומני איתור באגים אינם כוללים עקבות מחסנית @@ -117,6 +131,15 @@ Second \"item\" text" "השבתת הודעות שגיאה קופצות מסתירה את כל הודעות השגיאה של ReVanced. לא תקבל הודעה על אירועים בלתי צפויים." + ייצוא יומני איתור באגים + מעתיק יומנים לאיתור באגים של Revanced ללוח ההעתקה + תיעוד איתור באגים מושבת + לא נמצאו יומנים + היומנים הועתקו + נכשל לייצא יומנים: $s + נקה יומני איתור באגים + מנקה את כל היומנים לאיתור באגים של Revanced המאוחסנים + היומנים נוקו הסתר כרטיסי אלבום @@ -154,11 +177,17 @@ Second \"item\" text" הלחצן מוסתר הלחצן מוצג + הסתר תוויות המלצה על סרטון + \'אנשים צפו גם\' ו\'את/ה עשוי/ה לאהוב\' מוסתרים + \'אנשים צפו גם\' ו\'את/ה עשוי/ה לאהוב\' מוצגים הסתר לחצן \'הצג עוד\' הלחצן מוסתר הלחצן מוצג + הסתר מדף כרטיסים + מדף כרטיסים מוסתר + מדף כרטיסים מוצג הסתר תגובות באמוג\'י מתוזמנות תגובות באמוג\'י מתוזמנות מוסתרות תגובות באמוג\'י מתוזמנות מוצגות @@ -228,6 +257,9 @@ Second \"item\" text" הסתר את \'סיכום הווידאו שנוצר על ידי בינה מלאכותית\' מדור סיכום הסרטון מוסתר מדור סיכום הסרטון מוצג + הסתר Ask + מדור Ask מוסתר + מדור Ask מוצג הסתר מאפיינים המדורים \'מקומות שמככבים בסרטון\', \'משחקים\', \'מוזיקה\', ו\'אנשים שאוזכרו\' מוסתרים המדורים \'מקומות שמככבים בסרטון\', \'משחקים\', \'מוזיקה\', ו\'אנשים שאוזכרו\' מוצגים @@ -349,9 +381,6 @@ Second \"item\" text" תכונה זו זמינה רק עבור מכשירים ישנים יותר" מודעות מסך מלא מוצגות - הסתר מודעות מכופתרות - מודעות מכפותרות מוסתרות - מודעות מכפותרות מוצגות הסתר תווית קידום מכירות בתשלום תווית קידום מכירות בתשלום מוסתרת תווית קידום מכירות בתשלום מוצגת @@ -462,10 +491,25 @@ Second \"item\" text" אטימות רקע שכבת-על של החלקה ערך אטימות בין 0 ל-100 אטימות החלקה חייבת להיות בין 0 ל-100 + צבע שכבת-על של החלקת בהירות + הצבע של סרגל ההתקדמות עבור בקרות בהירות + צבע שכבת-על של החלקת עוצמת קול + הצבע של סרגל ההתקדמות עבור בקרות עוצמת קול + גודל טקסט שכבת-על של החלקה + גודל הטקסט עבור שכבת-על של החלקה בין 1 ל-30 + גודל הטקסט חייב להיות בין 1 ל-30 סף גודל החלקה כמות הסף להתרחשות החלקה רגישות החלקה בעוצמת הקול כמה משתנה עוצמת השמע לכל החלקה + סגנון שכבת-על להחלקה + שכבת-על אופקית + שכבת-על אופקית (מזערית - עליונה) + שכבת-על אופקית (מזערית - מרכזית) + שכבת-על מעגלית + שכבת-על מעגלית (מזערית) + שכבת-על אנכית + שכבת-על אנכית (מזערית) הפעל החלקה כדי לשנות סרטונים החלקה במצב מסך מלא תשנה לסרטון הבא/הקודם החלקה במצב מסך מלא לא תשנה לסרטון הבא/הקודם @@ -507,6 +551,9 @@ Second \"item\" text" לחצן תודה מוצג + הסתר Ask + לחצן Ask מוסתר + לחצן Ask מוצג הסתר קליפ לחצן קליפ מוסתר @@ -703,6 +750,9 @@ Second \"item\" text" הסתר תווית מיקום תווית מיקום מוסתרת תווית מיקום מוצגת + הסתר את לוח התגובות + לוח התגובות מוסתר + לוח התגובות מוצג הסתר לחצן שמור מוזיקה לחצן שמור מוזיקה מוסתר לחצן שמור מוזיקה מוצג @@ -776,6 +826,9 @@ Second \"item\" text" סרטון מוצע של מסך סיום מוצג + הסתר שכבת-על של סרטונים קשורים במסך מלא + שכבת-על של סרטונים קשורים מוסתרת + שכבת-על של סרטונים קשורים מוצגת הסתר חותמת זמן של סרטון @@ -1063,11 +1116,6 @@ Second \"item\" text" %s שניות אטימות: צבע: - צבע שונה - צבע אופס - קוד צבע לא חוקי - אפס צבע - איפוס אודות הנתונים מסופקים על ידי SponsorBlock API. הקש כאן כדי ללמוד עוד ולראות הורדות עבור פלטפורמות אחרות @@ -1292,7 +1340,24 @@ Second \"item\" text" הגדרות GmsCore הגדרות עבור GmsCore + + משוב ברטט + שנה משוב ברטט + השבת משוב ברטט עבור פרקים + משוב ברטט עבור פרקים מושבת + משוב ברטט עבור פרקים מופעל + השבת משוב ברטט עבור דילוג מדויק + משוב ברטט עבור דילוג מדויק מושבת + משוב ברטט עבור דילוג מדויק מופעל + השבת משוב ברטט עבור ביטול דילוג + משוב ברטט עבור ביטול דילוג מושבת + משוב ברטט עבור ביטול דילוג מופעל + השבת משוב זום ברטט + משוב ברטט עבור זום מושבת + משוב ברטט עבור זום מופעל + + אם פרטי הכניסה לחשבונך השתנו לאחרונה, אז יש להסיר ולהתקין מחדש את MicroG. עקוף הפניות מחדש של URL @@ -1309,11 +1374,6 @@ Second \"item\" text" פרמטר מעקב של שאילתה מוסר מקישורים פרמטר מעקב של שאילתה אינו מוסר מקישורים - - השבת משוב זום ברטט - משוב ברטט מושבת - משוב ברטט מופעל - כפה שפת שמע מקורית שימוש בשפת שמע מקורית @@ -1341,7 +1401,7 @@ Second \"item\" text" הצג לחצן דו-שיח של מהירות - הלחצן מוצג + הלחצן מוצג. יש להקיש ולהחזיק כדי לאפס את מהירות ההפעלה לברירת מחדל הלחצן אינו מוצג @@ -1353,6 +1413,7 @@ Second \"item\" text" מהירויות מותאמות אישית חייבות להיות קטנות מ-%s מהירויות הפעלה מותאמות אישית לא חוקיות אוטומטי + מהירות ההפעלה אופסה ל: %s מהירות הקשה והחזקה מותאמת אישית מהירות הפעלה בין 0 ל-8 diff --git a/patches/src/main/resources/addresources/values-ja-rJP/strings.xml b/patches/src/main/resources/addresources/values-ja-rJP/strings.xml index bdae717f7..711b0f8aa 100644 --- a/patches/src/main/resources/addresources/values-ja-rJP/strings.xml +++ b/patches/src/main/resources/addresources/values-ja-rJP/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" 設定 続行しますか? リセット + 色をリセット + 色の値が無効です 更新して再起動 再起動 インポート @@ -42,8 +44,8 @@ Second \"item\" text" ReVanced 設定をデフォルトにリセット %d 個の設定をインポートしました インポート失敗: %s - 設定を検索 - \'%s\' に一致する設定は見つかりませんでした + ReVanced の設定を検索 + \'%s\' に一致する ReVanced の設定は見つかりませんでした 別のキーワードを試してください 検索履歴から削除しますか? ReVanced 設定にアイコンを表示する @@ -98,9 +100,9 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ 設定メニューを旧バージョンに戻す 旧バージョンの設定メニューが表示されます 通常の設定メニューが表示されます - 設定の検索履歴を表示する - 設定の検索履歴は表示されます - 設定の検索履歴は表示されません + 設定検索の履歴を表示する + 設定検索の履歴は表示されます + 設定検索の履歴は表示されません ショート動画のバックグラウンド再生を無効にする @@ -110,21 +112,35 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ デバッグ デバッグの設定 - デバッグ ログを有効にする - デバッグ ログは有効です - デバッグ ログは無効です + デバッグログを有効にする + デバッグログは有効です + デバッグログは無効です protocol buffer を記録する - デバッグ ログに protocol buffer が含まれます - デバッグ ログに protocol buffer は含まれません + protocol buffer はデバッグログに含まれます + protocol buffer はデバッグログに含まれません + "この設定を有効にすると、一部の UI コンポーネントの画面上のテキストなど、追加のレイアウト データがデバッグログに記録されます。 + +この追加されたデータは、カスタム フィルタを作成する際にコンポーネントを特定するのに役立つ可能性があります。 + +ただし、この機能によりデバッグログに追加で記録されるデータには、IP アドレスなど、一部のユーザーデータも含まれます。" stack trace を記録する - デバッグ ログにstack trace が含まれます - デバッグ ログにstack trace は含まれません + stack trace はデバッグログに含まれます + stack trace はデバッグログに含まれません ReVanced エラーのトーストを表示する エラー発生時にトースト ポップアップが表示されます エラーが発生してもトースト ポップアップは表示されません "この機能をオフにすると、すべてのReVanced エラー通知が非表示になります。 あらゆる予期せぬイベントが通知されなくなります。" + デバッグログをエクスポート + ReVanced のデバッグログをクリップボードにコピーします + デバッグログが無効です + ログが見つかりませんでした + ログをコピーしました + ログのエクスポートに失敗: $s + デバッグログを消去する + 保存されている ReVanced のデバッグログをすべて消去します + ログを消去しました アルバム情報を非表示 @@ -248,8 +264,8 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ 質問セクションは表示されません 質問セクションは表示されます 関連情報を非表示 - 注目の場所 / ゲーム / 音楽 / 言及された人物セクションは表示されません - 注目の場所 / ゲーム / 音楽 / 言及された人物セクションは表示されます + 注目の場所 / ゲーム / 音楽 / 言及されている人物セクションは表示されません + 注目の場所 / ゲーム / 音楽 / 言及されている人物セクションは表示されます チャプター セクションを非表示 チャプター セクションは表示されません チャプター セクションは表示されます @@ -368,9 +384,6 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ この機能は、古いデバイスでのみ利用できます" 全画面広告は、アプリ起動時に表示されます - ボタン付き広告を非表示 - ボタン付き広告は表示されません - ボタン付き広告は表示されます 「プロモーションを含みます」ボタンを非表示 「プロモーションを含みます」ボタンはプレーヤー画面に表示されません 「プロモーションを含みます」ボタンはプレーヤー画面に表示されます @@ -415,10 +428,10 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ URL をクリップボードにコピーしました タイムスタンプ付きの URL がコピーされました - 「動画の URL をコピー」ボタンを表示 + 「動画の URL をコピー」ボタンを表示する ボタンはオーバーレイに表示されます。タップすると動画の URL を、長押しするとタイムスタンプ付きの URL をそれぞれコピーできます ボタンはオーバーレイに表示されません - 「動画のタイムスタンプ付き URL をコピー」ボタンを表示 + 「動画のタイムスタンプ付き URL をコピー」ボタンを表示する ボタンはオーバーレイに表示されます。タップするとタイムスタンプ付きの URL を、長押しするとタイムスタンプなしの URL をそれぞれコピーできます ボタンはオーバーレイに表示されません @@ -443,9 +456,9 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ %s はインストールされていません。インストールしてください。 - シーク ジェスチャーを無効にする - シークバーを上へスワイプしても、何も起こりません - シークバーを上へスワイプすると、再生位置を細かく調整できます + 精密シークモードを無効にする + シークバーを上へスワイプしても、精密シークモードになりません + シークバーを上へスワイプすると、精密シークモードになります タップによるシークを有効にする @@ -481,9 +494,10 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ オーバーレイの背景の透明度 透明度の範囲は 0-100 で、0 が透明です スワイプ: 透明度の範囲は 0-100 です - オーバーレイのグラフの色 - スワイプ中の音量や明るさの現在値を視覚的に表示するグラフの色 - グラフの色の値が無効です + 明るさグラフの色 + スワイプ中の明るさの現在値を視覚的に表示するグラフの色 + 音量グラフの色 + スワイプ中の音量の現在値を視覚的に表示するグラフの色 オーバーレイのテキストサイズ スワイプ オーバーレイのテキストサイズ (1-30) テキストサイズの範囲は 1-30 です @@ -703,17 +717,17 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ ショート動画プレーヤー ショート動画プレーヤーの設定 - ホームフィードのショート動画を非表示 + ホームフィードでショート動画を非表示 ショート動画はホームフィードや関連動画に表示されません ショート動画はホームフィードや関連動画に表示されます - 登録チャンネル フィードのショート動画を非表示 + 登録チャンネル フィードでショート動画を非表示 ショート動画は登録チャンネル フィードに表示されません ショート動画は登録チャンネル フィードに表示されます - 検索結果のショート動画を非表示 + 検索結果でショート動画を非表示 ショート動画は検索結果に表示されません ショート動画は検索結果に表示されます - 再生履歴のショート動画を非表示 + 再生履歴でショート動画を非表示 ショート動画は再生履歴に表示されません ショート動画は再生履歴に表示されます @@ -739,6 +753,9 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ 位置情報ラベルを非表示 位置情報ラベルは表示されません 位置情報ラベルは表示されます + コメント パネルを非表示 + コメント パネルは表示されません + コメント パネルが表示されます 「音楽を保存」ボタンを非表示 「音楽を保存」ボタンは表示されません 「音楽を保存」ボタンは表示されます @@ -1099,11 +1116,6 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ %s 秒 透明度: 色: - 色を変更しました - 色がリセットされました - 色の値が無効です - 色をリセット - リセット SponsorBlock について SponsorBlock APIによって提供されるデータです。詳細はこちらをタップしてください。 @@ -1167,7 +1179,7 @@ Automotive レイアウト "スタート画面の変更は常時適用されます 制限事項: ツールバーの [戻る] ボタンが機能しない可能性があります" - スタート画面の変更はアプリ起動時にのみ適用されます + スタート画面の変更は、アプリ起動時にのみ適用されます ショート動画プレーヤーの再開を無効にする @@ -1296,8 +1308,8 @@ Automotive レイアウト ReVanced のお知らせを表示する - アプリ起動時にお知らせが表示されます - アプリ起動時にお知らせは表示されません + お知らせは、アプリ起動時に表示されます + お知らせは、アプリ起動時に表示されません アプリ起動時にお知らせを表示する お知らせの取得に失敗しました 閉じる @@ -1327,6 +1339,22 @@ Automotive レイアウト GmsCore 設定 GmsCore の設定 + + 触覚フィードバック + 触覚フィードバックの設定 + チャプターの触覚フィードバックを無効にする + チャプターの触覚フィードバックは無効です + チャプターの触覚フィードバックは有効です + 精密シークモードの触覚フィードバックを無効にする + 精密シークモードの触覚フィードバックは無効です + 精密シークモードの触覚フィードバックは有効です + シーク取り消しの触覚フィードバックを無効にする + シーク取り消しの触覚フィードバックは無効です + シーク取り消しの触覚フィードバックは有効です + ズームの触覚フィードバックを無効にする + ズームの触覚フィードバックは無効です + ズームの触覚フィードバックは有効です + 最近アカウントのログイン情報を変更した場合は、MicroG をアンインストールして再インストールしてください。 @@ -1345,15 +1373,10 @@ Automotive レイアウト 追跡パラメータはリンクから削除されます 追跡パラメータはリンクから削除されません - - ズームの触覚フィードバックを無効にする - ズームの触覚フィードバックは無効です - ズームの触覚フィードバックは有効です - - デフォルトの吹き替えを無効にする - デフォルトの吹き替えは無効です - デフォルトの吹き替えは有効です + デフォルトの吹き替え再生を無効にする + デフォルトの吹き替え再生は無効です + デフォルトの吹き替え再生は有効です この機能を使用するには、「動画ストリームを偽装する」のクライアントを iOS TV に変更してください @@ -1376,9 +1399,9 @@ Automotive レイアウト ショートの画質 (%1$s): %2$s - 再生速度設定ボタンを非表示 - 再生速度設定ボタンはオーバーレイに表示されます - 再生速度設定ボタンはオーバーレイに表示されません + 再生速度設定ボタンを表示する + ボタンはオーバーレイに表示されます。長押しすると、再生速度がデフォルトの値にリセットされます + ボタンはオーバーレイに表示されません カスタムした再生速度リストを使用する @@ -1389,8 +1412,9 @@ Automotive レイアウト 再生速度は %s 未満である必要があります カスタム再生速度リストが無効です 自動 + 再生速度をリセットしました: %s 長押し倍速再生の速度 - 長押し倍速再生の速度の値は 0-8 の範囲で、0 および 8 は含まれません + 再生速度の範囲は 0-8 で、0 および 8 は含まれません 再生速度の変更を保存する @@ -1416,7 +1440,7 @@ Automotive レイアウト 動画ストリームを偽装する - 動画の再生に失敗しないために、クライアントの動画ストリームを偽装します + 動画再生の失敗を回避するために、クライアントの動画ストリームを偽装します 動画ストリームを偽装する 動画ストリームは偽装されます "動画ストリームは偽装されません @@ -1437,7 +1461,7 @@ AVC は、最大解像度が 1080p であり、Opus オーディオ コーデッ Android クライアントの副作用 "• 「音声トラック」がフライアウト メニューに表示されない • 「一定音量」が利用できない -• 「デフォルトの吹き替えを無効にする」が利用できない" +• 「デフォルトの吹き替え再生を無効にする」が利用できない" • AV1 コーデックが利用できない • ログアウト時またはシークレット モード時に、子ども向け動画が再生されない可能性がある 統計情報に表示する @@ -1497,9 +1521,9 @@ AVC は、最大解像度が 1080p であり、Opus オーディオ コーデッ その他の設定 クライアントサイド広告 サーバー側サレストリーム広告 - デバッグ ログ - デバッグ ログは有効です - デバッグ ログは無効です + デバッグログ + デバッグログは有効です + デバッグログは無効です diff --git a/patches/src/main/resources/addresources/values-ka-rGE/strings.xml b/patches/src/main/resources/addresources/values-ka-rGE/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-ka-rGE/strings.xml +++ b/patches/src/main/resources/addresources/values-ka-rGE/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-kk-rKZ/strings.xml b/patches/src/main/resources/addresources/values-kk-rKZ/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-kk-rKZ/strings.xml +++ b/patches/src/main/resources/addresources/values-kk-rKZ/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-km-rKH/strings.xml b/patches/src/main/resources/addresources/values-km-rKH/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-km-rKH/strings.xml +++ b/patches/src/main/resources/addresources/values-km-rKH/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-kn-rIN/strings.xml b/patches/src/main/resources/addresources/values-kn-rIN/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-kn-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-kn-rIN/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-ko-rKR/strings.xml b/patches/src/main/resources/addresources/values-ko-rKR/strings.xml index d5bb6263a..4aee55458 100644 --- a/patches/src/main/resources/addresources/values-ko-rKR/strings.xml +++ b/patches/src/main/resources/addresources/values-ko-rKR/strings.xml @@ -21,20 +21,22 @@ Second \"item\" text" - 환경 검사에 실패함 + 환경 검사에 실패하였습니다 공식 홈페이지 열기 닫기 <h5>이 앱은 사용자가 패치하지 않은 것 같습니다.</h5><br>이 앱은 제대로 작동하지 않을 수 있으며, <b>사용 시 해롭거나 심지어 위험할 수도 있습니다</b>.<br><br>이러한 검사는 이 앱이 사전에 패치되었거나 다른 사람으로부터 받은 것임을 의미합니다:<br><br><small>%1$s</small><br>검증되고 안전한 앱을 사용하고 있는지 확인하려면 <b>이 앱을 삭제하고 직접 패치하는 것</b>을 강력히 권장합니다.<p><br>이 경고는 두 번만 표시됩니다. - 다른 기기에서 패치됨 - ReVanced Manager에 의해 설치되지 않음 - 10분 이상 전에 패치됨 - %s 일 전에 패치됨 - APK 빌드 날짜가 손상됨 + 다른 기기에서 패치되었습니다 + ReVanced Manager에 의해 설치되지 않았습니다 + 10분 이상 전에 패치되었습니다 + %s 일 전에 패치되었습니다 + APK 빌드 날짜가 손상되었습니다 설정 계속하시겠습니까? 초기화 + 색상 초기화 + 잘못된 색상입니다 새로고침 및 다시 시작 다시 시작 가져오기 @@ -110,11 +112,16 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배 디버깅 디버깅 옵션을 활성화하거나 비활성화할 수 있습니다 디버그 로깅 - 디버그 로그를 출력합니다 - 디버그 로그를 출력하지 않습니다 + 디버그 로깅을 활성화합니다 + 디버그 로깅을 비활성화합니다 로그 프로토콜 버퍼 디버그 로그에 프로토콜 버퍼를 포함합니다 디버그 로그에 프로토콜 버퍼를 포함하지 않습니다 + "이 설정을 활성화하면 일부 UI 구성 요소에 대한 화면 텍스트를 포함한 추가 레이아웃 데이터가 기록됩니다. + +이 설정은 사용자 정의 필터를 만들 경우에 구성 요소를 식별하는 데 도움이 될 수 있습니다. + +그러나 이 설정을 활성화하면 IP 주소와 같은 일부 사용자 데이터도 기록됩니다." 로그 스택 트레이스 디버그 로그에 로그 스택 트레이스를 포함합니다 디버그 로그에 로그 스택 트레이스를 포함하지 않습니다 @@ -124,6 +131,15 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배 "오류 메시지를 비활성화하면 모든 ReVanced 오류 알림이 숨겨집니다. 예상되지 않은 이벤트에 대한 알림을 받지 못할 수 있습니다." + 디버그 로그 내보내기 + ReVanced 디버그 로그를 클립보드에 복사할 수 있습니다 + 디버그 로깅이 비활성화되어 있습니다 + 디버그 로그를 찾을 수 없습니다 + 디버그 로그를 복사하였습니다 + 디버그 로그를 내보낼 수 없습니다: $s + 디버그 로그 지우기 + 저장된 모든 ReVanced 디버그 로그를 지울 수 있습니다 + 디버그 로그가 지워졌습니다 음악 앨범 카드 숨기기 @@ -245,7 +261,7 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배 AI 생성 동영상 요약 섹션 숨기기 AI 생성 동영상 요약 섹션이 숨겨집니다 AI 생성 동영상 요약 섹션이 표시됩니다 - 요청 버튼 숨기기 + 요청 섹션 숨기기 요청 섹션이 숨겨집니다 요청 섹션이 표시됩니다 속성 섹션 숨기기 @@ -368,9 +384,6 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배 이 설정은 구형 기기에서만 사용할 수 있습니다" 전체 화면 광고가 표시됩니다 - 버튼형 광고 숨기기 - 버튼형 광고가 숨겨집니다 - 버튼형 광고가 표시됩니다 유료 광고 포함 라벨 숨기기 유료 광고 포함 라벨이 숨겨집니다 유료 광고 포함 라벨이 표시됩니다 @@ -443,9 +456,9 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배 %s 는 설치되어 있지 않습니다. 설치하세요 - 세밀하게 보면서 탐색 제스처 비활성화하기 - 세밀하게 보면서 탐색 제스처를 비활성화합니다\n• 필름 스트립 오버레이 - 세밀하게 보면서 탐색 제스처를 활성화합니다\n• 필름 스트립 오버레이 + 세밀한 탐색 제스처 비활성화하기 + 세밀한 탐색 제스처를 비활성화합니다 + 세밀한 탐색 제스처를 활성화합니다 재생바 터치 조작 활성화하기 @@ -475,26 +488,27 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배 스와이프 오버레이 타임아웃 오버레이가 표시되는 시간을 지정할 수 있습니다 (밀리초) 스와이프 오버레이 배경 불투명도 - 스와이프 불투명도 값은 0-100 사이여야 합니다 - 스와이프 불투명도 값은 0-100 사이여야 합니다 - 스와이프 오버레이 진행바 색상 - 볼륨 및 밝기 조절 진행바 색상의 헥스 코드를 입력하세요 - 잘못된 진행바 헥스 코드입니다 + 배경 불투명도 값을 0-100 사이에서 지정할 수 있습니다 + 스와이프 배경 불투명도 값은 0-100 사이여야 합니다 + 스와이프 오버레이 밝기 조절바 색상 + 밝기 조절바 색상을 지정할 수 있습니다 + 스와이프 오버레이 볼륨 조절바 색상 + 볼륨 조절바 색상을 지정할 수 있습니다 스와이프 오버레이 텍스트 크기 - 스와이프 오버레이 텍스트 크기를 지정할 수 있습니다 (1-30) + 텍스트 크기를 1-30 사이에서 지정할 수 있습니다 텍스트 크기는 1-30 사이여야 합니다 스와이프 한계치 제스처 인식을 위해 얼마나 스와이프를 해야 할지를 지정할 수 있으며, 원하지 않은 제스처 인식을 방지할 수 있습니다 볼륨 스와이프 민감도 스와이프할 때마다 볼륨이 얼마나 변경되는지를 지정할 수 있습니다 스와이프 오버레이 스타일 - 가로 오버레이 - 가로 오버레이 (최소화 - 상단) - 가로 오버레이 (최소화 - 중앙) - 원형 오버레이 - 원형 오버레이 (최소화) - 세로 오버레이 - 세로 오버레이 (최소화) + 가로 + 가로 (최소화 - 상단) + 가로 (최소화 - 중앙) + 원형 + 원형 (최소화) + 세로 + 세로 (최소화) 스와이프 제스처로 동영상 전환 활성화하기 전체 화면 중앙에서 위로/아래로 스와이프하여 다음/이전 동영상으로 전환합니다 전체 화면 중앙에서 위로/아래로 스와이프하여 다음/이전 동영상으로 전환하지 않습니다 @@ -736,6 +750,9 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배 위치 라벨 숨기기 위치 라벨이 숨겨집니다 위치 라벨이 표시됩니다 + 댓글 패널 숨기기 + 댓글 패널이 숨겨집니다 + 댓글 패널이 표시됩니다 (재생목록에) 음악 저장 버튼 숨기기 (재생목록에) 음악 저장 버튼이 숨겨집니다 (재생목록에) 음악 저장 버튼이 표시됩니다 @@ -836,7 +853,7 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배 플레이어 오버레이 불투명도 - 불투명도 값은 0-100 사이이며, 0은 투명입니다 + 불투명도 값을 0-100 사이에서 지정할 수 있습니다 (투명: 0) 플레이어 오버레이 불투명도는 0-100 사이여야 합니다 @@ -882,10 +899,10 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배 네트워크 호출한 적이 없습니다 %d 건의 네트워크 호출이 이루어졌습니다 API 투표 가져오기, 시간 초과 횟수 - 네트워크 호출 시간 초과한 적이 없습니다 + 네트워크 호출이 시간 초과한 적이 없습니다 %d 건의 네트워크 호출이 시간 초과하였습니다 API 클라이언트 비율 제한 - 클라이언트 비율 제한한 적이 없습니다 + 클라이언트 비율을 제한한 적이 없습니다 %d 건의 클라이언트 비율 제한이 발생하였습니다 %d 밀리초 @@ -1099,11 +1116,6 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배 %s 초 불투명도: 색상: - 설정한 색상을 적용하였습니다 - 색상을 초기화하였습니다 - 잘못된 헥스 코드입니다 - 색상 초기화 - 초기화 정보 건너뛸 구간의 데이터는 SponsorBlock API에 의해 제공됩니다. 자세한 내용을 보려면 여기를 누르세요 @@ -1240,7 +1252,7 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배 화면 크기 초기값을 지정할 수 있습니다 (픽셀) 픽셀 크기는 %1$s-%2$s 사이여야 합니다 미니 플레이어 오버레이 불투명도 - 불투명도 값은 0-100 사이이며, 0은 투명입니다 + 불투명도 값을 0-100 사이에서 지정할 수 있습니다 (투명: 0) 미니 플레이어 오버레이 불투명도는 0-100 사이여야 합니다 @@ -1251,10 +1263,10 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배 사용자 정의 재생바 색상을 활성화합니다 기본 재생바 색상을 활성화합니다 사용자 정의 재생바 메인 색상 - 사용하고 싶은 재생바 메인 색상의 헥스 코드를 입력하세요 + 재생바 메인 색상을 지정할 수 있습니다 사용자 정의 재생바 보조 색상 - 사용하고 싶은 재생바 보조 색상의 헥스 코드를 입력하세요 - 잘못된 재생바 헥스 코드입니다 + 재생바 보조 색상을 지정할 수 있습니다 + 잘못된 재생바 색상입니다 이미지 표시 제한 국가 우회하기 @@ -1331,6 +1343,22 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요" GmsCore 설정 알림 수신을 위한 클라우드 메시징을 설정할 수 있습니다 + + 진동 피드백 + 진동 피드백을 활성화하거나 비활성화할 수 있습니다 + 챕터 진동 피드백 비활성화하기 + 챕터 진동 피드백을 비활성화합니다 + 챕터 진동 피드백을 활성화합니다 + 세밀한 탐색 진동 피드백 비활성화하기 + 세밀한 탐색 진동 피드백을 비활성화합니다 + 세밀한 탐색 진동 피드백을 활성화합니다 + 탐색 취소 진동 피드백 비활성화하기 + 탐색 취소 진동 피드백을 비활성화합니다 + 탐색 취소 진동 피드백을 활성화합니다 + 동영상 확대 진동 피드백 비활성화하기 + 동영상 확대 진동 피드백을 비활성화합니다 + 동영상 확대 진동 피드백을 활성화합니다 + 최근에 계정 로그인 정보를 변경했다면 MicroG를 삭제하고 다시 설치하세요. @@ -1349,11 +1377,6 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요" 링크를 공유할 때, URL에서 추적 쿼리 매개변수를 삭제합니다 (URL의 뒷부분 \'?si=...\' 이 삭제됨) 링크를 공유할 때, URL에서 추적 쿼리 매개변수를 삭제하지 않습니다 - - 동영상을 확대할 때, 진동 피드백 비활성화하기 - 진동 피드백을 비활성화합니다 - 진동 피드백을 활성화합니다 - 원본 오디오 스트림 언어 강제로 활성화하기 원본 오디오 스트림 언어를 사용 중입니다 @@ -1381,7 +1404,7 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요" 동영상 재생 속도 다이얼로그 버튼 표시하기 - 버튼을 표시합니다 + 버튼을 표시합니다\n\n• 버튼을 길게 누르면 동영상 재생 속도가 기본값으로 초기화됩니다 버튼을 표시하지 않습니다 @@ -1389,10 +1412,11 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요" 사용자 정의 동영상 재생 속도를 활성화합니다 사용자 정의 동영상 재생 속도를 비활성화합니다 사용자 정의 동영상 재생 속도 편집하기 - 사용하고 싶은 동영상 재생 속도 값을 추가 또는 변경할 수 있습니다 + 동영상 재생 속도 값을 추가 또는 변경할 수 있습니다 재생 속도 값은 %s배속보다 작아야 합니다 잘못된 사용자 정의 재생 속도 값입니다 자동 + 동영상 재생 속도를 %s 으로 초기화하였습니다 사용자 정의 길게 눌러서 동영상 재생 속도 화면을 길게 누르는 동안에 변경되는 동영상 재생 속도를 0-8 사이에서 지정할 수 있습니다 @@ -1501,8 +1525,8 @@ AVC의 최대 화질 값은 1080p이고, OPUS 코덱을 사용불가 및 HDR 동 클라이언트 광고 서버 광고 디버그 로깅 - 디버그 로그를 출력합니다 - 디버그 로그를 출력하지 않습니다 + 디버그 로깅을 활성화합니다 + 디버그 로깅을 비활성화합니다 diff --git a/patches/src/main/resources/addresources/values-ky-rKG/strings.xml b/patches/src/main/resources/addresources/values-ky-rKG/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-ky-rKG/strings.xml +++ b/patches/src/main/resources/addresources/values-ky-rKG/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-lo-rLA/strings.xml b/patches/src/main/resources/addresources/values-lo-rLA/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-lo-rLA/strings.xml +++ b/patches/src/main/resources/addresources/values-lo-rLA/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-lt-rLT/strings.xml b/patches/src/main/resources/addresources/values-lt-rLT/strings.xml index 4542a178e..a859643b6 100644 --- a/patches/src/main/resources/addresources/values-lt-rLT/strings.xml +++ b/patches/src/main/resources/addresources/values-lt-rLT/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Nustatymai Ar norite tęsti? Atstatyti + Atkurti spalvą + Neteisinga spalva Atnaujinti ir paleisti iš naujo Paleisti iš naujo Importuoti @@ -115,6 +117,11 @@ Palieskite mygtuką Tęsti ir leiskite optimizavimo pakeitimus." Žurnalų protokolo buferis Debugavimo žurnalai apima protokolo buferį Debugavimo žurnalai neapima protokolo buferio + "Įjungus šį nustatymą bus registruojami papildomi išdėstymo duomenys, įskaitant ekrane rodomą tekstą kai kuriems vartotojo sąsajos komponentams. + +Tai gali padėti identifikuoti komponentus kuriant pasirinktinius filtrus. + +Tačiau įjungus šį nustatymą taip pat bus registruojami kai kurie vartotojo duomenys, pvz., jūsų IP adresas." Žurnalų steko pėdsakai Debugavimo žurnalai apima steko pėdsaką Debugavimo žurnalai neapima steko pėdsako @@ -124,6 +131,15 @@ Palieskite mygtuką Tęsti ir leiskite optimizavimo pakeitimus." "Klaidos isjungimas paslepia visus „ReVanced“ klaidu pranesimus. Apie netikėtus įvykius nebus pranešta." + Eksportuoti derinimo žurnalus + Nukopijuoja „ReVanced“ derinimo žurnalus į mainų sritį + Derinimo žurnalų registravimas išjungtas + Žurnalų nerasta + Žurnalai nukopijuoti + Nepavyko eksportuoti žurnalų: $s + Išvalyti derinimo žurnalus + Išvalo visus išsaugotus „ReVanced“ derinimo žurnalus + Žurnalai išvalyti Slėpti albumo korteles @@ -365,9 +381,6 @@ Apribojimai Ši funkcija yra prieinama tik senesniuose įrenginiuose" Viso ekrano reklamos yra rodomos - Slėpti reklamas su mygtukais - Reklamos su mygtukais yra paslėptos - Reklamos su mygtukais yra rodomos Slėpti apmokėtos reklamos etiketę Apmokėtos reklamos etiketė yra paslėpta Apmokėtos reklamos etiketė yra rodoma @@ -478,9 +491,10 @@ Reguliuokite garsumą braukdami vertikaliai dešinėje ekrano pusėje" Užšliaukite dangos nušveitimo fono permatinumas Permatnumo vertė nuo 0 iki 100 Slinkties permatnumas turi būti nuo 0 iki 100 - Perbraukimo perdangos eigos juostos spalva - Garso ir ryškumo valdiklių eigos juostos spalva - Netinkama eigos juostos spalva + Perbraukimo perdangos ryškumo spalva + Ryškumo valdiklių eigos juostos spalva + Perbraukimo perdangos garsumo spalva + Garsumo valdiklių eigos juostos spalva Perbraukimo perdangos teksto dydis Perbraukimo perdangos teksto dydis turi būti nuo 1 iki 30 Teksto dydis turi būti nuo 1 iki 30 @@ -734,6 +748,9 @@ Jei pakeitus šį nustatymą neįsigalioja, pabandykite perjungti į inkognito r Slėpti vietovės etiketę Vietovės etiketė paslėpta Vietovės etiketė rodoma + Slėpti komentarų skydelį + Komentarų skydelis yra paslėptas + Komentarų skydelis rodomas Paslėpti mygtuką „Įrašyti muziką\" \"Išsaugoti muziką\" mygtukas paslėptas \"Išsaugoti muziką\" mygtukas rodomas @@ -1098,11 +1115,6 @@ Ar paruošta pateikti?" %s sekundės Neskaidrumas: Spalva: - Spalva pakeista - Spalva atstatyta - Netinkamas spalvos kodas - Atstatyti spalvą - Atstatyti Apie Duomenys pateikiami per \"SponsorBlock\" API. Bakstelėkite čia, kad sužinotumėte daugiau ir pamatytumėte atsisiuntimus kitoms platformoms @@ -1327,6 +1339,22 @@ Gali būti atrakinta aukštesnės vaizdo įrašų kokybės, bet galite patirti v „GmsCore“ nustatymai „GmsCore“ nustatymai + + Vibracijos grįžtamasis ryšys + Keisti vibracijos grįžtamąjį ryšį + Išjungti skyrių vibraciją + Skyrių vibracija išjungta + Skyrių vibracija įjungta + Išjungti tikslaus slinkimo vibraciją + Tikslus ieškojimo vibracijos grįžtamasis ryšys išjungtas + Tikslaus slinkimo vibracija įjungta + Išjungti ieškojimo anuliavimo vibraciją + Ieškojimo anuliavimo vibracijos grįžtamasis ryšys išjungtas + Ieškojimo anuliavimo vibracijos grįžtamasis ryšys įjungtas + Išjungti priartinimo vibraciją + Priartinimo vibracija išjungta + Priartinimo vibracija įjungta + Jei neseniai pakeitėte savo paskyros prisijungimo duomenis, išdiekite ir iš naujo įdiekite „MicroG“. @@ -1345,11 +1373,6 @@ Gali būti atrakinta aukštesnės vaizdo įrašų kokybės, bet galite patirti v Stebėjimo užklausų parametras pašalinamas iš nuorodų Stebėjimo užklausų parametras nėra pašalinamas iš nuorodų - - Išjungti priartinimo vibraciją - Vibracija išjungta - Vibracija įjungta - Priversti originalią garso kalbą Naudojama originali garso kalba @@ -1377,7 +1400,7 @@ Gali būti atrakinta aukštesnės vaizdo įrašų kokybės, bet galite patirti v Rodyti greičio dialogo mygtuką - Mygtukas rodomas + Mygtukas rodomas. Palieskite ir palaikykite, kad atkūrimo greitį nustatytumėte į numatytąjį. Mygtukas nerodomas @@ -1389,6 +1412,7 @@ Gali būti atrakinta aukštesnės vaizdo įrašų kokybės, bet galite patirti v Pasirinktinis greitis turi būti mažesnis nei %s Netinkamas pasirinktinis atkūrimo greitis Automatinis + Atkūrimo greitis nustatytas iš naujo: %s Pritaikytas bakstelėjimo ir laikymo greitis Atkūrimo greitis: nuo 0 iki 8 diff --git a/patches/src/main/resources/addresources/values-lv-rLV/strings.xml b/patches/src/main/resources/addresources/values-lv-rLV/strings.xml index 149e74ac4..e4955efa5 100644 --- a/patches/src/main/resources/addresources/values-lv-rLV/strings.xml +++ b/patches/src/main/resources/addresources/values-lv-rLV/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Iestatījumi Vai vēlaties turpināt? Atiestatīt + Atiestatīt krāsu + Nederīga krāsa Atjaunināt un restartēt Restartēt Importēt @@ -115,6 +117,11 @@ Nospiediet turpināt pogu un atļaujiet optimizācijas izmaiņas." Reģistrēt protokola buferi Atkļūdošanas žurnāli ietver protokola buferi Atkļūdošanas žurnāli neietver protokola buferi + "Iespējojot šo iestatījumu, tiks reģistrēti papildu izkārtojuma dati, tostarp teksta attēlojums ekrānā dažiem lietotāja interfeisa komponentiem. + +Tas var palīdzēt identificēt komponentus, veidojot pielāgotus filtrus. + +Tomēr, iespējojot šo iestatījumu, tiks reģistrēti arī daži lietotāja dati, piemēram, jūsu IP adrese." Reģistrēt steka izsekošanu Atkļūdošanas žurnāli ietver steka izsekošanu Atkļūdošanas žurnāli neietver steka izsekošanu @@ -124,6 +131,15 @@ Nospiediet turpināt pogu un atļaujiet optimizācijas izmaiņas." "Kļūdu paziņojumu izslēgšana paslēpj visus ReVanced kļūdu paziņojumus. Jūs netiksit informēts par neparedzētiem notikumiem." + Eksportēt atkļūdošanas žurnālus + Kopē ReVanced atkļūdošanas žurnālus starpliktuvē + Atkļūdošanas žurnālu reģistrēšana ir atspējota + Žurnāli nav atrasti + Žurnāli ir kopēti + Neizdevās eksportēt žurnālus: $s + Notīrīt atkļūdošanas žurnālus + Notīra visus saglabātos ReVanced atkļūdošanas žurnālus + Žurnāli ir notīrīti Paslēpt albumu kartītes @@ -365,9 +381,6 @@ Ierobežojumi Šī funkcija ir pieejama tikai vecākiem ierīcēm" Pilnekrāna reklāmas ir redzamas - Paslēpt reklāmas ar pogām - Reklāmas ar pogām ir paslēptas - Reklāmas ar pogām ir redzamas Paslēpt apmaksātas reklāmas etiķeti Apmaksātas reklāmas etiķete ir paslēpta Apmaksātas reklāmas etiķete ir redzama @@ -478,9 +491,10 @@ Regulējiet skaļumu, velkot vertikāli ekrāna labajā pusē" Pārvilkšanas pārklājuma fona necaurredzamība Necaurredzamības vērtība no 0 līdz 100 Pārvilkšanas necaurredzamībai jābūt no 0 līdz 100 - Pārvelciet pārklājuma progresa joslas krāsu - Skaļuma un spilgtuma vadīklu progresa joslas krāsa - Nederīga progresa joslas krāsa + Velciet pārklājuma spilgtuma krāsu + Spilgtuma vadīklu progresa joslas krāsa + Velciet pārklājuma skaļuma krāsu + Skaļuma vadīklu progresa joslas krāsa Pārvelciet pārklājuma teksta lielumu Pārvelciet pārklājuma teksta lielumu starp 1–30 Teksta lielumam jābūt starp 1–30 @@ -736,6 +750,9 @@ Lai parādītu audio celiņu izvēlni, mainiet \"Video straumju viltošana\" uz Paslēpt atrašanās vietas nosaukumu Atrašanās vietas nosaukums ir paslēpts Atrašanās vietas nosaukums ir redzams + Slēpt komentāru paneli + Komentāru panelis ir paslēpts + Komentāru panelis ir redzams Paslēpt pogu \"Saglabāt mūziku\" “Saglabāt mūziku” poga ir paslēpta “Saglabāt mūziku” poga ir redzama @@ -1098,11 +1115,6 @@ Vai esat gatavs iesniegt?" %s sekundes Necaurredzamība: Krāsa: - Krāsa mainīta - Krāsa atiestatīta - Nederīgs krāsas kods - Atiestatīt krāsu - Atiestatīt Par Dati tiek sniegti no SponsorBlock API. Pieskarieties šeit, lai uzzinātu vairāk un skatītu lejupielādes citām platformām @@ -1327,6 +1339,22 @@ Var tikt atbloķētas augstākas video kvalitātes, taču var rasties video atsk GmsCore iestatījumi GmsCore iestatījumi + + Haptiskā atgriezeniskā saite + Mainīt haptisko atgriezenisko saiti + Atspējot nodaļu haptisko atgriezenisko saiti + Nodaļu haptiskā atgriezeniskā saite ir atspējota + Nodaļu haptiskā atgriezeniskā saite ir iespējota + Atspējot precīzas meklēšanas haptisko atgriezenisko saiti + Precīza meklēšanas haptiskā atgriezeniskā saite ir atspējota + Precīzas meklēšanas haptiskā atgriezeniskā saite ir iespējota + Atspējot meklēšanas atsaukšanas haptisko atgriezenisko saiti + Meklēšanas atsaukšanas haptiskā atgriezeniskā saite ir atspējota + Meklēšanas atsaukšanas haptiskā atgriezeniskā saite ir iespējota + Atspējot tālummaiņas haptisko atgriezenisko saiti + Tālummaiņas haptiskā atgriezeniskā saite ir atspējota + Tālummaiņas haptiskā atgriezeniskā saite ir iespējota + Ja nesen mainījāt sava konta pieteikšanās informāciju, atinstalējiet un atkārtoti instalējiet MicroG. @@ -1345,11 +1373,6 @@ Var tikt atbloķētas augstākas video kvalitātes, taču var rasties video atsk Izsekošanas vaicājuma parametrs tiek noņemts no saitēm Izsekošanas vaicājuma parametrs netiek noņemts no saitēm - - Atspējot tālummaiņas haptisko atgriezenisko saiti - Haptiskā atgriezeniskā saite ir atspējota - Haptiskā atgriezeniskā saite ir iespējota - Piespiest oriģinālo audio valodu Izmantot oriģinālo audio valodu @@ -1377,7 +1400,7 @@ Var tikt atbloķētas augstākas video kvalitātes, taču var rasties video atsk Rādīt ātruma dialoga pogu - Poga tiek rādīta + Poga ir redzama. Pieskarieties un turiet, lai atiestatītu atskaņošanas ātrumu uz noklusējuma Poga netiek rādīta @@ -1389,6 +1412,7 @@ Var tikt atbloķētas augstākas video kvalitātes, taču var rasties video atsk Pielāgoti ātrumi ir jābūt mazākiem par %s Nederīgi pielāgoti video atskaņošanas ātrumi Automātiski + Atskaņošanas ātrums atiestatīts uz: %s Pielāgots pieskaršanās un turēšanas ātrums Atskaņošanas ātrums no 0 līdz 8 diff --git a/patches/src/main/resources/addresources/values-mk-rMK/strings.xml b/patches/src/main/resources/addresources/values-mk-rMK/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-mk-rMK/strings.xml +++ b/patches/src/main/resources/addresources/values-mk-rMK/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-ml-rIN/strings.xml b/patches/src/main/resources/addresources/values-ml-rIN/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-ml-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-ml-rIN/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-mn-rMN/strings.xml b/patches/src/main/resources/addresources/values-mn-rMN/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-mn-rMN/strings.xml +++ b/patches/src/main/resources/addresources/values-mn-rMN/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-mr-rIN/strings.xml b/patches/src/main/resources/addresources/values-mr-rIN/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-mr-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-mr-rIN/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-ms-rMY/strings.xml b/patches/src/main/resources/addresources/values-ms-rMY/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-ms-rMY/strings.xml +++ b/patches/src/main/resources/addresources/values-ms-rMY/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-my-rMM/strings.xml b/patches/src/main/resources/addresources/values-my-rMM/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-my-rMM/strings.xml +++ b/patches/src/main/resources/addresources/values-my-rMM/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-nb-rNO/strings.xml b/patches/src/main/resources/addresources/values-nb-rNO/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-nb-rNO/strings.xml +++ b/patches/src/main/resources/addresources/values-nb-rNO/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-ne-rIN/strings.xml b/patches/src/main/resources/addresources/values-ne-rIN/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-ne-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-ne-rIN/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-nl-rNL/strings.xml b/patches/src/main/resources/addresources/values-nl-rNL/strings.xml index 3e613df68..1512b5245 100644 --- a/patches/src/main/resources/addresources/values-nl-rNL/strings.xml +++ b/patches/src/main/resources/addresources/values-nl-rNL/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Instellingen Wilt u doorgaan? Terugzetten + Kleur opnieuw instellen + Ongeldige kleur Vernieuwen en opnieuw starten Opnieuw starten Importeren @@ -115,6 +117,11 @@ Tik op de knop Doorgaan en sta wijzigingen in de optimalisatie toe." Stamlogboek Debuglogboeken bevatten stamlogboek Debuglogboeken bevatten geen stamlogboek + "Als u deze instelling inschakelt, worden extra lay-outgegevens geregistreerd, waaronder tekst op het scherm voor sommige UI-componenten. + +Dit kan helpen bij het identificeren van componenten bij het maken van aangepaste filters. + +Als u dit inschakelt, worden echter ook bepaalde gebruikersgegevens, zoals uw IP-adres, vastgelegd." Stacktraces loggen Debuglogboeken bevatten stacktrace Debuglogs bevatten geen stacktrace @@ -124,6 +131,15 @@ Tik op de knop Doorgaan en sta wijzigingen in de optimalisatie toe." "Het uitschakelen van foutmeldingen verbergt alle ReVanced-foutmeldingen. U wordt niet op de hoogte gesteld van onverwachte gebeurtenissen." + Foutopsporingslogboeken exporteren + Kopieert ReVanced-foutopsporingslogboeken naar het klembord + Foutopsporing is uitgeschakeld + Geen logboeken gevonden + Logboeken gekopieerd + Kan logboeken niet exporteren: $s + Foutopsporingslogboeken wissen + Wist alle opgeslagen ReVanced-foutopsporingslogboeken + Logboeken gewist Verberg albumkaarten @@ -365,9 +381,6 @@ Beperkingen Deze functie is alleen beschikbaar voor oudere apparaten" Volledig scherm advertenties worden getoond - Advertenties met knoppen verbergen - Advertenties met knoppen zijn verborgen - Advertenties met knoppen worden getoond Betaalde promotielabel verbergen Betaalde promotielabel is verborgen Betaalde promotielabel wordt getoond @@ -478,9 +491,10 @@ Pas het volume aan door verticaal over de rechterkant van het scherm te vegen"Dekking van de Swipe overlay Dekking tussen 0-100 Dekking moet tussen 0-100 zijn - Kleur van voortgangsbalk voor swipe-overlay - De kleur van de voortgangsbalk voor volume- en helderheidsbediening - Ongeldige kleur voor de voortgangsbalk + Veeg-overlay helderheidskleur + De kleur van de voortgangsbalk voor helderheidsbediening + Veeg-overlay volumekleur + De kleur van de voortgangsbalk voor volumebediening Tekengrootte swipe-overlay De tekstgrootte voor swipe-overlay tussen 1-30 De tekstgrootte moet tussen 1-30 liggen @@ -736,6 +750,9 @@ Om het audiotrackmenu weer te geven, wijzigt u 'Videostreams vervalsen' in iOS T Verberg locatie-etiket Locatie-etiket is verborgen Locatie-etiket wordt weergegeven + Commentaarvenster verbergen + Commentaarvenster is verborgen + Het commentaarvenster wordt weergegeven Verberg de knop \"Muziek opslaan\" Muziek opslaan-knop is verborgen Muziek opslaan-knop wordt weergegeven @@ -1099,11 +1116,6 @@ Klaar om in te dienen?" %s seconden Ondoorzichtigheid: Kleur: - Kleur gewijzigd - Kleur gereset - Ongeldige kleurcode - Kleur resetten - Herstellen naar standaard Over Gegevens worden geleverd door de SponsorBlock API. Tik hier om meer te weten te komen en downloads te bekijken voor andere platforms @@ -1326,6 +1338,22 @@ Het inschakelen hiervan kan hogere videokwaliteiten ontgrendelen" GmsCore-instellingen Instellingen voor GmsCore + + Haptische feedback + Haptische feedback wijzigen + Hoofdstuk-haptiek uitschakelen + Hoofdstuk-haptiek is uitgeschakeld + Hoofdstuk-haptiek is ingeschakeld + Precisie-zoekhaptiek uitschakelen + Precieze haptiek voor zoeken is uitgeschakeld + Precisie-zoekhaptiek is ingeschakeld + Haptiek voor ongedaan maken van zoeken uitschakelen + Haptiek voor ongedaan maken van zoeken is uitgeschakeld + Haptiek voor ongedaan maken van zoeken is ingeschakeld + Zoom-haptics uitschakelen + Zoom-haptics is uitgeschakeld + Zoom-haptics is ingeschakeld + Als u onlangs de inloggegevens van uw account hebt gewijzigd, verwijder dan MicroG en installeer het opnieuw. @@ -1344,11 +1372,6 @@ Het inschakelen hiervan kan hogere videokwaliteiten ontgrendelen" Tracking-queryparameter wordt verwijderd uit koppelingen Tracking-queryparameter wordt niet verwijderd uit koppelingen - - Zoom-haptics uitschakelen - Haptics zijn uitgeschakeld - Haptics zijn ingeschakeld - Forceer de originele audiotaal De oorspronkelijke audiotaal gebruiken @@ -1376,7 +1399,7 @@ Het inschakelen hiervan kan hogere videokwaliteiten ontgrendelen" Snelheidsdialoogknop weergeven - Knop wordt weergegeven + De knop wordt weergegeven. Tik en houd vast om de afspeelsnelheid terug te zetten naar de standaardwaarde Knop wordt niet weergegeven @@ -1388,6 +1411,7 @@ Het inschakelen hiervan kan hogere videokwaliteiten ontgrendelen" Aangepaste snelheden moeten lager zijn dan %s Ongeldige aangepaste afspeelsnelheden Automatisch + Afspeelsnelheid hersteld naar: %s De snelheid van aangepast tikken en vasthouden Afspeelsnelheid tussen 0-8 diff --git a/patches/src/main/resources/addresources/values-or-rIN/strings.xml b/patches/src/main/resources/addresources/values-or-rIN/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-or-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-or-rIN/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-pa-rIN/strings.xml b/patches/src/main/resources/addresources/values-pa-rIN/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-pa-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-pa-rIN/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-pl-rPL/strings.xml b/patches/src/main/resources/addresources/values-pl-rPL/strings.xml index 552507398..a284b13fc 100644 --- a/patches/src/main/resources/addresources/values-pl-rPL/strings.xml +++ b/patches/src/main/resources/addresources/values-pl-rPL/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Ustawienia Czy chcesz kontynuować? Zresetuj + Zresetuj kolor + Nieprawidłowy kolor Odśwież i uruchom ponownie Uruchom ponownie Zaimportuj @@ -115,6 +117,7 @@ Naciśnij przycisk Kontynuuj i zezwól na zmiany optymalizacji." Logi protokołu bufora Logi do debugowania zawierają bufory Logi do debugowania nie zawierają buforów + "Włączenie tego ustawienia spowoduje rejestrowanie dodatkowych danych układu, w tym tekstu na ekranie dla niektórych komponentów interfejsu użytkownika.\n\nMoże to pomóc w identyfikacji komponentów podczas tworzenia filtrów niestandardowych.\n\nWłączenie tej opcji spowoduje jednak również rejestrowanie niektórych danych użytkownika, takich jak adres IP." Logi śladów stosów Logi do debugowania zawierają ślady stosów Logi do debugowania nie zawierają śladów stosów @@ -124,6 +127,15 @@ Naciśnij przycisk Kontynuuj i zezwól na zmiany optymalizacji." "Wyłączenie notyfikacji błędów ukrywa wszystkie powiadomienia o błędach ReVanced. Nie będziesz informowany o żadnych nieoczekiwanych zdarzeniach." + Eksportuj dzienniki debugowania + Kopiuje dzienniki debugowania ReVanced do schowka + Rejestrowanie debugowania jest wyłączone + Nie znaleziono dzienników + Dzienniki skopiowane + Nie udało się wyeksportować dzienników: $s + Wyczyść dzienniki debugowania + Czyści wszystkie zapisane dzienniki debugowania ReVanced + Dzienniki wyczyszczone Ukryj karty albumów @@ -365,9 +377,6 @@ Ograniczenia Ta funkcja jest dostępna tylko dla starszych urządzeń" Reklamy pełnoekranowe są widoczne - Reklamy z przyciskami - Reklamy z przyciskami są ukryte - Reklamy z przyciskami są widoczne Etykiety płatnej promocji Etykiety płatnej promocji są ukryte Etykiety płatnej promocji są widoczne @@ -478,9 +487,10 @@ Dostosuj głośność, przesuwając pionowo po prawej stronie ekranu" Przejrzystość tła nakładki przesuwania Wartość przezroczystości od 0 do 100 Przezroczystość przesuwania musi być między 0 a 100 - Kolor paska postępu nakładki przesunięcia - Kolor paska postępu dla regulacji głośności i jasności - Nieprawidłowy kolor paska postępu + Kolor nakładki przesunięcia dla jasności + Kolor paska postępu dla elementów sterujących jasnością + Kolor nakładki przesunięcia dla głośności + Kolor paska postępu dla elementów sterujących głośnością Rozmiar tekstu nakładki przesuwania Rozmiar tekstu dla nakładki przesunięcia między 1-30 Rozmiar tekstu musi mieścić się w przedziale 1-30 @@ -736,6 +746,9 @@ Aby pokazać menu ścieżki audio, zmień opcję „Fałszuj strumienie wideo” Etykieta lokalizacji Etykieta lokalizacji jest ukryta Etykieta lokalizacji jest widoczna + Ukryj panel komentarzy + Panel komentarzy jest ukryty + Panel komentarzy jest wyświetlany Ukryj przycisk \"Zapisz muzykę\" Przycisk od zapisywania muzyki jest ukryty Przycisk od zapisywania muzyki jest widoczny @@ -1099,11 +1112,6 @@ Gotowy do przesłania?" %s sekund Krycie: Kolor: - Zmieniono kolor - Zresetowano kolor - Nieprawidłowy kod koloru - Resetuj kolor - Resetuj O aplikacji Dane są dostarczane przez API SponsorBlock. Dotknij tutaj, aby dowiedzieć się więcej i pobrać na inne platformy @@ -1328,6 +1336,22 @@ Włączenie tego może odblokować wyższe jakości wideo" Ustawienia GmsCore Ustawienia GmsCore + + Informacje zwrotne haptyczne + Zmień informacje zwrotne haptyczne + Wyłącz haptykę rozdziałów + Haptyka rozdziałów jest wyłączona + Haptyka rozdziałów jest włączona + Wyłącz haptykę precyzyjnego przewijania + Haptyka precyzyjnego wyszukiwania jest wyłączona + Haptyka precyzyjnego przewijania jest włączona + Wyłącz haptykę cofania wyszukiwania + Haptyka cofania wyszukiwania jest wyłączona + Haptyka cofania wyszukiwania jest włączona + Haptyka przy zoomowaniu + Haptyka przybliżania jest wyłączona + Haptyka przybliżania jest włączona + Jeśli niedawno zmieniono dane logowania do konta, odinstaluj i zainstaluj ponownie MicroG. @@ -1346,11 +1370,6 @@ Włączenie tego może odblokować wyższe jakości wideo" Parametr zapytania śledzenia jest usuwany z linków Parametr zapytania śledzenia nie jest usuwany z linków - - Haptyka przy zoomowaniu - Haptyka jest wyłączona - Haptyka jest włączona - Wymuś język oryginalnego dźwięku Używanie oryginalnego języka audio @@ -1378,7 +1397,7 @@ Włączenie tego może odblokować wyższe jakości wideo" Przycisk od prędkości - Przycisk jest widoczny + Przycisk jest widoczny. Dotknij i przytrzymaj, aby zresetować prędkość odtwarzania do domyślnej Przycisk nie jest widoczny @@ -1390,6 +1409,7 @@ Włączenie tego może odblokować wyższe jakości wideo" Prędkości niestandardowe muszą być mniejsze niż %s Nieprawidłowe prędkości odtwarzania niestandardowego Automatyczne + Prędkość odtwarzania zresetowana do: %s Szybkość dostosowywania dotknięciem i przytrzymaniem Prędkość odtwarzania w granicach 0-8 diff --git a/patches/src/main/resources/addresources/values-pt-rBR/strings.xml b/patches/src/main/resources/addresources/values-pt-rBR/strings.xml index 3d6027222..707784227 100644 --- a/patches/src/main/resources/addresources/values-pt-rBR/strings.xml +++ b/patches/src/main/resources/addresources/values-pt-rBR/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Configurações Você deseja prosseguir? Resetar + Redefinir cor + Cor inválida Atualizar e reiniciar Reiniciar Importar @@ -113,6 +115,11 @@ Toque no botão continuar e permita as mudanças de otimização. " Registro de buffer de protocolo Registro de depuração incluem buffer de protocolo Registro de depuração não incluem buffer de protocolo + "Ativar esta configuração registrará dados de layout adicionais, incluindo texto na tela para alguns componentes da IU. + +Isso pode ajudar a identificar componentes ao criar filtros personalizados. + +No entanto, ativar isso também registrará alguns dados do usuário, como seu endereço IP." Registro de rastreamento em pilha Registro de depuração incluem rastreamento em pilha Registro de depuração não incluem rastreamento em pilha @@ -122,6 +129,15 @@ Toque no botão continuar e permita as mudanças de otimização. " "Desligar as notificações de erro oculta todas as notificações de erro do ReVanced. Você não será notificado sobre nenhum evento inesperado." + Exportar registros de depuração + Copia os registros de depuração do ReVanced para a área de transferência + O registro de depuração está desativado + Nenhum registro encontrado + Registros copiados + Falha ao exportar os registros: $s + Limpar registros de depuração + Limpa todos os registros de depuração do ReVanced armazenados + Registros limpos Ocultar cartões de álbum @@ -363,9 +379,6 @@ Linitações Este recurso está disponível apenas para dispositivos mais antigos" Anúncios em tela cheia não estão ocultos - Ocultar anúncios com botões - Os anúncios com botões estão ocultos - Anúncios com botões não estão ocultos Ocultar o rótulo de promoção paga O rótulo de promoção paga está oculto O rótulo de promoção paga é mostrada @@ -476,9 +489,10 @@ Ajuste o volume deslizando verticalmente no lado direito da tela" Opacidade do plano de fundo de sobreposição de deslize Valor da opacidade entre 0-100 A opacidade do deslizar deve estar entre 0-100 - Cor da barra de progresso da sobreposição de deslize - A cor da barra de progresso para controles de volume e brilho - Cor da barra de progresso inválida + Cor da barra de brilho da sobreposição de deslize + A cor da barra de progresso para controles de brilho + Cor da barra de volume da sobreposição de deslize + A cor da barra de progresso para controles de volume Tamanho do texto da sobreposição de deslize O tamanho do texto para sobreposição de deslize entre 1 e 30 O tamanho do texto deve estar entre 1 e 30 @@ -734,6 +748,9 @@ Para exibir o menu da faixa de áudio, altere \"Spoof video streams\" para iOS T Ocultar rótulo de localização Rótulo de localização está oculto Rótulo de localização é mostrado + Ocultar painel de comentários + Painel de comentários está oculto + O painel de comentários é mostrado Ocultar botão Salvar música O botão Salvar música está oculto O botão Salvar música será exibido @@ -847,7 +864,7 @@ Configurações → Reprodução → Reproduzir próximo vídeo automaticamente" Recarregue o vídeo para votar usando o Return YouTube Dislike Oculto pelo proprietário - Não gostei está oculto + Não gostei é mostrado Não gostei não está oculto Mostrar não gostei no Shorts "\"Não gostei\" nos Shorts são mostrados @@ -1096,11 +1113,6 @@ Pronto para enviar?" %s segundos Opacidade: Cor: - Cor alterada - Redefinir cor - Código de cor inválido - Redefinir cor - Resetar Sobre Os dados são fornecidos pela API do SponsorBlock. Toque aqui para aprender mais e ver como baixar para outras plataformas @@ -1325,6 +1337,22 @@ Habilitar isso pode desbloquear qualidades de vídeo mais altas" Configurações do GmsCore Configurações do GmsCore + + Feedback tátil + Alterar feedback tátil + Desativar haptics de capítulos + Haptics de capítulos desativado + Haptics de capítulos ativado + Desativar haptics de busca precisa + O feedback tátil de busca precisa está desativado + Haptics de busca precisa ativado + Desativar feedback tátil de desfazer busca + O feedback tátil de desfazer busca está desativado + O feedback tátil de desfazer busca está ativado + Desativar zoom tátil + O zoom tátil está desativado + O zoom tátil está ativado + Se você alterou recentemente os detalhes de login da sua conta, desinstale e reinstale o MicroG. @@ -1343,11 +1371,6 @@ Habilitar isso pode desbloquear qualidades de vídeo mais altas" Parâmetro da consulta de rastreamento foi removido dos links Parâmetro da consulta de rastreamento não foi removido dos links - - Desativar zoom tátil - Zoom tátil está ativado - Zoom tátil está desativado - Forçar idioma do áudio original Usar o idioma original do áudio @@ -1375,7 +1398,7 @@ Habilitar isso pode desbloquear qualidades de vídeo mais altas" Mostrar botão de velocidade - Botão não esta oculto + O botão é exibido. Toque e mantenha pressionado para redefinir a velocidade de reprodução para o padrão Botão não está visível @@ -1387,6 +1410,7 @@ Habilitar isso pode desbloquear qualidades de vídeo mais altas" Velocidades personalizadas devem ser menores que %s Velocidades de reprodução personalizadas inválidas Automático + Velocidade de reprodução redefinida para: %s Velocidade personalizada de tocar e segurar Velocidade de reprodução entre 0-8 diff --git a/patches/src/main/resources/addresources/values-pt-rPT/strings.xml b/patches/src/main/resources/addresources/values-pt-rPT/strings.xml index 162ed02dd..af89ae2d2 100644 --- a/patches/src/main/resources/addresources/values-pt-rPT/strings.xml +++ b/patches/src/main/resources/addresources/values-pt-rPT/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Configurações Desejas continuar? Repor + Redefinir cor + Cor inválida Atualizar e reiniciar Reiniciar Importar @@ -115,6 +117,11 @@ Toque no botão continuar e permita as alterações de otimização." Registo do buffer de protocolo Registos de depuração incluem buffer de sondagem Os registos da depuração não incluem buffer de perfil + "Ativar esta definição irá registar dados de layout adicionais, incluindo o texto no ecrã para alguns componentes da IU. + +Isto pode ajudar a identificar componentes ao criar filtros personalizados. + +No entanto, ativar isto também irá registar alguns dados do utilizador, como o seu endereço IP." Pilha de registos Os registos da depuração incluem stack trace Os registos da depuração não incluem stack trace @@ -124,6 +131,15 @@ Toque no botão continuar e permita as alterações de otimização." "A desativação dos erros toasts oculta todas as notificações de erro do ReVanced. Não será notificado de quaisquer eventos inesperados." + Exportar registos de depuração + Copia os registos de depuração do ReVanced para a área de transferência + O registo de depuração está desativado + Nenhum registo encontrado + Registos copiados + Falha ao exportar os registos: $s + Limpar registos de depuração + Limpa todos os registos de depuração do ReVanced armazenados + Registos limpos Esconder cartões de álbuns @@ -365,9 +381,6 @@ Limitações Tính năng này chỉ khả dụng cho các thiết bị cũ" Os anúncios são visíveis em ecrã cheia - Esconder anúncios com botão - Anúncios com botões estão escondidos - Os anúncios com botões são visíveis Ocultar rótulo de promoção paga O rótulo de promoção pago está oculto Rótulo de promoção pago é mostrado @@ -478,9 +491,10 @@ Ajuste o volume deslizando verticalmente no lado direito da tela" Opacidade do plano de fundo da sobreposição de deslizar Valor de opacidade entre 0-100 A opacidade do deslizar deve estar entre 0-100 - Cor da barra de progresso da sobreposição de deslize - A cor da barra de progresso para os controles de volume e brilho - Cor da barra de progresso inválida + Cor da cor do brilho da sobreposição de deslizamento + A cor da barra de progresso para controles de brilho + Cor do volume da sobreposição de deslizamento + A cor da barra de progresso para controles de volume Tamanho do texto da sobreposição de deslize O tamanho do texto para a sobreposição de deslize entre 1 e 30 O tamanho do texto deve estar entre 1 e 30 @@ -736,6 +750,9 @@ Para mostrar o menu da faixa de áudio, altere \"Spoof video streams\" para iOS Ocultar rótulo de localização Rótulo de localização está oculto Rótulo de localização é mostrado + Ocultar painel de comentários + O painel de comentários está oculto + O painel de comentários está visível Ocultar botão de salvar música O botão salvar música está oculto O botão salvar música é mostrado @@ -1099,11 +1116,6 @@ Pronto para enviar?" %s segundos Opacidade: Cor: - Cor alterada - Redefinir cor - Código de cor inválido - Redefinir cor - Repor Sobre Os dados são fornecidos pela API do SponsorBlock. Toque aqui para aprender mais e ver downloads para outras plataformas @@ -1328,6 +1340,22 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn"Configurações do GmsCore Configurações para GmsCore + + Feedback háptico + Alterar feedback háptico + Desativar haptics dos capítulos + Haptics dos capítulos está desativado + Haptics dos capítulos está ativado + Desativar haptics de busca precisa + Haptics de busca precisa está desativado + Haptics de busca precisa está ativado + Desativar haptics de desfazer busca + Haptics de desfazer busca está desativado + Haptics de desfazer busca está ativado + Desativar zoom haptics + Zoom haptics está desativado + Zoom haptics está ativado + Se você alterou recentemente os detalhes de login da sua conta, desinstale e reinstale o MicroG. @@ -1346,11 +1374,6 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn"O parâmetro da consulta de rastreamento é removido dos links O parâmetro da consulta de rastreamento não é removido dos links - - Desativar zoom haptics - Hápticos estão desativados - Hábitos estão ativados - Forçar idioma original do áudio Usando o idioma de áudio original @@ -1378,7 +1401,7 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn" Mostrar botão de diálogo de velocidade - O botão está visível + O botão é mostrado. Toque e segure para redefinir a velocidade de reprodução para o padrão O botão não está visível @@ -1390,6 +1413,7 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn"Tốc độ tùy chỉnh phải nhỏ hơn %s Tốc độ phát lại tùy chỉnh không hợp lệ Automático + Velocidade de reprodução redefinida para: %s Velocidade personalizada ao tocar e segurar Velocidade de reprodução de 0 a 8 diff --git a/patches/src/main/resources/addresources/values-ro-rRO/strings.xml b/patches/src/main/resources/addresources/values-ro-rRO/strings.xml index 490018070..17976ac7e 100644 --- a/patches/src/main/resources/addresources/values-ro-rRO/strings.xml +++ b/patches/src/main/resources/addresources/values-ro-rRO/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Setări Doriți să continuați? Resetare + Resetează culoarea + Culoare nevalidă Reîmprospătare și repornire Repornire Importare @@ -115,6 +117,11 @@ Apăsați butonul continuare și permiteți modificările de optimizare."Jurnal protocol buffer Jurnalele de depanare includ bufferul de protocol Jurnalele de depanare nu includ memoria tampon + "Activarea acestei setări va înregistra date suplimentare despre aspect, inclusiv textul de pe ecran pentru unele componente UI. + +Acest lucru poate ajuta la identificarea componentelor atunci când creați filtre personalizate. + +Cu toate acestea, activarea acestei opțiuni va înregistra și unele date ale utilizatorului, cum ar fi adresa dvs. IP." Urme stive de jurnal Jurnalele depanării includ urmărirea stivelor Jurnalele de depanare nu includ urmărirea stivelor @@ -124,6 +131,15 @@ Apăsați butonul continuare și permiteți modificările de optimizare.""Oprirea toasturilor de eroare ascunde toate notificările de eroare ReVanced. Nu veți fi notificat de niciun eveniment neașteptat." + Exportare jurnale de depanare + Copiază jurnalele de depanare ReVanced în clipboard + Înregistrarea în jurnal de depanare este dezactivată + Nu au fost găsite jurnale + Jurnale copiate + Nu s-a putut exporta jurnalele: $s + Șterge jurnalele de depanare + Șterge toate jurnalele de depanare ReVanced stocate + Jurnale șterse Ascundeți cardurile de album @@ -365,9 +381,6 @@ Limitări Această funcție este disponibilă numai pentru dispozitivele mai vechi" Reclame pe ecran complet sunt afișate - Ascunde reclame butoane - Reclame nastate sunt ascunse - Reclame buttonate sunt afișate Ascunde eticheta promoției cu plată Eticheta promoției plătite este ascunsă Eticheta promoției plătite este afișată @@ -478,9 +491,10 @@ Reglați volumul glisând vertical pe partea dreaptă a ecranului" Opacitate suprapunere glisare Valoare opacitate între 0-100 Opacitatea glisării trebuie să fie între 0-100 - Culoare bară de progres suprapunere glisare - Culoarea barei de progres pentru comenzile de volum și luminozitate - Culoare nevalidă a barei de progres + Culoarea luminozității suprapunerii glisante + Culoarea barei de progres pentru comenzile de luminozitate + Culoarea volumului suprapunerii glisante + Culoarea barei de progres pentru comenzile de volum Dimensiune text suprapunere glisare Dimensiunea textului pentru suprapunerea glisării între 1-30 Dimensiunea textului trebuie să fie între 1-30 @@ -736,6 +750,9 @@ Pentru a afișa meniul pentru pista audio, schimbați opțiunea „Falsifică fl Ascunde eticheta locației Eticheta locației este ascunsă Eticheta locației este afișată + Ascunde panoul de comentarii + Panoul de comentarii este ascuns + Panoul de comentarii este afișat Ascunde butonul Salvează melodia Butonul de salvare a muzicii este ascuns Butonul de salvare a muzicii este afișat @@ -1098,11 +1115,6 @@ Ești gata să trimiți?" %s secunde Opacitate: Culoare: - Culoare schimbată - Resetare culoare - Cod culoare nevalid - Resetare culoare - Resetează Despre Datele sunt furnizate de API-ul SponsorBlock. Apasă aici pentru a afla mai multe și a vedea descărcările pentru alte platforme @@ -1327,6 +1339,22 @@ Activarea acestei opțiuni poate debloca calități video mai mari" Setări GmsCore Setări pentru GmsCore + + Feedback haptic + Schimbă feedback-ul haptic + Dezactivare haptics capitole + Haptics capitole este dezactivat + Haptics capitole este activat + Dezactivare haptics căutare precisă + Haptica precisă de căutare este dezactivată + Haptics căutare precisă este activat + Dezactivare haptics anulare căutare + Haptica de anulare a căutării este dezactivată + Haptica de anulare a căutării este activată + Dezactivare haptics zoom + Haptica zoom este dezactivată + Haptica zoom este activată + Dacă ți-ai schimbat recent detaliile de conectare la cont, dezinstalează și reinstalează MicroG. @@ -1345,11 +1373,6 @@ Activarea acestei opțiuni poate debloca calități video mai mari" Parametrul de urmărire a interogării este eliminat din link-uri Parametrul de urmărire a interogării nu este eliminat din link-uri - - Dezactivare haptics zoom - Hapticele sunt dezactivate - Haptic-urile sunt activate - Forțează limba audio originală Folosind limba audio originală @@ -1377,7 +1400,7 @@ Activarea acestei opțiuni poate debloca calități video mai mari" Arată butonul de dialog de viteză - Butonul este afișat + Butonul este afișat. Atingeți și mențineți apăsat pentru a reseta viteza de redare la cea implicită Butonul nu este afișat @@ -1389,6 +1412,7 @@ Activarea acestei opțiuni poate debloca calități video mai mari" Vitezele personalizate trebuie să fie mai mici de %s Viteze de redare personalizate nevalide Automat + Viteza de redare a fost resetată la: %s Viteză personalizată de apăsare și menținere Viteză de redare între 0-8 diff --git a/patches/src/main/resources/addresources/values-ru-rRU/strings.xml b/patches/src/main/resources/addresources/values-ru-rRU/strings.xml index f1e2135e7..56c0a6aed 100644 --- a/patches/src/main/resources/addresources/values-ru-rRU/strings.xml +++ b/patches/src/main/resources/addresources/values-ru-rRU/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Настройки Вы хотите продолжить? Сбросить + Сбросить цвет + Неверный цвет Обновить и перезапустить Перезапустить Импортировать @@ -115,6 +117,11 @@ Second \"item\" text" Журнал буфера протоколов В журналы отладки включен буфер протоколов В журналы отладки не включен буфер протоколов + "Включение этой настройки позволит регистрировать дополнительные данные макета, включая текст на экране для некоторых компонентов пользовательского интерфейса. + +Это может помочь определить компоненты при создании пользовательских фильтров. + +Однако включение этой функции также приведет к регистрации некоторых пользовательских данных, таких как ваш IP-адрес." Журнал трассировки стека В журналы отладки включена трассировка стека В журналы отладки не включена трассировка стека @@ -124,6 +131,15 @@ Second \"item\" text" "Отключение всплывающих уведомлений об ошибках скроет все сообщения об ошибках ReVanced. Вы не будете уведомлены о каких-либо непредвиденных событиях." + Экспортировать журналы отладки + Копирует журналы отладки ReVanced в буфер обмена + Журналы отладки отключены + Журналы не найдены + Журналы скопированы + Не удалось экспортировать журналы: $s + Очистить журналы отладки + Очищает все сохраненные журналы отладки ReVanced + Журналы очищены Скрыть карточки альбомов @@ -365,9 +381,6 @@ Second \"item\" text" Данная опция доступна только для старых устройств" Полноэкранная реклама при запуске приложения показана - Скрыть кнопочную рекламу - Кнопочная реклама в ленте скрыта - Кнопочная реклама в ленте показана Скрыть метку платной акции Метка платной акции в плеере скрыта Метка платной акции в плеере показана @@ -478,9 +491,10 @@ Second \"item\" text" Затемнение фона панели жестов Значение затемнения всплывающей панели при жестах от 0 до 100 Значение затемнения панели жестов должно быть от 0 до 100 - Цвет полосы прогресса при жестах - Цвет полосы прогресса при изменении громкости и яркости жестами - Недопустимый цвет полосы прогресса + Цвет индикатора яркости при жестах + Цвет полосы прогресса при изменении яркости жестами + Цвет индикатора громкости при жестах + Цвет полосы прогресса при изменении громкости жестами Размер текста панели жестов Размер текста панели жестов от 1 до 30 Размер текста должен быть в диапазоне от 1 до 30 @@ -736,6 +750,9 @@ Second \"item\" text" Скрыть метку местоположения Метка местоположения в Shorts скрыта Метка местоположения в Shorts показана + Скрыть панель комментариев + Панель комментариев скрыта + Панель комментариев отображается Скрыть кнопку \"Сохранить музыку\" Кнопка \"Сохранить музыку\" в Shorts скрыта Кнопка \"Сохранить музыку\" в Shorts показана @@ -1099,11 +1116,6 @@ Second \"item\" text" %s секунд Непрозрачность: Цвет: - Цвет изменен - Цвет сброшен - Неверный код цвета - Сбросить цвет - Сбросить Об интеграции Данные предоставлены SponsorBlock API. Нажмите для дополнительной информации и просмотра загрузок для других платформ @@ -1328,6 +1340,22 @@ Second \"item\" text" GmsCore Настройки GmsCore + + Виброотклик + Изменить виброотклик + Отключить виброотклик между эпизодов + Виброотклик между эпизодов отключен + Виброотклик между эпизодов включен + Отключить виброотклик при покадровой перемотке + Виброотклик при покадровой перемотке отключен + Виброотклик при покадровой перемотке включен + Отключить виброотклик отмены перемотки + Виброотклик отмены перемотки отключен + Виброотклик отмены перемотки включен + Отключить виброотклик при масштабировании + Виброотклик при масштабировании отключен + Виброотклик при масштабировании включен + Если Вы недавно изменили данные для входа в свою учетную запись, удалите и переустановите MicroG. @@ -1346,11 +1374,6 @@ Second \"item\" text" Параметр отслеживания запросов из ссылок удален Параметр отслеживания запросов из ссылок не удален - - Отключить виброотклик при масштабировании - Виброотклик при масштабировании отключен - Виброотклик при масштабировании включен - Принудительно оригинальная звуковая дорожка Используется оригинальная звуковая дорожка @@ -1378,7 +1401,7 @@ Second \"item\" text" Показать кнопку скорости воспроизведения - Кнопка выбора скорости воспроизведения показана + Кнопка показана. Нажмите и удерживайте, чтобы сбросить скорость воспроизведения до значения по умолчанию Кнопка выбора скорости воспроизведения скрыта @@ -1390,6 +1413,7 @@ Second \"item\" text" Кастомные скорости должны быть меньше, чем %s Недопустимые кастомные скорости воспроизведения Автоматически + Скорость воспроизведения сброшена до: %s Кастомная скорость при нажатии и удержании Значение кастомной скорости воспроизведения при нажатии и удержании от 0 до 8 diff --git a/patches/src/main/resources/addresources/values-si-rLK/strings.xml b/patches/src/main/resources/addresources/values-si-rLK/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-si-rLK/strings.xml +++ b/patches/src/main/resources/addresources/values-si-rLK/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-sk-rSK/strings.xml b/patches/src/main/resources/addresources/values-sk-rSK/strings.xml index 3ce11cac4..e1151bd2f 100644 --- a/patches/src/main/resources/addresources/values-sk-rSK/strings.xml +++ b/patches/src/main/resources/addresources/values-sk-rSK/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Nastavenia Chcete pokračovať? Resetovať + Obnovi farbu + Neplatn farba Obnovte a reštartujte Reštart Importovať @@ -113,6 +115,11 @@ Vypnutie optimalizácie batérie pre MicroG nebude mať negatívny vplyv na spot Vyrovnávacia pamäť protokolu Protokoly ladenia obsahujú proto buffer Protokoly ladenia neobsahujú proto buffer + "Povolením tohto nastavenia sa budú zaznamenávať ďalšie údaje o rozložení, vrátane textu na obrazovke pre niektoré komponenty používateľského rozhrania. + +Toto môže pomôcť identifikovať komponenty pri vytváraní vlastných filtrov. + +Povolením tejto funkcie sa však budú zaznamenávať aj niektoré používateľské údaje, ako napríklad vaša IP adresa." Zaznamenať stopy zásobníka Denníky ladenia obsahujú sledovanie zásobníka Denníky ladenia neobsahujú sledovanie zásobníka @@ -122,6 +129,15 @@ Vypnutie optimalizácie batérie pre MicroG nebude mať negatívny vplyv na spot "Vypnutie upozornení o chybách skryje všetky upozornenia o chybách v ReVanced. Nebudete informovaní o žiadnych nepredvídaných udalostiach." + Exportovať protokoly ladenia + Skopíruje protokoly ladenia ReVanced do schránky + Protokolovanie ladenia je vypnuté + Nenašli sa žiadne protokoly + Protokoly skopírované + Nepodarilo sa exportovať protokoly: $s + Vymazať protokoly ladenia + Vymaže všetky uložené protokoly ladenia ReVanced + Protokoly vymazané Skryť karty albumov @@ -358,9 +374,6 @@ Slová s veľkými písmenami v strede musia byť zadané s použitím veľkých Táto funkcia je dostupná len pre staršie zariadenia" Zobrazujú sa reklamy na celú obrazovku - Skryť zapnuté reklamy - Zapnuté reklamy sú skryté - Zobrazujú sa reklamy s tlačidlami Skryť štítok platenej propagácie Štítok platenej propagácie je skrytý Zobrazuje sa štítok platenej propagácie @@ -471,9 +484,10 @@ Upravte hlasitosť posúvaním vertikálne na pravej strane obrazovky" Priehľadnosť pozadia prekrytia potiahnutia Hodnota priehľadnosti medzi 0-100 Priehľadnosť prekrytia potiahnutia musí byť medzi 0-100 - Farba panela priebehu prekrytia posunutím - Farba panela priebehu pre ovládanie hlasitosti a jasu - Neplatná farba panela priebehu + Farba prekrytia jasu potiahnutím + Farba panela s indikátorom priebehu pre ovládacie prvky jasu + Farba prekrytia hlasitosti potiahnutím + Farba panela s indikátorom priebehu pre ovládacie prvky hlasitosti Veľkosť textu prekrytia posunutím Veľkosť textu pre prekrytie posunutím medzi 1 – 30 Veľkosť textu musí byť medzi 1 – 30 @@ -729,6 +743,9 @@ Ak chcete zobraziť ponuku zvukovej stopy, zmeňte možnosť „Oklamať videost Skryť štítok polohy Štítok miesta je skrytý Zobrazí sa štítok s umiestnením + Skryť panel komentárov + Panel komentárov je skrytý + Panel komentárov je zobrazený Skryť tlačidlo Uložiť hudbu Tlačidlo na uloženie hudby je skryté Tlačidlo na uloženie hudby sa zobrazuje @@ -1089,11 +1106,6 @@ Pripravené na odoslanie?" %s sekúnd Priehľadnosť: Farba: - Farba bola zmenená - Farba bola resetovaná - Neplatný kód farby - Obnoviť farbu - Resetovať Informácie Údaje poskytuje SponsorBlock API. Klepnutím sem sa dozviete viac a zobrazíte súbory na stiahnutie pre iné platformy @@ -1316,6 +1328,22 @@ Povolením tejto možnosti môžete odomknúť vyššie kvality videa" Nastavenia GmsCore Nastavenia pre GmsCore + + Haptická odozva + Zmeniť haptickú odozvu + Zakázať haptiku kapitol + Haptika kapitol je zakázaná + Haptika kapitol je povolená + Zakázať haptiku presného vyhľadávania + Haptika presného vyhľadávania je vypnutá + Haptika presného vyhľadávania je povolená + Vypnúť haptiku vrátenia späť vyhľadávania + Haptika vrátenia späť vyhľadávania je vypnutá + Haptika vrátenia späť vyhľadávania je zapnutá + Zakázať haptiku priblíženia + Haptika priblíženia je vypnutá + Haptika priblíženia je zapnutá + Ak ste nedávno zmenili prihlasovacie údaje svojho účtu, odinštalujte a znova nainštalujte MicroG. @@ -1334,11 +1362,6 @@ Povolením tejto možnosti môžete odomknúť vyššie kvality videa" Parameter dopytu sledovania je odstránený z odkazov Parameter dopytu sledovania nie je odstránený z odkazov - - Zakázať haptiku priblíženia - Haptika je vypnutá - Haptika je povolená - Vynútiť pôvodný jazyk zvuku Používa sa pôvodný jazyk zvuku @@ -1366,7 +1389,7 @@ Povolením tejto možnosti môžete odomknúť vyššie kvality videa" Zobraziť dialógové tlačidlo rýchlosti - Tlačidlo je zobrazené + Zobrazuje sa tlačidlo. Ťuknite a podržte, ak chcete obnoviť predvolenú rýchlosť prehrávania Tlačidlo nie je zobrazené @@ -1378,6 +1401,7 @@ Povolením tejto možnosti môžete odomknúť vyššie kvality videa" Vlastné rýchlosti musia byť menšie ako %s Neplatné vlastné rýchlosti prehrávania Automaticky + Rýchlosť prehrávania obnovená na: %s Vlastná rýchlosť ťuknutia a podržania Rýchlosť prehrávania medzi 0-8 diff --git a/patches/src/main/resources/addresources/values-sl-rSI/strings.xml b/patches/src/main/resources/addresources/values-sl-rSI/strings.xml index 8a665c963..08050a5e4 100644 --- a/patches/src/main/resources/addresources/values-sl-rSI/strings.xml +++ b/patches/src/main/resources/addresources/values-sl-rSI/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Nastavitve Ali želite nadaljevati? Ponastavi + Ponastavi barvo + Neveljavna barva Osveži in ponovno zaženi Ponovno zaženi Uvozi @@ -115,6 +117,11 @@ Tapnite gumb za nadaljevanje in dovolite spremembe optimizacij." Dnevnik protokola pufra Dnevniki napak vključujejo protokol pufra Dnevniki napak ne vključujejo protokola pufra + "Če omogočite to nastavitev, se bodo beležili dodatni podatki o postavitvi, vključno z besedilom na zaslonu za nekatere komponente uporabniškega vmesnika. + +To lahko pomaga prepoznati komponente pri ustvarjanju filtrov po meri. + +Vendar pa bo omogočitev tega beležila tudi nekatere uporabniške podatke, kot je vaš naslov IP." Dnevnik sledov steka Dnevniki napak vključujejo sled sledov Dnevniki napak ne vključujejo sledi sledov @@ -124,6 +131,15 @@ Tapnite gumb za nadaljevanje in dovolite spremembe optimizacij." "Onemogočanje obvestil o napakah skrije vsa obvestila o napakah v ReVancedu. Ne boste obveščeni o nobenih nepričakovanih dogodkih." + Izvozi dnevnike napak + Kopira dnevnike napak ReVanced v odložišče + Beleženje napak je onemogočeno + Dnevnikov ni mogoče najti + Dnevniki so bili kopirani + Izvoz dnevnikov ni uspel: $s + Počisti dnevnike napak + Počisti vse shranjene dnevnike napak ReVanced + Dnevniki so bili izbrisani Skrij kartice albuma @@ -365,9 +381,6 @@ Omejitve Ta funkcija je na voljo samo za starejše naprave" Oglasi na celotnem zaslonu so prikazani - Skrij oglase z gumbi - Oglasi z gumbi so skriti - Oglasi z gumbi so prikazani Skrij nalepko plačane promocije Nalepka plačane promocije je skrita Nalepka plačane promocije je prikazana @@ -478,9 +491,10 @@ Prilagodite glasnost s potegom navpično na desni strani zaslona" Prosojnost prekrivanja poteze Vrednost prosojnosti med 0 in 100 Prosojnost drsenja mora biti med 0 in 100 - Barva vrstice napredka prekrivnega drsenja - Barva vrstice napredka za upravljanje glasnosti in svetlosti - Neveljavna barva vrstice napredka + Barva svetlosti prekrivnega potega + Barva vrstice napredka za upravljanje svetlosti + Barva glasnosti prekrivnega potega + Barva vrstice napredka za upravljanje glasnosti Velikost besedila prekrivnega drsenja Velikost besedila za prekrivni sloj drsenja med 1 in 30 Velikost besedila mora biti med 1 in 30 @@ -736,6 +750,9 @@ Opomba: Omogočanje tega tudi prisilno skrije video oglase" Skrij oznako lokacije Oznaka lokacije je skrita Oznaka lokacije je prikazana + Skrij ploščo s komentarji + Plošča s komentarji je skrita + Plošča s komentarji je prikazana Skrij gumb \'Shrani glasbo\' Gumb za shranjevanje glasbe je skrit Gumb za shranjevanje glasbe je prikazan @@ -1098,11 +1115,6 @@ Ali ste pripravljeni na oddajo?" %s sekund Prosojnost: Barva: - Barva spremenjena - Barva ponastavljena - Neveljavna koda barve - Ponastavi barvo - Ponastavi O programu Podatki so zagotovljeni s strani SponsorBlock API. Tapnite tukaj, da izveste več in si ogledate prenose za druge platforme @@ -1327,6 +1339,22 @@ Omogočanje tega lahko odklene višje kakovosti videa" Nastavitve GmsCore Nastavitve za GmsCore + + Haptični odziv + Spremeni haptični odziv + Onemogoči haptiko poglavij + Haptika poglavij je onemogočena + Haptika poglavij je omogočena + Onemogoči haptiko natančnega iskanja + Natančna haptika pri iskanju je onemogočena + Haptika natančnega iskanja je omogočena + Onemogoči haptiko za razveljavitev iskanja + Haptika za razveljavitev iskanja je onemogočena + Haptika za razveljavitev iskanja je omogočena + Onemogoči haptiko pri povečavi + Haptika pri povečavi je onemogočena + Haptika pri povečavi je omogočena + Če ste nedavno spremenili podatke za prijavo v račun, odstranite in znova namestite MicroG. @@ -1345,11 +1373,6 @@ Omogočanje tega lahko odklene višje kakovosti videa" Parameter poizvedbe za sledenje je odstranjen iz povezav Parameter poizvedbe za sledenje ni odstranjen iz povezav - - Onemogoči haptiko pri povečavi - Haptika je onemogočena - Haptika je omogočena - Izsili izvirni jezik zvoka Uporabi izvirni jezik zvoka @@ -1377,7 +1400,7 @@ Omogočanje tega lahko odklene višje kakovosti videa" Pokaži gumb za pogovor o hitrosti - Gumb je prikazan + Gumb je prikazan. Dotaknite se ga in ga pridržite, da ponastavite hitrost predvajanja na privzeto. Gumb ni prikazan @@ -1389,6 +1412,7 @@ Omogočanje tega lahko odklene višje kakovosti videa" Hitrosti predvajanja po meri morajo biti manjše od %s Neveljavne hitrosti predvajanja po meri Samodejno + Hitrost predvajanja je bila ponastavljena na: %s Hitrost pritiska in pridržanja po meri Hitrost predvajanja med 0 in 8 diff --git a/patches/src/main/resources/addresources/values-sq-rAL/strings.xml b/patches/src/main/resources/addresources/values-sq-rAL/strings.xml index 00acf2823..96222800b 100644 --- a/patches/src/main/resources/addresources/values-sq-rAL/strings.xml +++ b/patches/src/main/resources/addresources/values-sq-rAL/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Cilësimet Dëshironi të vazhdoni? Rivendos + Rikthe ngjyrën + Ngjyrë e pavlefshme Rifresko dhe rifillo Rifillo Importo @@ -115,6 +117,11 @@ Prekni butonin vazhdo dhe lejoni ndryshimet e optimizimit." Regjistro protokol buffer Regjistrimet e depurimit përfshijnë proto buffer Regjistrimet e depurimit nuk përfshijnë proto buffer + "Aktivizimi i këtij opsioni do të regjistrojë të dhëna shtesë të paraqitjes, duke përfshirë tekstin në ekran për disa komponentë të ndërfaqes përdoruese. + +Kjo mund të ndihmojë në identifikimin e komponentëve kur krijoni filtra të personalizuar. + +Gjithsesi, aktivizimi i këtij opsioni do të regjistrojë edhe disa të dhëna të përdoruesit, siç është adresa juaj IP." Regjistro gjurmët e grumbullimit Regjistrimet e depurimit përfshijnë gjurmë grumbullimi Regjistrimet e depurimit nuk përfshijnë gjurmë grumbullimi @@ -124,6 +131,15 @@ Prekni butonin vazhdo dhe lejoni ndryshimet e optimizimit." "Fshirja e toast-eve të gabimit fsheh të gjitha njoftimet e gabimeve të ReVanced. Ju nuk do të njoftoheni për ndonjë ngjarje të papritur." + Eksporto regjistrat e korrigjimit + Kopjon regjistrat e korrigjimit të ReVanced në kujtesën e shkurtër + Regjistrimi i korrigjimeve është çaktivizuar + Nuk u gjetën regjistra + Regjistrat u kopjuan + Eksportimi i regjistrave dështoi: $s + Pastro regjistrat e korrigjimit + Pastro të gjithë regjistrat e ruajtur të korrigjimit të ReVanced + Regjistrat u pastruan Fshih kartat e albumit @@ -365,9 +381,6 @@ Kufizime Kjo veçori është e disponueshme vetëm për pajisje më të vjetra" Reklamimet me ekran të plotë janë të dukshme - Fsheh reklamimet me butona - Reklamimet me butona janë të fshehur - Reklamimet me butona janë të dukshme Fsheh etiketën e promovimit të paguar Etiketë e promovimit të paguar është e fshehur Etiketë e promovimit të paguar është e dukshme @@ -478,9 +491,10 @@ Përshtate shkëlqimin duke rrëshqitur vertikalisht në anën e majtë të ekra Opasiteti i sfondit mbivendosës shtypëse Vlera e opacitetit midis 0-100 Opaciteti i shtypjes duhet të jetë midis 0-100 - Ngjyra e shiritit të progresit të mbivendosjes së rrëshqitjes - Ngjyra e shiritit të progresit për kontrollet e volumit dhe të ndriçimit - Ngjyrë e pavlefshme e shiritit të progresit + Ngjyra e ndriçimit të mbivendosjes me rrëshqitje + Ngjyra e shiritit të progresit për kontrollet e ndriçimit + Ngjyra e volumit të mbivendosjes me rrëshqitje + Ngjyra e shiritit të progresit për kontrollet e volumit Madhësia e tekstit të mbivendosjes së rrëshqitjes Madhësia e tekstit për mbivendosjen e rrëshqitjes midis 1-30 Madhësia e tekstit duhet të jetë midis 1-30 @@ -736,6 +750,9 @@ Për të shfaqur menunë e pistës audio, ndryshoni 'Falsifiko transmetimet vide Fsheh etiketën e vendndodhjes Etiketë e vendndodhjes është e fshehur Etiketë e vendndodhjes shfaqet + Fshih panelin e komenteve + Paneli i komenteve është i fshehur + Paneli i komenteve është i dukshëm Fsheh butonin Ruaj muzikën Butoni \"Ruaj muzikën\" është i fshehur Butoni \"Ruaj muzikën\" shfaqet @@ -1097,11 +1114,6 @@ Gati per te dhene?" %s sekonda Opaciteti: Ngjyra: - Ngjyra është ndryshuar - Ngjyra u rikthye - Kod ngjyre i pavlefshëm - Rikthe ngjyrën - Rikthe Rreth Të dhënat janë siguruar nga API e SponsorBlock. Prekni këtu për të mësuar më shumë dhe për të parë shkarkimet për platformat e tjera @@ -1326,6 +1338,22 @@ Aktivizimi i kësaj mund të zhbllokojë cilësi më të larta video" Cilësimet e GmsCore Cilësimet për GmsCore + + Reagimi haptik + Ndrysho reagimin haptik + Çaktivizo haptikën e kapitujve + Haptika e kapitujve është çaktivizuar + Haptika e kapitujve është aktivizuar + Çaktivizo haptikën e kërkimit të saktë + Haptika e kërkimit të saktë është çaktivizuar + Haptika e saktë e kërkimit është aktivizuar + Çaktivizo haptikën e zhbërjes së kërkimit + Haptika e zhbërjes së kërkimit është çaktivizuar + Haptika e zhbërjes së kërkimit është aktivizuar + Çaktivizo haptikën e zmadhimit + Haptika e zmadhimit është çaktivizuar + Haptika e zmadhimit është aktivizuar + Nëse së fundmi keni ndryshuar detajet e hyrjes në llogarinë tuaj, atëherë çinstaloni dhe riinstaloni MicroG. @@ -1344,11 +1372,6 @@ Aktivizimi i kësaj mund të zhbllokojë cilësi më të larta video" Parametri i gjurmimit të kërkesës hiqet nga linket Parametri i gjurmimit të kërkesës nuk hiqet nga linket - - Çaktivizo haptikën e zmadhimit - Haptikët janë të çaktivizuar - Haptikët janë të aktivizuar - Forco gjuhën origjinale të audios Duke përdorur gjuhën origjinale audio @@ -1376,7 +1399,7 @@ Aktivizimi i kësaj mund të zhbllokojë cilësi më të larta video" Shfaq butonin e dialogut të shpejtësisë - Butoni shfaqet + Butoni shfaqet. Prekni dhe mbani për të rivendosur shpejtësinë e riprodhimit në atë të parazgjedhur Butoni nuk shfaqet @@ -1388,6 +1411,7 @@ Aktivizimi i kësaj mund të zhbllokojë cilësi më të larta video" Shpejtësitë e personalizuara duhet të jenë më të vogla se %s Shpejtësi të pavlefshme të personalizuar të riprodhimit Automatik + Shpejtësia e riprodhimit u rivendos në: %s Shpejtësia sipas dëshirës së përdoruesit gjatë përdorimit Shpejtësi e riprodhimit midis 0 dhe 8 diff --git a/patches/src/main/resources/addresources/values-sr-rCS/strings.xml b/patches/src/main/resources/addresources/values-sr-rCS/strings.xml index c1ecfd1cb..6721c2110 100644 --- a/patches/src/main/resources/addresources/values-sr-rCS/strings.xml +++ b/patches/src/main/resources/addresources/values-sr-rCS/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Podešavanja Želite li da nastavite? Resetuj + Resetuj boju + Nevažeća boja Osvežite i restartujte Restartuj Uvoz @@ -115,6 +117,11 @@ Dodirnite dugme „Nastavi” i dozvolite promene optimizacije." Evidentiranje bafera protokola Evidencije otklanjanja grešaka sadrže bafer protokola Evidencije otklanjanja grešaka ne sadrže bafer protokola + "Omogućavanjem ove opcije evidentiraće se dodatni podaci o izgledu, uključujući tekst na ekranu za neke komponente korisničkog interfejsa. + +Ovo može pomoći u identifikaciji komponenti prilikom pravljenja prilagođenih filtera. + +Međutim, omogućavanje ovoga će takođe evidentirati neke korisničke podatke, kao što je vaša IP adresa." Evidentiranje praćenja steka Evidencije otklanjanja grešaka sadrže praćenje steka Evidencije otklanjanja grešaka ne sadrže praćenje steka @@ -124,6 +131,15 @@ Dodirnite dugme „Nastavi” i dozvolite promene optimizacije." "Isključivanje iskačućih obaveštenja o greškama sakriva sve obaveštenja o greškama u ReVancedu. Nećete biti obavešteni ni o kakvim neočekivanim događajima." + Izvezi evidencije otklanjanja grešaka + Kopira evidencije otklanjanja grešaka ReVanceda u privremenu memoriju + Evidentiranje otklanjanja grešaka je onemogućeno + Nema pronađenih evidencija + Evidencije su kopirane + Izvoz evidencija nije uspeo: $s + Izbriši evidencije otklanjanja grešaka + Briše sve sačuvane evidencije otklanjanja grešaka ReVanceda + Evidencije su izbrisane Sakrij kartice albuma @@ -365,9 +381,6 @@ Ograničenja Ova funkcija je dostupna samo za starije uređaje" Oglasi preko celog ekrana su prikazani - Sakrij oglase u obliku dugmadi - Oglasi u obliku dugmadi su skriveni - Oglasi u obliku dugmadi su prikazani Sakrij oznaku plaćene promocije Oznaka plaćeme promocije je skrivena Oznaka plaćene promocije je prikazana @@ -478,9 +491,10 @@ Podesite jačinu zvuka prevlačenjem vertikalno na desnoj strani ekrana"Neprozirnost pozadine pokreta prevlačenja Vrednost neprozirnosti između 0 i 100 Neprozirnost pokreta prevlačenja mora biti između 0 i 100 - Boja trake napretka pokreta prevlačenja - Boja trake napretka za kontrolu jačine zvuka i osvetljenosti - Nevažeća boja trake napretka + Boja pokreta prevlačenja za osvetljenost + Boja trake napretka za kontrolu osvetljenosti + Boja pokreta prevlačenja za jačinu zvuka + Boja trake napretka za kontrolu jačine zvuka Veličina teksta pokreta prevlačenja Veličina teksta za pokret prevlačenja između 1 i 30 Veličina teksta mora biti između 1 i 30 @@ -736,6 +750,9 @@ Da biste prikazali meni „Audio snimak”, promenite opciju „Lažirani video Sakrij oznaku lokacije Oznaka lokacije je skrivena Oznaka lokacije je prikazana + Sakrij tablu sa komentarima + Panel sa komentarima je skriven + Tabla sa komentarima je prikazana Sakrij dugme „Sačuvaj muziku” Dugme „Sačuvaj zvuk” je skriveno Dugme „Sačuvaj zvuk” je prikazano @@ -1098,11 +1115,6 @@ Spreman za podnošenje?" %s sekundi Neprozirnost: Boja: - Boja promenjena - Boja resetovana - Nevažeći kôd boje - Resetuj boju - Resetuj O programu Podatke obezbeđuje SponsorBlock API. Dodirnite ovde da saznate više i vidite preuzimanja za druge platforme @@ -1327,6 +1339,22 @@ Ako ovo omogućite, mogu biti otključani viši kvaliteti videa" Podešavanja GmsCorea Podešavanja za GmsCore + + Vibracija pri dodiru + Promeni vibraciju pri dodiru + Onemogući vibraciju poglavlja + Vibracija poglavlja je onemogućena + Vibracija poglavlja je omogućena + Onemogući vibraciju preciznog premotavanja + Vibracija preciznog premotavanja je onemogućena + Vibracija preciznog premotavanja je omogućena + Onemogući vibraciju poništavanja premotavanja + Vibracija poništavanja premotavanja je onemogućena + Vibracija poništavanja premotavanja je omogućena + Onemogući vibraciju pri uveličavanju + Vibracija pri uveličavanju je onemogućena + Vibracija pri uveličavanju je omogućena + Ako ste nedavno promenili podatke za prijavu na nalog, deinstalirajte i ponovo instalirajte MicroG. @@ -1345,11 +1373,6 @@ Ako ovo omogućite, mogu biti otključani viši kvaliteti videa" Parametar upita za praćenje je uklonjen iz linkova Parametar upita za praćenje nije uklonjen iz linkova - - Onemogući vibraciju pri uveličavanju - Vibracija pri uveličavanju je onemogućena - Vibracija pri uveličavanju je omogućena - Prisili originalni jezik zvuka Korišćenje originalnog jezika zvuka @@ -1377,7 +1400,7 @@ Ako ovo omogućite, mogu biti otključani viši kvaliteti videa" Prikaži dugme dijaloga za brzinu - Dugme dijaloga za brzinu je prikazano + Dugme je prikazano. Dodirnite i zadržite da biste vratili brzinu reprodukcije na podrazumevanu vrednost Dugme dijaloga za brzinu nije prikazano @@ -1389,6 +1412,7 @@ Ako ovo omogućite, mogu biti otključani viši kvaliteti videa" Prilagođene brzine moraju biti manje od %s Nevažeće prilagođene brzine reprodukcije Automatski + Brzina reprodukcije vraćena na: %s Prilagođena brzina dodirivanja i zadržavanja Brzina reprodukcije između 0 i 8 diff --git a/patches/src/main/resources/addresources/values-sr-rSP/strings.xml b/patches/src/main/resources/addresources/values-sr-rSP/strings.xml index 8ca4c7ebf..debd8e046 100644 --- a/patches/src/main/resources/addresources/values-sr-rSP/strings.xml +++ b/patches/src/main/resources/addresources/values-sr-rSP/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Подешавања Желите ли да наставите? Ресетуј + Ресетуј боју + Неважећа боја Освежите и рестартујте Рестартуј Увоз @@ -115,6 +117,11 @@ Second \"item\" text" Евидентирање бафера протокола Евиденције отклањања грешака садрже бафер протокола Евиденције отклањања грешака не садрже бафер протокола + "Омогућавањем ове опције ће се евидентирати додатни подаци о изгледу, укључујући текст на екрану за неке компоненте корисничког интерфејса. + +Ово може помоћи у идентификацији компоненти приликом прављења прилагођених филтера. + +Међутим, омогућавање овога ће такође евидентирати неке корисничке податке, као што је ваша IP адреса." Евидентирање праћења стека Евиденције отклањања грешака садрже праћење стека Евиденције отклањања грешака не садрже праћење стека @@ -124,6 +131,15 @@ Second \"item\" text" "Искључивање искачућих обавештења о грешкама сакрива сва обавештења о грешкама у ReVanced-у. Нећете бити обавештени ни о каквим неочекиваним догађајима." + Извези евиденције отклањања грешака + Копира евиденције отклањања грешака ReVanced-а у привремену меморију + Евидентирање отклањања грешака је онемогућено + Нема пронађених евиденција + Евиденције су копиране + Извоз евиденција није успео: $s + Избриши евиденције отклањања грешака + Брише све сачуване евиденције отклањања грешака ReVanced-а + Евиденције су избрисане Сакриј картице албума @@ -365,9 +381,6 @@ Second \"item\" text" Ова функција је доступна само за старије уређаје" Огласи преко целог екрана су приказани - Сакриј огласе у облику дугмади - Огласи у облику дугмади су скривени - Огласи у облику дугмади су приказани Сакриј ознаку плаћене промоције Ознака плаћене промоције је скривена Ознака плаћене промоције је приказана @@ -478,9 +491,10 @@ Second \"item\" text" Непрозирност позадине покрета превлачења Вредност непрозирности између 0 и 100 Непрозирност покрета превлачења мора бити између 0 и 100 - Боја траке напретка покрета превлачења - Боја траке напретка за контролу јачине звука и осветљености - Неважећа боја траке напретка + Боја покрета превлачења за осветљеност + Боја траке напретка за контролу осветљености + Боја покрета превлачења за јачину звука + Боја траке напретка за контролу јачине звука Величина текста покрета превлачења Величина текста за покрет превлачења између 1 и 30 Величина текста мора бити између 1 и 30 @@ -736,6 +750,9 @@ Second \"item\" text" Сакриј ознаку локације Ознака локације је скривена Ознака локације је приказана + Сакриј панел за коментаре + Панел за коментаре је сакривен + „Резиме коментара” је приказан Сакриј дугме „Сачувај музику” Дугме „Сачувај звук” је скривено Дугме „Сачувај звук” је приказано @@ -1098,11 +1115,6 @@ Second \"item\" text" %s секунди Непрозирност: Боја: - Боја промењена - Боја ресетована - Неважећи кôд боје - Ресетуј боју - Ресетуј О програму Податке обезбеђује SponsorBlock API. Додирните овде да сазнате више и видите преузимања за друге платформе @@ -1327,6 +1339,22 @@ Second \"item\" text" Подешавања GmsCore-а Подешавања за GmsCore + + Вибрација при додиру + Промени вибрацију при додиру + Онемогући вибрацију поглавља + Вибрација поглавља је онемогућена + Вибрација поглавља је омогућена + Онемогући вибрацију прецизног премотавања + Вибрација прецизног премотавања је онемогућена + Вибрација прецизног премотавања је омогућена + Онемогући вибрацију поништавања премотавања + Вибрација поништавања премотавања је онемогућена + Вибрација поништавања премотавања је омогућена + Онемогући вибрацију при увеличавању + Вибрација при увеличавању је онемогућена + Вибрација при увеличавању је омогућена + Ако сте недавно променили податке за пријаву на налог, деинсталирајте и поново инсталирајте MicroG. @@ -1345,11 +1373,6 @@ Second \"item\" text" Параметар упита за праћење је уклоњен из линкова Параметар упита за праћење није уклоњен из линкова - - Онемогући вибрацију при увеличавању - Вибрација при увеличавању је онемогућена - Вибрација при увеличавању је омогућена - Присили оригинални језик звука Коришћење оригиналног језика звука @@ -1377,7 +1400,7 @@ Second \"item\" text" Прикажи дугме дијалога за брзину - Дугме дијалога за брзину је приказано + Дугме је приказано. Додирните и задржите да бисте вратили брзину репродукције на подразумевану вредност Дугме дијалога за брзину није приказано @@ -1389,6 +1412,7 @@ Second \"item\" text" Прилагођене брзине морају бити мање од %s Неважеће прилагођене брзине репродукције Аутоматски + Брзина репродукције враћена на: %s Прилагођена брзина додиривања и задржавања Брзина репродукције између 0 и 8 diff --git a/patches/src/main/resources/addresources/values-sv-rSE/strings.xml b/patches/src/main/resources/addresources/values-sv-rSE/strings.xml index 0eca7a7f7..362ddcc09 100644 --- a/patches/src/main/resources/addresources/values-sv-rSE/strings.xml +++ b/patches/src/main/resources/addresources/values-sv-rSE/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Inställningar Vill du fortsätta? Återställ + Återställ färg + Ogiltig färg Uppdatera och starta om Starta om Importera @@ -115,6 +117,11 @@ Tryck på Fortsätt-knappen och tillåt optimeringsändringar." Logga protokollbuffert Felsökningsloggar inkluderar protobuffert Felsökningsloggar inkluderar inte protobuffert + "Om du aktiverar den här inställningen loggas ytterligare layoutdata, inklusive text på skärmen för vissa UI-komponenter. + +Detta kan hjälpa till att identifiera komponenter när du skapar anpassade filter. + +Men om du aktiverar detta kommer även vissa användardata, t.ex. din IP-adress, att loggas." Logga stackspår Felsökningsloggar inkluderar stackspår Felsökningsloggar inkluderar inte stackspår @@ -124,6 +131,15 @@ Tryck på Fortsätt-knappen och tillåt optimeringsändringar." "Att stänga av felmeddelanden döljer alla ReVanced-felmeddelanden. Du kommer inte att bli meddelad om oväntade händelser." + Exportera felsökningsloggar + Kopierar ReVanced-felsökningsloggar till Urklipp + Felsökningsloggar är inaktiverade + Inga loggar hittades + Loggar kopierade + Det gick inte att exportera loggar: $s + Rensa felsökningsloggar + Rensar alla lagrade ReVanced-felsökningsloggar + Loggar rensade Dölj albumkort @@ -365,9 +381,6 @@ Begränsningar Den här funktionen är endast tillgänglig för äldre enheter" Fullskärmsannonser är synliga - Dölj knappannonser - Knappannonser är dolda - Knappannonser är synliga Dölj betald kampanjetikett Betald kampanjetikett är dold Betald kampanjetikett är synlig @@ -478,9 +491,10 @@ Justera volymen genom att svepa vertikalt på höger sida av skärmen" Överlägg svepbakgrund opacitet Opacitetsvärde mellan 0-100 Överlagrad svepopacitet måste vara mellan 0-100 - Färg på förloppsindikatorn för svepöverlagring - Färgen på förloppsindikatorn för volym- och ljusstyrkekontroller - Ogiltig färg på förloppsindikatorn + Färg för svepgestöverlagringens ljusstyrka + Färgen på förloppsindikatorn för ljusstyrkekontroller + Färg för svepgestöverlagringens volym + Färgen på förloppsindikatorn för volymkontroller Textstorlek för svepöverlagring Textstorleken för svepöverlagring mellan 1 och 30 Textstorleken måste vara mellan 1 och 30 @@ -736,6 +750,9 @@ För att visa ljudspårsmenyn, ändra \"Spoof video streams\" till iOS TV"Dölj platsetikett Platsetiketten är dold Platsetikett är synlig + Dölj kommentarsfältet + Kommentarsfältet är dolt + Kommentarsfältet visas Dölj knapp \'Spara musik\' Spara musikknappen är dold Spara musikknappen visas @@ -1098,11 +1115,6 @@ Redo att skicka in?" %s sekunder Opacitet: Färg: - Färg ändrad - Färg återställning - Ogiltig färgkod - Återställ färg - Återställ Om Data tillhandahålls av SponsorBlock API. Tryck här för att läsa mer och se nedladdningar för andra plattformar @@ -1327,6 +1339,22 @@ Att aktivera detta kan låsa upp högre videokvalitet" GmsCore inställningar Inställningar för GmsCore + + Haptisk återkoppling + Ändra haptisk återkoppling + Inaktivera haptik för kapitel + Haptik för kapitel är inaktiverad + Haptik för kapitel är aktiverad + Inaktivera exakt sökhaptik + Precisionssökning med haptik är inaktiverad + Exakt sökhaptik är aktiverad + Inaktivera ångra-sökning haptik + Ångra-sökning haptik är inaktiverad + Ångra-sökning haptik är aktiverad + Inaktivera zoomhaptik + Zoomhaptik är inaktiverad + Zoomhaptik är aktiverad + Om du nyligen har ändrat dina inloggningsuppgifter, avinstallera och installera om MicroG. @@ -1345,11 +1373,6 @@ Att aktivera detta kan låsa upp högre videokvalitet" Spårnings frågeparameter har tagits bort från länkar Spårnings frågeparameter har inte tagits bort från länkar - - Inaktivera zoomhaptik - Haptikerna är inaktiverade - Haptikerna är aktiverade - Forcera originalljudspråk Använder originalljudspråk @@ -1377,7 +1400,7 @@ Att aktivera detta kan låsa upp högre videokvalitet" Visa hastighetsdialogruta knapp - Knappen är synlig + Knappen visas. Tryck och håll ned för att återställa uppspelningshastigheten till standard. Knappen är dold @@ -1389,6 +1412,7 @@ Att aktivera detta kan låsa upp högre videokvalitet" Anpassade hastigheter måste vara mindre än %s Ogiltiga anpassade uppspelningshastigheter Automatiskt + Uppspelningshastighet återställd till: %s Anpassad hastighet vid tryck och håll Uppspelningshastighet mellan 0 och 8. diff --git a/patches/src/main/resources/addresources/values-sw-rKE/strings.xml b/patches/src/main/resources/addresources/values-sw-rKE/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-sw-rKE/strings.xml +++ b/patches/src/main/resources/addresources/values-sw-rKE/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-ta-rIN/strings.xml b/patches/src/main/resources/addresources/values-ta-rIN/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-ta-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-ta-rIN/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-te-rIN/strings.xml b/patches/src/main/resources/addresources/values-te-rIN/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-te-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-te-rIN/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-th-rTH/strings.xml b/patches/src/main/resources/addresources/values-th-rTH/strings.xml index 4c8d7fb4e..5cbf5ac33 100644 --- a/patches/src/main/resources/addresources/values-th-rTH/strings.xml +++ b/patches/src/main/resources/addresources/values-th-rTH/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" การตั้งค่า คุณต้องการดำเนินการต่อหรือไม่? รีเซ็ต + รีเซ็ตสี + สีไม่ถูกต้อง รีเฟรชและเริ่มต้นใหม่ เริ่มต้นใหม่ นำเข้า @@ -115,6 +117,11 @@ Second \"item\" text" บันทึกโปรโตคอลบัฟเฟอร์ การบันทึกการแก้ไขข้อบกพร่องรวมถึงโปรโตคอลบัฟเฟอร์ การบันทึกการแก้ไขข้อบกพร่องไม่รวมโปรโตคอลบัฟเฟอร์ + "การเปิดใช้งานการตั้งค่านี้จะบันทึกข้อมูลเค้าโครงเพิ่มเติม รวมถึงข้อความบนหน้าจอสำหรับส่วนประกอบ UI บางส่วน + +ซึ่งจะช่วยระบุส่วนประกอบเมื่อสร้างตัวกรองที่กำหนดเองได้ + +อย่างไรก็ตาม การเปิดใช้งานนี้จะบันทึกข้อมูลผู้ใช้บางอย่าง เช่น ที่อยู่ IP ของคุณด้วย" บันทึกการติดตามสแต็ก การบันทึกการแก้ไขข้อบกพร่องรวมถึงการติดตามสแต็ก การบันทึกการแก้ไขข้อบกพร่องไม่รวมการติดตามสแต็ก @@ -124,6 +131,15 @@ Second \"item\" text" "การปิดการแจ้งเตือนข้อผิดพลาดจะซ่อนการแจ้งเตือนข้อผิดพลาดของ ReVanced ทั้งหมด คุณจะไม่ได้รับแจ้งเกี่ยวกับเหตุการณ์ที่ไม่คาดคิดใดๆ" + ส่งออกบันทึกการแก้ไขข้อบกพร่อง + คัดลอกบันทึกการแก้ไขข้อบกพร่องของ ReVanced ไปยังคลิปบอร์ด + ปิดใช้งานการบันทึกการแก้ไขข้อบกพร่อง + ไม่พบบันทึก + คัดลอกบันทึกแล้ว + ส่งออกบันทึกล้มเหลว: $s + ล้างบันทึกการแก้ไขข้อบกพร่อง + ล้างบันทึกการแก้ไขข้อบกพร่องของ ReVanced ที่จัดเก็บไว้ทั้งหมด + ล้างบันทึกแล้ว ซ่อนการ์ดอัลบั้ม @@ -365,9 +381,6 @@ Second \"item\" text" คุณสมบัตินี้มีเฉพาะสําหรับอุปกรณ์รุ่นเก่า" โฆษณาแบบเต็มหน้าจอจะแสดง - ซ่อนโฆษณาแบบมีปุ่ม - โฆษณาแบบมีปุ่มถูกซ่อน - โฆษณาแบบมีปุ่มจะแสดง ซ่อนป้ายโฆษณาที่จ่ายเงิน ป้ายโฆษณาที่จ่ายเงินถูกซ่อน ป้ายโฆษณาที่จ่ายเงินจะแสดง @@ -476,9 +489,10 @@ Second \"item\" text" ความทึบแสงพื้นหลังของสไลด์โอเวอร์เลย์ ค่าความทึบแสงระหว่าง 0-100 ค่าความทึบแสงของสไลด์ต้องอยู่ระหว่าง 0-100 - สีของแถบความคืบหน้าของการปัด - สีของแถบความคืบหน้าสำหรับการควบคุมระดับเสียงและความสว่าง - สีของแถบความคืบหน้าไม่ถูกต้อง + สีความสว่างของการซ้อนทับการปัด + สีของแถบความคืบหน้าสำหรับตัวควบคุมความสว่าง + สีระดับเสียงของการซ้อนทับการปัด + สีของแถบความคืบหน้าสำหรับตัวควบคุมระดับเสียง ขนาดข้อความของการปัด ขนาดข้อความสำหรับการปัดระหว่าง 1-30 ขนาดข้อความต้องอยู่ระหว่าง 1-30 @@ -734,6 +748,9 @@ Second \"item\" text" ซ่อนป้ายกำกับสถานที่ ป้ายกำกับสถานที่ถูกซ่อน ป้ายกำกับสถานที่แสดงอยู่ + ซ่อนแผงความคิดเห็น + ส่วนความคิดเห็นถูกซ่อนไว้ + แผงความคิดเห็นจะแสดง ซ่อนปุ่มบันทึกเพลง ปุ่มบันทึกเพลงถูกซ่อน ปุ่มบันทึกเพลงแสดงอยู่ @@ -1097,11 +1114,6 @@ User id ของคุณเหมือนกับรหัสผ่าน %s วินาที ความทึบ: สี: - เปลื่ยนสีแล้ว - สีเปลื่ยนเป็นค่าเริ่มต้นแล้ว - รหัสสีไม่ถูกต้อง - รีเซ็ตสี - รีเซ็ต เกี่ยวกับ ข้อมูลนี้มาจาก SponsorBlock API แตะที่นี่เพื่อเรียนรู้เพิ่มเติมและดูการดาวน์โหลดสำหรับแพลตฟอร์มอื่น ๆ @@ -1326,6 +1338,22 @@ User id ของคุณเหมือนกับรหัสผ่าน การตั้งค่า GmsCore การตั้งค่าสำหรับ GmsCore + + การตอบสนองแบบสัมผัส + เปลี่ยนการตอบสนองแบบสัมผัส + ปิดใช้งานแฮปติกบท + ปิดใช้งานแฮปติกบทแล้ว + เปิดใช้งานแฮปติกบทแล้ว + ปิดใช้งานแฮปติกการค้นหาแบบแม่นยำ + ปิดใช้งานแฮปติกการค้นหาที่แม่นยำ + เปิดใช้งานแฮปติกการค้นหาแบบแม่นยำแล้ว + ปิดใช้งานแฮปติกยกเลิกการค้นหา + ปิดใช้งานแฮปติกยกเลิกการค้นหา + เปิดใช้งานแฮปติกยกเลิกการค้นหา + ปิดใช้งานแฮปติกซูม + ปิดใช้งานแฮปติกซูม + เปิดใช้งานแฮปติกซูม + หากคุณเพิ่งเปลี่ยนรายละเอียดการเข้าสู่ระบบบัญชีของคุณ ให้ถอนการติดตั้งและติดตั้ง MicroG ใหม่อีกครั้ง @@ -1344,11 +1372,6 @@ User id ของคุณเหมือนกับรหัสผ่าน พารามิเตอร์การติดตามแบบสอบถามถูกลบออกจากลิงก์ พารามิเตอร์การติดตามแบบสอบถามไม่ได้ถูกลบออกจากลิงก์ - - ปิดใช้งานแฮปติกซูม - แฮปติกถูกปิดใช้งาน - แฮปติกเปิดใช้งาน - บังคับใช้ภาษาเสียงต้นฉบับ กำลังใช้ภาษาเสียงต้นฉบับ @@ -1376,7 +1399,7 @@ User id ของคุณเหมือนกับรหัสผ่าน แสดงปุ่มกล่องโต้ตอบความเร็ว - แสดงปุ่ม + ปุ่มจะปรากฏขึ้น แตะค้างไว้เพื่อรีเซ็ตความเร็วในการเล่นเป็นค่าเริ่มต้น ไม่แสดงปุ่ม @@ -1388,6 +1411,7 @@ User id ของคุณเหมือนกับรหัสผ่าน ความเร็วที่กําหนดเองต้องน้อยกว่า %s ความเร็วในการเล่นที่กําหนดเองไม่ถูกต้อง อัตโนมัติ + ความเร็วในการเล่นรีเซ็ตเป็น: %s **Custom tap and hold speed** ความเร็วในการเล่นระหว่าง 0-8 diff --git a/patches/src/main/resources/addresources/values-tr-rTR/strings.xml b/patches/src/main/resources/addresources/values-tr-rTR/strings.xml index 51c6302b8..fc5545605 100644 --- a/patches/src/main/resources/addresources/values-tr-rTR/strings.xml +++ b/patches/src/main/resources/addresources/values-tr-rTR/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Ayarlar Devam etmek istiyor musunuz? Sıfırla + Rengi sıfırla + Geçersiz renk Yenile ve yeniden başlat Yeniden başlat İçe aktar @@ -115,6 +117,11 @@ Devam düğmesine dokunun ve optimizasyon değişikliklerine izin verin."Protocol buffer\'ın kaydını tut Hata ayıklama kayıtları proto buffer\'ı içerir Hata ayıklama kayıtları proto buffer\'ı içermez + "Bu ayarın etkinleştirilmesi, bazı kullanıcı arayüzü bileşenleri için ek düzen verilerini, ekran üzerindeki metin dahil olmak üzere günlüğe kaydeder. + +Bu, özel filtreler oluştururken bileşenlerin belirlenmesine yardımcı olabilir. + +Ancak, bunun etkinleştirilmesi IP adresiniz gibi bazı kullanıcı verilerini de günlüğe kaydeder." Stack traces\'in kaydını tut Hata ayıklama kayıtları stack traces\'i içerir Hata ayıklama kayıtları stack traces\'i içermez @@ -124,6 +131,15 @@ Devam düğmesine dokunun ve optimizasyon değişikliklerine izin verin.""Hata bildirimlerini kapatmak, tüm ReVanced hata bildirimlerini gizler. Beklenmedik olaylar hakkında bilgilendirilmeyeceksiniz." + Hata ayıklama kayıtlarını dışa aktar + ReVanced hata ayıklama kayıtlarını panoya kopyalar + Hata ayıklama kaydı devre dışı + Kayıt bulunamadı + Kayıtlar kopyalandı + Kayıtlar dışa aktarılamadı: $s + Hata ayıklama kayıtlarını temizle + Kaydedilmiş tüm ReVanced hata ayıklama kayıtlarını temizler + Kayıtlar temizlendi Albüm kartlarını gizle @@ -365,9 +381,6 @@ Sınırlamalar Bu özellik yalnızca eski cihazlarda kullanılabilir" Tam ekran reklamlar görünür - Düğmeli reklamları gizle - Düğmeli reklamlar gizli - Düğmeli reklamlar görünür Ücretli tanıtım etiketini gizle Ücretli tanıtım etiketi gizli Ücretli tanıtım etiketi görünür @@ -478,9 +491,10 @@ Ekranın sağ tarafında dikey olarak kaydırarak sesi ayarlayın" Kaydırma paneli arka plan opaklığı 0-100 arasında opaklık değeri Kaydırma opaklığı 0-100 arasında olmalıdır - Kaydırma katmanı ilerleme çubuğu rengi - Ses ve parlaklık kontrolleri için ilerleme çubuğunun rengi - Geçersiz ilerleme çubuğu rengi + Kaydırma katmanı parlaklık rengi + Parlaklık kontrolleri için ilerleme çubuğunun rengi + Kaydırma katmanı ses rengi + Ses kontrolleri için ilerleme çubuğunun rengi Kaydırma katmanı metin boyutu Kaydırma katmanı için 1-30 arası metin boyutu Metin boyutu 1-30 arasında olmalıdır @@ -736,6 +750,9 @@ Ses parçası menüsünü göstermek için \"Video akışlarını taklit et\" ay Konum etiketini gizle Konum etiketi gizli Konum etiketi görünür + Yorum panelini gizle + Yorum paneli gizli + Yorum paneli görünür Müziği kaydet düğmesini gizle Müziği kaydet düğmesi gizli Müziği kaydet düğmesi görünür @@ -1099,11 +1116,6 @@ Göndermeye hazır mısınız?" %s saniye Opaklık: Renk: - Renk değiştirildi - Renk sıfırlandı - Geçersiz renk kodu - Rengi sıfırla - Sıfırla Hakkında Veri, SponsorBlock API\'sinden sağlanır. Daha fazla bilgi ve diğer platformlar için indirmeleri görmek için dokunun @@ -1328,6 +1340,22 @@ Bunu etkinleştirmek daha yüksek video kalitelerini açabilir" GmsCore Ayarları GmsCore için ayarlar + + Titreşimli geri bildirim + Titreşimli geri bildirimi değiştir + Bölümler titreşimini devre dışı bırak + Bölümler titreşimi devre dışı + Bölümler titreşimi etkin + Hassas sarma titreşimini devre dışı bırak + Hassas sarma titreşimi devre dışı + Hassas sarma titreşimi etkin + Sardırmayı geri alma titreşimini devre dışı bırak + Sardırmayı geri alma titreşimi devre dışı + Sardırmayı geri alma titreşimi etkin + Yakınlaştırma titreşimini devre dışı bırak + Yakınlaştırma titreşimi devre dışı + Yakınlaştırma titreşimi etkin + Yakın zamanda hesap giriş bilgilerinizi değiştirdiyseniz MicroG\'yi kaldırıp yeniden yükleyin. @@ -1346,11 +1374,6 @@ Bunu etkinleştirmek daha yüksek video kalitelerini açabilir" Bağlantılardan izleyici sorgu parametresi kaldırılır Bağlantılardan izleyici sorgu parametresi kaldırılmaz - - Yakınlaştırırken titreşimi devre dışı bırak - Titreşim devre dışı - Titreşim etkin - Orijinal ses dilini zorla Orijinal ses dili kullanılıyor @@ -1378,7 +1401,7 @@ Bunu etkinleştirmek daha yüksek video kalitelerini açabilir" Hız diyaloğu düğmesini göster - Düğme gösterilir + Düğme görünür. Oynatma hızını varsayılana sıfırlamak için dokunup basılı tutun Düğme gösterilmez @@ -1390,6 +1413,7 @@ Bunu etkinleştirmek daha yüksek video kalitelerini açabilir" Özel hızlar %s\'den az olmalıdır Geçersiz özel oynatma hızları Oto + Oynatma hızı şu değere sıfırlandı: %s Dokunup basılı tutma özel hızı 0-8 arası oynatma hızı diff --git a/patches/src/main/resources/addresources/values-uk-rUA/strings.xml b/patches/src/main/resources/addresources/values-uk-rUA/strings.xml index 3c2326c9f..e2fb0df6b 100644 --- a/patches/src/main/resources/addresources/values-uk-rUA/strings.xml +++ b/patches/src/main/resources/addresources/values-uk-rUA/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Налаштування Бажаєте продовжити? Скинути + Скинути колір + Недійсний колір Оновити та перезавантажити? Перезавантажити Імпортувати @@ -115,6 +117,11 @@ Second \"item\" text" Реєструвати буфер протоколу Журнали налагодження містять протобуфер Журнали налагодження не містять протобуфер + "Увімкнення цього налаштування реєструватиме додаткові дані про макет, зокрема текст на екрані для деяких компонентів інтерфейсу. + +Це може допомогти визначити компоненти під час створення користувацьких фільтрів. + +Однак, увімкнувши це, також буде записано деякі дані користувача, наприклад Вашу IP-адресу." Реєструвати трасування стека Журнали налагодження містять трасування стека Журнали налагодження не містять трасування стека @@ -124,6 +131,15 @@ Second \"item\" text" "Вимкнення сповіщень про помилки приховує всі сповіщення про помилки ReVanced. Ви не будете отримувати сповіщення про будь-які непередбачувані події." + Експортувати журнали налагодження + Копіює журнали налагодження ReVanced до буфера обміну + Журнали налагодження вимкнено + Журнали не знайдено + Журнали скопійовано + Не вдалося експортувати журнали: $s + Очистити журнали налагодження + Очищує всі збережені журнали налагодження ReVanced + Журнали очищено Приховати картки альбому @@ -366,9 +382,6 @@ Second \"item\" text" Ця функція доступна тільки для старих пристроїв" Повноекранна реклама показується - Приховати рекламу з кнопкою - Рекламу з кнопкою приховано - Реклама з кнопкою показується Приховати \"Містить пряму рекламу\" Мітку \"Містить пряму рекламу\" приховано Мітка \"Містить пряму рекламу\" показується @@ -441,14 +454,14 @@ Second \"item\" text" %s не встановлено. Встановіть його. - Вимкнути жест покадрового перемотування - Жест для покадрового перемотування вимкнено - Жест для покадрового перемотування ввімкнено + Вимкнути жест точного перемотування + Жест для точного покадрового перемотування вимкнено + Жест для точного покадрового перемотування ввімкнено Увімкнути перемотку натисканням - Перемотку натисканням на панель прогресу ввімкнено - Перемотку натисканням на панель прогресу вимкнено + Перемотку натисканням на смугу прогресу ввімкнено + Перемотку натисканням на смугу прогресу вимкнено Зміна яскравості жестом @@ -479,9 +492,10 @@ Second \"item\" text" Затемнення фону панелі жесту Значення затемнення від 0 до 100 Значення затемнення панелі жесту має бути в межах від 0 до 100 - Колір смуги прогресу панелі жесту - Колір смуги прогресу під час регулювання гучності та яскравості - Недійсний колір смуги прогресу + Колір смуги прогресу яскравості + Колір смуги прогресу під час регулювання яскравості + Колір смуги прогресу гучності + Колір смуги прогресу під час регулювання гучності Розмір тексту панелі жесту Розмір тексту панелі жесту від 1 до 30 Розмір тексту має бути від 1 до 30 @@ -737,6 +751,9 @@ Second \"item\" text" Приховати мітку місцезнаходження Мітку місцезнаходження приховано Мітка місцезнаходження показується + Приховати панель коментарів + Панель коментарів приховано + Панель коментарів показується Приховати \"Зберегти музику\" Кнопку \"Зберегти музику\" приховано Кнопка \"Зберегти музику\" показується @@ -1099,11 +1116,6 @@ Second \"item\" text" %s секунд(и) Непрозорість: Колір: - Колір змінено - Колір скинуто - Невірний код кольору - Скинути колір - Скинути Про інтеграцію Дані надаються через API SponsorBlock. Натисніть тут, щоб дізнатися більше та побачити завантаження для інших платформ @@ -1141,13 +1153,13 @@ Second \"item\" text" Змінити початкову сторінку За замовчуванням Усі підписки - Усі підписки + Перегляд каналів Навчання - Навігатор - Мода і краса + Що нового + Мода та краса Ігри Історія - Бібліотека + Вкладка \"Ви\" Відео, які сподобалися Прямі трансляції Фільми @@ -1245,13 +1257,13 @@ Second \"item\" text" Екран завантаження макета матиме градієнтне тло Екран завантаження макета матиме суцільне тло Увімкнути користувацький колір - Показується користувацький колір панелі прогресу - Показується оригінальний колір панелі прогресу - Користувацький колір - Значення кольору панелі прогресу - Користувацький вторинний колір - Значення вторинного кольору панелі прогресу - Недійсне значення кольору панелі прогресу + Показується користувацький колір смуги прогресу + Показується оригінальний колір смуги прогресу + Користувацький колір смуги + Значення кольору смуги прогресу + Користувацький вторинний колір смуги + Значення вторинного кольору смуги прогресу + Недійсне значення кольору смуги прогресу Змінити хост зображень @@ -1328,6 +1340,22 @@ Second \"item\" text" Налаштування GmsCore Відкрити GmsCore для налаштування та входу в обліковий запис Google + + Тактильна віддача + Змінити тактильну віддачу + Вимкнути вібрацію між розділами + Вібрацію між розділами вимкнено + Вібрацію між розділами ввімкнено + Вимкнути вібрацію точного перемотування + Вібрацію точного перемотування вимкнено + Вібрацію точного перемотування ввімкнено + Вимкнути вібрацію скасування перемотування + Вібрацію скасування перемотування вимкнено + Вібрацію скасування перемотування ввімкнено + Вимкнути вібрацію при масштабуванні + Вібрацію при масштабуванні вимкнено + Вібрацію при масштабуванні ввімкнено + Якщо Ви нещодавно змінили дані для входу у свій обліковий запис, видаліть і повторно встановіть MicroG. @@ -1346,11 +1374,6 @@ Second \"item\" text" Параметри запиту відстеження вилучаються з посилань під час поширення посилань Параметри запиту відстеження не вилучаються з посилань під час поширення посилань - - Вимкнути вібрацію при масштабуванні - Вібрації при масштабуванні вимкнено - Вібрації при масштабуванні ввімкнено - Примусово оригінальна мова звукової доріжки Використовується оригінальна мова звукової доріжки @@ -1378,7 +1401,7 @@ Second \"item\" text" Кнопка швидкості відтворення - Кнопка швидкості відтворення показується + Кнопка показується. Натисніть і утримуйте, щоб відновити стандартну швидкість відтворення Кнопка швидкості відтворення не показується @@ -1390,6 +1413,7 @@ Second \"item\" text" Користувацькі швидкості повинні бути менші ніж %s Неправильні користувацькі швидкості відтворення Авто + Швидкість відтворення скинуто до: %s Користувацька швидкість при натисканні та утриманні Швидкість відтворення від 0 до 8 diff --git a/patches/src/main/resources/addresources/values-ur-rIN/strings.xml b/patches/src/main/resources/addresources/values-ur-rIN/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-ur-rIN/strings.xml +++ b/patches/src/main/resources/addresources/values-ur-rIN/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-uz-rUZ/strings.xml b/patches/src/main/resources/addresources/values-uz-rUZ/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-uz-rUZ/strings.xml +++ b/patches/src/main/resources/addresources/values-uz-rUZ/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values-vi-rVN/strings.xml b/patches/src/main/resources/addresources/values-vi-rVN/strings.xml index 885b15e6d..518d46319 100644 --- a/patches/src/main/resources/addresources/values-vi-rVN/strings.xml +++ b/patches/src/main/resources/addresources/values-vi-rVN/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" Thiết lập Bạn có muốn tiếp tục không? Đặt lại + Đặt lại màu + Màu không hợp lệ Làm mới và khởi động lại Khởi động lại Nhập @@ -47,12 +49,12 @@ Second \"item\" text" Thử một từ khóa khác Xóa khỏi lịch sử tìm kiếm? Hiện biểu tượng cài đặt ReVanced - Các biểu tượng cài đặt được hiển thị + Các biểu tượng cài đặt được hiện Các biểu tượng cài đặt không được hiển thị Ngôn ngữ ReVanced - "Một số ngôn ngữ có thể chưa được dịch đầy đủ hoặc bị thiếu. + "Bản dịch cho một số ngôn ngữ có thể bị thiếu hoặc không đầy đủ. -Để đóng góp bản dịch các ngôn ngữ mới, hãy truy cập translate.revanced.app" +Để dịch các ngôn ngữ mới, hãy truy cập translate.revanced.app" Ngôn ngữ ứng dụng Nhập / Xuất Nhập / Xuất cài đặt ReVanced @@ -74,11 +76,11 @@ Hãy làm theo hướng dẫn \"Don't kill my app\" dành cho điện thoại c Việc cấp quyền chạy nền là bắt buộc để ứng dụng hoạt động." Mở trang web - "Cần phải tắt tối ưu hóa pin cho MicroG GmsCore để tránh sự cố. + "Tối ưu hóa pin cho MicroG GmsCore phải được tắt để tránh sự cố. -Tắt tối ưu hóa pin cho MicroG sẽ không ảnh hưởng đáng kể đến hiệu suất sử dụng pin. +Tắt tối ưu hóa pin cho MicroG sẽ không ảnh hưởng tiêu cực đến việc sử dụng pin. -Nhấn nút tiếp tục và cho phép thay đổi lựa chọn tối ưu hóa." +Nhấn nút tiếp tục và cho phép thay đổi tối ưu hóa." Tiếp tục @@ -115,15 +117,29 @@ Nhấn nút tiếp tục và cho phép thay đổi lựa chọn tối ưu hóa." Bộ đệm giao thức nhật ký Ghi nhật ký gỡ lỗi bao gồm thông tin bộ đệm nguyên mẫu Ghi nhật ký gỡ lỗi mà không có thông tin bộ đệm nguyên mẫu - Ghi nhật ký truy vết stack - Nhật ký gỡ lỗi bao gồm truy vết stack - Nhật ký gỡ lỗi không bao gồm truy vết stack + "Bật cài đặt này sẽ ghi lại dữ liệu bố cục bổ sung, bao gồm cả văn bản trên màn hình cho một số thành phần giao diện người dùng. + +Điều này có thể giúp xác định các thành phần khi tạo bộ lọc tùy chỉnh. + +Tuy nhiên, việc bật tính năng này cũng sẽ ghi lại một số dữ liệu người dùng, chẳng hạn như địa chỉ IP của bạn." + Ghi nhật ký truy vết ngăn xếp + Nhật ký gỡ lỗi bao gồm truy vết ngăn xếp + Nhật ký gỡ lỗi không bao gồm truy vết ngăn xếp Hiện thông báo nổi về lỗi ReVanced Thông báo nổi được hiển thị nếu xảy ra lỗi Thông báo nổi không được hiển thị nếu xảy ra lỗi "Tắt thông báo lỗi sẽ ẩn tất cả thông báo lỗi của ReVanced. Bạn sẽ không được thông báo về bất kỳ sự kiện bất ngờ nào." + Xuất nhật ký gỡ lỗi + Sao chép nhật ký gỡ lỗi ReVanced vào bảng nhớ tạm + Tính năng ghi nhật ký gỡ lỗi đã tắt + Không tìm thấy nhật ký + Đã sao chép nhật ký + Không xuất được nhật ký: $s + Xóa nhật ký gỡ lỗi + Xóa tất cả nhật ký gỡ lỗi ReVanced đã lưu trữ + Đã xóa nhật ký Ẩn các thẻ album @@ -153,7 +169,7 @@ Bạn sẽ không được thông báo về bất kỳ sự kiện bất ngờ n Nút được hiển thị Ẩn kệ \'Dành cho bạn\' - Kệ trên trang kênh đã bị ẩn + Kệ trên trang kênh được ẩn Kệ trên trang kênh được hiển thị @@ -162,16 +178,16 @@ Bạn sẽ không được thông báo về bất kỳ sự kiện bất ngờ n Nút được hiển thị Ẩn nhãn video đề xuất - Nhãn “Mọi người cũng xem” và “Bạn cũng có thể thích” đã bị ẩn - Nhãn “Mọi người cũng xem” và “Bạn cũng có thể thích” được hiển thị + Nhãn “Mọi người cũng xem” và “Bạn cũng có thể thích” được ẩn + Nhãn “Mọi người cũng xem” và “Bạn cũng có thể thích” được hiện Ẩn nút \'Hiện thêm\' Nút đã bị ẩn Nút được hiển thị Ẩn kệ vé - Kệ vé đã bị ẩn - Kệ vé đang hiển thị + Kệ vé được ẩn + Kệ vé được hiện Ẩn phản ứng theo thời gian Phản ứng theo thời gian đã bị ẩn Phản ứng theo thời gian được hiển thị @@ -182,8 +198,8 @@ Bạn sẽ không được thông báo về bất kỳ sự kiện bất ngờ n Kệ danh mục được đề xuất đã bị ẩn Kệ danh mục được đề xuất được hiển thị Ẩn thẻ có thể mở rộng bên dưới video - Thẻ có thể mở rộng đã bị ẩn - Thẻ có thể mở rộng được hiển thị + Thẻ có thể mở rộng được ẩn + Thẻ có thể mở rộng được hiện Ẩn bài đăng cộng đồng Bài đăng cộng đồng đã bị ẩn Bài đăng cộng đồng được hiển thị @@ -201,7 +217,7 @@ Bạn sẽ không được thông báo về bất kỳ sự kiện bất ngờ n Nguyên tắc cộng đồng được hiển thị Ẩn nguyên tắc cộng đồng cho người đăng ký Nguyên tắc cộng đồng cho người đăng ký đã bị ẩn - Nguyên tắc cộng đồng dành cho người đăng ký được hiển thị + Nguyên tắc cộng đồng dành cho người đăng ký được hiện Ẩn kệ hội viên kênh Kệ hội viên kênh đã bị ẩn Kệ hội viên kênh được hiển thị @@ -213,13 +229,13 @@ Bạn sẽ không được thông báo về bất kỳ sự kiện bất ngờ n Bảng thông tin được hiển thị Ẩn bảng thông tin y tế Bảng thông tin y tế đã bị ẩn - Bảng thông tin y tế được hiển thị + Bảng thông tin y tế được hiện Ẩn nút kênh Nút kênh đã bị ẩn Nút kênh được hiển thị - Ẩn Playables - Chơi game đã bị ẩn - Chơi game được hiển thị + Ẩn kệ Chơi trò chơi + Kệ Chơi trò chơi được ẩn + Kệ Chơi trò chơi được hiện Ẩn các hành động nhanh khi ở toàn màn hình Hành động nhanh đã bị ẩn Hành động nhanh được hiển thị @@ -239,20 +255,20 @@ Bạn sẽ không được thông báo về bất kỳ sự kiện bất ngờ n Thẻ nghệ sĩ đã bị ẩn Thẻ nghệ sĩ được hiển thị Ẩn \'Bản tóm tắt video do AI tạo\' - Phần tóm tắt video đã bị ẩn + Phần tóm tắt video được ẩn Phần tóm tắt video được hiển thị Ẩn Hỏi - Phần Hỏi đã bị ẩn - Phần Hỏi được hiển thị + Phần Hỏi được ẩn + Phần Hỏi được hiện Ẩn Thuộc tính - Phần Địa điểm nổi bật, Trò chơi, Âm nhạc và Người được đề cập đã bị ẩn + Phần Địa điểm nổi bật, Trò chơi, Âm nhạc và Người được đề cập được ẩn Phần Địa điểm nổi bật, Trò chơi, Âm nhạc và Người được đề cập được hiển thị Ẩn Chương Phần chương đã bị ẩn Phần chương được hiển thị Ẩn \'Cách nội dung này được tạo ra\' - Phần cách nội dung được tạo ra đã bị ẩn - Phần cách nội dung được tạo ra được hiển thị + Phần cách nội dung được tạo ra được ẩn + Phần cách nội dung được tạo ra được hiện Ẩn \'Khám phá podcast\' Phần Khám phá podcast đã bị ẩn Phần Khám phá podcast được hiển thị @@ -285,10 +301,10 @@ Bạn sẽ không được thông báo về bất kỳ sự kiện bất ngờ n Tóm tắt cuộc trò chuyện được hiển thị Ẩn tóm tắt Bình luận AI Tóm tắt bình luận đã bị ẩn - Tóm tắt bình luận được hiển thị + Tóm tắt bình luận được hiện Ẩn tiêu đề \'Bình luận của hội viên\' - Tiêu đề bình luận của hội viên đã bị ẩn - Tiêu đề bình luận của hội viên được hiển thị + Tiêu đề Bình luận của hội viên được ẩn + Tiêu đề Bình luận của hội viên được hiện Ẩn phần bình luận Phần Bình luận đã bị ẩn Phần Bình luận được hiển thị @@ -296,7 +312,7 @@ Bạn sẽ không được thông báo về bất kỳ sự kiện bất ngờ n Nút Tạo video ngắn đã bị ẩn Nút Tạo video ngắn được hiển thị Ẩn nút biểu tượng cảm xúc và dấu thời gian - Nút biểu tượng cảm xúc và dấu thời gian đã bị ẩn + Nút biểu tượng cảm xúc và dấu thời gian được ẩn Nút biểu tượng cảm xúc và dấu thời gian được hiển thị Ẩn xem trước bình luận Xem trước bình luận đã bị ẩn @@ -314,7 +330,7 @@ Nếu cài đặt này được bật và Doodle đang hiển thị tại khu v Bộ lọc tùy chỉnh Ẩn các thành phần bằng bộ lọc tùy chỉnh Bật bộ lọc tùy chỉnh - Bộ lọc tùy chỉnh đã bật + Bộ lọc tùy chỉnh được bật Bộ lọc tuỳ chỉnh đã tắt Bộ lọc tùy chỉnh @@ -365,9 +381,6 @@ Hạn chế Tính năng này chỉ khả dụng cho các thiết bị cũ hơn" Quảng cáo toàn màn hình được hiển thị - Ẩn quảng cáo có nút - Quảng cáo có nút đã bị ẩn - Quảng cáo có nút được hiển thị Ẩn nhãn quảng cáo được tài trợ Nhãn quảng cáo được tài trợ đã bị ẩn Nhãn quảng cáo được tài trợ được hiển thị @@ -413,10 +426,10 @@ Tính năng này chỉ khả dụng cho các thiết bị cũ hơn" Đã chép URL vào bảng nhớ tạm Đã chép URL với dấu thời gian Hiện nút sao chép URL video - Nút được hiển thị. Chạm để sao chép video URL. Chạm và giữ để sao chép với dấu thời gian + Nút được hiển thị. Chạm để sao chép URL video. Chạm và giữ để sao chép với dấu thời gian Nút không được hiển thị Hiện nút sao chép URL với dấu thời gian - Nút được hiển thị. Chạm để sao chép video URL với dấu thời gian. Chạm và giữ để sao chép video không kèm theo dấu thời gian + Nút được hiện. Chạm để sao chép video URL với dấu thời gian. Chạm và giữ để sao chép video không kèm theo dấu thời gian Nút không được hiển thị @@ -430,9 +443,9 @@ Tính năng này chỉ khả dụng cho các thiết bị cũ hơn" Các thiết lập trình tải xuống bên ngoài Hiện nút tải xuống bên ngoài Nút tải xuống trong trình phát đã được hiển thị - Nút tải xuống trong trình phát không được hiển thị + Nút tải xuống trong trình phát không được hiện - Thay thế nút hành động Tải xuống + Thay thế Nút hành động tải xuống Nút tải xuống mở trình tải xuống bên ngoài Nút tải xuống mở trình tải xuống nội bộ ứng dụng Tên gói trình tải xuống @@ -446,17 +459,17 @@ Tính năng này chỉ khả dụng cho các thiết bị cũ hơn" Bật nhấn để tua - Nhấn để tua được bật - Nhấn để tua bị tắt + Nhấn để tua đã bật + Nhấn để tua đã tắt Bật cử chỉ độ sáng - "Đã bật vuốt độ sáng toàn màn hình + "Vuốt chỉnh độ sáng toàn màn hình đã bật Điều chỉnh độ sáng bằng cách vuốt dọc ở bên trái màn hình" - Đã tắt vuốt độ sáng toàn màn hình + Vuốt độ sáng toàn màn hình đã tắt Bật cử chỉ âm lượng - "Đã bật vuốt âm lượng toàn màn hình + "Vuốt âm lượng toàn màn hình đã bật Điều chỉnh âm lượng bằng cách vuốt dọc ở bên phải màn hình" Vuốt âm lượng toàn màn hình đã tắt @@ -478,9 +491,10 @@ Tính năng này chỉ khả dụng cho các thiết bị cũ hơn" Độ mờ nền phủ vuốt Giá trị độ mờ từ 0-100 Độ mờ vuốt phải nằm trong khoảng từ 0-100 - Màu thanh tiến trình lớp phủ vuốt - Màu của thanh tiến trình cho các điều khiển âm lượng và độ sáng - Màu thanh tiến trình không hợp lệ + Màu lớp phủ vuốt độ sáng + Màu của thanh điều chỉnh độ sáng + Màu lớp phủ vuốt âm lượng + Màu của thanh điều chỉnh âm lượng Kích thước văn bản lớp phủ vuốt Kích thước văn bản cho lớp phủ vuốt từ 1-30 Kích thước văn bản phải nằm trong khoảng 1-30 @@ -554,23 +568,23 @@ Tính năng này chỉ khả dụng cho các thiết bị cũ hơn" Ẩn hoặc thay đổi các nút ở thanh điều hướng Ẩn Trang chủ - Nút trang chủ đã bị ẩn - Nút trang chủ được hiển thị + Nút trang chủ được ẩn + Nút trang chủ được hiện Ẩn Shorts Nút Shorts đã bị ẩn - Nút Shorts được hiển thị + Nút Shorts được hiện - Ẩn Tạo + Ẩn nút Tạo Nút tạo đã bị ẩn Nút tạo được hiển thị Ẩn Kênh đăng ký - Nút kênh đăng ký đã bị ẩn - Nút kênh đăng ký được hiển thị + Nút kênh đăng ký được ẩn + Nút kênh đăng ký được hiện Ẩn Thông báo - Nút thông báo đã bị ẩn - Nút thông báo được hiển thị + Nút thông báo được ẩn + Nút thông báo được hiện Chuyển vị nút Tạo với nút Thông báo "Nút tạo được chuyển đổi với nút Thông báo @@ -642,16 +656,16 @@ Nếu việc thay đổi cài đặt này không có hiệu lực, hãy thử ch Nút bản âm thanh đã bị ẩn Nút bản âm thanh được hiển thị - "Trình đơn bản âm thanh đã bị ẩn + "Menu theo dõi âm thanh được ẩn -Để hiển thị trình đơn Bản âm thanh, hãy thay đổi 'Giả mạo luồng phát video' thành iOS TV" +Để hiện trình đơn Theo dõi âm thanh, hãy thay đổi 'Giả mạo luồng video' thành iOS TV" Ẩn Xem trong thực tế ảo Trình đơn xem trong thực tế ảo đã bị ẩn Trình đơn xem trong thực tế ảo được hiển thị - Ẩn trình đơn chất lượng video dưới - Trình đơn chất lượng video bên dưới đã bị ẩn - Trình đơn chất lượng video bên dưới được hiển thị + Ẩn trình đơn chất lượng chân video + Trình đơn chất lượng chân video được ẩn + Trình đơn chất lượng chân video được hiện Ẩn các nút Trước & Tiếp theo @@ -659,12 +673,12 @@ Nếu việc thay đổi cài đặt này không có hiệu lực, hãy thử ch Các nút được hiển thị Ẩn nút truyền Nút Truyền đã bị ẩn - Nút Truyền được hiển thị + Nút Truyền được hiện Ẩn nút Chú thích Nút phụ đề đã bị ẩn Nút phụ đề được hiển thị - Ẩn nút Phát tự động + Ẩn nút Tự động phát Nút tự động phát đã bị ẩn Nút tự động phát được hiển thị @@ -676,16 +690,16 @@ Nếu việc thay đổi cài đặt này không có hiệu lực, hãy thử ch Tắt Chế độ môi trường khi toàn màn hình Chế độ môi trường đã tắt - Chế độ môi trường được bật + Chế độ môi trường đã bật Ẩn thẻ thông tin Thẻ thông tin đã bị ẩn - Thẻ thông tin được hiển thị + Thẻ thông tin được hiện Tắt chuyển động cuộn số - Số cuộn không chuyển động + Số cuộn không được chuyển động Số cuộn được chuyển động @@ -736,6 +750,9 @@ Nếu việc thay đổi cài đặt này không có hiệu lực, hãy thử ch Ẩn nhãn vị trí Nhãn vị trí đã bị ẩn Nhãn vị trí được hiển thị + Ẩn bảng Bình luận + Đã ẩn bảng điều khiển bình luận + Bảng bình luận đang hiển thị Ẩn nút Lưu âm thanh Nút lưu nhạc đã bị ẩn Nút lưu nhạc được hiển thị @@ -757,9 +774,9 @@ Nếu việc thay đổi cài đặt này không có hiệu lực, hãy thử ch Ẩn nhãn dán Nhãn dán đã bị ẩn Nhãn dán được hiển thị - Ẩn hiệu ứng thị giác nút Thích - Hiệu ứng đài phun nút thích đã bị ẩn - Hiệu ứng đài phun nút thích được hiển thị + Ẩn hiệu ứng đài phun nút Thích + Hiệu ứng đài phun nút thích được ẩn + Hiệu ứng đài phun nút thích được hiện Ẩn nút Thích Nút thích đã bị ẩn Nút thích được hiển thị @@ -890,8 +907,8 @@ Hạn chế: Số lượt không thích có thể không xuất hiện ở chế Bật thanh tìm kiếm rộng - Thanh tìm kiếm rộng được bật - Thanh tìm kiếm rộng được tắt + Thanh tìm kiếm rộng đã bật + Thanh tìm kiếm rộng đã tắt Bật hình thu nhỏ chất lượng cao @@ -949,8 +966,8 @@ Tính năng này hoạt động tốt nhất với chất lượng video 720p tr Thông báo nổi được hiển thị nếu SponsorBlock không khả dụng Thông báo nổi không được hiển thị nếu SponsorBlock không khả dụng Bật theo dõi số lần bỏ qua - Để bảng xếp hạng SponsorBlock biết đã tiết kiệm bao nhiêu thời gian. Một tin nhắn được gửi đến bảng xếp hạng mỗi khi một phân đoạn được bỏ qua - Theo dõi số lần bỏ qua được bật + Cho phép bảng xếp hạng SponsorBlock biết đã tiết kiệm được bao nhiêu thời gian. Một tin nhắn được gửi đến bảng xếp hạng mỗi khi một phân đoạn bị bỏ qua + Theo dõi số lần bỏ qua không được bật Thời lượng phân đoạn tối thiểu Các phân đoạn ngắn hơn giá trị này (bằng giây) sẽ không được hiển thị hoặc bị bỏ qua Thời lượng không hợp lệ @@ -1098,11 +1115,6 @@ Bạn đã sẵn sàng gửi?" %s giây Độ mờ: Màu: - Màu sắc đã được thay đổi - Đặt lại màu sắc - Mã màu không hợp lệ - Đặt lại màu - Đặt lại Giới thiệu Dữ liệu được cung cấp bởi API SponsorBlock. Nhấn vào đây để tìm hiểu thêm và xem các bản tải cho các nền tảng khác @@ -1327,6 +1339,22 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn"Cài đặt GmsCore Các cài đặt cho GmsCore + + Phản hồi xúc giác + Thay đổi phản hồi xúc giác + Tắt phản hồi xúc giác chương + Phản hồi xúc giác chương đã tắt + Phản hồi xúc giác chương đã bật + Tắt phản hồi xúc giác khi tua chính xác + Phản hồi xúc giác khi tua chính xác đã tắt + Phản hồi xúc giác khi tua chính xác đã bật + Tắt phản hồi xúc giác khi huỷ tua + Phản hồi xúc giác khi huỷ tua đã tắt + Phản hồi xúc giác khi huỷ tua đã bật + Tắt phản hồi xúc giác khi thu phóng + Phản hồi xúc giác khi thu phóng đã tắt + Phản hồi xúc giác khi thu phóng đã bật + Nếu gần đây bạn đã cập nhật thông tin đăng nhập tài khoản của mình, hãy gỡ và cài đặt lại MicroG. @@ -1345,11 +1373,6 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn"Tham số truy vấn theo dõi đã bị loại bỏ khỏi liên kết Tham số truy vấn theo dõi không được loại bỏ khỏi liên kết - - Tắt phản hồi xúc giác khi thu phóng - Phản hồi xúc giác được tắt - Phản hồi xúc giác được bật - Buộc sử dụng ngôn ngữ âm thanh gốc Sử dụng ngôn ngữ âm thanh gốc @@ -1377,7 +1400,7 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn" Hiện nút hộp thoại tốc độ phát - Nút được hiển thị + Nút được hiển thị. Nhấn và giữ để đặt lại tốc độ phát về mặc định Nút không được hiển thị @@ -1389,6 +1412,7 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn"Tốc độ tùy chỉnh phải nhỏ hơn %s Tốc độ phát lại tùy chỉnh không hợp lệ Tự động + Tốc độ phát đã được đặt lại thành: %s Tốc độ chạm và giữ tùy chỉnh Tốc độ phát từ 0 đến 8 @@ -1411,7 +1435,7 @@ Bật tính năng này có thể mở khóa chất lượng video cao hơn" Bật vuốt để tua - Vuốt để tua được bật + Vuốt để tua đã bật Vuốt để tua không được bật @@ -1480,8 +1504,8 @@ AVC có độ phân giải tối đa là 1080p, bộ giải mã âm thanh Opus k Bật chế độ gỡ lỗi Twitch - Chế độ gỡ lỗi Twitch được bật (không khuyến nghị) - Chế độ gỡ lỗi Twitch được tắt + Chế độ gỡ lỗi Twitch đã bật (không khuyến nghị) + Chế độ gỡ lỗi Twitch đã tắt Cài đặt ReVanced @@ -1498,8 +1522,8 @@ AVC có độ phân giải tối đa là 1080p, bộ giải mã âm thanh Opus k Quảng cáo phía máy khách Quảng cáo luồng đảm bảo phía máy khách Nhật ký gỡ lỗi - Nhật ký gỡ lỗi được bật - Nhật ký gỡ lỗi được tắt + Nhật ký gỡ lỗi đã bật + Nhật ký gỡ lỗi đã tắt diff --git a/patches/src/main/resources/addresources/values-zh-rCN/strings.xml b/patches/src/main/resources/addresources/values-zh-rCN/strings.xml index 116e28465..0150ac38b 100644 --- a/patches/src/main/resources/addresources/values-zh-rCN/strings.xml +++ b/patches/src/main/resources/addresources/values-zh-rCN/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" 设置 您想要继续吗? 重置 + 重置颜色 + 无效的颜色 刷新并重启 重启 导入 @@ -115,6 +117,11 @@ Second \"item\" text" 记录协议缓冲区 调试日志包括协议缓冲区 调试日志不包括协议缓冲区 + "启用此设置将记录额外的布局数据,包括某些 UI 组件的屏幕文本。 + +这有助于在创建自定义过滤器时识别组件。 + +但是,启用此设置也会记录一些用户数据,例如您的 IP 地址。" 记录堆栈跟踪 调试日志包括堆栈跟踪 调试日志不包括堆栈跟踪 @@ -124,6 +131,15 @@ Second \"item\" text" "关闭错误 Toast 会隐藏所有 ReVanced 错误通知。 您不会收到任何意外事件的通知。" + 导出调试日志 + 将 ReVanced 调试日志复制到剪贴板 + 调试日志记录已禁用 + 未找到日志 + 日志已复制 + 导出日志失败:$s + 清除调试日志 + 清除所有存储的 ReVanced 调试日志 + 日志已清除 隐藏专辑卡片 @@ -365,9 +381,6 @@ Second \"item\" text" 此功能仅适用于旧设备" 全屏广告已显示 - 隐藏信息流视频广告 - 按钮广告已隐藏 - 按钮广告已显示 隐藏付费推广标签 付费推广标签已隐藏 付费推广标签已显示 @@ -478,9 +491,10 @@ Second \"item\" text" 滑动提示层背景的不透明度 不透明度值介于 0-100 之间 滑动不透明度必须介于 0-100 之间 - 滑动提示层进度条颜色 - 音量和亮度控件的进度条颜色 - 无效的进度条颜色 + 滑动提示层亮度颜色 + 亮度控件进度条的颜色 + 滑动提示层音量颜色 + 音量控件进度条的颜色 滑动提示层文字大小 滑动提示层的文字大小,范围为 1-30 文字大小必须在 1-30 之间 @@ -736,6 +750,9 @@ Second \"item\" text" 隐藏位置标签 位置标签已隐藏 位置标签已显示 + 隐藏评论面板 + 已隐藏评论面板 + 评论面板已显示 隐藏「保存音乐」按钮 保存音乐按钮已隐藏 保存音乐按钮已显示 @@ -1103,11 +1120,6 @@ Second \"item\" text" %s 秒 不透明度: 颜色: - 已更改颜色 - 重置颜色 - 无效的颜色代码 - 重置颜色 - 重置 关于 数据由 SponsorBlock API 提供。点击这里了解更多信息并查看其他平台的下载内容 @@ -1332,6 +1344,22 @@ Second \"item\" text" GmsCore 设置 GmsCore 的设置 + + 触感反馈 + 更改触感反馈 + 禁用章节触感反馈 + 已禁用章节触感反馈 + 已启用章节触感反馈 + 禁用精确搜索触感反馈 + 精确查找触觉反馈已禁用 + 已启用精确搜索触感反馈 + 禁用撤销查找触觉反馈 + 撤销查找触觉反馈已禁用 + 撤销查找触觉反馈已启用 + 禁用缩放触觉反馈 + 缩放触觉反馈已禁用 + 缩放触觉反馈已启用 + 如果您最近更改了帐户登录详细信息,请卸载并重新安装 MicroG。 @@ -1350,11 +1378,6 @@ Second \"item\" text" 链接中跟踪参数已去除 链接中跟踪参数未去除 - - 禁用缩放触觉反馈 - 触觉反馈已禁用 - 触觉反馈已启用 - 强制使用原始音频语言 使用原始音频语言 @@ -1382,7 +1405,7 @@ Second \"item\" text" 显示播放速度对话框按钮 - 按钮已显示 + 按钮已显示。点住即可将播放速度重置为默认值 按钮未显示 @@ -1394,6 +1417,7 @@ Second \"item\" text" 自定义速度必须小于 %s 自定义播放速度无效 自动 + 已将播放速度重置为:%s 自定义长按速度 0-8之间的播放速度 diff --git a/patches/src/main/resources/addresources/values-zh-rTW/strings.xml b/patches/src/main/resources/addresources/values-zh-rTW/strings.xml index ac4b3c1fd..ccdf4dbe5 100644 --- a/patches/src/main/resources/addresources/values-zh-rTW/strings.xml +++ b/patches/src/main/resources/addresources/values-zh-rTW/strings.xml @@ -355,9 +355,6 @@ Second \"item\" text" 此功能僅適用於舊版裝置" 已顯示全螢幕廣告 - 隱藏按鈕型廣告 - 已隱藏按鈕型廣告 - 已顯示按鈕型廣告 隱藏付費推廣標籤 已隱藏付費推廣標籤 已顯示付費推廣標籤 @@ -468,7 +465,6 @@ Second \"item\" text" 滑動覆蓋背景透明度 不透明度值介於 0 到 100 之間 滑動透明度必須介於 0 到 100 之間 - 音量和亮度控制的進度列顏色 滑動幅度臨界點 滑動幅度臨界點 音量滑動靈敏度 @@ -1075,11 +1071,6 @@ Second \"item\" text" %s 秒 不透明度: 顏色: - 已變更顏色 - 重設顏色 - 無效的顏色代碼 - 重設顏色 - 重設 關於 資料由 SponsorBlock API 提供。輕觸這裡來了解更多資訊和查看其他平台的下載 @@ -1308,6 +1299,9 @@ Second \"item\" text" GmsCore 設定 GmsCore 設定 + + 停用縮放震動 + 如果您最近變更了帳戶登入詳細資訊,請解除安裝並重新安裝 MicroG。 @@ -1326,11 +1320,6 @@ Second \"item\" text" 已從連結移除追蹤查詢參數 未從連結移除追蹤查詢參數 - - 停用縮放震動 - 已停用震動 - 已啟用震動 - 強制使用原始音訊語言 正在使用原始音訊語言 @@ -1358,7 +1347,6 @@ Second \"item\" text" 顯示速度對話方塊按鈕 - 已顯示按鈕 不顯示按鈕 @@ -1370,6 +1358,7 @@ Second \"item\" text" 自訂速度必須小於 %s 自訂播放速度格式不正確 自動 + 已將播放速度重設為:%s 自訂輕觸和按住的速度 播放速度介於 0 到 8 之間 diff --git a/patches/src/main/resources/addresources/values-zu-rZA/strings.xml b/patches/src/main/resources/addresources/values-zu-rZA/strings.xml index 24e47c741..c22e2c4a4 100644 --- a/patches/src/main/resources/addresources/values-zu-rZA/strings.xml +++ b/patches/src/main/resources/addresources/values-zu-rZA/strings.xml @@ -199,6 +199,8 @@ Second \"item\" text" + + @@ -207,8 +209,6 @@ Second \"item\" text" - - diff --git a/patches/src/main/resources/addresources/values/strings.xml b/patches/src/main/resources/addresources/values/strings.xml index 95a31b71f..2aed55eba 100644 --- a/patches/src/main/resources/addresources/values/strings.xml +++ b/patches/src/main/resources/addresources/values/strings.xml @@ -35,6 +35,8 @@ Second \"item\" text" ReVanced Do you wish to proceed? Reset + Reset color + Invalid color Refresh and restart Restart Import @@ -173,6 +175,11 @@ Tap the continue button and allow optimization changes." Log protocol buffer Debug logs include proto buffer Debug logs do not include proto buffer + "Enabling this setting will log additional layout data, including on-screen text for some UI components. + +This can help identify components when creating custom filters. + +However, enabling this will also log some user data such as your IP address." Log stack traces Debug logs include stack trace Debug logs do not include stack trace @@ -182,6 +189,15 @@ Tap the continue button and allow optimization changes." "Turning off error toasts hides all ReVanced error notifications. You will not be notified of any unexpected events." + Export debug logs + Copies ReVanced debug logs to the clipboard + Debug logging is disabled + No logs found + Logs copied + Failed to export logs: $s + Clear debug logs + Clears all stored ReVanced debug logs + Logs cleared Hide album cards @@ -427,9 +443,6 @@ Limitations This feature is only available for older devices" Fullscreen ads are shown - Hide buttoned ads - Buttoned ads are hidden - Buttoned ads are shown Hide paid promotion label Paid promotion label is hidden Paid promotion label is shown @@ -540,9 +553,10 @@ Adjust volume by swiping vertically on the right side of the screen" Swipe overlay background opacity Opacity value between 0-100 Swipe opacity must be between 0-100 - Swipe overlay progress bar color - The color of the progress bar for volume and brightness controls - Invalid progress bar color + Swipe overlay brightness color + The color of the progress bar for brightness controls + Swipe overlay volume color + The color of the progress bar for volume controls Swipe overlay text size The text size for swipe overlay between 1-30 The text size must be between 1-30 @@ -798,6 +812,9 @@ To show the Audio track menu, change \'Spoof video streams\' to iOS TV" Hide location label Location label is hidden Location label is shown + Hide Comment panel + Comment panel is hidden + Comment panel is shown Hide Save music button Save music button is hidden Save music button is shown @@ -1164,11 +1181,6 @@ Ready to submit?" %s seconds Opacity: Color: - Color changed - Color reset - Invalid color code - Reset color - Reset About sponsor.ajay.app Data is provided by the SponsorBlock API. Tap here to learn more and see downloads for other platforms @@ -1396,6 +1408,22 @@ Enabling this can unlock higher video qualities" GmsCore Settings Settings for GmsCore + + Haptic feedback + Change haptic feedback + Disable chapters haptics + Chapters haptics is disabled + Chapters haptics is enabled + Disable precise seeking haptics + Precise seeking haptics is disabled + Precise seeking haptics is enabled + Disable seek undo haptics + Seek undo haptics is disabled + Seek undo haptics is enabled + Disable zoom haptics + Zoom haptics is disabled + Zoom haptics is enabled + If you recently changed your account login details, then uninstall and reinstall MicroG. @@ -1414,11 +1442,6 @@ Enabling this can unlock higher video qualities" Tracking query parameter is removed from links Tracking query parameter is not removed from links - - Disable zoom haptics - Haptics are disabled - Haptics are enabled - Force original audio language Using original audio language @@ -1446,7 +1469,7 @@ Enabling this can unlock higher video qualities" Show speed dialog button - Button is shown + Button is shown. Tap and hold to reset playback speed to default Button is not shown @@ -1458,6 +1481,7 @@ Enabling this can unlock higher video qualities" Custom speeds must be less than %s Invalid custom playback speeds Auto + Playback speed reset to: %s Custom tap and hold speed Playback speed between 0-8 diff --git a/patches/src/main/resources/settings/drawable/revanced_settings_circle_background.xml b/patches/src/main/resources/settings/drawable/revanced_settings_circle_background.xml new file mode 100644 index 000000000..d0c8a7ae4 --- /dev/null +++ b/patches/src/main/resources/settings/drawable/revanced_settings_circle_background.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/patches/src/main/resources/settings/layout/revanced_color_dot_widget.xml b/patches/src/main/resources/settings/layout/revanced_color_dot_widget.xml new file mode 100644 index 000000000..ea61afb8d --- /dev/null +++ b/patches/src/main/resources/settings/layout/revanced_color_dot_widget.xml @@ -0,0 +1,18 @@ + + + + diff --git a/patches/src/main/resources/settings/layout/revanced_color_picker.xml b/patches/src/main/resources/settings/layout/revanced_color_picker.xml new file mode 100644 index 000000000..0c8a3db85 --- /dev/null +++ b/patches/src/main/resources/settings/layout/revanced_color_picker.xml @@ -0,0 +1,11 @@ + + + + +