mirror of
https://github.com/ReVanced/revanced-patches.git
synced 2026-01-23 18:51:03 +00:00
Compare commits
40 Commits
v5.24.0-de
...
v5.25.0-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53587f190d | ||
|
|
83c148addc | ||
|
|
5c8ed05727 | ||
|
|
33833d7a1e | ||
|
|
b712f38017 | ||
|
|
517368eda7 | ||
|
|
2093c0c175 | ||
|
|
a7cfd80bfe | ||
|
|
2990dc6d4e | ||
|
|
c0e52bb6b3 | ||
|
|
93fdd6f538 | ||
|
|
decd249f20 | ||
|
|
d79cb3eea8 | ||
|
|
584b00fd87 | ||
|
|
795016abce | ||
|
|
dc1dbd50a8 | ||
|
|
2984d7362d | ||
|
|
627aed4010 | ||
|
|
4ab1f0cfa9 | ||
|
|
86e8e61ab2 | ||
|
|
e286dab74e | ||
|
|
712a82439f | ||
|
|
4449546c85 | ||
|
|
8d61ba90c3 | ||
|
|
689be79f71 | ||
|
|
b6047fa6b3 | ||
|
|
82bbd603ac | ||
|
|
bc0c3c452d | ||
|
|
fe864d8331 | ||
|
|
4f686935c3 | ||
|
|
798596fd83 | ||
|
|
38b37f182a | ||
|
|
52b9dc5c9f | ||
|
|
dea7108c45 | ||
|
|
24b4579cb9 | ||
|
|
0b52f3d192 | ||
|
|
18c374a81e | ||
|
|
092303e431 | ||
|
|
6bf5bf9d45 | ||
|
|
b2b09a2025 |
6
.github/workflows/build_pull_request.yml
vendored
6
.github/workflows/build_pull_request.yml
vendored
@@ -19,11 +19,11 @@ jobs:
|
|||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: "temurin"
|
distribution: 'temurin'
|
||||||
java-version: "17"
|
java-version: '17'
|
||||||
|
|
||||||
- name: Cache Gradle
|
- name: Cache Gradle
|
||||||
uses: burrunan/gradle-cache-action@v1
|
uses: burrunan/gradle-cache-action@v3
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
env:
|
env:
|
||||||
|
|||||||
23
.github/workflows/release.yml
vendored
23
.github/workflows/release.yml
vendored
@@ -13,24 +13,23 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
packages: write
|
packages: write
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
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
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: "temurin"
|
distribution: 'temurin'
|
||||||
java-version: "17"
|
java-version: '17'
|
||||||
|
|
||||||
- name: Cache Gradle
|
- name: Cache Gradle
|
||||||
uses: burrunan/gradle-cache-action@v1
|
uses: burrunan/gradle-cache-action@v3
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
env:
|
env:
|
||||||
@@ -40,7 +39,7 @@ jobs:
|
|||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: "lts/*"
|
node-version: 'lts/*'
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@@ -54,6 +53,14 @@ jobs:
|
|||||||
fingerprint: ${{ vars.GPG_FINGERPRINT }}
|
fingerprint: ${{ vars.GPG_FINGERPRINT }}
|
||||||
|
|
||||||
- name: Release
|
- name: Release
|
||||||
|
uses: cycjimmy/semantic-release-action@v4
|
||||||
|
id: release
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
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
|
||||||
|
|||||||
10
.releaserc
10
.releaserc
@@ -22,7 +22,7 @@
|
|||||||
{
|
{
|
||||||
"assets": [
|
"assets": [
|
||||||
"CHANGELOG.md",
|
"CHANGELOG.md",
|
||||||
"gradle.properties",
|
"gradle.properties"
|
||||||
],
|
],
|
||||||
"message": "chore: Release v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
"message": "chore: Release v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
||||||
}
|
}
|
||||||
@@ -33,16 +33,16 @@
|
|||||||
"assets": [
|
"assets": [
|
||||||
{
|
{
|
||||||
"path": "patches/build/libs/patches-!(*sources*|*javadoc*).rvp?(.asc)"
|
"path": "patches/build/libs/patches-!(*sources*|*javadoc*).rvp?(.asc)"
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
successComment: false
|
"successComment": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"@saithodev/semantic-release-backmerge",
|
"@saithodev/semantic-release-backmerge",
|
||||||
{
|
{
|
||||||
backmergeBranches: [{"from": "main", "to": "dev"}],
|
"backmergeBranches": [{"from": "main", "to": "dev"}],
|
||||||
clearWorkspace: true
|
"clearWorkspace": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|||||||
125
CHANGELOG.md
125
CHANGELOG.md
@@ -1,3 +1,128 @@
|
|||||||
|
# [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)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **Spotify - Fix third party launchers widgets:** Add missing compatibility annotation ([0493f80](https://github.com/ReVanced/revanced-patches/commit/0493f8035b26b90c5f8e42be2e2a5ce73d8685a5))
|
||||||
|
* **YouTube - Hide layout components:** Fix `Hide video recommendation labels` ([#4956](https://github.com/ReVanced/revanced-patches/issues/4956)) ([ae05ac3](https://github.com/ReVanced/revanced-patches/commit/ae05ac38151ebd3197953af97ca0dd847a04cc2d))
|
||||||
|
* **YouTube - Settings:** Correctly show summary text if search box is closed before searching ([d0ae835](https://github.com/ReVanced/revanced-patches/commit/d0ae835d3381fc659c9bb4a2d130d4db8a1499cf))
|
||||||
|
* **YouTube - SponsorBlock:** Fix segment category summary not showing category description ([06934a6](https://github.com/ReVanced/revanced-patches/commit/06934a60d91b40a5cdf7f4cd92deae4a136c149b))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **GmsCore support:** Open vendor specific DontKillMyApp if available ([#4952](https://github.com/ReVanced/revanced-patches/issues/4952)) ([b89927a](https://github.com/ReVanced/revanced-patches/commit/b89927a10e3b909a3c37fbb75c16a7abbce44560))
|
||||||
|
* **NU.nl:** Support version `11.3.0` ([#4925](https://github.com/ReVanced/revanced-patches/issues/4925)) ([bedde60](https://github.com/ReVanced/revanced-patches/commit/bedde60fc1a52b0fd491174b3b5b887435eb621a))
|
||||||
|
* **Spotify:** Add `Fix third party launchers widgets` patch ([#4893](https://github.com/ReVanced/revanced-patches/issues/4893)) ([23bfdc9](https://github.com/ReVanced/revanced-patches/commit/23bfdc98fbbcc8ecf0ffbf8704f58dd2272e4af2))
|
||||||
|
* **YouTube - Hide description components:** Add `Hide Ask` ([#4972](https://github.com/ReVanced/revanced-patches/issues/4972)) ([ebc94a5](https://github.com/ReVanced/revanced-patches/commit/ebc94a5da6214b67399c9c01515689bd4b20547c))
|
||||||
|
* **YouTube - Hide layout components:** Add `Hide ticket shelf` ([#4969](https://github.com/ReVanced/revanced-patches/issues/4969)) ([6436af7](https://github.com/ReVanced/revanced-patches/commit/6436af7e77c77d2034dfceba8bc51132ad7632be))
|
||||||
|
* **YouTube - Hide player components:** Hide related video overlay in fullscreen ([#4938](https://github.com/ReVanced/revanced-patches/issues/4938)) ([ac9be97](https://github.com/ReVanced/revanced-patches/commit/ac9be9760c9965e54df196b227a310d64ead4bf5))
|
||||||
|
* **YouTube - Settings:** Add ability to search in settings ([#4881](https://github.com/ReVanced/revanced-patches/issues/4881)) ([aca8b20](https://github.com/ReVanced/revanced-patches/commit/aca8b207c15f254bcc9ad94bc7dfb895f21d4058))
|
||||||
|
|
||||||
|
# [5.24.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.24.0-dev.8...v5.24.0-dev.9) (2025-05-18)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **YouTube - SponsorBlock:** Fix segment category summary not showing category description ([06934a6](https://github.com/ReVanced/revanced-patches/commit/06934a60d91b40a5cdf7f4cd92deae4a136c149b))
|
||||||
|
|
||||||
# [5.24.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.24.0-dev.7...v5.24.0-dev.8) (2025-05-17)
|
# [5.24.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.24.0-dev.7...v5.24.0-dev.8) (2025-05-17)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
3
extensions/messenger/build.gradle.kts
Normal file
3
extensions/messenger/build.gradle.kts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
dependencies {
|
||||||
|
compileOnly(project(":extensions:shared:library"))
|
||||||
|
}
|
||||||
1
extensions/messenger/src/main/AndroidManifest.xml
Normal file
1
extensions/messenger/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<manifest/>
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,26 @@
|
|||||||
package app.revanced.extension.shared;
|
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 android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import app.revanced.extension.shared.settings.BaseSettings;
|
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
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 {
|
public class Logger {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -17,99 +28,158 @@ public class Logger {
|
|||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface LogMessage {
|
public interface LogMessage {
|
||||||
|
/**
|
||||||
|
* @return Logger string message. This method is only called if logging is enabled.
|
||||||
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
String buildMessageString();
|
String buildMessageString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
private enum LogLevel {
|
||||||
* @return For outer classes, this returns {@link Class#getSimpleName()}.
|
DEBUG,
|
||||||
* For static, inner, or anonymous classes, this returns the simple name of the enclosing class.
|
INFO,
|
||||||
* <br>
|
ERROR
|
||||||
* For example, each of these classes return 'SomethingView':
|
}
|
||||||
* <code>
|
|
||||||
* com.company.SomethingView
|
|
||||||
* com.company.SomethingView$StaticClass
|
|
||||||
* com.company.SomethingView$1
|
|
||||||
* </code>
|
|
||||||
*/
|
|
||||||
private String findOuterClassSimpleName() {
|
|
||||||
var selfClass = this.getClass();
|
|
||||||
|
|
||||||
String fullClassName = selfClass.getName();
|
private static final String REVANCED_LOG_TAG = "revanced";
|
||||||
final int dollarSignIndex = fullClassName.indexOf('$');
|
|
||||||
if (dollarSignIndex < 0) {
|
private static final String LOGGER_CLASS_NAME = Logger.class.getName();
|
||||||
return selfClass.getSimpleName(); // Already an outer class.
|
|
||||||
|
/**
|
||||||
|
* @return For outer classes, this returns {@link Class#getSimpleName()}.
|
||||||
|
* For static, inner, or anonymous classes, this returns the simple name of the enclosing class.
|
||||||
|
* <br>
|
||||||
|
* For example, each of these classes returns 'SomethingView':
|
||||||
|
* <code>
|
||||||
|
* com.company.SomethingView
|
||||||
|
* com.company.SomethingView$StaticClass
|
||||||
|
* com.company.SomethingView$1
|
||||||
|
* </code>
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
|
||||||
|
StringBuilder logBuilder = new StringBuilder(className.length() + 2
|
||||||
|
+ messageString.length());
|
||||||
|
logBuilder.append(className).append(": ").append(messageString);
|
||||||
|
|
||||||
|
String toastMessage = showToast ? logBuilder.toString() : null;
|
||||||
|
|
||||||
|
// Append exception message if present.
|
||||||
|
if (ex != null) {
|
||||||
|
var exceptionMessage = ex.getMessage();
|
||||||
|
if (exceptionMessage != null) {
|
||||||
|
logBuilder.append("\nException: ").append(exceptionMessage);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Class is inner, static, or anonymous.
|
if (includeStackTrace) {
|
||||||
// Parse the simple name full name.
|
var sw = new StringWriter();
|
||||||
// A class with no package returns index of -1, but incrementing gives index zero which is correct.
|
new Throwable().printStackTrace(new PrintWriter(sw));
|
||||||
final int simpleClassNameStartIndex = fullClassName.lastIndexOf('.') + 1;
|
String stackTrace = sw.toString();
|
||||||
return fullClassName.substring(simpleClassNameStartIndex, dollarSignIndex);
|
// Remove the stacktrace elements of this class.
|
||||||
|
final int loggerIndex = stackTrace.lastIndexOf(LOGGER_CLASS_NAME);
|
||||||
|
final int loggerBegins = stackTrace.indexOf('\n', loggerIndex);
|
||||||
|
logBuilder.append(stackTrace, loggerBegins, stackTrace.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
String logText = logBuilder.toString();
|
||||||
|
LogBufferManager.appendToLogBuffer(logText);
|
||||||
|
|
||||||
|
switch (logLevel) {
|
||||||
|
case DEBUG:
|
||||||
|
if (ex == null) Log.d(REVANCED_LOG_TAG, logText);
|
||||||
|
else Log.d(REVANCED_LOG_TAG, logText, ex);
|
||||||
|
break;
|
||||||
|
case INFO:
|
||||||
|
if (ex == null) Log.i(REVANCED_LOG_TAG, logText);
|
||||||
|
else Log.i(REVANCED_LOG_TAG, logText, ex);
|
||||||
|
break;
|
||||||
|
case ERROR:
|
||||||
|
if (ex == null) Log.e(REVANCED_LOG_TAG, logText);
|
||||||
|
else Log.e(REVANCED_LOG_TAG, logText, ex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toastMessage != null) {
|
||||||
|
Utils.showToastLong(toastMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String REVANCED_LOG_PREFIX = "revanced: ";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs debug messages under the outer class name of the code calling this method.
|
* 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()}
|
* <p>
|
||||||
* 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);
|
printDebug(message, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs debug messages under the outer class name of the code calling this method.
|
* 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()}
|
* <p>
|
||||||
* 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()) {
|
if (DEBUG.get()) {
|
||||||
String logMessage = message.buildMessageString();
|
logInternal(LogLevel.DEBUG, message, ex, DEBUG_STACKTRACE.get(), false);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs information messages using the outer class name of the code calling this method.
|
* 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);
|
printInfo(message, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs information messages using the outer class name of the code calling this method.
|
* Logs information messages using the outer class name of the code calling this method.
|
||||||
*/
|
*/
|
||||||
public static void printInfo(@NonNull LogMessage message, @Nullable Exception ex) {
|
public static void printInfo(LogMessage message, @Nullable Exception ex) {
|
||||||
String logTag = REVANCED_LOG_PREFIX + message.findOuterClassSimpleName();
|
logInternal(LogLevel.INFO, message, ex, DEBUG_STACKTRACE.get(), false);
|
||||||
String logMessage = message.buildMessageString();
|
|
||||||
if (ex == null) {
|
|
||||||
Log.i(logTag, logMessage);
|
|
||||||
} else {
|
|
||||||
Log.i(logTag, logMessage, ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs exceptions under the outer class name of the code calling this method.
|
* 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);
|
printException(message, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,35 +192,23 @@ public class Logger {
|
|||||||
* @param message log message
|
* @param message log message
|
||||||
* @param ex exception (optional)
|
* @param ex exception (optional)
|
||||||
*/
|
*/
|
||||||
public static void printException(@NonNull LogMessage message, @Nullable Throwable ex) {
|
public static void printException(LogMessage message, @Nullable Throwable ex) {
|
||||||
String messageString = message.buildMessageString();
|
logInternal(LogLevel.ERROR, message, ex, DEBUG_STACKTRACE.get(), DEBUG_TOAST_ON_ERROR.get());
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logging to use if {@link BaseSettings#DEBUG} or {@link Utils#getContext()} may not be initialized.
|
* Logging to use if {@link BaseSettings#DEBUG} or {@link Utils#getContext()} may not be initialized.
|
||||||
* Normally this method should not be used.
|
* Normally this method should not be used.
|
||||||
*/
|
*/
|
||||||
public static void initializationInfo(@NonNull Class<?> callingClass, @NonNull String message) {
|
public static void initializationInfo(LogMessage message) {
|
||||||
Log.i(REVANCED_LOG_PREFIX + callingClass.getSimpleName(), message);
|
logInternal(LogLevel.INFO, message, null, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logging to use if {@link BaseSettings#DEBUG} or {@link Utils#getContext()} may not be initialized.
|
* Logging to use if {@link BaseSettings#DEBUG} or {@link Utils#getContext()} may not be initialized.
|
||||||
* Normally this method should not be used.
|
* Normally this method should not be used.
|
||||||
*/
|
*/
|
||||||
public static void initializationException(@NonNull Class<?> callingClass, @NonNull String message,
|
public static void initializationException(LogMessage message, @Nullable Exception ex) {
|
||||||
@Nullable Exception ex) {
|
logInternal(LogLevel.ERROR, message, ex, false, false);
|
||||||
Log.e(REVANCED_LOG_PREFIX + callingClass.getSimpleName(), message, ex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
package app.revanced.extension.shared;
|
package app.revanced.extension.shared;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
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.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
@@ -18,6 +22,8 @@ import android.os.Looper;
|
|||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceGroup;
|
import android.preference.PreferenceGroup;
|
||||||
import android.preference.PreferenceScreen;
|
import android.preference.PreferenceScreen;
|
||||||
|
import android.util.Pair;
|
||||||
|
import android.util.TypedValue;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.ViewParent;
|
import android.view.ViewParent;
|
||||||
@@ -357,15 +363,17 @@ public class Utils {
|
|||||||
|
|
||||||
public static Context getContext() {
|
public static Context getContext() {
|
||||||
if (context == null) {
|
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;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setContext(Context appContext) {
|
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.
|
// Must initially set context to check the app language.
|
||||||
context = appContext;
|
context = appContext;
|
||||||
Logger.initializationInfo(Utils.class, "Set context: " + appContext);
|
|
||||||
|
|
||||||
AppLanguage language = BaseSettings.REVANCED_LANGUAGE.get();
|
AppLanguage language = BaseSettings.REVANCED_LANGUAGE.get();
|
||||||
if (language != AppLanguage.DEFAULT) {
|
if (language != AppLanguage.DEFAULT) {
|
||||||
@@ -377,8 +385,9 @@ public class Utils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setClipboard(@NonNull String text) {
|
public static void setClipboard(CharSequence text) {
|
||||||
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) context
|
||||||
|
.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||||
android.content.ClipData clip = android.content.ClipData.newPlainText("ReVanced", text);
|
android.content.ClipData clip = android.content.ClipData.newPlainText("ReVanced", text);
|
||||||
clipboard.setPrimaryClip(clip);
|
clipboard.setPrimaryClip(clip);
|
||||||
}
|
}
|
||||||
@@ -542,24 +551,25 @@ public class Utils {
|
|||||||
private static void showToast(@NonNull String messageToToast, int toastDuration) {
|
private static void showToast(@NonNull String messageToToast, int toastDuration) {
|
||||||
Objects.requireNonNull(messageToToast);
|
Objects.requireNonNull(messageToToast);
|
||||||
runOnMainThreadNowOrLater(() -> {
|
runOnMainThreadNowOrLater(() -> {
|
||||||
if (context == null) {
|
Context currentContext = context;
|
||||||
Logger.initializationException(Utils.class, "Cannot show toast (context is null): " + messageToToast, null);
|
|
||||||
} else {
|
if (currentContext == null) {
|
||||||
Logger.printDebug(() -> "Showing toast: " + messageToToast);
|
Logger.initializationException(() -> "Cannot show toast (context is null): " + messageToToast, null);
|
||||||
Toast.makeText(context, messageToToast, toastDuration).show();
|
} else {
|
||||||
}
|
Logger.printDebug(() -> "Showing toast: " + messageToToast);
|
||||||
}
|
Toast.makeText(currentContext, messageToToast, toastDuration).show();
|
||||||
);
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isDarkModeEnabled(Context context) {
|
public static boolean isDarkModeEnabled() {
|
||||||
Configuration config = context.getResources().getConfiguration();
|
Configuration config = Resources.getSystem().getConfiguration();
|
||||||
final int currentNightMode = config.uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
final int currentNightMode = config.uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
||||||
return currentNightMode == Configuration.UI_MODE_NIGHT_YES;
|
return currentNightMode == Configuration.UI_MODE_NIGHT_YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isLandscapeOrientation() {
|
public static boolean isLandscapeOrientation() {
|
||||||
final int orientation = context.getResources().getConfiguration().orientation;
|
final int orientation = Resources.getSystem().getConfiguration().orientation;
|
||||||
return orientation == Configuration.ORIENTATION_LANDSCAPE;
|
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) {
|
public static void runOnMainThreadDelayed(@NonNull Runnable runnable, long delayMillis) {
|
||||||
Runnable loggingRunnable = () -> {
|
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() {
|
public static boolean isCurrentlyOnMainThread() {
|
||||||
return Looper.getMainLooper().isCurrentThread();
|
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 {
|
public static void verifyOnMainThread() throws IllegalStateException {
|
||||||
if (!isCurrentlyOnMainThread()) {
|
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 {
|
public static void verifyOffMainThread() throws IllegalStateException {
|
||||||
if (isCurrentlyOnMainThread()) {
|
if (isCurrentlyOnMainThread()) {
|
||||||
@@ -629,13 +639,23 @@ public class Utils {
|
|||||||
OTHER,
|
OTHER,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calling extension code must ensure the un-patched app has the permission
|
||||||
|
* <code>android.permission.ACCESS_NETWORK_STATE</code>, otherwise the app will crash
|
||||||
|
* if this method is used.
|
||||||
|
*/
|
||||||
public static boolean isNetworkConnected() {
|
public static boolean isNetworkConnected() {
|
||||||
NetworkType networkType = getNetworkType();
|
NetworkType networkType = getNetworkType();
|
||||||
return networkType == NetworkType.MOBILE
|
return networkType == NetworkType.MOBILE
|
||||||
|| networkType == NetworkType.OTHER;
|
|| networkType == NetworkType.OTHER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint({"MissingPermission", "deprecation"}) // Permission already included in YouTube.
|
/**
|
||||||
|
* Calling extension code must ensure the un-patched app has the permission
|
||||||
|
* <code>android.permission.ACCESS_NETWORK_STATE</code>, otherwise the app will crash
|
||||||
|
* if this method is used.
|
||||||
|
*/
|
||||||
|
@SuppressLint({"MissingPermission", "deprecation"})
|
||||||
public static NetworkType getNetworkType() {
|
public static NetworkType getNetworkType() {
|
||||||
Context networkContext = getContext();
|
Context networkContext = getContext();
|
||||||
if (networkContext == null) {
|
if (networkContext == null) {
|
||||||
@@ -738,9 +758,9 @@ public class Utils {
|
|||||||
* then the preferences are left unsorted.
|
* then the preferences are left unsorted.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public static void sortPreferenceGroups(@NonNull PreferenceGroup group) {
|
public static void sortPreferenceGroups(PreferenceGroup group) {
|
||||||
Sort groupSort = Sort.fromKey(group.getKey(), Sort.UNSORTED);
|
Sort groupSort = Sort.fromKey(group.getKey(), Sort.UNSORTED);
|
||||||
SortedMap<String, Preference> preferences = new TreeMap<>();
|
List<Pair<String, Preference>> preferences = new ArrayList<>();
|
||||||
|
|
||||||
for (int i = 0, prefCount = group.getPreferenceCount(); i < prefCount; i++) {
|
for (int i = 0, prefCount = group.getPreferenceCount(); i < prefCount; i++) {
|
||||||
Preference preference = group.getPreference(i);
|
Preference preference = group.getPreference(i);
|
||||||
@@ -769,17 +789,22 @@ public class Utils {
|
|||||||
throw new IllegalStateException();
|
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;
|
int index = 0;
|
||||||
for (Preference pref : preferences.values()) {
|
for (Pair<String, Preference> pair : preferences) {
|
||||||
int order = index++;
|
int order = index++;
|
||||||
|
Preference pref = pair.second;
|
||||||
|
|
||||||
// Move any screens, intents, and the one off About preference to the top.
|
// Move any screens, intents, and the one off About preference to the top.
|
||||||
if (pref instanceof PreferenceScreen || pref instanceof ReVancedAboutPreference
|
if (pref instanceof PreferenceScreen || pref instanceof ReVancedAboutPreference
|
||||||
|| pref.getIntent() != null) {
|
|| pref.getIntent() != null) {
|
||||||
// Arbitrary high number.
|
// Any arbitrary large number.
|
||||||
order -= 1000;
|
order -= 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -843,6 +868,20 @@ public class Utils {
|
|||||||
return getResourceColor(colorString);
|
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) {
|
public static int clamp(int value, int lower, int upper) {
|
||||||
return Math.max(lower, Math.min(value, upper));
|
return Math.max(lower, Math.min(value, upper));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This view displays two main components for color selection:
|
||||||
|
* <ul>
|
||||||
|
* <li><b>Hue Bar:</b> A vertical bar on the right that allows the user to select the hue component of the color.
|
||||||
|
* <li><b>Saturation-Value Selector:</b> A rectangular area that allows the user to select the saturation and value (brightness)
|
||||||
|
* components of the color based on the selected hue.
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 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).
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 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.
|
||||||
|
* <p>
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -70,7 +70,7 @@ public class ImportExportPreference extends EditTextPreference implements Prefer
|
|||||||
|
|
||||||
// Show the user the settings in JSON format.
|
// Show the user the settings in JSON format.
|
||||||
builder.setNeutralButton(str("revanced_settings_import_copy"), (dialog, which) -> {
|
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) -> {
|
}).setPositiveButton(str("revanced_settings_import"), (dialog, which) -> {
|
||||||
importSettings(builder.getContext(), getEditText().getText().toString());
|
importSettings(builder.getContext(), getEditText().getText().toString());
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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<String> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,6 @@ import android.app.Dialog;
|
|||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@@ -54,7 +53,7 @@ public class ReVancedAboutPreference extends Preference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isDarkModeEnabled() {
|
protected boolean isDarkModeEnabled() {
|
||||||
return Utils.isDarkModeEnabled(getContext());
|
return Utils.isDarkModeEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -6,9 +6,8 @@ import android.util.AttributeSet;
|
|||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.SortedMap;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
import app.revanced.extension.shared.Utils;
|
import app.revanced.extension.shared.Utils;
|
||||||
|
|
||||||
@@ -46,17 +45,25 @@ public class SortedListPreference extends ListPreference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Pair<CharSequence, CharSequence>> firstEntries = new ArrayList<>(firstEntriesToPreserve);
|
List<Pair<CharSequence, CharSequence>> firstEntries = new ArrayList<>(firstEntriesToPreserve);
|
||||||
SortedMap<String, Pair<CharSequence, CharSequence>> 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<Pair<String, Pair<CharSequence, CharSequence>>> lastEntries = new ArrayList<>();
|
||||||
|
|
||||||
for (int i = 0; i < entrySize; i++) {
|
for (int i = 0; i < entrySize; i++) {
|
||||||
Pair<CharSequence, CharSequence> pair = new Pair<>(entries[i], entryValues[i]);
|
Pair<CharSequence, CharSequence> pair = new Pair<>(entries[i], entryValues[i]);
|
||||||
if (i < firstEntriesToPreserve) {
|
if (i < firstEntriesToPreserve) {
|
||||||
firstEntries.add(pair);
|
firstEntries.add(pair);
|
||||||
} else {
|
} 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[] sortedEntries = new CharSequence[entrySize];
|
||||||
CharSequence[] sortedEntryValues = new CharSequence[entrySize];
|
CharSequence[] sortedEntryValues = new CharSequence[entrySize];
|
||||||
|
|
||||||
@@ -67,9 +74,10 @@ public class SortedListPreference extends ListPreference {
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Pair<CharSequence, CharSequence> pair : lastEntries.values()) {
|
for (Pair<String, Pair<CharSequence, CharSequence>> outer : lastEntries) {
|
||||||
sortedEntries[i] = pair.first;
|
Pair<CharSequence, CharSequence> inner = outer.second;
|
||||||
sortedEntryValues[i] = pair.second;
|
sortedEntries[i] = inner.first;
|
||||||
|
sortedEntryValues[i] = inner.second;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package app.revanced.extension.tiktok;
|
|||||||
|
|
||||||
import static app.revanced.extension.shared.Utils.isDarkModeEnabled;
|
import static app.revanced.extension.shared.Utils.isDarkModeEnabled;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
@@ -43,8 +42,8 @@ public class Utils {
|
|||||||
private static final @ColorInt int TEXT_LIGHT_MODE_SUMMARY
|
private static final @ColorInt int TEXT_LIGHT_MODE_SUMMARY
|
||||||
= Color.argb(255, 80, 80, 80);
|
= Color.argb(255, 80, 80, 80);
|
||||||
|
|
||||||
public static void setTitleAndSummaryColor(Context context, View view) {
|
public static void setTitleAndSummaryColor(View view) {
|
||||||
final boolean darkModeEnabled = isDarkModeEnabled(context);
|
final boolean darkModeEnabled = isDarkModeEnabled();
|
||||||
|
|
||||||
TextView title = view.findViewById(android.R.id.title);
|
TextView title = view.findViewById(android.R.id.title);
|
||||||
title.setTextColor(darkModeEnabled
|
title.setTextColor(darkModeEnabled
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public class DownloadPathPreference extends DialogPreference {
|
|||||||
protected void onBindView(View view) {
|
protected void onBindView(View view) {
|
||||||
super.onBindView(view);
|
super.onBindView(view);
|
||||||
|
|
||||||
Utils.setTitleAndSummaryColor(getContext(), view);
|
Utils.setTitleAndSummaryColor(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -22,6 +22,6 @@ public class InputTextPreference extends EditTextPreference {
|
|||||||
protected void onBindView(View view) {
|
protected void onBindView(View view) {
|
||||||
super.onBindView(view);
|
super.onBindView(view);
|
||||||
|
|
||||||
Utils.setTitleAndSummaryColor(getContext(), view);
|
Utils.setTitleAndSummaryColor(view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ public class RangeValuePreference extends DialogPreference {
|
|||||||
protected void onBindView(View view) {
|
protected void onBindView(View view) {
|
||||||
super.onBindView(view);
|
super.onBindView(view);
|
||||||
|
|
||||||
Utils.setTitleAndSummaryColor(getContext(), view);
|
Utils.setTitleAndSummaryColor(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -48,6 +48,6 @@ public class ReVancedTikTokAboutPreference extends ReVancedAboutPreference {
|
|||||||
protected void onBindView(View view) {
|
protected void onBindView(View view) {
|
||||||
super.onBindView(view);
|
super.onBindView(view);
|
||||||
|
|
||||||
Utils.setTitleAndSummaryColor(getContext(), view);
|
Utils.setTitleAndSummaryColor(view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,6 @@ public class TogglePreference extends SwitchPreference {
|
|||||||
protected void onBindView(View view) {
|
protected void onBindView(View view) {
|
||||||
super.onBindView(view);
|
super.onBindView(view);
|
||||||
|
|
||||||
Utils.setTitleAndSummaryColor(getContext(), view);
|
Utils.setTitleAndSummaryColor(view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,7 @@ public class SpoofSimPatch {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.initializationException(SpoofSimPatch.class,
|
Logger.initializationException(() -> "Context is not yet set, cannot spoof: " + fieldSpoofed, null);
|
||||||
"Context is not yet set, cannot spoof: " + fieldSpoofed, null);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -95,7 +95,7 @@ public final class NavigationButtonsPatch {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Utils.isDarkModeEnabled(Utils.getContext())
|
return Utils.isDarkModeEnabled()
|
||||||
? !DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK
|
? !DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK
|
||||||
: !DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT;
|
: !DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ public class OpenShortsInRegularPlayerPatch {
|
|||||||
|
|
||||||
private static WeakReference<Activity> mainActivityRef = new WeakReference<>(null);
|
private static WeakReference<Activity> mainActivityRef = new WeakReference<>(null);
|
||||||
|
|
||||||
|
private static volatile boolean overrideBackPressToExit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injection point.
|
* Injection point.
|
||||||
*/
|
*/
|
||||||
@@ -38,6 +40,18 @@ public class OpenShortsInRegularPlayerPatch {
|
|||||||
mainActivityRef = new WeakReference<>(activity);
|
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.
|
* Injection point.
|
||||||
*/
|
*/
|
||||||
@@ -45,6 +59,7 @@ public class OpenShortsInRegularPlayerPatch {
|
|||||||
try {
|
try {
|
||||||
ShortsPlayerType type = Settings.SHORTS_PLAYER_TYPE.get();
|
ShortsPlayerType type = Settings.SHORTS_PLAYER_TYPE.get();
|
||||||
if (type == ShortsPlayerType.SHORTS_PLAYER) {
|
if (type == ShortsPlayerType.SHORTS_PLAYER) {
|
||||||
|
overrideBackPressToExit = false;
|
||||||
return false; // Default unpatched behavior.
|
return false; // Default unpatched behavior.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,13 +76,17 @@ public class OpenShortsInRegularPlayerPatch {
|
|||||||
// set to open in the regular player, so it's ignored as
|
// set to open in the regular player, so it's ignored as
|
||||||
// checking the map makes the patch more complicated.
|
// checking the map makes the patch more complicated.
|
||||||
Logger.printDebug(() -> "Ignoring Short with no videoId");
|
Logger.printDebug(() -> "Ignoring Short with no videoId");
|
||||||
|
overrideBackPressToExit = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NavigationButton.getSelectedNavigationButton() == NavigationButton.SHORTS) {
|
if (NavigationButton.getSelectedNavigationButton() == NavigationButton.SHORTS) {
|
||||||
|
overrideBackPressToExit = false;
|
||||||
return false; // Always use Shorts player for the Shorts nav button.
|
return false; // Always use Shorts player for the Shorts nav button.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
overrideBackPressToExit = true;
|
||||||
|
|
||||||
final boolean forceFullScreen = (type == ShortsPlayerType.REGULAR_PLAYER_FULLSCREEN);
|
final boolean forceFullScreen = (type == ShortsPlayerType.REGULAR_PLAYER_FULLSCREEN);
|
||||||
OpenVideosFullscreenHookPatch.setOpenNextVideoFullscreen(forceFullScreen);
|
OpenVideosFullscreenHookPatch.setOpenNextVideoFullscreen(forceFullScreen);
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class OpenVideosFullscreenHookPatch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isFullScreenPatchIncluded()) {
|
if (!isFullScreenPatchIncluded()) {
|
||||||
return false;
|
return original;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Settings.OPEN_VIDEOS_FULLSCREEN_PORTRAIT.get();
|
return Settings.OPEN_VIDEOS_FULLSCREEN_PORTRAIT.get();
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package app.revanced.extension.youtube.patches;
|
package app.revanced.extension.youtube.patches;
|
||||||
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.util.TypedValue;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import app.revanced.extension.shared.Logger;
|
import app.revanced.extension.shared.Logger;
|
||||||
@@ -33,8 +31,7 @@ public final class WideSearchbarPatch {
|
|||||||
final int paddingRight = searchBarView.getPaddingRight();
|
final int paddingRight = searchBarView.getPaddingRight();
|
||||||
final int paddingTop = searchBarView.getPaddingTop();
|
final int paddingTop = searchBarView.getPaddingTop();
|
||||||
final int paddingBottom = searchBarView.getPaddingBottom();
|
final int paddingBottom = searchBarView.getPaddingBottom();
|
||||||
final int paddingStart = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
|
final int paddingStart = Utils.dipToPixels(8);
|
||||||
8, Resources.getSystem().getDisplayMetrics());
|
|
||||||
|
|
||||||
if (Utils.isRightToLeftLocale()) {
|
if (Utils.isRightToLeftLocale()) {
|
||||||
searchBarView.setPadding(paddingLeft, paddingTop, paddingStart, paddingBottom);
|
searchBarView.setPadding(paddingLeft, paddingTop, paddingStart, paddingBottom);
|
||||||
|
|||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -64,48 +64,45 @@ public final class AdsFilter extends Filter {
|
|||||||
"_interstitial"
|
"_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(
|
final var generalAds = new StringFilterGroup(
|
||||||
Settings.HIDE_GENERAL_ADS,
|
Settings.HIDE_GENERAL_ADS,
|
||||||
|
"_ad_with",
|
||||||
|
"_buttoned_layout",
|
||||||
"ads_video_with_context",
|
"ads_video_with_context",
|
||||||
"banner_text_icon",
|
"banner_text_icon",
|
||||||
"square_image_layout",
|
"brand_video_shelf",
|
||||||
"watch_metadata_app_promo",
|
"brand_video_singleton",
|
||||||
"video_display_full_layout",
|
|
||||||
"hero_promo_image",
|
|
||||||
"statement_banner",
|
|
||||||
"carousel_footered_layout",
|
"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",
|
"primetime_promo",
|
||||||
"product_details",
|
"product_details",
|
||||||
"composite_concurrent_carousel_layout",
|
"square_image_layout",
|
||||||
"carousel_headered_layout",
|
"statement_banner",
|
||||||
"full_width_portrait_image_layout",
|
"text_image_button_layout",
|
||||||
"brand_video_shelf",
|
"text_image_no_button_layout", // Tablet layout search results.
|
||||||
"brand_video_singleton"
|
"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(
|
final var movieAds = new StringFilterGroup(
|
||||||
Settings.HIDE_MOVIES_SECTION,
|
Settings.HIDE_MOVIES_SECTION,
|
||||||
"browsy_bar",
|
"browsy_bar",
|
||||||
"compact_movie",
|
"compact_movie",
|
||||||
|
"compact_tvfilm_item",
|
||||||
"horizontal_movie_shelf",
|
"horizontal_movie_shelf",
|
||||||
"movie_and_show_upsell_card",
|
"movie_and_show_upsell_card",
|
||||||
"compact_tvfilm_item",
|
|
||||||
"offer_module_root"
|
"offer_module_root"
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -160,7 +157,6 @@ public final class AdsFilter extends Filter {
|
|||||||
|
|
||||||
addPathCallbacks(
|
addPathCallbacks(
|
||||||
generalAds,
|
generalAds,
|
||||||
buttonedAd,
|
|
||||||
merchandise,
|
merchandise,
|
||||||
viewProducts,
|
viewProducts,
|
||||||
selfSponsor,
|
selfSponsor,
|
||||||
@@ -181,17 +177,19 @@ public final class AdsFilter extends Filter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for the index because of likelihood of false positives.
|
// Check for the index because of likelihood of false positives.
|
||||||
if (matchedGroup == shoppingLinks && contentIndex != 0) {
|
if (contentIndex != 0 && matchedGroup == shoppingLinks) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exceptions.matches(path))
|
if (exceptions.matches(path)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (matchedGroup == fullscreenAd) {
|
if (matchedGroup == fullscreenAd) {
|
||||||
if (path.contains("|ImageType|")) closeFullscreenAd();
|
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) {
|
if (matchedGroup == channelProfile) {
|
||||||
|
|||||||
@@ -20,13 +20,16 @@ import app.revanced.extension.youtube.settings.Settings;
|
|||||||
public class ProgressBarDrawable extends Drawable {
|
public class ProgressBarDrawable extends Drawable {
|
||||||
|
|
||||||
private final Paint paint = new Paint();
|
private final Paint paint = new Paint();
|
||||||
|
{
|
||||||
|
paint.setColor(SeekbarColorPatch.getSeekbarColor());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(@NonNull Canvas canvas) {
|
public void draw(@NonNull Canvas canvas) {
|
||||||
if (Settings.HIDE_SEEKBAR_THUMBNAIL.get()) {
|
if (Settings.HIDE_SEEKBAR_THUMBNAIL.get()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
paint.setColor(SeekbarColorPatch.getSeekbarColor());
|
|
||||||
canvas.drawRect(getBounds(), paint);
|
canvas.drawRect(getBounds(), paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ public final class SeekbarColorPatch {
|
|||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
if (false) { // Set true to force slow animation for development.
|
if (false) { // Set true to force slow animation for development.
|
||||||
final int longAnimation = Utils.getResourceIdentifier(
|
final int longAnimation = Utils.getResourceIdentifier(
|
||||||
Utils.isDarkModeEnabled(Utils.getContext())
|
Utils.isDarkModeEnabled()
|
||||||
? "startup_animation_5s_30fps_dark"
|
? "startup_animation_5s_30fps_dark"
|
||||||
: "startup_animation_5s_30fps_light",
|
: "startup_animation_5s_30fps_light",
|
||||||
"raw");
|
"raw");
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ import android.text.Spanned;
|
|||||||
import android.text.style.ForegroundColorSpan;
|
import android.text.style.ForegroundColorSpan;
|
||||||
import android.text.style.ImageSpan;
|
import android.text.style.ImageSpan;
|
||||||
import android.text.style.ReplacementSpan;
|
import android.text.style.ReplacementSpan;
|
||||||
import android.util.DisplayMetrics;
|
|
||||||
import android.util.TypedValue;
|
|
||||||
|
|
||||||
import androidx.annotation.GuardedBy;
|
import androidx.annotation.GuardedBy;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@@ -120,16 +118,13 @@ public class ReturnYouTubeDislike {
|
|||||||
private static final ShapeDrawable leftSeparatorShape;
|
private static final ShapeDrawable leftSeparatorShape;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
DisplayMetrics dp = Objects.requireNonNull(Utils.getContext()).getResources().getDisplayMetrics();
|
|
||||||
|
|
||||||
leftSeparatorBounds = new Rect(0, 0,
|
leftSeparatorBounds = new Rect(0, 0,
|
||||||
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1.2f, dp),
|
Utils.dipToPixels(1.2f),
|
||||||
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14, dp));
|
Utils.dipToPixels(14f));
|
||||||
final int middleSeparatorSize =
|
final int middleSeparatorSize = Utils.dipToPixels(3.7f);
|
||||||
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3.7f, dp);
|
|
||||||
middleSeparatorBounds = new Rect(0, 0, middleSeparatorSize, middleSeparatorSize);
|
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 = new ShapeDrawable(new RectShape());
|
||||||
leftSeparatorShape.setBounds(leftSeparatorBounds);
|
leftSeparatorShape.setBounds(leftSeparatorBounds);
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import android.annotation.SuppressLint;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.preference.PreferenceFragment;
|
import android.preference.PreferenceFragment;
|
||||||
import android.util.TypedValue;
|
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toolbar;
|
import android.widget.Toolbar;
|
||||||
@@ -119,8 +118,7 @@ public class LicenseActivityHook {
|
|||||||
toolbar.setNavigationIcon(ReVancedPreferenceFragment.getBackButtonDrawable());
|
toolbar.setNavigationIcon(ReVancedPreferenceFragment.getBackButtonDrawable());
|
||||||
toolbar.setTitle(getResourceIdentifier("revanced_settings_title", "string"));
|
toolbar.setTitle(getResourceIdentifier("revanced_settings_title", "string"));
|
||||||
|
|
||||||
final int margin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16,
|
final int margin = Utils.dipToPixels(16);
|
||||||
Utils.getContext().getResources().getDisplayMetrics());
|
|
||||||
toolbar.setTitleMarginStart(margin);
|
toolbar.setTitleMarginStart(margin);
|
||||||
toolbar.setTitleMarginEnd(margin);
|
toolbar.setTitleMarginEnd(margin);
|
||||||
TextView toolbarTextView = Utils.getChildView(toolbar, false,
|
TextView toolbarTextView = Utils.getChildView(toolbar, false,
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ public class Settings extends BaseSettings {
|
|||||||
public static final BooleanSetting FORCE_ORIGINAL_AUDIO = new BooleanSetting("revanced_force_original_audio", FALSE, new ForceOriginalAudioAvailability());
|
public static final BooleanSetting FORCE_ORIGINAL_AUDIO = new BooleanSetting("revanced_force_original_audio", FALSE, new ForceOriginalAudioAvailability());
|
||||||
|
|
||||||
// Ads
|
// 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_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_FULLSCREEN_ADS = new BooleanSetting("revanced_hide_fullscreen_ads", TRUE);
|
||||||
public static final BooleanSetting HIDE_GENERAL_ADS = new BooleanSetting("revanced_hide_general_ads", TRUE);
|
public static final BooleanSetting HIDE_GENERAL_ADS = new BooleanSetting("revanced_hide_general_ads", TRUE);
|
||||||
@@ -310,16 +309,16 @@ public class Settings extends BaseSettings {
|
|||||||
public static final BooleanSetting AUTO_REPEAT = new BooleanSetting("revanced_auto_repeat", FALSE);
|
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 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 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 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 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,
|
public static final BooleanSetting SPOOF_DEVICE_DIMENSIONS = new BooleanSetting("revanced_spoof_device_dimensions", FALSE, true,
|
||||||
"revanced_spoof_device_dimensions_user_dialog_message");
|
"revanced_spoof_device_dimensions_user_dialog_message");
|
||||||
/**
|
public static final BooleanSetting DEBUG_PROTOBUFFER = new BooleanSetting("revanced_debug_protobuffer", FALSE, false,
|
||||||
* When enabled, share the debug logs with care.
|
"revanced_debug_protobuffer_user_dialog_message", parent(BaseSettings.DEBUG));
|
||||||
* 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));
|
|
||||||
|
|
||||||
// Swipe controls
|
// Swipe controls
|
||||||
public static final BooleanSetting SWIPE_CHANGE_VIDEO = new BooleanSetting("revanced_swipe_change_video", FALSE, true);
|
public static final BooleanSetting SWIPE_CHANGE_VIDEO = new BooleanSetting("revanced_swipe_change_video", FALSE, true);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,7 +17,6 @@ import android.preference.SwitchPreference;
|
|||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.style.BackgroundColorSpan;
|
import android.text.style.BackgroundColorSpan;
|
||||||
import android.util.TypedValue;
|
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.WindowInsets;
|
import android.view.WindowInsets;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
@@ -245,9 +244,7 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
|
|||||||
toolbar.setNavigationIcon(getBackButtonDrawable());
|
toolbar.setNavigationIcon(getBackButtonDrawable());
|
||||||
toolbar.setNavigationOnClickListener(view -> preferenceScreenDialog.dismiss());
|
toolbar.setNavigationOnClickListener(view -> preferenceScreenDialog.dismiss());
|
||||||
|
|
||||||
final int margin = (int) TypedValue.applyDimension(
|
final int margin = Utils.dipToPixels(16);
|
||||||
TypedValue.COMPLEX_UNIT_DIP, 16, getResources().getDisplayMetrics()
|
|
||||||
);
|
|
||||||
toolbar.setTitleMargin(margin, 0, margin, 0);
|
toolbar.setTitleMargin(margin, 0, margin, 0);
|
||||||
|
|
||||||
TextView toolbarTextView = Utils.getChildView(toolbar,
|
TextView toolbarTextView = Utils.getChildView(toolbar,
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import static app.revanced.extension.shared.StringRef.str;
|
|||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.TypedValue;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
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() {
|
* Actual screen pixel width to use for the highlight segment time bar.
|
||||||
if (highlightSegmentTimeBarScreenWidth == -1) {
|
*/
|
||||||
highlightSegmentTimeBarScreenWidth = (int) TypedValue.applyDimension(
|
private static final int highlightSegmentTimeBarScreenWidth
|
||||||
TypedValue.COMPLEX_UNIT_DIP, HIGHLIGHT_SEGMENT_DRAW_BAR_WIDTH,
|
= Utils.dipToPixels(HIGHLIGHT_SEGMENT_DRAW_BAR_WIDTH);
|
||||||
Objects.requireNonNull(Utils.getContext()).getResources().getDisplayMetrics());
|
|
||||||
}
|
|
||||||
return highlightSegmentTimeBarScreenWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injection point.
|
* Injection point.
|
||||||
@@ -757,7 +752,7 @@ public class SegmentPlaybackController {
|
|||||||
final float left = leftPadding + segment.start * videoMillisecondsToPixels;
|
final float left = leftPadding + segment.start * videoMillisecondsToPixels;
|
||||||
final float right;
|
final float right;
|
||||||
if (segment.category == SegmentCategory.HIGHLIGHT) {
|
if (segment.category == SegmentCategory.HIGHLIGHT) {
|
||||||
right = left + getHighlightSegmentTimeBarScreenWidth();
|
right = left + highlightSegmentTimeBarScreenWidth;
|
||||||
} else {
|
} else {
|
||||||
right = leftPadding + segment.end * videoMillisecondsToPixels;
|
right = leftPadding + segment.end * videoMillisecondsToPixels;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package app.revanced.extension.youtube.sponsorblock.objects;
|
package app.revanced.extension.youtube.sponsorblock.objects;
|
||||||
|
|
||||||
import static app.revanced.extension.shared.StringRef.sf;
|
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 static app.revanced.extension.youtube.settings.Settings.*;
|
||||||
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
@@ -9,7 +10,9 @@ import android.text.Spannable;
|
|||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.style.ForegroundColorSpan;
|
import android.text.style.ForegroundColorSpan;
|
||||||
|
import android.text.style.RelativeSizeSpan;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorInt;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
@@ -134,7 +137,8 @@ public enum SegmentCategory {
|
|||||||
updateEnabledCategories();
|
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) {
|
if (opacity < 0 || opacity > 1.0f) {
|
||||||
throw new IllegalArgumentException("Invalid opacity: " + opacity);
|
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
|
* Skipped segment toast, if the skip occurred in the first quarter of the video
|
||||||
*/
|
*/
|
||||||
@NonNull
|
|
||||||
public final StringRef skippedToastBeginning;
|
public final StringRef skippedToastBeginning;
|
||||||
/**
|
/**
|
||||||
* Skipped segment toast, if the skip occurred in the middle half of the video
|
* Skipped segment toast, if the skip occurred in the middle half of the video
|
||||||
*/
|
*/
|
||||||
@NonNull
|
|
||||||
public final StringRef skippedToastMiddle;
|
public final StringRef skippedToastMiddle;
|
||||||
/**
|
/**
|
||||||
* Skipped segment toast, if the skip occurred in the last quarter of the video
|
* Skipped segment toast, if the skip occurred in the last quarter of the video
|
||||||
*/
|
*/
|
||||||
@NonNull
|
|
||||||
public final StringRef skippedToastEnd;
|
public final StringRef skippedToastEnd;
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public final Paint paint;
|
public final Paint paint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Category color with opacity applied.
|
||||||
|
*/
|
||||||
|
@ColorInt
|
||||||
private int color;
|
private int color;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Value must be changed using {@link #setBehaviour(CategoryBehaviour)}.
|
* Value must be changed using {@link #setBehaviour(CategoryBehaviour)}.
|
||||||
* Caller must also {@link #updateEnabledCategories()}.
|
* Caller must also {@link #updateEnabledCategories()}.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
|
||||||
public CategoryBehaviour behaviour = CategoryBehaviour.IGNORE;
|
public CategoryBehaviour behaviour = CategoryBehaviour.IGNORE;
|
||||||
|
|
||||||
SegmentCategory(String keyValue, StringRef title, StringRef description,
|
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.behaviour = Objects.requireNonNull(behaviour);
|
||||||
this.behaviorSetting.save(behaviour.reVancedKeyValue);
|
this.behaviorSetting.save(behaviour.reVancedKeyValue);
|
||||||
}
|
}
|
||||||
@@ -273,6 +276,10 @@ public enum SegmentCategory {
|
|||||||
return opacitySetting.get();
|
return opacitySetting.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float getOpacityDefault() {
|
||||||
|
return opacitySetting.defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
public void resetColorAndOpacity() {
|
public void resetColorAndOpacity() {
|
||||||
setColor(colorSetting.defaultValue);
|
setColor(colorSetting.defaultValue);
|
||||||
setOpacity(opacitySetting.defaultValue);
|
setOpacity(opacitySetting.defaultValue);
|
||||||
@@ -291,10 +298,19 @@ public enum SegmentCategory {
|
|||||||
/**
|
/**
|
||||||
* @return Integer color of #RRGGBB format.
|
* @return Integer color of #RRGGBB format.
|
||||||
*/
|
*/
|
||||||
|
@ColorInt
|
||||||
public int getColorNoOpacity() {
|
public int getColorNoOpacity() {
|
||||||
return color & 0x00FFFFFF;
|
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.
|
* @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());
|
return String.format(Locale.US, "#%06X", getColorNoOpacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SpannableString getCategoryColorDotSpan(String text, int color) {
|
private static SpannableString getCategoryColorDotSpan(String text, @ColorInt int color) {
|
||||||
SpannableString dotSpan = new SpannableString('⬤' + text);
|
SpannableString dotSpan = new SpannableString(COLOR_DOT_STRING + text);
|
||||||
dotSpan.setSpan(new ForegroundColorSpan(color), 0, 1,
|
dotSpan.setSpan(new ForegroundColorSpan(color), 0, 1,
|
||||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
return dotSpan;
|
return dotSpan;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SpannableString getCategoryColorDot(int color) {
|
public static SpannableString getCategoryColorDot(@ColorInt int color) {
|
||||||
return getCategoryColorDotSpan("", 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() {
|
public SpannableString getCategoryColorDot() {
|
||||||
return getCategoryColorDot(color);
|
return getCategoryColorDot(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SpannableString getTitleWithColorDot(int categoryColor) {
|
public SpannableString getTitleWithColorDot(@ColorInt int categoryColor) {
|
||||||
return getCategoryColorDotSpan(" " + title, categoryColor);
|
return getCategoryColorDotSpan(" " + title, categoryColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +1,46 @@
|
|||||||
package app.revanced.extension.youtube.sponsorblock.objects;
|
package app.revanced.extension.youtube.sponsorblock.objects;
|
||||||
|
|
||||||
import static app.revanced.extension.shared.StringRef.str;
|
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 static app.revanced.extension.youtube.sponsorblock.objects.SegmentCategory.applyOpacityToColor;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Typeface;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.preference.ListPreference;
|
import android.preference.ListPreference;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.GridLayout;
|
import android.widget.GridLayout;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorInt;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import app.revanced.extension.shared.Logger;
|
import app.revanced.extension.shared.Logger;
|
||||||
import app.revanced.extension.shared.Utils;
|
import app.revanced.extension.shared.Utils;
|
||||||
|
import app.revanced.extension.shared.settings.preference.ColorPickerPreference;
|
||||||
|
import app.revanced.extension.shared.settings.preference.ColorPickerView;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public class SegmentCategoryListPreference extends ListPreference {
|
public class SegmentCategoryListPreference extends ListPreference {
|
||||||
private final SegmentCategory category;
|
private final SegmentCategory category;
|
||||||
private TextView colorDotView;
|
|
||||||
private EditText colorEditText;
|
|
||||||
private EditText opacityEditText;
|
|
||||||
/**
|
/**
|
||||||
* #RRGGBB
|
* RGB format (no alpha).
|
||||||
*/
|
*/
|
||||||
|
@ColorInt
|
||||||
private int categoryColor;
|
private int categoryColor;
|
||||||
/**
|
/**
|
||||||
* [0, 1]
|
* [0, 1]
|
||||||
@@ -37,6 +48,11 @@ public class SegmentCategoryListPreference extends ListPreference {
|
|||||||
private float categoryOpacity;
|
private float categoryOpacity;
|
||||||
private int selectedDialogEntryIndex;
|
private int selectedDialogEntryIndex;
|
||||||
|
|
||||||
|
private TextView dialogColorDotView;
|
||||||
|
private EditText dialogColorEditText;
|
||||||
|
private EditText dialogOpacityEditText;
|
||||||
|
private ColorPickerView dialogColorPickerView;
|
||||||
|
|
||||||
public SegmentCategoryListPreference(Context context, SegmentCategory category) {
|
public SegmentCategoryListPreference(Context context, SegmentCategory category) {
|
||||||
super(context);
|
super(context);
|
||||||
this.category = Objects.requireNonNull(category);
|
this.category = Objects.requireNonNull(category);
|
||||||
@@ -53,7 +69,7 @@ public class SegmentCategoryListPreference extends ListPreference {
|
|||||||
setEntryValues(isHighlightCategory
|
setEntryValues(isHighlightCategory
|
||||||
? CategoryBehaviour.getBehaviorKeyValuesWithoutSkipOnce()
|
? CategoryBehaviour.getBehaviorKeyValuesWithoutSkipOnce()
|
||||||
: CategoryBehaviour.getBehaviorKeyValues());
|
: CategoryBehaviour.getBehaviorKeyValues());
|
||||||
setSummary(category.description.toString());
|
super.setSummary(category.description.toString());
|
||||||
|
|
||||||
updateUI();
|
updateUI();
|
||||||
}
|
}
|
||||||
@@ -67,8 +83,20 @@ public class SegmentCategoryListPreference extends ListPreference {
|
|||||||
categoryOpacity = category.getOpacity();
|
categoryOpacity = category.getOpacity();
|
||||||
|
|
||||||
Context context = builder.getContext();
|
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 gridLayout = new GridLayout(context);
|
||||||
gridLayout.setPadding(70, 0, 150, 0); // Padding for the entire layout.
|
|
||||||
gridLayout.setColumnCount(3);
|
gridLayout.setColumnCount(3);
|
||||||
gridLayout.setRowCount(2);
|
gridLayout.setRowCount(2);
|
||||||
|
|
||||||
@@ -84,19 +112,22 @@ public class SegmentCategoryListPreference extends ListPreference {
|
|||||||
gridParams.rowSpec = GridLayout.spec(0); // First row.
|
gridParams.rowSpec = GridLayout.spec(0); // First row.
|
||||||
gridParams.columnSpec = GridLayout.spec(1); // Second column.
|
gridParams.columnSpec = GridLayout.spec(1); // Second column.
|
||||||
gridParams.setMargins(0, 0, 10, 0);
|
gridParams.setMargins(0, 0, 10, 0);
|
||||||
colorDotView = new TextView(context);
|
dialogColorDotView = new TextView(context);
|
||||||
colorDotView.setLayoutParams(gridParams);
|
dialogColorDotView.setLayoutParams(gridParams);
|
||||||
gridLayout.addView(colorDotView);
|
gridLayout.addView(dialogColorDotView);
|
||||||
updateCategoryColorDot();
|
updateCategoryColorDot();
|
||||||
|
|
||||||
gridParams = new GridLayout.LayoutParams();
|
gridParams = new GridLayout.LayoutParams();
|
||||||
gridParams.rowSpec = GridLayout.spec(0); // First row.
|
gridParams.rowSpec = GridLayout.spec(0); // First row.
|
||||||
gridParams.columnSpec = GridLayout.spec(2); // Third column.
|
gridParams.columnSpec = GridLayout.spec(2); // Third column.
|
||||||
colorEditText = new EditText(context);
|
dialogColorEditText = new EditText(context);
|
||||||
colorEditText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS);
|
dialogColorEditText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS
|
||||||
colorEditText.setTextLocale(Locale.US);
|
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||||
colorEditText.setText(category.getColorString());
|
dialogColorEditText.setAutofillHints((String) null);
|
||||||
colorEditText.addTextChangedListener(new TextWatcher() {
|
dialogColorEditText.setTypeface(Typeface.MONOSPACE);
|
||||||
|
dialogColorEditText.setTextLocale(Locale.US);
|
||||||
|
dialogColorEditText.setText(getColorString(categoryColor));
|
||||||
|
dialogColorEditText.addTextChangedListener(new TextWatcher() {
|
||||||
@Override
|
@Override
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
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) {
|
public void afterTextChanged(Editable edit) {
|
||||||
try {
|
try {
|
||||||
String colorString = edit.toString();
|
String colorString = edit.toString();
|
||||||
final int colorStringLength = colorString.length();
|
String normalizedColorString = ColorPickerPreference.cleanupColorCodeString(colorString);
|
||||||
|
|
||||||
if (!colorString.startsWith("#")) {
|
if (!normalizedColorString.equals(colorString)) {
|
||||||
edit.insert(0, "#"); // Recursively calls back into this method.
|
edit.replace(0, colorString.length(), normalizedColorString);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int maxColorStringLength = 7; // #RRGGBB
|
if (normalizedColorString.length() != ColorPickerPreference.COLOR_STRING_LENGTH) {
|
||||||
if (colorStringLength > maxColorStringLength) {
|
// User is still typing out the color.
|
||||||
edit.delete(maxColorStringLength, colorStringLength);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
categoryColor = Color.parseColor(colorString);
|
// Remove the alpha channel.
|
||||||
updateCategoryColorDot();
|
final int newColor = Color.parseColor(colorString) & 0x00FFFFFF;
|
||||||
} catch (IllegalArgumentException ex) {
|
// Changing view color causes callback into this class.
|
||||||
// Ignore.
|
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);
|
dialogColorEditText.setLayoutParams(gridParams);
|
||||||
gridLayout.addView(colorEditText);
|
gridLayout.addView(dialogColorEditText);
|
||||||
|
|
||||||
gridParams = new GridLayout.LayoutParams();
|
gridParams = new GridLayout.LayoutParams();
|
||||||
gridParams.rowSpec = GridLayout.spec(1); // Second row.
|
gridParams.rowSpec = GridLayout.spec(1); // Second row.
|
||||||
@@ -143,9 +176,13 @@ public class SegmentCategoryListPreference extends ListPreference {
|
|||||||
gridParams = new GridLayout.LayoutParams();
|
gridParams = new GridLayout.LayoutParams();
|
||||||
gridParams.rowSpec = GridLayout.spec(1); // Second row.
|
gridParams.rowSpec = GridLayout.spec(1); // Second row.
|
||||||
gridParams.columnSpec = GridLayout.spec(2); // Third column.
|
gridParams.columnSpec = GridLayout.spec(2); // Third column.
|
||||||
opacityEditText = new EditText(context);
|
dialogOpacityEditText = new EditText(context);
|
||||||
opacityEditText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
|
dialogOpacityEditText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL
|
||||||
opacityEditText.addTextChangedListener(new TextWatcher() {
|
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||||
|
dialogOpacityEditText.setAutofillHints((String) null);
|
||||||
|
dialogOpacityEditText.setTypeface(Typeface.MONOSPACE);
|
||||||
|
dialogOpacityEditText.setTextLocale(Locale.US);
|
||||||
|
dialogOpacityEditText.addTextChangedListener(new TextWatcher() {
|
||||||
@Override
|
@Override
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
}
|
}
|
||||||
@@ -183,31 +220,40 @@ public class SegmentCategoryListPreference extends ListPreference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateCategoryColorDot();
|
updateCategoryColorDot();
|
||||||
} catch (NumberFormatException ex) {
|
} catch (Exception ex) {
|
||||||
// Should never happen.
|
// Should never happen.
|
||||||
Logger.printException(() -> "Could not parse opacity string", ex);
|
Logger.printException(() -> "opacityEditText afterTextChanged failure", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
opacityEditText.setLayoutParams(gridParams);
|
dialogOpacityEditText.setLayoutParams(gridParams);
|
||||||
gridLayout.addView(opacityEditText);
|
gridLayout.addView(dialogOpacityEditText);
|
||||||
updateOpacityText();
|
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.setTitle(category.title.toString());
|
||||||
|
|
||||||
builder.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
builder.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||||
onClick(dialog, DialogInterface.BUTTON_POSITIVE);
|
onClick(dialog, DialogInterface.BUTTON_POSITIVE);
|
||||||
});
|
});
|
||||||
builder.setNeutralButton(str("revanced_sb_reset_color"), (dialog, which) -> {
|
builder.setNeutralButton(str("revanced_settings_reset_color"), null);
|
||||||
try {
|
|
||||||
category.resetColorAndOpacity();
|
|
||||||
updateUI();
|
|
||||||
Utils.showToastShort(str("revanced_sb_color_reset"));
|
|
||||||
} catch (Exception ex) {
|
|
||||||
Logger.printException(() -> "setNeutralButton failure", ex);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
builder.setNegativeButton(android.R.string.cancel, null);
|
builder.setNegativeButton(android.R.string.cancel, null);
|
||||||
|
|
||||||
selectedDialogEntryIndex = findIndexOfValue(getValue());
|
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
|
@Override
|
||||||
protected void onDialogClosed(boolean positiveResult) {
|
protected void onDialogClosed(boolean positiveResult) {
|
||||||
try {
|
try {
|
||||||
@@ -230,42 +295,50 @@ public class SegmentCategoryListPreference extends ListPreference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String colorString = colorEditText.getText().toString();
|
category.setColor(dialogColorEditText.getText().toString());
|
||||||
if (!colorString.equals(category.getColorString()) || categoryOpacity != category.getOpacity()) {
|
category.setOpacity(categoryOpacity);
|
||||||
category.setColor(colorString);
|
|
||||||
category.setOpacity(categoryOpacity);
|
|
||||||
Utils.showToastShort(str("revanced_sb_color_changed"));
|
|
||||||
}
|
|
||||||
} catch (IllegalArgumentException ex) {
|
} catch (IllegalArgumentException ex) {
|
||||||
Utils.showToastShort(str("revanced_sb_color_invalid"));
|
Utils.showToastShort(str("revanced_settings_color_invalid"));
|
||||||
}
|
}
|
||||||
|
|
||||||
updateUI();
|
updateUI();
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.printException(() -> "onDialogClosed failure", ex);
|
Logger.printException(() -> "onDialogClosed failure", ex);
|
||||||
|
} finally {
|
||||||
|
dialogColorDotView = null;
|
||||||
|
dialogColorEditText = null;
|
||||||
|
dialogOpacityEditText = null;
|
||||||
|
dialogColorPickerView = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyOpacityToCategoryColor() {
|
@ColorInt
|
||||||
categoryColor = applyOpacityToColor(categoryColor, categoryOpacity);
|
private int applyOpacityToCategoryColor() {
|
||||||
|
return applyOpacityToColor(categoryColor, categoryOpacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateUI() {
|
public void updateUI() {
|
||||||
categoryColor = category.getColorNoOpacity();
|
categoryColor = category.getColorNoOpacity();
|
||||||
categoryOpacity = category.getOpacity();
|
categoryOpacity = category.getOpacity();
|
||||||
applyOpacityToCategoryColor();
|
|
||||||
|
|
||||||
setTitle(category.getTitleWithColorDot(categoryColor));
|
setTitle(category.getTitleWithColorDot(applyOpacityToCategoryColor()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateCategoryColorDot() {
|
private void updateCategoryColorDot() {
|
||||||
applyOpacityToCategoryColor();
|
dialogColorDotView.setText(SegmentCategory.getCategoryColorDot(applyOpacityToCategoryColor()));
|
||||||
|
|
||||||
colorDotView.setText(SegmentCategory.getCategoryColorDot(categoryColor));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateOpacityText() {
|
private void updateOpacityText() {
|
||||||
opacityEditText.setText(String.format(Locale.US, "%.2f", categoryOpacity));
|
dialogOpacityEditText.setText(String.format(Locale.US, "%.2f", categoryOpacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSummary(CharSequence summary) {
|
||||||
|
// Ignore calls to set the summary.
|
||||||
|
// Summary is always the description of the category.
|
||||||
|
//
|
||||||
|
// This is required otherwise the ReVanced preference fragment
|
||||||
|
// sets all ListPreference summaries to show the current selection.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -376,7 +376,11 @@ public class SponsorBlockPreferenceGroup extends PreferenceGroup {
|
|||||||
Utils.setEditTextDialogTheme(builder);
|
Utils.setEditTextDialogTheme(builder);
|
||||||
|
|
||||||
builder.setNeutralButton(str("revanced_sb_settings_copy"), (dialog, which) -> {
|
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())
|
.setTitle(apiUrl.getTitle())
|
||||||
.setView(editText)
|
.setView(editText)
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.setNeutralButton(str("revanced_sb_reset"), urlChangeListener)
|
.setNeutralButton(str("revanced_settings_reset"), urlChangeListener)
|
||||||
.setPositiveButton(android.R.string.ok, urlChangeListener)
|
.setPositiveButton(android.R.string.ok, urlChangeListener)
|
||||||
.show();
|
.show();
|
||||||
return true;
|
return true;
|
||||||
@@ -433,7 +437,11 @@ public class SponsorBlockPreferenceGroup extends PreferenceGroup {
|
|||||||
Utils.setEditTextDialogTheme(builder);
|
Utils.setEditTextDialogTheme(builder);
|
||||||
|
|
||||||
builder.setNeutralButton(str("revanced_sb_settings_copy"), (dialog, which) -> {
|
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);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
|
|||||||
org.gradle.parallel = true
|
org.gradle.parallel = true
|
||||||
android.useAndroidX = true
|
android.useAndroidX = true
|
||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
version = 5.24.0-dev.8
|
version = 5.25.0-dev.11
|
||||||
|
|||||||
@@ -284,6 +284,14 @@ public final class app/revanced/patches/messenger/inputfield/DisableTypingIndica
|
|||||||
public static final fun getDisableTypingIndicatorPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
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 final class app/revanced/patches/messenger/navbar/RemoveMetaAITabPatchKt {
|
||||||
public static final fun getRemoveMetaAITabPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getRemoveMetaAITabPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
@@ -652,6 +660,10 @@ public final class app/revanced/patches/shared/misc/mapping/ResourceMappingPatch
|
|||||||
public static final fun getResourceMappings ()Ljava/util/List;
|
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 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 (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;
|
public static final fun settingsPatch (Lkotlin/Pair;Ljava/util/Set;)Lapp/revanced/patcher/patch/ResourcePatch;
|
||||||
@@ -872,6 +884,10 @@ public final class app/revanced/patches/spotify/misc/fix/SpoofSignaturePatchKt {
|
|||||||
public static final fun getSpoofSignaturePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
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 final class app/revanced/patches/spotify/misc/privacy/SanitizeSharingLinksPatchKt {
|
||||||
public static final fun getSanitizeSharingLinksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getSanitizeSharingLinksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
@@ -1383,6 +1399,10 @@ public final class app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatchKt {
|
|||||||
public static final fun getGmsCoreSupportPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
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 final class app/revanced/patches/youtube/misc/imageurlhook/CronetImageUrlHookKt {
|
||||||
public static final fun addImageUrlErrorCallbackHook (Ljava/lang/String;)V
|
public static final fun addImageUrlErrorCallbackHook (Ljava/lang/String;)V
|
||||||
public static final fun addImageUrlHook (Ljava/lang/String;Z)V
|
public static final fun addImageUrlHook (Ljava/lang/String;Z)V
|
||||||
@@ -1615,8 +1635,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 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 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 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 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 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 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
|
public static final fun traverseClassHierarchy (Lapp/revanced/patcher/patch/BytecodePatchContext;Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lkotlin/jvm/functions/Function1;)V
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ val hideAdbStatusPatch = bytecodePatch(
|
|||||||
.takeIf { it.opcode == Opcode.INVOKE_STATIC }
|
.takeIf { it.opcode == Opcode.INVOKE_STATIC }
|
||||||
?.getReference<MethodReference>()
|
?.getReference<MethodReference>()
|
||||||
?.takeIf {
|
?.takeIf {
|
||||||
it.anyMethodSignatureMatches(it,
|
it.anyMethodSignatureMatches(
|
||||||
SETTINGS_GLOBAL_GET_INT_OR_THROW_METHOD_REFERENCE,
|
SETTINGS_GLOBAL_GET_INT_OR_THROW_METHOD_REFERENCE,
|
||||||
SETTINGS_GLOBAL_GET_INT_OR_DEFAULT_METHOD_REFERENCE
|
SETTINGS_GLOBAL_GET_INT_OR_DEFAULT_METHOD_REFERENCE
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ val removeShareTargetsPatch = resourcePatch(
|
|||||||
try {
|
try {
|
||||||
document("res/xml/shortcuts.xml")
|
document("res/xml/shortcuts.xml")
|
||||||
} catch (_: FileNotFoundException) {
|
} 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 ->
|
}.use { document ->
|
||||||
val rootNode = document.getNode("shortcuts") as? Element ?: return@use
|
val rootNode = document.getNode("shortcuts") as? Element ?: return@use
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
package app.revanced.patches.angulus.ads
|
package app.revanced.patches.angulus.ads
|
||||||
|
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.patches.shared.misc.pairip.license.disableLicenseCheckPatch
|
||||||
import app.revanced.util.returnEarly
|
import app.revanced.util.returnEarly
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
val angulusPatch = bytecodePatch(name = "Hide ads") {
|
val angulusPatch = bytecodePatch(name = "Hide ads") {
|
||||||
compatibleWith("com.drinkplusplus.angulus")
|
compatibleWith("com.drinkplusplus.angulus")
|
||||||
|
|
||||||
|
dependsOn(disableLicenseCheckPatch)
|
||||||
|
|
||||||
execute {
|
execute {
|
||||||
// Always return 0 as the daily measurement count.
|
// Always return 0 as the daily measurement count.
|
||||||
getDailyMeasurementCountFingerprint.method.returnEarly()
|
getDailyMeasurementCountFingerprint.method.returnEarly(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,14 @@ import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
|||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
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")
|
@Suppress("unused")
|
||||||
val disableSwitchingEmojiToStickerPatch = bytecodePatch(
|
val disableSwitchingEmojiToStickerPatch = bytecodePatch(
|
||||||
name = "Disable switching emoji to sticker",
|
|
||||||
description = "Disables switching from emoji to sticker search mode in message input field.",
|
description = "Disables switching from emoji to sticker search mode in message input field.",
|
||||||
) {
|
) {
|
||||||
compatibleWith("com.facebook.orca"("439.0.0.29.119"))
|
compatibleWith("com.facebook.orca"("439.0.0.29.119"))
|
||||||
|
|||||||
@@ -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;")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<OneRegisterInstruction>(returnIndex).registerA
|
||||||
|
|
||||||
|
addInstructions(
|
||||||
|
returnIndex,
|
||||||
|
"""
|
||||||
|
invoke-static { p1, p2, v$returnRegister }, $EXTENSION_CLASS_DESCRIPTOR->overrideConfigBool(JZ)Z
|
||||||
|
move-result v$returnRegister
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package app.revanced.patches.messenger.misc.extension
|
||||||
|
|
||||||
|
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
|
||||||
|
|
||||||
|
val sharedExtensionPatch = sharedExtensionPatch("messenger", mainActivityOnCreateHook)
|
||||||
@@ -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")
|
||||||
|
}
|
||||||
@@ -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,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,25 +1,12 @@
|
|||||||
package app.revanced.patches.messenger.navbar
|
package app.revanced.patches.messenger.navbar
|
||||||
|
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
import app.revanced.patches.messenger.metaai.removeMetaAIPatch
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
|
||||||
|
|
||||||
|
@Deprecated("Superseded by removeMetaAIPatch", ReplaceWith("removeMetaAIPatch"))
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
val removeMetaAITabPatch = bytecodePatch(
|
val removeMetaAITabPatch = bytecodePatch(
|
||||||
name = "Remove Meta AI tab",
|
|
||||||
description = "Removes the 'Meta AI' tab from the navbar.",
|
description = "Removes the 'Meta AI' tab from the navbar.",
|
||||||
) {
|
) {
|
||||||
compatibleWith("com.facebook.orca")
|
dependsOn(removeMetaAIPatch)
|
||||||
|
|
||||||
execute {
|
|
||||||
createTabConfigurationFingerprint.let {
|
|
||||||
val moveResultIndex = it.patternMatch!!.startIndex + 1
|
|
||||||
val enabledRegister = it.method.getInstruction<OneRegisterInstruction>(moveResultIndex).registerA
|
|
||||||
it.method.replaceInstruction(
|
|
||||||
moveResultIndex,
|
|
||||||
"const/4 v$enabledRegister, 0x0"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ fun gmsCoreSupportPatch(
|
|||||||
|
|
||||||
// Google Play Utility is not present in all apps, so we need to check if it's present.
|
// Google Play Utility is not present in all apps, so we need to check if it's present.
|
||||||
if (googlePlayUtilityFingerprint.methodOrNull != null) {
|
if (googlePlayUtilityFingerprint.methodOrNull != null) {
|
||||||
googlePlayUtilityFingerprint.method.returnEarly()
|
googlePlayUtilityFingerprint.method.returnEarly(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify GmsCore is installed and whitelisted for power optimizations and background usage.
|
// Verify GmsCore is installed and whitelisted for power optimizations and background usage.
|
||||||
|
|||||||
@@ -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 = "Disable Play Integrity Protect (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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,9 +3,9 @@ package app.revanced.patches.spotify.lite.ondemand
|
|||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
|
||||||
|
@Deprecated("Patch no longer works and will be deleted soon")
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
val onDemandPatch = bytecodePatch(
|
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.",
|
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")
|
compatibleWith("com.spotify.lite")
|
||||||
|
|||||||
@@ -7,7 +7,5 @@ import app.revanced.patcher.patch.bytecodePatch
|
|||||||
val spoofSignaturePatch = bytecodePatch(
|
val spoofSignaturePatch = bytecodePatch(
|
||||||
description = "Spoofs the signature of the app fix various functions of the app.",
|
description = "Spoofs the signature of the app fix various functions of the app.",
|
||||||
) {
|
) {
|
||||||
compatibleWith("com.spotify.music")
|
|
||||||
|
|
||||||
dependsOn(spoofPackageInfoPatch)
|
dependsOn(spoofPackageInfoPatch)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 }
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -46,7 +46,6 @@ private val hideAdsResourcePatch = resourcePatch {
|
|||||||
SwitchPreference("revanced_hide_general_ads"),
|
SwitchPreference("revanced_hide_general_ads"),
|
||||||
SwitchPreference("revanced_hide_end_screen_store_banner"),
|
SwitchPreference("revanced_hide_end_screen_store_banner"),
|
||||||
SwitchPreference("revanced_hide_fullscreen_ads"),
|
SwitchPreference("revanced_hide_fullscreen_ads"),
|
||||||
SwitchPreference("revanced_hide_buttoned_ads"),
|
|
||||||
SwitchPreference("revanced_hide_paid_promotion_label"),
|
SwitchPreference("revanced_hide_paid_promotion_label"),
|
||||||
SwitchPreference("revanced_hide_player_store_shelf"),
|
SwitchPreference("revanced_hide_player_store_shelf"),
|
||||||
SwitchPreference("revanced_hide_self_sponsor_ads"),
|
SwitchPreference("revanced_hide_self_sponsor_ads"),
|
||||||
|
|||||||
@@ -48,7 +48,9 @@ private val swipeControlsResourcePatch = resourcePatch {
|
|||||||
summaryKey = null,
|
summaryKey = null,
|
||||||
),
|
),
|
||||||
TextPreference("revanced_swipe_overlay_background_opacity", inputType = InputType.NUMBER),
|
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_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_text_overlay_size", inputType = InputType.NUMBER),
|
||||||
TextPreference("revanced_swipe_overlay_timeout", inputType = InputType.NUMBER),
|
TextPreference("revanced_swipe_overlay_timeout", inputType = InputType.NUMBER),
|
||||||
TextPreference("revanced_swipe_threshold", inputType = InputType.NUMBER),
|
TextPreference("revanced_swipe_threshold", inputType = InputType.NUMBER),
|
||||||
|
|||||||
@@ -15,9 +15,6 @@ internal val openVideosFullscreenPortraitFingerprint = fingerprint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to enable opening regular videos fullscreen.
|
|
||||||
*/
|
|
||||||
internal val openVideosFullscreenHookPatchExtensionFingerprint = fingerprint {
|
internal val openVideosFullscreenHookPatchExtensionFingerprint = fingerprint {
|
||||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||||
returns("Z")
|
returns("Z")
|
||||||
|
|||||||
@@ -54,3 +54,11 @@ internal val shortsPlaybackIntentFingerprint = fingerprint {
|
|||||||
"reels_fragment_descriptor"
|
"reels_fragment_descriptor"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal val exitVideoPlayerFingerprint = fingerprint {
|
||||||
|
returns("V")
|
||||||
|
parameters()
|
||||||
|
literal {
|
||||||
|
mdx_drawer_layout_id
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,16 @@
|
|||||||
package app.revanced.patches.youtube.layout.shortsplayer
|
package app.revanced.patches.youtube.layout.shortsplayer
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
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.addInstructionsWithLabels
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
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.addResources
|
||||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
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.shared.misc.settings.preference.ListPreference
|
||||||
import app.revanced.patches.youtube.layout.player.fullscreen.openVideosFullscreenHookPatch
|
import app.revanced.patches.youtube.layout.player.fullscreen.openVideosFullscreenHookPatch
|
||||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
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.findFreeRegister
|
||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
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.instruction.OneRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
|
|
||||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||||
"Lapp/revanced/extension/youtube/patches/OpenShortsInRegularPlayerPatch;"
|
"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")
|
@Suppress("unused")
|
||||||
val openShortsInRegularPlayerPatch = bytecodePatch(
|
val openShortsInRegularPlayerPatch = bytecodePatch(
|
||||||
name = "Open Shorts in regular player",
|
name = "Open Shorts in regular player",
|
||||||
@@ -36,7 +58,8 @@ val openShortsInRegularPlayerPatch = bytecodePatch(
|
|||||||
addResourcesPatch,
|
addResourcesPatch,
|
||||||
openVideosFullscreenHookPatch,
|
openVideosFullscreenHookPatch,
|
||||||
navigationBarHookPatch,
|
navigationBarHookPatch,
|
||||||
versionCheckPatch
|
versionCheckPatch,
|
||||||
|
openShortsInRegularPlayerResourcePatch
|
||||||
)
|
)
|
||||||
|
|
||||||
compatibleWith(
|
compatibleWith(
|
||||||
@@ -127,5 +150,28 @@ val openShortsInRegularPlayerPatch = bytecodePatch(
|
|||||||
${extensionInstructions(0, 1)}
|
${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<MethodReference>()
|
||||||
|
reference?.name == "finish"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Index of PlayerType.isWatchWhileMaximizedOrFullscreen()
|
||||||
|
val index = indexOfFirstInstructionReversedOrThrow(finishIndex, Opcode.MOVE_RESULT)
|
||||||
|
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||||
|
|
||||||
|
addInstructions(
|
||||||
|
index + 1,
|
||||||
|
"""
|
||||||
|
invoke-static { v$register }, ${EXTENSION_CLASS_DESCRIPTOR}->overrideBackPressToExit(Z)Z
|
||||||
|
move-result v$register
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,14 +89,15 @@ val themePatch = bytecodePatch(
|
|||||||
execute {
|
execute {
|
||||||
val preferences = mutableSetOf<BasePreference>(
|
val preferences = mutableSetOf<BasePreference>(
|
||||||
SwitchPreference("revanced_seekbar_custom_color"),
|
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) {
|
if (is_19_25_or_greater) {
|
||||||
preferences += TextPreference(
|
preferences += TextPreference("revanced_seekbar_custom_color_accent",
|
||||||
"revanced_seekbar_custom_color_accent",
|
tag = "app.revanced.extension.shared.settings.preference.ColorPickerPreference",
|
||||||
inputType = InputType.TEXT_CAP_CHARACTERS
|
inputType = InputType.TEXT_CAP_CHARACTERS)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PreferenceScreen.SEEKBAR.addPreferences(
|
PreferenceScreen.SEEKBAR.addPreferences(
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
|||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
import app.revanced.patches.all.misc.resources.addResources
|
import app.revanced.patches.all.misc.resources.addResources
|
||||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
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
|
||||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting
|
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting
|
||||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||||
@@ -23,7 +24,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR =
|
|||||||
|
|
||||||
val enableDebuggingPatch = bytecodePatch(
|
val enableDebuggingPatch = bytecodePatch(
|
||||||
name = "Enable debugging",
|
name = "Enable debugging",
|
||||||
description = "Adds options for debugging.",
|
description = "Adds options for debugging and exporting ReVanced logs to the clipboard.",
|
||||||
) {
|
) {
|
||||||
dependsOn(
|
dependsOn(
|
||||||
sharedExtensionPatch,
|
sharedExtensionPatch,
|
||||||
@@ -56,6 +57,16 @@ val enableDebuggingPatch = bytecodePatch(
|
|||||||
SwitchPreference("revanced_debug_protobuffer"),
|
SwitchPreference("revanced_debug_protobuffer"),
|
||||||
SwitchPreference("revanced_debug_stacktrace"),
|
SwitchPreference("revanced_debug_stacktrace"),
|
||||||
SwitchPreference("revanced_debug_toast_on_error"),
|
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
|
return-wide v0
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
experimentalStringFeatureFlagFingerprint.match(
|
experimentalStringFeatureFlagFingerprint.match(
|
||||||
|
|||||||
@@ -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))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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")
|
||||||
|
}
|
||||||
@@ -74,6 +74,7 @@ private val settingsResourcePatch = resourcePatch {
|
|||||||
|
|
||||||
arrayOf(
|
arrayOf(
|
||||||
ResourceGroup("drawable",
|
ResourceGroup("drawable",
|
||||||
|
"revanced_settings_circle_background.xml",
|
||||||
"revanced_settings_cursor.xml",
|
"revanced_settings_cursor.xml",
|
||||||
"revanced_settings_icon.xml",
|
"revanced_settings_icon.xml",
|
||||||
"revanced_settings_screen_00_about.xml",
|
"revanced_settings_screen_00_about.xml",
|
||||||
@@ -91,6 +92,8 @@ private val settingsResourcePatch = resourcePatch {
|
|||||||
"revanced_settings_screen_12_video.xml",
|
"revanced_settings_screen_12_video.xml",
|
||||||
),
|
),
|
||||||
ResourceGroup("layout",
|
ResourceGroup("layout",
|
||||||
|
"revanced_color_dot_widget.xml",
|
||||||
|
"revanced_color_picker.xml",
|
||||||
"revanced_preference_with_icon_no_search_result.xml",
|
"revanced_preference_with_icon_no_search_result.xml",
|
||||||
"revanced_search_suggestion_item.xml",
|
"revanced_search_suggestion_item.xml",
|
||||||
"revanced_settings_with_toolbar.xml"),
|
"revanced_settings_with_toolbar.xml"),
|
||||||
|
|||||||
@@ -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")
|
|
||||||
}
|
|
||||||
@@ -1,54 +1,11 @@
|
|||||||
package app.revanced.patches.youtube.misc.zoomhaptics
|
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.patch.bytecodePatch
|
||||||
import app.revanced.patcher.util.smali.ExternalLabel
|
import app.revanced.patches.youtube.misc.hapticfeedback.disableHapticFeedbackPatch
|
||||||
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
|
|
||||||
|
|
||||||
|
@Deprecated("Superseded by disableHapticFeedbackPatch", ReplaceWith("disableHapticFeedbackPatch"))
|
||||||
val zoomHapticsPatch = bytecodePatch(
|
val zoomHapticsPatch = bytecodePatch(
|
||||||
name = "Disable zoom haptics",
|
|
||||||
description = "Adds an option to disable haptics when zooming.",
|
description = "Adds an option to disable haptics when zooming.",
|
||||||
) {
|
) {
|
||||||
dependsOn(
|
dependsOn(disableHapticFeedbackPatch)
|
||||||
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)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -3,10 +3,10 @@ package app.revanced.patches.yuka.misc.unlockpremium
|
|||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
|
||||||
|
@Deprecated("This patch no longer works and will be removed in the future.")
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
val unlockPremiumPatch = bytecodePatch(
|
val unlockPremiumPatch = bytecodePatch {
|
||||||
name = "Unlock premium",
|
|
||||||
) {
|
|
||||||
compatibleWith("io.yuka.android"("4.29"))
|
compatibleWith("io.yuka.android"("4.29"))
|
||||||
|
|
||||||
execute {
|
execute {
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ internal val Instruction.registersUsed: List<Int>
|
|||||||
else -> listOf(registerC, registerD, registerE, registerF, registerG)
|
else -> listOf(registerC, registerD, registerE, registerF, registerG)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is ThreeRegisterInstruction -> listOf(registerA, registerB, registerC)
|
is ThreeRegisterInstruction -> listOf(registerA, registerB, registerC)
|
||||||
is TwoRegisterInstruction -> listOf(registerA, registerB)
|
is TwoRegisterInstruction -> listOf(registerA, registerB)
|
||||||
is OneRegisterInstruction -> listOf(registerA)
|
is OneRegisterInstruction -> listOf(registerA)
|
||||||
@@ -170,7 +171,7 @@ internal val Instruction.isReturnInstruction: Boolean
|
|||||||
/**
|
/**
|
||||||
* Adds public [AccessFlags] and removes private and protected flags (if present).
|
* 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)
|
return this.or(AccessFlags.PUBLIC.value)
|
||||||
.and(AccessFlags.PROTECTED.value.inv())
|
.and(AccessFlags.PROTECTED.value.inv())
|
||||||
.and(AccessFlags.PRIVATE.value.inv())
|
.and(AccessFlags.PRIVATE.value.inv())
|
||||||
@@ -489,9 +490,10 @@ fun Method.indexOfFirstInstruction(targetOpcode: Opcode): Int = indexOfFirstInst
|
|||||||
* @return The index of the first opcode specified, or -1 if not found.
|
* @return The index of the first opcode specified, or -1 if not found.
|
||||||
* @see indexOfFirstInstructionOrThrow
|
* @see indexOfFirstInstructionOrThrow
|
||||||
*/
|
*/
|
||||||
fun Method.indexOfFirstInstruction(startIndex: Int = 0, targetOpcode: Opcode): Int = indexOfFirstInstruction(startIndex) {
|
fun Method.indexOfFirstInstruction(startIndex: Int = 0, targetOpcode: Opcode): Int =
|
||||||
opcode == targetOpcode
|
indexOfFirstInstruction(startIndex) {
|
||||||
}
|
opcode == targetOpcode
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the index of the first [Instruction] that matches the predicate, starting from [startIndex].
|
* Get the index of the first [Instruction] that matches the predicate, starting from [startIndex].
|
||||||
@@ -526,9 +528,10 @@ fun Method.indexOfFirstInstructionOrThrow(targetOpcode: Opcode): Int = indexOfFi
|
|||||||
* @throws PatchException
|
* @throws PatchException
|
||||||
* @see indexOfFirstInstruction
|
* @see indexOfFirstInstruction
|
||||||
*/
|
*/
|
||||||
fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, targetOpcode: Opcode): Int = indexOfFirstInstructionOrThrow(startIndex) {
|
fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, targetOpcode: Opcode): Int =
|
||||||
opcode == targetOpcode
|
indexOfFirstInstructionOrThrow(startIndex) {
|
||||||
}
|
opcode == targetOpcode
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the index of the first [Instruction] that matches the predicate, starting from [startIndex].
|
* Get the index of the first [Instruction] that matches the predicate, starting from [startIndex].
|
||||||
@@ -554,9 +557,10 @@ fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, filter: Instructi
|
|||||||
* @return -1 if the instruction is not found.
|
* @return -1 if the instruction is not found.
|
||||||
* @see indexOfFirstInstructionReversedOrThrow
|
* @see indexOfFirstInstructionReversedOrThrow
|
||||||
*/
|
*/
|
||||||
fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, targetOpcode: Opcode): Int = indexOfFirstInstructionReversed(startIndex) {
|
fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, targetOpcode: Opcode): Int =
|
||||||
opcode == targetOpcode
|
indexOfFirstInstructionReversed(startIndex) {
|
||||||
}
|
opcode == targetOpcode
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the index of matching instruction,
|
* Get the index of matching instruction,
|
||||||
@@ -593,9 +597,10 @@ fun Method.indexOfFirstInstructionReversed(targetOpcode: Opcode): Int = indexOfF
|
|||||||
* @return The index of the instruction.
|
* @return The index of the instruction.
|
||||||
* @see indexOfFirstInstructionReversed
|
* @see indexOfFirstInstructionReversed
|
||||||
*/
|
*/
|
||||||
fun Method.indexOfFirstInstructionReversedOrThrow(startIndex: Int? = null, targetOpcode: Opcode): Int = indexOfFirstInstructionReversedOrThrow(startIndex) {
|
fun Method.indexOfFirstInstructionReversedOrThrow(startIndex: Int? = null, targetOpcode: Opcode): Int =
|
||||||
opcode == targetOpcode
|
indexOfFirstInstructionReversedOrThrow(startIndex) {
|
||||||
}
|
opcode == targetOpcode
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the index of matching instruction,
|
* Get the index of matching instruction,
|
||||||
@@ -652,7 +657,8 @@ fun Method.findInstructionIndicesReversedOrThrow(filter: Instruction.() -> Boole
|
|||||||
* _Returns an empty list if no indices are found_
|
* _Returns an empty list if no indices are found_
|
||||||
* @see findInstructionIndicesReversedOrThrow
|
* @see findInstructionIndicesReversedOrThrow
|
||||||
*/
|
*/
|
||||||
fun Method.findInstructionIndicesReversed(opcode: Opcode): List<Int> = findInstructionIndicesReversed { this.opcode == opcode }
|
fun Method.findInstructionIndicesReversed(opcode: Opcode): List<Int> =
|
||||||
|
findInstructionIndicesReversed { this.opcode == opcode }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return An immutable list of indices of the opcode in reverse order.
|
* @return An immutable list of indices of the opcode in reverse order.
|
||||||
@@ -726,43 +732,222 @@ fun BytecodePatchContext.forEachLiteralValueInstruction(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private const val RETURN_TYPE_MISMATCH = "Mismatch between override type and Method return type"
|
||||||
* 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)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
* All method code is executed the same as unpatched.
|
||||||
*
|
*
|
||||||
* @see returnEarly
|
* @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()) {
|
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
|
return-object v0
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
|
|
||||||
'V' -> {
|
'V' -> {
|
||||||
if (returnLate) throw IllegalArgumentException("Cannot return late for method of void type")
|
|
||||||
"return-void"
|
"return-void"
|
||||||
}
|
}
|
||||||
|
|
||||||
'I', 'Z' -> {
|
'B', 'Z' -> {
|
||||||
"""
|
"""
|
||||||
const/4 v0, $const
|
const/4 v0, $value
|
||||||
return v0
|
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")
|
else -> throw Exception("Return type is not supported: $this")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,3 +6,5 @@ internal object Utils {
|
|||||||
.joinToString("\n") { it.trimIndent() } // Remove the leading whitespace from each line.
|
.joinToString("\n") { it.trimIndent() } // Remove the leading whitespace from each line.
|
||||||
.trimIndent() // Remove the leading newline.
|
.trimIndent() // Remove the leading newline.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun Boolean.toHexString(): String = if (this) "0x1" else "0x0"
|
||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">الإعدادات</string>
|
<string name="revanced_settings_submenu_title">الإعدادات</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">هل ترغب في المتابعة؟</string>
|
<string name="revanced_settings_confirm_user_dialog_title">هل ترغب في المتابعة؟</string>
|
||||||
<string name="revanced_settings_reset">إعادة التعيين</string>
|
<string name="revanced_settings_reset">إعادة التعيين</string>
|
||||||
|
<string name="revanced_settings_reset_color">إعادة تعيين اللون</string>
|
||||||
|
<string name="revanced_settings_color_invalid">لون غير صالح</string>
|
||||||
<string name="revanced_settings_restart_title">تحديث وإعادة التشغيل</string>
|
<string name="revanced_settings_restart_title">تحديث وإعادة التشغيل</string>
|
||||||
<string name="revanced_settings_restart">إعادة التشغيل</string>
|
<string name="revanced_settings_restart">إعادة التشغيل</string>
|
||||||
<string name="revanced_settings_import">استيراد</string>
|
<string name="revanced_settings_import">استيراد</string>
|
||||||
@@ -42,7 +44,7 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_import_reset">إعادة تعيين إعدادات ReVanced إلى الوضع الافتراضي</string>
|
<string name="revanced_settings_import_reset">إعادة تعيين إعدادات ReVanced إلى الوضع الافتراضي</string>
|
||||||
<string name="revanced_settings_import_success">تم استيراد %d إعدادات</string>
|
<string name="revanced_settings_import_success">تم استيراد %d إعدادات</string>
|
||||||
<string name="revanced_settings_import_failure_parse">فشل الاستيراد: %s</string>
|
<string name="revanced_settings_import_failure_parse">فشل الاستيراد: %s</string>
|
||||||
<string name="revanced_settings_search_hint">إعدادات البحث</string>
|
<string name="revanced_settings_search_hint">بحث الإعدادات</string>
|
||||||
<string name="revanced_settings_search_no_results_title">لم يتم العثور على نتائج لـ \".%s\"</string>
|
<string name="revanced_settings_search_no_results_title">لم يتم العثور على نتائج لـ \".%s\"</string>
|
||||||
<string name="revanced_settings_search_no_results_summary">جرّب كلمة مفتاحية أخرى</string>
|
<string name="revanced_settings_search_no_results_summary">جرّب كلمة مفتاحية أخرى</string>
|
||||||
<string name="revanced_settings_search_remove_message">إزالة من سجل البحث؟</string>
|
<string name="revanced_settings_search_remove_message">إزالة من سجل البحث؟</string>
|
||||||
@@ -97,9 +99,9 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_restore_old_settings_menus_title">استعادة قوائم الإعدادات القديمة</string>
|
<string name="revanced_restore_old_settings_menus_title">استعادة قوائم الإعدادات القديمة</string>
|
||||||
<string name="revanced_restore_old_settings_menus_summary_on">يتم عرض قوائم الإعدادات القديمة</string>
|
<string name="revanced_restore_old_settings_menus_summary_on">يتم عرض قوائم الإعدادات القديمة</string>
|
||||||
<string name="revanced_restore_old_settings_menus_summary_off">لا يتم عرض قوائم الإعدادات القديمة</string>
|
<string name="revanced_restore_old_settings_menus_summary_off">لا يتم عرض قوائم الإعدادات القديمة</string>
|
||||||
<string name="revanced_settings_search_history_title">إظهار سجل البحث في الإعدادات</string>
|
<string name="revanced_settings_search_history_title">عرض سجل بحث الإعدادات</string>
|
||||||
<string name="revanced_settings_search_history_summary_on">سجل البحث في الإعدادات معروض</string>
|
<string name="revanced_settings_search_history_summary_on">يتم عرض سجل البحث في الإعدادات</string>
|
||||||
<string name="revanced_settings_search_history_summary_off">لم يتم عرض سجل البحث في الإعدادات</string>
|
<string name="revanced_settings_search_history_summary_off">لا يتم عرض سجل البحث في الإعدادات</string>
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="misc.backgroundplayback.backgroundPlaybackPatch">
|
<patch id="misc.backgroundplayback.backgroundPlaybackPatch">
|
||||||
<string name="revanced_shorts_disable_background_playback_title">تعطيل تشغيل فيديوهات Shorts في الخلفية</string>
|
<string name="revanced_shorts_disable_background_playback_title">تعطيل تشغيل فيديوهات Shorts في الخلفية</string>
|
||||||
@@ -365,9 +367,6 @@ Second \"item\" text"</string>
|
|||||||
|
|
||||||
هذه الميزة متاحة فقط للأجهزة القديمة"</string>
|
هذه الميزة متاحة فقط للأجهزة القديمة"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">يتم عرض إعلانات ملء الشاشة</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">يتم عرض إعلانات ملء الشاشة</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">إخفاء الإعلانات الزرية</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">تم إخفاء الإعلانات الزرية</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">يتم عرض الإعلانات الزرية</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">إخفاء تسمية الترقية المدفوعة</string>
|
<string name="revanced_hide_paid_promotion_label_title">إخفاء تسمية الترقية المدفوعة</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">تم إخفاء تسمية الترقية المدفوعة</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">تم إخفاء تسمية الترقية المدفوعة</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">يتم عرض تسمية الترقية المدفوعة</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">يتم عرض تسمية الترقية المدفوعة</string>
|
||||||
@@ -1099,11 +1098,6 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s ثانية</string>
|
<string name="revanced_sb_stats_saved_second_format">%s ثانية</string>
|
||||||
<string name="revanced_sb_color_opacity_label">الشفافية:</string>
|
<string name="revanced_sb_color_opacity_label">الشفافية:</string>
|
||||||
<string name="revanced_sb_color_dot_label">اللون:</string>
|
<string name="revanced_sb_color_dot_label">اللون:</string>
|
||||||
<string name="revanced_sb_color_changed">تم تغيير اللون</string>
|
|
||||||
<string name="revanced_sb_color_reset">إعادة ضبط اللون</string>
|
|
||||||
<string name="revanced_sb_color_invalid">رمز اللون غير صالح</string>
|
|
||||||
<string name="revanced_sb_reset_color">إعادة تعيين اللون</string>
|
|
||||||
<string name="revanced_sb_reset">إعادة التعيين</string>
|
|
||||||
<string name="revanced_sb_about_title">لمحة</string>
|
<string name="revanced_sb_about_title">لمحة</string>
|
||||||
<string name="revanced_sb_about_api_summary">يتم توفير البيانات بواسطة SponsorBlock API. انقر هنا لمعرفة المزيد ومشاهدة التنزيلات لمنصات أخرى</string>
|
<string name="revanced_sb_about_api_summary">يتم توفير البيانات بواسطة SponsorBlock API. انقر هنا لمعرفة المزيد ومشاهدة التنزيلات لمنصات أخرى</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_import_reset">ReVanced tənzimləmələr standarta təyin edildi</string>
|
<string name="revanced_settings_import_reset">ReVanced tənzimləmələr standarta təyin edildi</string>
|
||||||
<string name="revanced_settings_import_success">%d tənzimləmə idxal edildi</string>
|
<string name="revanced_settings_import_success">%d tənzimləmə idxal edildi</string>
|
||||||
<string name="revanced_settings_import_failure_parse">Uğursuz idxal prosesi: %s</string>
|
<string name="revanced_settings_import_failure_parse">Uğursuz idxal prosesi: %s</string>
|
||||||
<string name="revanced_settings_search_hint">Axtarış tənzimləmələri</string>
|
<string name="revanced_settings_search_hint">Tənzimləmələri axtar</string>
|
||||||
<string name="revanced_settings_search_no_results_title">‘%s’ üçün nəticə tapılmadı</string>
|
<string name="revanced_settings_search_no_results_title">‘%s’ üçün nəticə tapılmadı</string>
|
||||||
<string name="revanced_settings_search_no_results_summary">Başqa açar sözü yoxla</string>
|
<string name="revanced_settings_search_no_results_summary">Başqa açar sözü yoxla</string>
|
||||||
<string name="revanced_settings_search_remove_message">Axtarış tarixçəsindən silinsin?</string>
|
<string name="revanced_settings_search_remove_message">Axtarış tarixçəsindən silinsin?</string>
|
||||||
@@ -365,9 +365,6 @@ Məhdudiyyətlər
|
|||||||
|
|
||||||
Bu xüsusiyyət yalnız köhnə cihazlar üçün mövcuddur"</string>
|
Bu xüsusiyyət yalnız köhnə cihazlar üçün mövcuddur"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">Tam ekran reklamları göstərilir</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">Tam ekran reklamları göstərilir</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">Düyməli reklamları gizlət</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">Düyməli reklamlar gizlədilir</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">Düyməli reklamlar göstərilir</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Ödənişli tanıtım etiketini gizlət</string>
|
<string name="revanced_hide_paid_promotion_label_title">Ödənişli tanıtım etiketini gizlət</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">Ödənişli reklam etiketi gizlədilib</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">Ödənişli reklam etiketi gizlədilib</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">Ödənişli reklam etiketi göstərilir</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">Ödənişli reklam etiketi göstərilir</string>
|
||||||
@@ -1098,11 +1095,6 @@ Təqdim etməyə hazırdır?"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s saniyə</string>
|
<string name="revanced_sb_stats_saved_second_format">%s saniyə</string>
|
||||||
<string name="revanced_sb_color_opacity_label">Qeyri-şəffaflıq:</string>
|
<string name="revanced_sb_color_opacity_label">Qeyri-şəffaflıq:</string>
|
||||||
<string name="revanced_sb_color_dot_label">Rəng:</string>
|
<string name="revanced_sb_color_dot_label">Rəng:</string>
|
||||||
<string name="revanced_sb_color_changed">Rəng dəyişdirildi</string>
|
|
||||||
<string name="revanced_sb_color_reset">Rəngi sıfırla</string>
|
|
||||||
<string name="revanced_sb_color_invalid">Etibarsız rəng kodu</string>
|
|
||||||
<string name="revanced_sb_reset_color">Rəngi sıfırla</string>
|
|
||||||
<string name="revanced_sb_reset">Sıfırlayın</string>
|
|
||||||
<string name="revanced_sb_about_title">Haqqında</string>
|
<string name="revanced_sb_about_title">Haqqında</string>
|
||||||
<string name="revanced_sb_about_api_summary">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</string>
|
<string name="revanced_sb_about_api_summary">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</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">Налады</string>
|
<string name="revanced_settings_submenu_title">Налады</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">Вы хочаце працягнуць?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">Вы хочаце працягнуць?</string>
|
||||||
<string name="revanced_settings_reset">Скінуць</string>
|
<string name="revanced_settings_reset">Скінуць</string>
|
||||||
|
<string name="revanced_settings_reset_color">Скінуць колер</string>
|
||||||
|
<string name="revanced_settings_color_invalid">Несапраўдны колер</string>
|
||||||
<string name="revanced_settings_restart_title">Абнавіце і перазагрузіце</string>
|
<string name="revanced_settings_restart_title">Абнавіце і перазагрузіце</string>
|
||||||
<string name="revanced_settings_restart">Перазапуск</string>
|
<string name="revanced_settings_restart">Перазапуск</string>
|
||||||
<string name="revanced_settings_import">Імпарт</string>
|
<string name="revanced_settings_import">Імпарт</string>
|
||||||
@@ -365,9 +367,6 @@ Second \"item\" text"</string>
|
|||||||
|
|
||||||
Гэтая функцыя даступная толькі для старых прылад"</string>
|
Гэтая функцыя даступная толькі для старых прылад"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">Адлюстроўваецца поўнаэкранная рэклама</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">Адлюстроўваецца поўнаэкранная рэклама</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">Схаваць рэкламу на кнопках</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">Аб\"явы на кнопках схаваныя</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">Паказваюцца аб\"явы на кнопках</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Схаваць метку аплачанай акцыі</string>
|
<string name="revanced_hide_paid_promotion_label_title">Схаваць метку аплачанай акцыі</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">Пазнака платнай акцыі схавана</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">Пазнака платнай акцыі схавана</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">Адлюстроўваецца ярлык платнай акцыі</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">Адлюстроўваецца ярлык платнай акцыі</string>
|
||||||
@@ -1100,11 +1099,6 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s секунд</string>
|
<string name="revanced_sb_stats_saved_second_format">%s секунд</string>
|
||||||
<string name="revanced_sb_color_opacity_label">Непразрыстасць:</string>
|
<string name="revanced_sb_color_opacity_label">Непразрыстасць:</string>
|
||||||
<string name="revanced_sb_color_dot_label">колер:</string>
|
<string name="revanced_sb_color_dot_label">колер:</string>
|
||||||
<string name="revanced_sb_color_changed">Колер змяніўся</string>
|
|
||||||
<string name="revanced_sb_color_reset">Скід колеру</string>
|
|
||||||
<string name="revanced_sb_color_invalid">Няправільны код колеру</string>
|
|
||||||
<string name="revanced_sb_reset_color">Скінуць колер</string>
|
|
||||||
<string name="revanced_sb_reset">Скінуць</string>
|
|
||||||
<string name="revanced_sb_about_title">Пра праграму</string>
|
<string name="revanced_sb_about_title">Пра праграму</string>
|
||||||
<string name="revanced_sb_about_api_summary">Дадзеныя прадастаўляюцца API SponsorBlock. Націсніце тут, каб даведацца больш і паглядзець спампоўкі для іншых платформаў</string>
|
<string name="revanced_sb_about_api_summary">Дадзеныя прадастаўляюцца API SponsorBlock. Націсніце тут, каб даведацца больш і паглядзець спампоўкі для іншых платформаў</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">Настройки</string>
|
<string name="revanced_settings_submenu_title">Настройки</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">Искате ли да продължите?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">Искате ли да продължите?</string>
|
||||||
<string name="revanced_settings_reset">Възстанови</string>
|
<string name="revanced_settings_reset">Възстанови</string>
|
||||||
|
<string name="revanced_settings_reset_color">Нулиране на цвета</string>
|
||||||
|
<string name="revanced_settings_color_invalid">Невалиден цвят</string>
|
||||||
<string name="revanced_settings_restart_title">Рестартирай и опресни</string>
|
<string name="revanced_settings_restart_title">Рестартирай и опресни</string>
|
||||||
<string name="revanced_settings_restart">Рестартиране</string>
|
<string name="revanced_settings_restart">Рестартиране</string>
|
||||||
<string name="revanced_settings_import">Импортиране</string>
|
<string name="revanced_settings_import">Импортиране</string>
|
||||||
@@ -365,9 +367,6 @@ Second \"item\" text"</string>
|
|||||||
|
|
||||||
Тази функция е налична само за по-стари устройства"</string>
|
Тази функция е налична само за по-стари устройства"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">Рекламите в режим на цял екран са показани</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">Рекламите в режим на цял екран са показани</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">Скриване на рекламни бутони</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">Бутонираните реклами са скрити</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">Бутонираните реклами са показани</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Скриване на платените промоции</string>
|
<string name="revanced_hide_paid_promotion_label_title">Скриване на платените промоции</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">Промоционалните етикети са скрити</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">Промоционалните етикети са скрити</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">Промоционалните етикети се показват</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">Промоционалните етикети се показват</string>
|
||||||
@@ -1099,11 +1098,6 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s секунди</string>
|
<string name="revanced_sb_stats_saved_second_format">%s секунди</string>
|
||||||
<string name="revanced_sb_color_opacity_label">Непрозрачност:</string>
|
<string name="revanced_sb_color_opacity_label">Непрозрачност:</string>
|
||||||
<string name="revanced_sb_color_dot_label">Цвят:</string>
|
<string name="revanced_sb_color_dot_label">Цвят:</string>
|
||||||
<string name="revanced_sb_color_changed">Цветът е променен</string>
|
|
||||||
<string name="revanced_sb_color_reset">Възстанови цвета</string>
|
|
||||||
<string name="revanced_sb_color_invalid">Невалидна стойност за цвета</string>
|
|
||||||
<string name="revanced_sb_reset_color">Възстановяване на цвят</string>
|
|
||||||
<string name="revanced_sb_reset">Възстанови</string>
|
|
||||||
<string name="revanced_sb_about_title">За програмата</string>
|
<string name="revanced_sb_about_title">За програмата</string>
|
||||||
<string name="revanced_sb_about_api_summary">Данните са предоставени от SponsorBlock API. Докоснете тук за повече информация и изтеглияния</string>
|
<string name="revanced_sb_about_api_summary">Данните са предоставени от SponsorBlock API. Докоснете тук за повече информация и изтеглияния</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">সেটিংস</string>
|
<string name="revanced_settings_submenu_title">সেটিংস</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">আপনি কি এগিয়ে যেতে ইচ্ছুক?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">আপনি কি এগিয়ে যেতে ইচ্ছুক?</string>
|
||||||
<string name="revanced_settings_reset">আবার সেট করুন</string>
|
<string name="revanced_settings_reset">আবার সেট করুন</string>
|
||||||
|
<string name="revanced_settings_reset_color">রঙ রিসেট করুন</string>
|
||||||
|
<string name="revanced_settings_color_invalid">অবৈধ রঙ</string>
|
||||||
<string name="revanced_settings_restart_title">রিফ্রেশ করুন এবং আবার চালু করুন</string>
|
<string name="revanced_settings_restart_title">রিফ্রেশ করুন এবং আবার চালু করুন</string>
|
||||||
<string name="revanced_settings_restart">আবার চালু করুন</string>
|
<string name="revanced_settings_restart">আবার চালু করুন</string>
|
||||||
<string name="revanced_settings_import">আমদানি করুন</string>
|
<string name="revanced_settings_import">আমদানি করুন</string>
|
||||||
@@ -365,9 +367,6 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
|
|||||||
|
|
||||||
এই বৈশিষ্ট্যটি কেবল পুরনো ডিভাইসের জন্য উপলব্ধ"</string>
|
এই বৈশিষ্ট্যটি কেবল পুরনো ডিভাইসের জন্য উপলব্ধ"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">পূর্ণ স্ক্রীন বিজ্ঞাপন প্রদর্শিত হয়েছে</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">পূর্ণ স্ক্রীন বিজ্ঞাপন প্রদর্শিত হয়েছে</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">বোতামযুক্ত বিজ্ঞাপন লুকান</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">বোতামযুক্ত বিজ্ঞাপন লুকিয়ে রয়েছে</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">বোতামযুক্ত বিজ্ঞাপন প্রদর্শিত হয়েছে</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">অর্থের বিনিময়ে প্রচার অন্তর্ভুক্ত রয়েছে ব্যানার লুকান</string>
|
<string name="revanced_hide_paid_promotion_label_title">অর্থের বিনিময়ে প্রচার অন্তর্ভুক্ত রয়েছে ব্যানার লুকান</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">অর্থের বিনিময়ে প্রচার অন্তর্ভুক্ত রয়েছে ব্যানার লুকিয়ে রয়েছে</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">অর্থের বিনিময়ে প্রচার অন্তর্ভুক্ত রয়েছে ব্যানার লুকিয়ে রয়েছে</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">অর্থের বিনিময়ে প্রচার অন্তর্ভুক্ত রয়েছে ব্যানার প্রদর্শিত হয়েছে</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">অর্থের বিনিময়ে প্রচার অন্তর্ভুক্ত রয়েছে ব্যানার প্রদর্শিত হয়েছে</string>
|
||||||
@@ -1099,11 +1098,6 @@ YouTube সেটিংসে অটো প্লে পরিবর্তন
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s সেকেন্ড</string>
|
<string name="revanced_sb_stats_saved_second_format">%s সেকেন্ড</string>
|
||||||
<string name="revanced_sb_color_opacity_label">স্বচ্ছতা:</string>
|
<string name="revanced_sb_color_opacity_label">স্বচ্ছতা:</string>
|
||||||
<string name="revanced_sb_color_dot_label">রং:</string>
|
<string name="revanced_sb_color_dot_label">রং:</string>
|
||||||
<string name="revanced_sb_color_changed">রং পরিবর্তন করা হয়েছে</string>
|
|
||||||
<string name="revanced_sb_color_reset">রং আবার সেট করুন</string>
|
|
||||||
<string name="revanced_sb_color_invalid">রংয়ের ভুল কোড</string>
|
|
||||||
<string name="revanced_sb_reset_color">রং আবার সেট করুন</string>
|
|
||||||
<string name="revanced_sb_reset">পুনরায় সেট করুন</string>
|
|
||||||
<string name="revanced_sb_about_title">সম্পর্কিত</string>
|
<string name="revanced_sb_about_title">সম্পর্কিত</string>
|
||||||
<string name="revanced_sb_about_api_summary">ডেটা SponsorBlock API দ্বারা সরবরাহ করা হয়। আরও জানতে এবং অন্যান্য প্ল্যাটফর্মের ডাউনলোড দেখতে এখানে ট্যাপ করুন</string>
|
<string name="revanced_sb_about_api_summary">ডেটা SponsorBlock API দ্বারা সরবরাহ করা হয়। আরও জানতে এবং অন্যান্য প্ল্যাটফর্মের ডাউনলোড দেখতে এখানে ট্যাপ করুন</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">Configuració</string>
|
<string name="revanced_settings_submenu_title">Configuració</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">Vols continuar?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">Vols continuar?</string>
|
||||||
<string name="revanced_settings_reset">Restablir</string>
|
<string name="revanced_settings_reset">Restablir</string>
|
||||||
|
<string name="revanced_settings_reset_color">Restablir el color</string>
|
||||||
|
<string name="revanced_settings_color_invalid">Color no vàlid</string>
|
||||||
<string name="revanced_settings_restart_title">Actualitza i reinicia</string>
|
<string name="revanced_settings_restart_title">Actualitza i reinicia</string>
|
||||||
<string name="revanced_settings_restart">Reinicia</string>
|
<string name="revanced_settings_restart">Reinicia</string>
|
||||||
<string name="revanced_settings_import">Importa</string>
|
<string name="revanced_settings_import">Importa</string>
|
||||||
@@ -365,9 +367,6 @@ Limitacions
|
|||||||
|
|
||||||
Aquesta funció només està disponible per a dispositius antics"</string>
|
Aquesta funció només està disponible per a dispositius antics"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">Els anuncis de pantalla completa es mostren</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">Els anuncis de pantalla completa es mostren</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">Amaga els anuncis amb botó</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">Els anuncis amb botó estan amagats</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">Els anuncis amb botó es mostren</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Amaga l\'etiqueta de promoció de pagament</string>
|
<string name="revanced_hide_paid_promotion_label_title">Amaga l\'etiqueta de promoció de pagament</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">L\'etiqueta de promoció de pagament està amagada</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">L\'etiqueta de promoció de pagament està amagada</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">Es mostra l\'etiqueta de promoció de pagament</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">Es mostra l\'etiqueta de promoció de pagament</string>
|
||||||
@@ -1098,11 +1097,6 @@ Preparat per enviar?"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s segons</string>
|
<string name="revanced_sb_stats_saved_second_format">%s segons</string>
|
||||||
<string name="revanced_sb_color_opacity_label">Opacitat:</string>
|
<string name="revanced_sb_color_opacity_label">Opacitat:</string>
|
||||||
<string name="revanced_sb_color_dot_label">Color:</string>
|
<string name="revanced_sb_color_dot_label">Color:</string>
|
||||||
<string name="revanced_sb_color_changed">Color canviat</string>
|
|
||||||
<string name="revanced_sb_color_reset">Color restablert</string>
|
|
||||||
<string name="revanced_sb_color_invalid">Codi de color invàlid</string>
|
|
||||||
<string name="revanced_sb_reset_color">Restableix el color</string>
|
|
||||||
<string name="revanced_sb_reset">Restablir</string>
|
|
||||||
<string name="revanced_sb_about_title">Quant a</string>
|
<string name="revanced_sb_about_title">Quant a</string>
|
||||||
<string name="revanced_sb_about_api_summary">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</string>
|
<string name="revanced_sb_about_api_summary">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</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">Nastavení</string>
|
<string name="revanced_settings_submenu_title">Nastavení</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">Přejete si pokračovat?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">Přejete si pokračovat?</string>
|
||||||
<string name="revanced_settings_reset">Výchozí</string>
|
<string name="revanced_settings_reset">Výchozí</string>
|
||||||
|
<string name="revanced_settings_reset_color">Obnovit barvu</string>
|
||||||
|
<string name="revanced_settings_color_invalid">Neplatná barva</string>
|
||||||
<string name="revanced_settings_restart_title">Obnovit a restartovat</string>
|
<string name="revanced_settings_restart_title">Obnovit a restartovat</string>
|
||||||
<string name="revanced_settings_restart">Restartovat</string>
|
<string name="revanced_settings_restart">Restartovat</string>
|
||||||
<string name="revanced_settings_import">Importovat</string>
|
<string name="revanced_settings_import">Importovat</string>
|
||||||
@@ -365,9 +367,6 @@ Omezení:
|
|||||||
|
|
||||||
Tato funkce je dostupná pouze pro starší zařízení"</string>
|
Tato funkce je dostupná pouze pro starší zařízení"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">Celostránkové reklamy jsou zobrazeny</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">Celostránkové reklamy jsou zobrazeny</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">Skrýt reklamy s tlačítky</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">Reklamy s tlačítky jsou skryty</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">Reklamy s tlačítky jsou zobrazeny</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Skrýt štítek placené propagace</string>
|
<string name="revanced_hide_paid_promotion_label_title">Skrýt štítek placené propagace</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">Štítek placené propagace je skryt</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">Štítek placené propagace je skryt</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">Štítek placené propagace je zobrazen</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">Štítek placené propagace je zobrazen</string>
|
||||||
@@ -1098,11 +1097,6 @@ Jste připraveni k odeslání?"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s sekund</string>
|
<string name="revanced_sb_stats_saved_second_format">%s sekund</string>
|
||||||
<string name="revanced_sb_color_opacity_label">Průhlednost:</string>
|
<string name="revanced_sb_color_opacity_label">Průhlednost:</string>
|
||||||
<string name="revanced_sb_color_dot_label">Barva:</string>
|
<string name="revanced_sb_color_dot_label">Barva:</string>
|
||||||
<string name="revanced_sb_color_changed">Barva změněna</string>
|
|
||||||
<string name="revanced_sb_color_reset">Barva resetována</string>
|
|
||||||
<string name="revanced_sb_color_invalid">Neplatný kód barvy</string>
|
|
||||||
<string name="revanced_sb_reset_color">Resetovat barvu</string>
|
|
||||||
<string name="revanced_sb_reset">Výchozí</string>
|
|
||||||
<string name="revanced_sb_about_title">O aplikaci</string>
|
<string name="revanced_sb_about_title">O aplikaci</string>
|
||||||
<string name="revanced_sb_about_api_summary">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</string>
|
<string name="revanced_sb_about_api_summary">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</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">Indstillinger</string>
|
<string name="revanced_settings_submenu_title">Indstillinger</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">Ønsker du at fortsætte?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">Ønsker du at fortsætte?</string>
|
||||||
<string name="revanced_settings_reset">Nulstil</string>
|
<string name="revanced_settings_reset">Nulstil</string>
|
||||||
|
<string name="revanced_settings_reset_color">Nulstil farve</string>
|
||||||
|
<string name="revanced_settings_color_invalid">Ugyldig farve</string>
|
||||||
<string name="revanced_settings_restart_title">Opdater og genstart</string>
|
<string name="revanced_settings_restart_title">Opdater og genstart</string>
|
||||||
<string name="revanced_settings_restart">Genstart</string>
|
<string name="revanced_settings_restart">Genstart</string>
|
||||||
<string name="revanced_settings_import">Importer</string>
|
<string name="revanced_settings_import">Importer</string>
|
||||||
@@ -338,9 +340,6 @@ Begrænsninger
|
|||||||
|
|
||||||
Denne funktion er kun tilgængelig for ældre enheder"</string>
|
Denne funktion er kun tilgængelig for ældre enheder"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">Fuldskærms annoncer vises</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">Fuldskærms annoncer vises</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">Skjul knapfyldte annoncer</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">Knappede annoncer er skjult</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">Knappede annoncer vises</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Skjul betalt kampagneetiket</string>
|
<string name="revanced_hide_paid_promotion_label_title">Skjul betalt kampagneetiket</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">Betalt reklamemærke er skjult</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">Betalt reklamemærke er skjult</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">Betalt salgsfremmende mærke er vist</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">Betalt salgsfremmende mærke er vist</string>
|
||||||
@@ -1048,11 +1047,6 @@ Er du klar til at indsende?"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s sekunder</string>
|
<string name="revanced_sb_stats_saved_second_format">%s sekunder</string>
|
||||||
<string name="revanced_sb_color_opacity_label">Opacitet:</string>
|
<string name="revanced_sb_color_opacity_label">Opacitet:</string>
|
||||||
<string name="revanced_sb_color_dot_label">Farve:</string>
|
<string name="revanced_sb_color_dot_label">Farve:</string>
|
||||||
<string name="revanced_sb_color_changed">Farve ændret</string>
|
|
||||||
<string name="revanced_sb_color_reset">Nulstil farve</string>
|
|
||||||
<string name="revanced_sb_color_invalid">Ugyldig farvekode</string>
|
|
||||||
<string name="revanced_sb_reset_color">Nulstil farve</string>
|
|
||||||
<string name="revanced_sb_reset">Nulstil</string>
|
|
||||||
<string name="revanced_sb_about_title">Om</string>
|
<string name="revanced_sb_about_title">Om</string>
|
||||||
<string name="revanced_sb_about_api_summary">Data leveres af SponsorBlock API. Tryk her for at få flere oplysninger og se downloads til andre platforme</string>
|
<string name="revanced_sb_about_api_summary">Data leveres af SponsorBlock API. Tryk her for at få flere oplysninger og se downloads til andre platforme</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">Einstellungen</string>
|
<string name="revanced_settings_submenu_title">Einstellungen</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">Möchtest du fortfahren?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">Möchtest du fortfahren?</string>
|
||||||
<string name="revanced_settings_reset">Zurücksetzen</string>
|
<string name="revanced_settings_reset">Zurücksetzen</string>
|
||||||
|
<string name="revanced_settings_reset_color">Farbe zurücksetzen</string>
|
||||||
|
<string name="revanced_settings_color_invalid">Ungültige Farbe</string>
|
||||||
<string name="revanced_settings_restart_title">Aktualisieren und neu starten</string>
|
<string name="revanced_settings_restart_title">Aktualisieren und neu starten</string>
|
||||||
<string name="revanced_settings_restart">Neustart</string>
|
<string name="revanced_settings_restart">Neustart</string>
|
||||||
<string name="revanced_settings_import">Importieren</string>
|
<string name="revanced_settings_import">Importieren</string>
|
||||||
@@ -360,9 +362,6 @@ Einschränkungen
|
|||||||
|
|
||||||
Diese Funktion ist nur für ältere Geräte verfügbar"</string>
|
Diese Funktion ist nur für ältere Geräte verfügbar"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">Vollbild-Anzeigen werden angezeigt</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">Vollbild-Anzeigen werden angezeigt</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">Verknüpfte Werbung ausblenden</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">Verknüpfte Anzeigen sind ausgeblendet</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">Verknüpfte Werbung wird angezeigt</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Bezahltes Werbe-Label ausblenden</string>
|
<string name="revanced_hide_paid_promotion_label_title">Bezahltes Werbe-Label ausblenden</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">Bezahltes Werbelabel ist ausgeblendet</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">Bezahltes Werbelabel ist ausgeblendet</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">Bezahltes Werbe-Label wird angezeigt</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">Bezahltes Werbe-Label wird angezeigt</string>
|
||||||
@@ -1092,11 +1091,6 @@ Bereit zum Einreichen?"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s Sekunden</string>
|
<string name="revanced_sb_stats_saved_second_format">%s Sekunden</string>
|
||||||
<string name="revanced_sb_color_opacity_label">Deckkraft:</string>
|
<string name="revanced_sb_color_opacity_label">Deckkraft:</string>
|
||||||
<string name="revanced_sb_color_dot_label">Farbe:</string>
|
<string name="revanced_sb_color_dot_label">Farbe:</string>
|
||||||
<string name="revanced_sb_color_changed">Farbe geändert</string>
|
|
||||||
<string name="revanced_sb_color_reset">Farbe zurücksetzen</string>
|
|
||||||
<string name="revanced_sb_color_invalid">Ungültiger Farbcode</string>
|
|
||||||
<string name="revanced_sb_reset_color">Farbe zurücksetzen</string>
|
|
||||||
<string name="revanced_sb_reset">Zurücksetzen</string>
|
|
||||||
<string name="revanced_sb_about_title">Über</string>
|
<string name="revanced_sb_about_title">Über</string>
|
||||||
<string name="revanced_sb_about_api_summary">Daten werden von der SponsorBlock API bereitgestellt. Tippe hier, um mehr zu erfahren und Downloads für andere Plattformen zu sehen</string>
|
<string name="revanced_sb_about_api_summary">Daten werden von der SponsorBlock API bereitgestellt. Tippe hier, um mehr zu erfahren und Downloads für andere Plattformen zu sehen</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">Ρυθμίσεις</string>
|
<string name="revanced_settings_submenu_title">Ρυθμίσεις</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">Θέλετε να συνεχίσετε;</string>
|
<string name="revanced_settings_confirm_user_dialog_title">Θέλετε να συνεχίσετε;</string>
|
||||||
<string name="revanced_settings_reset">Επαναφορά</string>
|
<string name="revanced_settings_reset">Επαναφορά</string>
|
||||||
|
<string name="revanced_settings_reset_color">Επαναφορά χρώματος</string>
|
||||||
|
<string name="revanced_settings_color_invalid">Μη έγκυρο χρώμα</string>
|
||||||
<string name="revanced_settings_restart_title">Ανανέωση και επανεκκίνηση</string>
|
<string name="revanced_settings_restart_title">Ανανέωση και επανεκκίνηση</string>
|
||||||
<string name="revanced_settings_restart">Επανεκκίνηση</string>
|
<string name="revanced_settings_restart">Επανεκκίνηση</string>
|
||||||
<string name="revanced_settings_import">Εισαγωγή</string>
|
<string name="revanced_settings_import">Εισαγωγή</string>
|
||||||
@@ -367,9 +369,6 @@ Second \"item\" text"</string>
|
|||||||
|
|
||||||
Αυτή η λειτουργία είναι διαθέσιμη μόνο για παλιότερες συσκευές"</string>
|
Αυτή η λειτουργία είναι διαθέσιμη μόνο για παλιότερες συσκευές"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">Οι διαφημίσεις πλήρους οθόνης εμφανίζονται</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">Οι διαφημίσεις πλήρους οθόνης εμφανίζονται</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">Διαφημίσεις κουμπιών</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">Κρυμμένες</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">Εμφανίζονται</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Ετικέτες προώθησης επί πληρωμή</string>
|
<string name="revanced_hide_paid_promotion_label_title">Ετικέτες προώθησης επί πληρωμή</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">Κρυμμένες</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">Κρυμμένες</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">Εμφανίζονται</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">Εμφανίζονται</string>
|
||||||
@@ -1100,11 +1099,6 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s δευτερόλεπτα</string>
|
<string name="revanced_sb_stats_saved_second_format">%s δευτερόλεπτα</string>
|
||||||
<string name="revanced_sb_color_opacity_label">Αδιαφάνεια:</string>
|
<string name="revanced_sb_color_opacity_label">Αδιαφάνεια:</string>
|
||||||
<string name="revanced_sb_color_dot_label">Χρώμα:</string>
|
<string name="revanced_sb_color_dot_label">Χρώμα:</string>
|
||||||
<string name="revanced_sb_color_changed">Το χρώμα άλλαξε</string>
|
|
||||||
<string name="revanced_sb_color_reset">Το χρώμα επαναφέρθηκε</string>
|
|
||||||
<string name="revanced_sb_color_invalid">Μη έγκυρος κωδικός χρώματος</string>
|
|
||||||
<string name="revanced_sb_reset_color">Επαναφορά χρώματος</string>
|
|
||||||
<string name="revanced_sb_reset">Επαναφορά</string>
|
|
||||||
<string name="revanced_sb_about_title">Σχετικά με</string>
|
<string name="revanced_sb_about_title">Σχετικά με</string>
|
||||||
<string name="revanced_sb_about_api_summary">Τα δεδομένα παρέχονται από το SponsorBlock API. Πατήστε για να μάθετε περισσότερα και να δείτε λήψεις για άλλες πλατφόρμες</string>
|
<string name="revanced_sb_about_api_summary">Τα δεδομένα παρέχονται από το SponsorBlock API. Πατήστε για να μάθετε περισσότερα και να δείτε λήψεις για άλλες πλατφόρμες</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">Ajustes</string>
|
<string name="revanced_settings_submenu_title">Ajustes</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">¿Desea continuar?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">¿Desea continuar?</string>
|
||||||
<string name="revanced_settings_reset">Restablecer</string>
|
<string name="revanced_settings_reset">Restablecer</string>
|
||||||
|
<string name="revanced_settings_reset_color">Restablecer color</string>
|
||||||
|
<string name="revanced_settings_color_invalid">Color no válido</string>
|
||||||
<string name="revanced_settings_restart_title">Actualizar y reiniciar</string>
|
<string name="revanced_settings_restart_title">Actualizar y reiniciar</string>
|
||||||
<string name="revanced_settings_restart">Reiniciar</string>
|
<string name="revanced_settings_restart">Reiniciar</string>
|
||||||
<string name="revanced_settings_import">Importar</string>
|
<string name="revanced_settings_import">Importar</string>
|
||||||
@@ -362,9 +364,6 @@ Limitaciones
|
|||||||
|
|
||||||
Esta función solo está disponible para dispositivos antiguos"</string>
|
Esta función solo está disponible para dispositivos antiguos"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">Se muestran anuncios a pantalla completa</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">Se muestran anuncios a pantalla completa</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">Ocultar anuncios botonados</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">Los anuncios botonados están ocultos</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">Se muestran anuncios botonados</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Ocultar etiqueta de promoción de pago</string>
|
<string name="revanced_hide_paid_promotion_label_title">Ocultar etiqueta de promoción de pago</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">Etiqueta de promoción pagada está oculta</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">Etiqueta de promoción pagada está oculta</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">Etiqueta de promoción pagada se muestra</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">Etiqueta de promoción pagada se muestra</string>
|
||||||
@@ -1087,11 +1086,6 @@ Ya existe"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s segundos</string>
|
<string name="revanced_sb_stats_saved_second_format">%s segundos</string>
|
||||||
<string name="revanced_sb_color_opacity_label">Opacidad:</string>
|
<string name="revanced_sb_color_opacity_label">Opacidad:</string>
|
||||||
<string name="revanced_sb_color_dot_label">Color:</string>
|
<string name="revanced_sb_color_dot_label">Color:</string>
|
||||||
<string name="revanced_sb_color_changed">Color cambiado</string>
|
|
||||||
<string name="revanced_sb_color_reset">Restablecer color</string>
|
|
||||||
<string name="revanced_sb_color_invalid">Código de color inválido</string>
|
|
||||||
<string name="revanced_sb_reset_color">Reiniciar color</string>
|
|
||||||
<string name="revanced_sb_reset">Restablecer</string>
|
|
||||||
<string name="revanced_sb_about_title">Acerca de</string>
|
<string name="revanced_sb_about_title">Acerca de</string>
|
||||||
<string name="revanced_sb_about_api_summary">Los datos son proporcionados por la API de SponsorBlock. Pulsa aquí para aprender más y ver las descargas para otras plataformas</string>
|
<string name="revanced_sb_about_api_summary">Los datos son proporcionados por la API de SponsorBlock. Pulsa aquí para aprender más y ver las descargas para otras plataformas</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">Seaded</string>
|
<string name="revanced_settings_submenu_title">Seaded</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">Kas soovite jätkata?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">Kas soovite jätkata?</string>
|
||||||
<string name="revanced_settings_reset">Lähtesta</string>
|
<string name="revanced_settings_reset">Lähtesta</string>
|
||||||
|
<string name="revanced_settings_reset_color">Lähtesta värv</string>
|
||||||
|
<string name="revanced_settings_color_invalid">Vigane värv</string>
|
||||||
<string name="revanced_settings_restart_title">Värskenda ja taaskäivita</string>
|
<string name="revanced_settings_restart_title">Värskenda ja taaskäivita</string>
|
||||||
<string name="revanced_settings_restart">Taaskäivita</string>
|
<string name="revanced_settings_restart">Taaskäivita</string>
|
||||||
<string name="revanced_settings_import">Impordi</string>
|
<string name="revanced_settings_import">Impordi</string>
|
||||||
@@ -365,9 +367,6 @@ Piirangud
|
|||||||
|
|
||||||
See funktsioon on saadaval ainult vanemates seadmetes"</string>
|
See funktsioon on saadaval ainult vanemates seadmetes"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">Täisekraanireklaamid kuvatakse</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">Täisekraanireklaamid kuvatakse</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">Peida nuppudega reklaamid</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">Nuppudega reklaamid on peidetud</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">Nuked onukleitud reklaamid näidatakse</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Peida makstud edendamise silt</string>
|
<string name="revanced_hide_paid_promotion_label_title">Peida makstud edendamise silt</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">Makstud edendamise silt on peidus</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">Makstud edendamise silt on peidus</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">Makstud edendamise silt on näidatud</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">Makstud edendamise silt on näidatud</string>
|
||||||
@@ -1099,11 +1098,6 @@ Kas olete esitamiseks valmis?"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s sekundit</string>
|
<string name="revanced_sb_stats_saved_second_format">%s sekundit</string>
|
||||||
<string name="revanced_sb_color_opacity_label">Läbipaistmatus:</string>
|
<string name="revanced_sb_color_opacity_label">Läbipaistmatus:</string>
|
||||||
<string name="revanced_sb_color_dot_label">Värv:</string>
|
<string name="revanced_sb_color_dot_label">Värv:</string>
|
||||||
<string name="revanced_sb_color_changed">Värv muudetud</string>
|
|
||||||
<string name="revanced_sb_color_reset">Värv lähtestatud</string>
|
|
||||||
<string name="revanced_sb_color_invalid">Vigane värvikood</string>
|
|
||||||
<string name="revanced_sb_reset_color">Lähtesta värv</string>
|
|
||||||
<string name="revanced_sb_reset">Lähtesta</string>
|
|
||||||
<string name="revanced_sb_about_title">Teave</string>
|
<string name="revanced_sb_about_title">Teave</string>
|
||||||
<string name="revanced_sb_about_api_summary">Andmed on pärit SponsorBlock API-st. Puudutage siia, et saada lisateavet ja vaadata allalaadimisi teistele platvormidele</string>
|
<string name="revanced_sb_about_api_summary">Andmed on pärit SponsorBlock API-st. Puudutage siia, et saada lisateavet ja vaadata allalaadimisi teistele platvormidele</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -42,21 +42,48 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_import_reset">بازگرداندن تنظیمات ReVanced به پیشفرض</string>
|
<string name="revanced_settings_import_reset">بازگرداندن تنظیمات ReVanced به پیشفرض</string>
|
||||||
<string name="revanced_settings_import_success">%d تنظیمات وارد شدند</string>
|
<string name="revanced_settings_import_success">%d تنظیمات وارد شدند</string>
|
||||||
<string name="revanced_settings_import_failure_parse">واردکردن انجام نشد: %s</string>
|
<string name="revanced_settings_import_failure_parse">واردکردن انجام نشد: %s</string>
|
||||||
|
<string name="revanced_settings_search_hint">تنظیمات جستجو</string>
|
||||||
|
<string name="revanced_settings_search_no_results_title">نتایجی برای %s یافت نشد</string>
|
||||||
|
<string name="revanced_settings_search_no_results_summary">کلیدواژه دیگری را امتحان کنید</string>
|
||||||
|
<string name="revanced_settings_search_remove_message">حذف از تاریخچه جستجو؟</string>
|
||||||
|
<string name="revanced_show_menu_icons_title">نمایش آیکون تنظیمات ReVanced</string>
|
||||||
|
<string name="revanced_show_menu_icons_summary_on">نمادهای تنظیمات نشان داده میشوند</string>
|
||||||
|
<string name="revanced_show_menu_icons_summary_off">نمادهای تنظیمات نمایش داده نمی شوند</string>
|
||||||
<string name="revanced_language_title">زبان ReVanced</string>
|
<string name="revanced_language_title">زبان ReVanced</string>
|
||||||
|
<string name="revanced_language_DEFAULT">زبان برنامه</string>
|
||||||
|
<string name="revanced_pref_import_export_title">وارد کردن/صادر کردن</string>
|
||||||
|
<string name="revanced_pref_import_export_summary">وارد کردن / صادر کردن تنظیمات ReVanced</string>
|
||||||
<!-- Settings about dialog. -->
|
<!-- Settings about dialog. -->
|
||||||
|
<string name="revanced_settings_about_links_body">شما درحال استفاده از نسخه <i>%s</i> از پچ Revanced هستید</string>
|
||||||
|
<string name="revanced_settings_about_links_dev_header">توجه</string>
|
||||||
|
<string name="revanced_settings_about_links_header">لینکهای رسمی</string>
|
||||||
<!-- NOTE: the about strings above are duplicated in the TikTok about screen code,
|
<!-- NOTE: the about strings above are duplicated in the TikTok about screen code,
|
||||||
and changes made here must also be made there. -->
|
and changes made here must also be made there. -->
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||||
|
<string name="gms_core_toast_not_installed_message">MicroG GmsCore نصب نشده است. آنرا نصب کنید.</string>
|
||||||
|
<string name="gms_core_dialog_title">اقدام لازم است</string>
|
||||||
|
<string name="gms_core_dialog_open_website_text">باز کردن تارنما</string>
|
||||||
|
<string name="gms_core_dialog_continue_text">ادامه</string>
|
||||||
</patch>
|
</patch>
|
||||||
</app>
|
</app>
|
||||||
<app id="youtube">
|
<app id="youtube">
|
||||||
<patch id="misc.settings.settingsPatch">
|
<patch id="misc.settings.settingsPatch">
|
||||||
|
<string name="revanced_settings_screen_00_about_title">درباره</string>
|
||||||
|
<string name="revanced_settings_screen_04_general_title">عمومی</string>
|
||||||
|
<string name="revanced_settings_screen_05_player_title">اجراکننده</string>
|
||||||
|
<string name="revanced_settings_screen_07_seekbar_title">نوار جریان پخش</string>
|
||||||
|
<string name="revanced_settings_screen_12_video_title">ويدئو</string>
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="misc.backgroundplayback.backgroundPlaybackPatch">
|
<patch id="misc.backgroundplayback.backgroundPlaybackPatch">
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="misc.debugging.enableDebuggingPatch">
|
<patch id="misc.debugging.enableDebuggingPatch">
|
||||||
|
<string name="revanced_debug_screen_title">عیبیابی</string>
|
||||||
|
<string name="revanced_debug_screen_summary">فعال یا غیرفعال کردن گزینههای عیب یابی</string>
|
||||||
|
<string name="revanced_debug_title">گزارش عیب</string>
|
||||||
|
<string name="revanced_debug_summary_on">لاگ عیب فعال است</string>
|
||||||
|
<string name="revanced_debug_summary_off">لاگ عیب غیرفعال است</string>
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="layout.hide.general.hideLayoutComponentsPatch">
|
<patch id="layout.hide.general.hideLayoutComponentsPatch">
|
||||||
<!-- 'Join' should be translated using the same localized wording YouTube displays.
|
<!-- 'Join' should be translated using the same localized wording YouTube displays.
|
||||||
@@ -67,6 +94,10 @@ Second \"item\" text"</string>
|
|||||||
<!-- 'People also watched' and 'You might also like' should be translated using the same localized wording YouTube displays. -->
|
<!-- 'People also watched' and 'You might also like' should be translated using the same localized wording YouTube displays. -->
|
||||||
<!-- 'Show more' should be translated with the same localized wording that YouTube displays.
|
<!-- 'Show more' should be translated with the same localized wording that YouTube displays.
|
||||||
This button usually appears when searching for a YT creator. -->
|
This button usually appears when searching for a YT creator. -->
|
||||||
|
<string name="revanced_hide_show_more_button_title">پنهان سازی دکمه \'نمایش بیشتر\'</string>
|
||||||
|
<string name="revanced_hide_show_more_button_summary_on">دکمه پنهان است</string>
|
||||||
|
<string name="revanced_hide_show_more_button_summary_off">دکمه نمایان است</string>
|
||||||
|
<string name="revanced_hide_ticket_shelf_title">پنهان سازی قفسه بلیط</string>
|
||||||
<!-- https://logos.fandom.com/wiki/YouTube/Yoodles -->
|
<!-- https://logos.fandom.com/wiki/YouTube/Yoodles -->
|
||||||
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
|
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
|
||||||
<!-- For localization, it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word.
|
<!-- For localization, it is preferred, but not required, if 'LeBlanc' is replaced with a localized name or a familiar word that has upper case letters in the middle of the word.
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">Asetukset</string>
|
<string name="revanced_settings_submenu_title">Asetukset</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">Haluatko jatkaa?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">Haluatko jatkaa?</string>
|
||||||
<string name="revanced_settings_reset">Nollaa</string>
|
<string name="revanced_settings_reset">Nollaa</string>
|
||||||
|
<string name="revanced_settings_reset_color">Nollaa väri</string>
|
||||||
<string name="revanced_settings_restart_title">Päivitä ja käynnistä uudelleen</string>
|
<string name="revanced_settings_restart_title">Päivitä ja käynnistä uudelleen</string>
|
||||||
<string name="revanced_settings_restart">Käynnistä uudelleen</string>
|
<string name="revanced_settings_restart">Käynnistä uudelleen</string>
|
||||||
<string name="revanced_settings_import">Tuo</string>
|
<string name="revanced_settings_import">Tuo</string>
|
||||||
@@ -360,9 +361,6 @@ Rajoitukset
|
|||||||
|
|
||||||
Tämä ominaisuus on käytettävissä vain vanhemmilla laitteilla"</string>
|
Tämä ominaisuus on käytettävissä vain vanhemmilla laitteilla"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">Koko näytön mainokset näytetään</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">Koko näytön mainokset näytetään</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">Piilota painikkeelliset mainokset</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">Painikkeelliset mainokset on piilotettu</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">Painikkeelliset mainokset näytetään</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Piilota maksetun mainostuksen tunniste</string>
|
<string name="revanced_hide_paid_promotion_label_title">Piilota maksetun mainostuksen tunniste</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">Maksetun mainostuksen tunniste on piilotettu</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">Maksetun mainostuksen tunniste on piilotettu</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">Maksetun mainostuksen tunniste näytetään</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">Maksetun mainostuksen tunniste näytetään</string>
|
||||||
@@ -1091,11 +1089,6 @@ Oletko valmis lähettämään?"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s sekuntia</string>
|
<string name="revanced_sb_stats_saved_second_format">%s sekuntia</string>
|
||||||
<string name="revanced_sb_color_opacity_label">Läpikuultamattomuus:</string>
|
<string name="revanced_sb_color_opacity_label">Läpikuultamattomuus:</string>
|
||||||
<string name="revanced_sb_color_dot_label">Väri:</string>
|
<string name="revanced_sb_color_dot_label">Väri:</string>
|
||||||
<string name="revanced_sb_color_changed">Väri vaihdettu</string>
|
|
||||||
<string name="revanced_sb_color_reset">Väri nollattu</string>
|
|
||||||
<string name="revanced_sb_color_invalid">Virheellinen värikoodi</string>
|
|
||||||
<string name="revanced_sb_reset_color">Nollaa väri</string>
|
|
||||||
<string name="revanced_sb_reset">Nollaa</string>
|
|
||||||
<string name="revanced_sb_about_title">Tietoja</string>
|
<string name="revanced_sb_about_title">Tietoja</string>
|
||||||
<string name="revanced_sb_about_api_summary">Tiedot tarjoaa SponsorBlock API. Napauta tätä saadaksesi lisätietoja ja nähdäksesi lataukset muille alustoille</string>
|
<string name="revanced_sb_about_api_summary">Tiedot tarjoaa SponsorBlock API. Napauta tätä saadaksesi lisätietoja ja nähdäksesi lataukset muille alustoille</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">Mga Setting</string>
|
<string name="revanced_settings_submenu_title">Mga Setting</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">Gusto mo bang magpatuloy?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">Gusto mo bang magpatuloy?</string>
|
||||||
<string name="revanced_settings_reset">I-reset</string>
|
<string name="revanced_settings_reset">I-reset</string>
|
||||||
|
<string name="revanced_settings_reset_color">I-reset ang kulay</string>
|
||||||
|
<string name="revanced_settings_color_invalid">Hindi wasto ang kulay</string>
|
||||||
<string name="revanced_settings_restart_title">I-refresh at i-restart</string>
|
<string name="revanced_settings_restart_title">I-refresh at i-restart</string>
|
||||||
<string name="revanced_settings_restart">I-restart</string>
|
<string name="revanced_settings_restart">I-restart</string>
|
||||||
<string name="revanced_settings_import">Angkat</string>
|
<string name="revanced_settings_import">Angkat</string>
|
||||||
@@ -365,9 +367,6 @@ Mga limitasyon
|
|||||||
|
|
||||||
Ang tampok na ito ay magagamit lamang para sa mga mas lumang device"</string>
|
Ang tampok na ito ay magagamit lamang para sa mga mas lumang device"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">Ipinapakita ang mga fullscreen na ad</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">Ipinapakita ang mga fullscreen na ad</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">Itago ang mga naka-button na ad</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">Nakatago ang mga naka-button na ad</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">Ipinapakita ang mga naka-button na ad</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Itago ang may bayad na label ng promosyon</string>
|
<string name="revanced_hide_paid_promotion_label_title">Itago ang may bayad na label ng promosyon</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">Nakatago ang label ng bayad na promosyon</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">Nakatago ang label ng bayad na promosyon</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">Ipinapakita ang may bayad na label ng promosyon</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">Ipinapakita ang may bayad na label ng promosyon</string>
|
||||||
@@ -1097,11 +1096,6 @@ Isumite na ba?"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s segundo</string>
|
<string name="revanced_sb_stats_saved_second_format">%s segundo</string>
|
||||||
<string name="revanced_sb_color_opacity_label">Opacity:</string>
|
<string name="revanced_sb_color_opacity_label">Opacity:</string>
|
||||||
<string name="revanced_sb_color_dot_label">Kulay:</string>
|
<string name="revanced_sb_color_dot_label">Kulay:</string>
|
||||||
<string name="revanced_sb_color_changed">Nagbago ang kulay</string>
|
|
||||||
<string name="revanced_sb_color_reset">Pag-reset ng kulay</string>
|
|
||||||
<string name="revanced_sb_color_invalid">Di-wastong code ng kulay</string>
|
|
||||||
<string name="revanced_sb_reset_color">I-reset ang kulay</string>
|
|
||||||
<string name="revanced_sb_reset">I-reset</string>
|
|
||||||
<string name="revanced_sb_about_title">Tungkol</string>
|
<string name="revanced_sb_about_title">Tungkol</string>
|
||||||
<string name="revanced_sb_about_api_summary">Ang data ay ibinibigay ng SponsorBlock API. Mag-tap dito para matuto pa at makakita ng mga download para sa iba pang platform</string>
|
<string name="revanced_sb_about_api_summary">Ang data ay ibinibigay ng SponsorBlock API. Mag-tap dito para matuto pa at makakita ng mga download para sa iba pang platform</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">Paramètres</string>
|
<string name="revanced_settings_submenu_title">Paramètres</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">Voulez-vous continuer ?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">Voulez-vous continuer ?</string>
|
||||||
<string name="revanced_settings_reset">Réinitialiser</string>
|
<string name="revanced_settings_reset">Réinitialiser</string>
|
||||||
|
<string name="revanced_settings_reset_color">Réinitialiser la couleur</string>
|
||||||
|
<string name="revanced_settings_color_invalid">Couleur invalide</string>
|
||||||
<string name="revanced_settings_restart_title">Actualiser et redémarrer</string>
|
<string name="revanced_settings_restart_title">Actualiser et redémarrer</string>
|
||||||
<string name="revanced_settings_restart">Redémarrer</string>
|
<string name="revanced_settings_restart">Redémarrer</string>
|
||||||
<string name="revanced_settings_import">Importer</string>
|
<string name="revanced_settings_import">Importer</string>
|
||||||
@@ -42,8 +44,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_import_reset">Paramètres ReVanced réinitialisés aux valeurs par défaut</string>
|
<string name="revanced_settings_import_reset">Paramètres ReVanced réinitialisés aux valeurs par défaut</string>
|
||||||
<string name="revanced_settings_import_success">%d paramètres importés</string>
|
<string name="revanced_settings_import_success">%d paramètres importés</string>
|
||||||
<string name="revanced_settings_import_failure_parse">Importation échouée : %s</string>
|
<string name="revanced_settings_import_failure_parse">Importation échouée : %s</string>
|
||||||
<string name="revanced_settings_search_hint">Paramètres de recherche</string>
|
<string name="revanced_settings_search_hint">Rechercher dans les paramètres</string>
|
||||||
<string name="revanced_settings_search_no_results_title">Aucun résultat trouvé pour \".%s\".</string>
|
<string name="revanced_settings_search_no_results_title">Aucun résultat trouvé pour \"%s\"</string>
|
||||||
<string name="revanced_settings_search_no_results_summary">Essayez un autre mot-clé</string>
|
<string name="revanced_settings_search_no_results_summary">Essayez un autre mot-clé</string>
|
||||||
<string name="revanced_settings_search_remove_message">Supprimer de l\'historique des recherches ?</string>
|
<string name="revanced_settings_search_remove_message">Supprimer de l\'historique des recherches ?</string>
|
||||||
<string name="revanced_show_menu_icons_title">Afficher les icônes des paramètres ReVanced</string>
|
<string name="revanced_show_menu_icons_title">Afficher les icônes des paramètres ReVanced</string>
|
||||||
@@ -169,9 +171,9 @@ Vous ne serez pas informé des événements inattendus."</string>
|
|||||||
<string name="revanced_hide_show_more_button_title">Masquer le bouton Afficher plus</string>
|
<string name="revanced_hide_show_more_button_title">Masquer le bouton Afficher plus</string>
|
||||||
<string name="revanced_hide_show_more_button_summary_on">Le bouton est masqué</string>
|
<string name="revanced_hide_show_more_button_summary_on">Le bouton est masqué</string>
|
||||||
<string name="revanced_hide_show_more_button_summary_off">Le bouton est affiché</string>
|
<string name="revanced_hide_show_more_button_summary_off">Le bouton est affiché</string>
|
||||||
<string name="revanced_hide_ticket_shelf_title">Masquer le rayon de billets</string>
|
<string name="revanced_hide_ticket_shelf_title">Masquer l\'étagère des billets</string>
|
||||||
<string name="revanced_hide_ticket_shelf_summary_on">Le rayon de billets est masqué</string>
|
<string name="revanced_hide_ticket_shelf_summary_on">L\'étagère des billets est masquée</string>
|
||||||
<string name="revanced_hide_ticket_shelf_summary_off">Le rayon de billets est affiché</string>
|
<string name="revanced_hide_ticket_shelf_summary_off">L\'étagère des billets est affichée</string>
|
||||||
<string name="revanced_hide_timed_reactions_title">Masquer les réactions minutées</string>
|
<string name="revanced_hide_timed_reactions_title">Masquer les réactions minutées</string>
|
||||||
<string name="revanced_hide_timed_reactions_summary_on">Les réactions minutées sont masquées</string>
|
<string name="revanced_hide_timed_reactions_summary_on">Les réactions minutées sont masquées</string>
|
||||||
<string name="revanced_hide_timed_reactions_summary_off">Les réactions minutées sont affichées</string>
|
<string name="revanced_hide_timed_reactions_summary_off">Les réactions minutées sont affichées</string>
|
||||||
@@ -241,9 +243,9 @@ Vous ne serez pas informé des événements inattendus."</string>
|
|||||||
<string name="revanced_hide_ai_generated_video_summary_section_title">Masquer \"Résumé de la vidéo généré par IA\"</string>
|
<string name="revanced_hide_ai_generated_video_summary_section_title">Masquer \"Résumé de la vidéo généré par IA\"</string>
|
||||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">La section du résumé de la vidéo est masquée</string>
|
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">La section du résumé de la vidéo est masquée</string>
|
||||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">La section du résumé de la vidéo est affichée</string>
|
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">La section du résumé de la vidéo est affichée</string>
|
||||||
<string name="revanced_hide_ask_section_title">Masquer la section \"Demander\"</string>
|
<string name="revanced_hide_ask_section_title">Masquer \"Demander\"</string>
|
||||||
<string name="revanced_hide_ask_section_summary_on">La section \"Demander\" est masquée</string>
|
<string name="revanced_hide_ask_section_summary_on">La section Demander est masquée</string>
|
||||||
<string name="revanced_hide_ask_section_summary_off">La section \"Demander\" est affichée</string>
|
<string name="revanced_hide_ask_section_summary_off">La section Demander est affichée</string>
|
||||||
<string name="revanced_hide_attributes_section_title">Masquer les attributions</string>
|
<string name="revanced_hide_attributes_section_title">Masquer les attributions</string>
|
||||||
<string name="revanced_hide_attributes_section_summary_on">Les sections Lieux mentionnés, Jeux, Musique et Personnes mentionnées sont masquées</string>
|
<string name="revanced_hide_attributes_section_summary_on">Les sections Lieux mentionnés, Jeux, Musique et Personnes mentionnées sont masquées</string>
|
||||||
<string name="revanced_hide_attributes_section_summary_off">Les sections Lieux mentionnés, Jeux, Musique et Personnes mentionnées sont affichées</string>
|
<string name="revanced_hide_attributes_section_summary_off">Les sections Lieux mentionnés, Jeux, Musique et Personnes mentionnées sont affichées</string>
|
||||||
@@ -365,9 +367,6 @@ Limitations
|
|||||||
|
|
||||||
Cette fonctionnalité est disponible uniquement pour les appareils anciens"</string>
|
Cette fonctionnalité est disponible uniquement pour les appareils anciens"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">Les annonces plein écran sont affichées</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">Les annonces plein écran sont affichées</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">Masquer les annonces au format bouton</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">Les annonces au format bouton sont masquées</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">Les annonces au format bouton sont affichées</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Masquer la bannière de promotion rémunérée</string>
|
<string name="revanced_hide_paid_promotion_label_title">Masquer la bannière de promotion rémunérée</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">La bannière \"Inclut une promotion rémunérée\" est masquée</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">La bannière \"Inclut une promotion rémunérée\" est masquée</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">La bannière \"Inclut une promotion rémunérée\" est affichée</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">La bannière \"Inclut une promotion rémunérée\" est affichée</string>
|
||||||
@@ -1098,11 +1097,6 @@ Prêt à soumettre ?"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s secondes</string>
|
<string name="revanced_sb_stats_saved_second_format">%s secondes</string>
|
||||||
<string name="revanced_sb_color_opacity_label">Opacité :</string>
|
<string name="revanced_sb_color_opacity_label">Opacité :</string>
|
||||||
<string name="revanced_sb_color_dot_label">Couleur :</string>
|
<string name="revanced_sb_color_dot_label">Couleur :</string>
|
||||||
<string name="revanced_sb_color_changed">Couleur modifiée</string>
|
|
||||||
<string name="revanced_sb_color_reset">Couleur réinitialisée</string>
|
|
||||||
<string name="revanced_sb_color_invalid">Code couleur invalide</string>
|
|
||||||
<string name="revanced_sb_reset_color">Réinitialiser la couleur</string>
|
|
||||||
<string name="revanced_sb_reset">Réinitialiser</string>
|
|
||||||
<string name="revanced_sb_about_title">À propos</string>
|
<string name="revanced_sb_about_title">À propos</string>
|
||||||
<string name="revanced_sb_about_api_summary">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.</string>
|
<string name="revanced_sb_about_api_summary">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.</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">Socruithe</string>
|
<string name="revanced_settings_submenu_title">Socruithe</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">Ar mhaith leat dul ar aghaidh?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">Ar mhaith leat dul ar aghaidh?</string>
|
||||||
<string name="revanced_settings_reset">Athshocraigh</string>
|
<string name="revanced_settings_reset">Athshocraigh</string>
|
||||||
|
<string name="revanced_settings_reset_color">Dath a athshocrú</string>
|
||||||
|
<string name="revanced_settings_color_invalid">Dath neamhbhailí</string>
|
||||||
<string name="revanced_settings_restart_title">Athnuachan agus atosaigh</string>
|
<string name="revanced_settings_restart_title">Athnuachan agus atosaigh</string>
|
||||||
<string name="revanced_settings_restart">Athosaigh</string>
|
<string name="revanced_settings_restart">Athosaigh</string>
|
||||||
<string name="revanced_settings_import">Iompórtáil</string>
|
<string name="revanced_settings_import">Iompórtáil</string>
|
||||||
@@ -162,8 +164,8 @@ Ní chuirfear ar an eolas thú faoi aon imeachtaí gan choinne."</string>
|
|||||||
<string name="revanced_hide_notify_me_button_summary_off">Taispeántar an cnaipe</string>
|
<string name="revanced_hide_notify_me_button_summary_off">Taispeántar an cnaipe</string>
|
||||||
<!-- 'People also watched' and 'You might also like' should be translated using the same localized wording YouTube displays. -->
|
<!-- 'People also watched' and 'You might also like' should be translated using the same localized wording YouTube displays. -->
|
||||||
<string name="revanced_hide_search_result_recommendation_labels_title">Folaigh lipéid moltaí físeáin</string>
|
<string name="revanced_hide_search_result_recommendation_labels_title">Folaigh lipéid moltaí físeáin</string>
|
||||||
<string name="revanced_hide_search_result_recommendation_labels_summary_on">Tá lipéid \",,D’fhéach daoine eile air freisin\",, agus \",,B’fhéidir gur mhaith leat é seo freisin\",, folaithe</string>
|
<string name="revanced_hide_search_result_recommendation_labels_summary_on">Tá na lipéid \'Daoine a d\'fhéach orthu freisin\' agus \'B\'fhéidir gur mhaith leat freisin\' i bhfolach</string>
|
||||||
<string name="revanced_hide_search_result_recommendation_labels_summary_off">Tá lipéid \",,D’fhéach daoine eile air freisin\",, agus \",,B’fhéidir gur mhaith leat é seo freisin\",, ar taispeáint</string>
|
<string name="revanced_hide_search_result_recommendation_labels_summary_off">Taispeántar lipéid ‘Daoine a d’fhéach freisin’ agus ‘B’fhéidir gur mhaith leat freisin’</string>
|
||||||
<!-- 'Show more' should be translated with the same localized wording that YouTube displays.
|
<!-- 'Show more' should be translated with the same localized wording that YouTube displays.
|
||||||
This button usually appears when searching for a YT creator. -->
|
This button usually appears when searching for a YT creator. -->
|
||||||
<string name="revanced_hide_show_more_button_title">Folaigh cnaipe \'Taispeáin tuilleadh\'</string>
|
<string name="revanced_hide_show_more_button_title">Folaigh cnaipe \'Taispeáin tuilleadh\'</string>
|
||||||
@@ -263,8 +265,8 @@ Ní chuirfear ar an eolas thú faoi aon imeachtaí gan choinne."</string>
|
|||||||
<string name="revanced_hide_key_concepts_section_summary_on">Tá an chuid Príomhchoincheapa i bhfolach</string>
|
<string name="revanced_hide_key_concepts_section_summary_on">Tá an chuid Príomhchoincheapa i bhfolach</string>
|
||||||
<string name="revanced_hide_key_concepts_section_summary_off">Taispeántar an chuid Príomhchoincheapa</string>
|
<string name="revanced_hide_key_concepts_section_summary_off">Taispeántar an chuid Príomhchoincheapa</string>
|
||||||
<string name="revanced_hide_transcript_section_title">Folaigh Tras-scríbhinn</string>
|
<string name="revanced_hide_transcript_section_title">Folaigh Tras-scríbhinn</string>
|
||||||
<string name="revanced_hide_transcript_section_summary_on">Tá an chuid trasscríbhinne i bhfolach</string>
|
<string name="revanced_hide_transcript_section_summary_on">Tá alt an tras-scríbhinn i bhfolach</string>
|
||||||
<string name="revanced_hide_transcript_section_summary_off">Taispeántar alt an trasscríbhinne</string>
|
<string name="revanced_hide_transcript_section_summary_off">Taispeántar alt an tras-scríbhinn</string>
|
||||||
<string name="revanced_hide_description_components_screen_title">Cur síos físeán</string>
|
<string name="revanced_hide_description_components_screen_title">Cur síos físeán</string>
|
||||||
<string name="revanced_hide_description_components_screen_summary">Folaigh nó taispeáint comhpháirteanna tuairisc</string>
|
<string name="revanced_hide_description_components_screen_summary">Folaigh nó taispeáint comhpháirteanna tuairisc</string>
|
||||||
<string name="revanced_hide_filter_bar_screen_title">Barra scagaire</string>
|
<string name="revanced_hide_filter_bar_screen_title">Barra scagaire</string>
|
||||||
@@ -278,8 +280,8 @@ Ní chuirfear ar an eolas thú faoi aon imeachtaí gan choinne."</string>
|
|||||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_title">Folaigh i bhfíseáin gaolmhara</string>
|
<string name="revanced_hide_filter_bar_feed_in_related_videos_title">Folaigh i bhfíseáin gaolmhara</string>
|
||||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">I bhfolach i bhfíseáin ghaolmhara</string>
|
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_on">I bhfolach i bhfíseáin ghaolmhara</string>
|
||||||
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">Taispeántar i bhfíseáin ghaolmhara</string>
|
<string name="revanced_hide_filter_bar_feed_in_related_videos_summary_off">Taispeántar i bhfíseáin ghaolmhara</string>
|
||||||
<string name="revanced_comments_screen_title">Tuairimí</string>
|
<string name="revanced_comments_screen_title">Tráchtanna</string>
|
||||||
<string name="revanced_comments_screen_summary">Folaigh nó taispeáin comhpháirteanna na rannóige tuairimí</string>
|
<string name="revanced_comments_screen_summary">Folaigh nó taispeáin comhpháirteanna na rannóige tráchtanna</string>
|
||||||
<string name="revanced_hide_comments_ai_chat_summary_title">Folaigh achoimre Comhrá AI</string>
|
<string name="revanced_hide_comments_ai_chat_summary_title">Folaigh achoimre Comhrá AI</string>
|
||||||
<string name="revanced_hide_comments_ai_chat_summary_summary_on">Tá achoimre comhrá i bhfolach</string>
|
<string name="revanced_hide_comments_ai_chat_summary_summary_on">Tá achoimre comhrá i bhfolach</string>
|
||||||
<string name="revanced_hide_comments_ai_chat_summary_summary_off">Taispeántar achoimre comhrá</string>
|
<string name="revanced_hide_comments_ai_chat_summary_summary_off">Taispeántar achoimre comhrá</string>
|
||||||
@@ -365,9 +367,6 @@ Teorainneacha
|
|||||||
|
|
||||||
Níl an ghné seo ar fáil ach do ghléasanna níos sine"</string>
|
Níl an ghné seo ar fáil ach do ghléasanna níos sine"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">Taispeántar fógraí lánscáileáin</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">Taispeántar fógraí lánscáileáin</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">Folaigh fógraí cnaipe</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">Tá fógraí cnaipe i bhfolach</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">Taispeántar fógraí cnaipe</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Folaigh lipéad chun cinn íoctha</string>
|
<string name="revanced_hide_paid_promotion_label_title">Folaigh lipéad chun cinn íoctha</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">Tá an lipéad promóisin íoctha i bhfolach</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">Tá an lipéad promóisin íoctha i bhfolach</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">Taispeántar lipéad promóisin íoctha</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">Taispeántar lipéad promóisin íoctha</string>
|
||||||
@@ -1099,11 +1098,6 @@ Maithe chun cur isteach?"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s soicindí</string>
|
<string name="revanced_sb_stats_saved_second_format">%s soicindí</string>
|
||||||
<string name="revanced_sb_color_opacity_label">Teimhneacht:</string>
|
<string name="revanced_sb_color_opacity_label">Teimhneacht:</string>
|
||||||
<string name="revanced_sb_color_dot_label">Dath:</string>
|
<string name="revanced_sb_color_dot_label">Dath:</string>
|
||||||
<string name="revanced_sb_color_changed">Athraigh dath</string>
|
|
||||||
<string name="revanced_sb_color_reset">Athshocrú dath</string>
|
|
||||||
<string name="revanced_sb_color_invalid">Cód dath neamhbhailí</string>
|
|
||||||
<string name="revanced_sb_reset_color">Athshocraigh dath</string>
|
|
||||||
<string name="revanced_sb_reset">Athshocraigh</string>
|
|
||||||
<string name="revanced_sb_about_title">Maidir</string>
|
<string name="revanced_sb_about_title">Maidir</string>
|
||||||
<string name="revanced_sb_about_api_summary">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</string>
|
<string name="revanced_sb_about_api_summary">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</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">Beállítások</string>
|
<string name="revanced_settings_submenu_title">Beállítások</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">Szeretné folytatni?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">Szeretné folytatni?</string>
|
||||||
<string name="revanced_settings_reset">Visszaállítás</string>
|
<string name="revanced_settings_reset">Visszaállítás</string>
|
||||||
|
<string name="revanced_settings_reset_color">Szín alaphelyzetbe állítása</string>
|
||||||
|
<string name="revanced_settings_color_invalid">Érvénytelen szín</string>
|
||||||
<string name="revanced_settings_restart_title">Frissítés és újraindítás</string>
|
<string name="revanced_settings_restart_title">Frissítés és újraindítás</string>
|
||||||
<string name="revanced_settings_restart">Újraindítás</string>
|
<string name="revanced_settings_restart">Újraindítás</string>
|
||||||
<string name="revanced_settings_import">Importálás</string>
|
<string name="revanced_settings_import">Importálás</string>
|
||||||
@@ -365,9 +367,6 @@ Korlátozások
|
|||||||
|
|
||||||
Ez a funkció csak régebbi eszközökön érhető el"</string>
|
Ez a funkció csak régebbi eszközökön érhető el"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">A teljes képernyős hirdetések láthatók</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">A teljes képernyős hirdetések láthatók</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">Gomb hirdetések elrejtése</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">A gomb hirdetések el vannak rejtve</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">A gomb hirdetések láthatók</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Fizetett promóció címke elrejtése</string>
|
<string name="revanced_hide_paid_promotion_label_title">Fizetett promóció címke elrejtése</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">A fizetett promóciós címke el van rejtve</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">A fizetett promóciós címke el van rejtve</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">A fizetett promóciós címke meg van jelenítve</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">A fizetett promóciós címke meg van jelenítve</string>
|
||||||
@@ -1098,11 +1097,6 @@ Készen állsz a beküldésre?"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s másodperc</string>
|
<string name="revanced_sb_stats_saved_second_format">%s másodperc</string>
|
||||||
<string name="revanced_sb_color_opacity_label">Áttetszőség:</string>
|
<string name="revanced_sb_color_opacity_label">Áttetszőség:</string>
|
||||||
<string name="revanced_sb_color_dot_label">Szín:</string>
|
<string name="revanced_sb_color_dot_label">Szín:</string>
|
||||||
<string name="revanced_sb_color_changed">A szín megváltoztatva</string>
|
|
||||||
<string name="revanced_sb_color_reset">Szín alaphelyzetbe</string>
|
|
||||||
<string name="revanced_sb_color_invalid">Érvénytelen színkód</string>
|
|
||||||
<string name="revanced_sb_reset_color">Színek visszaállítása</string>
|
|
||||||
<string name="revanced_sb_reset">Visszaállítás</string>
|
|
||||||
<string name="revanced_sb_about_title">Rólunk</string>
|
<string name="revanced_sb_about_title">Rólunk</string>
|
||||||
<string name="revanced_sb_about_api_summary">Az adatokat a SponsorBlock API biztosítja. Koppintson ide, ha többet szeretne megtudni és megtekintené a letöltéseket más platformokra</string>
|
<string name="revanced_sb_about_api_summary">Az adatokat a SponsorBlock API biztosítja. Koppintson ide, ha többet szeretne megtudni és megtekintené a letöltéseket más platformokra</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">Կարգավորումներ</string>
|
<string name="revanced_settings_submenu_title">Կարգավորումներ</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">Դուք ցանկանում եք շարունակել?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">Դուք ցանկանում եք շարունակել?</string>
|
||||||
<string name="revanced_settings_reset">Վերականգնել</string>
|
<string name="revanced_settings_reset">Վերականգնել</string>
|
||||||
|
<string name="revanced_settings_reset_color">Գույնը վերականգնել</string>
|
||||||
|
<string name="revanced_settings_color_invalid">Անվավեր գույն</string>
|
||||||
<string name="revanced_settings_restart_title">Թարմացնել և վերագործարկել</string>
|
<string name="revanced_settings_restart_title">Թարմացնել և վերագործարկել</string>
|
||||||
<string name="revanced_settings_restart">Վերսկսել</string>
|
<string name="revanced_settings_restart">Վերսկսել</string>
|
||||||
<string name="revanced_settings_import">Ներմուծել</string>
|
<string name="revanced_settings_import">Ներմուծել</string>
|
||||||
@@ -365,9 +367,6 @@ MicroG-ի համար մարտկոցի օպտիմալացումը անջատել
|
|||||||
|
|
||||||
Այս հատկությունը հասանելի է միայն հին սարքերի համար"</string>
|
Այս հատկությունը հասանելի է միայն հին սարքերի համար"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">Լի էկրանի գովազդները երևում են</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">Լի էկրանի գովազդները երևում են</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">Թաքցնել կոճակավորված գովազդները</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">Կոճակավորված գովազդները թաքցված են</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">Կոճակավորված գովազդները երևում են</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Թաքցնել վճարված խթանման նշանը</string>
|
<string name="revanced_hide_paid_promotion_label_title">Թաքցնել վճարված խթանման նշանը</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">Վճարված խթանման նշանը թաքցված է</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">Վճարված խթանման նշանը թաքցված է</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">Վճարված խթանման նշանը երևում է</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">Վճարված խթանման նշանը երևում է</string>
|
||||||
@@ -1099,11 +1098,6 @@ Seekbar thumbnails-ները կօգտագործեն նույն որակը, ինչ
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s վայրկյան</string>
|
<string name="revanced_sb_stats_saved_second_format">%s վայրկյան</string>
|
||||||
<string name="revanced_sb_color_opacity_label">Թափանցիկություն․</string>
|
<string name="revanced_sb_color_opacity_label">Թափանցիկություն․</string>
|
||||||
<string name="revanced_sb_color_dot_label">Գույն։</string>
|
<string name="revanced_sb_color_dot_label">Գույն։</string>
|
||||||
<string name="revanced_sb_color_changed">Գույնը փոխվել է</string>
|
|
||||||
<string name="revanced_sb_color_reset">Գույնը վերագործարկվել է</string>
|
|
||||||
<string name="revanced_sb_color_invalid">Անվավեր գույնի կոդ</string>
|
|
||||||
<string name="revanced_sb_reset_color">Վերագործարկել գույնը</string>
|
|
||||||
<string name="revanced_sb_reset">Վերագործարկել</string>
|
|
||||||
<string name="revanced_sb_about_title">Ծրագրի մասին</string>
|
<string name="revanced_sb_about_title">Ծրագրի մասին</string>
|
||||||
<string name="revanced_sb_about_api_summary">Տվյալները մատուցվում են SponsorBlock API-ի կողմից։ Սեղմեք այստեղ՝ ավելի շատ իմանալու և այլ հարթակների համար ներբեռնումները տեսնելու</string>
|
<string name="revanced_sb_about_api_summary">Տվյալները մատուցվում են SponsorBlock API-ի կողմից։ Սեղմեք այստեղ՝ ավելի շատ իմանալու և այլ հարթակների համար ներբեռնումները տեսնելու</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">Pengaturan</string>
|
<string name="revanced_settings_submenu_title">Pengaturan</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">Apakah Anda ingin melanjutkan?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">Apakah Anda ingin melanjutkan?</string>
|
||||||
<string name="revanced_settings_reset">Setel ulang</string>
|
<string name="revanced_settings_reset">Setel ulang</string>
|
||||||
|
<string name="revanced_settings_reset_color">Setel ulang warna</string>
|
||||||
|
<string name="revanced_settings_color_invalid">Warna tidak sah</string>
|
||||||
<string name="revanced_settings_restart_title">Segarkan dan mulai ulang</string>
|
<string name="revanced_settings_restart_title">Segarkan dan mulai ulang</string>
|
||||||
<string name="revanced_settings_restart">Mulai ulang</string>
|
<string name="revanced_settings_restart">Mulai ulang</string>
|
||||||
<string name="revanced_settings_import">Impor</string>
|
<string name="revanced_settings_import">Impor</string>
|
||||||
@@ -365,9 +367,6 @@ Keterbatasan
|
|||||||
|
|
||||||
Fitur ini hanya tersedia untuk perangkat yang lebih lama"</string>
|
Fitur ini hanya tersedia untuk perangkat yang lebih lama"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">Iklan layar penuh ditampilkan</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">Iklan layar penuh ditampilkan</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">Sembunyikan iklan bertombol</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">Iklan bertombol disembunyikan</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">Iklan bertombol ditampilkan</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Sembunyikan label promosi berbayar</string>
|
<string name="revanced_hide_paid_promotion_label_title">Sembunyikan label promosi berbayar</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">Label promosi berbayar disembunyikan</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">Label promosi berbayar disembunyikan</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">Label promosi berbayar ditampilkan</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">Label promosi berbayar ditampilkan</string>
|
||||||
@@ -1098,11 +1097,6 @@ Siap mengirim?"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s detik</string>
|
<string name="revanced_sb_stats_saved_second_format">%s detik</string>
|
||||||
<string name="revanced_sb_color_opacity_label">Opasitas:</string>
|
<string name="revanced_sb_color_opacity_label">Opasitas:</string>
|
||||||
<string name="revanced_sb_color_dot_label">Warna:</string>
|
<string name="revanced_sb_color_dot_label">Warna:</string>
|
||||||
<string name="revanced_sb_color_changed">Warna berubah</string>
|
|
||||||
<string name="revanced_sb_color_reset">Reset warna</string>
|
|
||||||
<string name="revanced_sb_color_invalid">Kode warna tidak sah</string>
|
|
||||||
<string name="revanced_sb_reset_color">Atur ulang warna</string>
|
|
||||||
<string name="revanced_sb_reset">Setel ulang</string>
|
|
||||||
<string name="revanced_sb_about_title">Tentang</string>
|
<string name="revanced_sb_about_title">Tentang</string>
|
||||||
<string name="revanced_sb_about_api_summary">Data disediakan oleh API SponsorBlock. Tekan di sini untuk mempelajari lebih lanjut dan melihat hasil pengunduhan untuk platform lain</string>
|
<string name="revanced_sb_about_api_summary">Data disediakan oleh API SponsorBlock. Tekan di sini untuk mempelajari lebih lanjut dan melihat hasil pengunduhan untuk platform lain</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">Impostazioni</string>
|
<string name="revanced_settings_submenu_title">Impostazioni</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">Sei sicuro di voler continuare?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">Sei sicuro di voler continuare?</string>
|
||||||
<string name="revanced_settings_reset">Reimposta</string>
|
<string name="revanced_settings_reset">Reimposta</string>
|
||||||
|
<string name="revanced_settings_reset_color">Reimposta colore</string>
|
||||||
|
<string name="revanced_settings_color_invalid">Colore non valido</string>
|
||||||
<string name="revanced_settings_restart_title">Aggiorna e riavvia</string>
|
<string name="revanced_settings_restart_title">Aggiorna e riavvia</string>
|
||||||
<string name="revanced_settings_restart">Riavvia</string>
|
<string name="revanced_settings_restart">Riavvia</string>
|
||||||
<string name="revanced_settings_import">Importa</string>
|
<string name="revanced_settings_import">Importa</string>
|
||||||
@@ -365,9 +367,6 @@ Note:
|
|||||||
|
|
||||||
Questa funzione è disponibile solo per i dispositivi più vecchi"</string>
|
Questa funzione è disponibile solo per i dispositivi più vecchi"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">Le pubblicità a schermo intero sono visibili</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">Le pubblicità a schermo intero sono visibili</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">Nascondi le pubblicità a pulsante</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">Le pubblicità a pulsante sono nascoste</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">Le pubblicità a pulsante sono visibili</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Nascondi l\'etichetta della promozione a pagamento</string>
|
<string name="revanced_hide_paid_promotion_label_title">Nascondi l\'etichetta della promozione a pagamento</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">L\'etichetta della promozione a pagamento è nascosta</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">L\'etichetta della promozione a pagamento è nascosta</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">L\'etichetta della promozione a pagamento è visibile</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">L\'etichetta della promozione a pagamento è visibile</string>
|
||||||
@@ -1098,11 +1097,6 @@ Pronto per l'invio?"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s secondi</string>
|
<string name="revanced_sb_stats_saved_second_format">%s secondi</string>
|
||||||
<string name="revanced_sb_color_opacity_label">Opacità:</string>
|
<string name="revanced_sb_color_opacity_label">Opacità:</string>
|
||||||
<string name="revanced_sb_color_dot_label">Colore:</string>
|
<string name="revanced_sb_color_dot_label">Colore:</string>
|
||||||
<string name="revanced_sb_color_changed">Colore modificato</string>
|
|
||||||
<string name="revanced_sb_color_reset">Ripristino colore</string>
|
|
||||||
<string name="revanced_sb_color_invalid">Codice colore non valido</string>
|
|
||||||
<string name="revanced_sb_reset_color">Ripristina colore</string>
|
|
||||||
<string name="revanced_sb_reset">Reimposta</string>
|
|
||||||
<string name="revanced_sb_about_title">Informazioni</string>
|
<string name="revanced_sb_about_title">Informazioni</string>
|
||||||
<string name="revanced_sb_about_api_summary">I dati sono forniti dall\'API di SponsorBlock. Tocca qui per saperne di più e vedere i download per altre piattaforme</string>
|
<string name="revanced_sb_about_api_summary">I dati sono forniti dall\'API di SponsorBlock. Tocca qui per saperne di più e vedere i download per altre piattaforme</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">הגדרות</string>
|
<string name="revanced_settings_submenu_title">הגדרות</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">האם ברצונך להמשיך?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">האם ברצונך להמשיך?</string>
|
||||||
<string name="revanced_settings_reset">איפוס</string>
|
<string name="revanced_settings_reset">איפוס</string>
|
||||||
|
<string name="revanced_settings_reset_color">אפס צבע</string>
|
||||||
<string name="revanced_settings_restart_title">רענן והפעל מחדש</string>
|
<string name="revanced_settings_restart_title">רענן והפעל מחדש</string>
|
||||||
<string name="revanced_settings_restart">הפעלה מחדש</string>
|
<string name="revanced_settings_restart">הפעלה מחדש</string>
|
||||||
<string name="revanced_settings_import">ייבוא</string>
|
<string name="revanced_settings_import">ייבוא</string>
|
||||||
@@ -349,9 +350,6 @@ Second \"item\" text"</string>
|
|||||||
|
|
||||||
תכונה זו זמינה רק עבור מכשירים ישנים יותר"</string>
|
תכונה זו זמינה רק עבור מכשירים ישנים יותר"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">מודעות מסך מלא מוצגות</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">מודעות מסך מלא מוצגות</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">הסתר מודעות מכופתרות</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">מודעות מכפותרות מוסתרות</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">מודעות מכפותרות מוצגות</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">הסתר תווית קידום מכירות בתשלום</string>
|
<string name="revanced_hide_paid_promotion_label_title">הסתר תווית קידום מכירות בתשלום</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">תווית קידום מכירות בתשלום מוסתרת</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">תווית קידום מכירות בתשלום מוסתרת</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">תווית קידום מכירות בתשלום מוצגת</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">תווית קידום מכירות בתשלום מוצגת</string>
|
||||||
@@ -1063,11 +1061,6 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s שניות</string>
|
<string name="revanced_sb_stats_saved_second_format">%s שניות</string>
|
||||||
<string name="revanced_sb_color_opacity_label">אטימות:</string>
|
<string name="revanced_sb_color_opacity_label">אטימות:</string>
|
||||||
<string name="revanced_sb_color_dot_label">צבע:</string>
|
<string name="revanced_sb_color_dot_label">צבע:</string>
|
||||||
<string name="revanced_sb_color_changed">צבע שונה</string>
|
|
||||||
<string name="revanced_sb_color_reset">צבע אופס</string>
|
|
||||||
<string name="revanced_sb_color_invalid">קוד צבע לא חוקי</string>
|
|
||||||
<string name="revanced_sb_reset_color">אפס צבע</string>
|
|
||||||
<string name="revanced_sb_reset">איפוס</string>
|
|
||||||
<string name="revanced_sb_about_title">אודות</string>
|
<string name="revanced_sb_about_title">אודות</string>
|
||||||
<string name="revanced_sb_about_api_summary">הנתונים מסופקים על ידי SponsorBlock API. הקש כאן כדי ללמוד עוד ולראות הורדות עבור פלטפורמות אחרות</string>
|
<string name="revanced_sb_about_api_summary">הנתונים מסופקים על ידי SponsorBlock API. הקש כאן כדי ללמוד עוד ולראות הורדות עבור פלטפורמות אחרות</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">設定</string>
|
<string name="revanced_settings_submenu_title">設定</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">続行しますか?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">続行しますか?</string>
|
||||||
<string name="revanced_settings_reset">リセット</string>
|
<string name="revanced_settings_reset">リセット</string>
|
||||||
|
<string name="revanced_settings_reset_color">色をリセット</string>
|
||||||
|
<string name="revanced_settings_color_invalid">色の値が無効です</string>
|
||||||
<string name="revanced_settings_restart_title">更新して再起動</string>
|
<string name="revanced_settings_restart_title">更新して再起動</string>
|
||||||
<string name="revanced_settings_restart">再起動</string>
|
<string name="revanced_settings_restart">再起動</string>
|
||||||
<string name="revanced_settings_import">インポート</string>
|
<string name="revanced_settings_import">インポート</string>
|
||||||
@@ -42,8 +44,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_import_reset">ReVanced 設定をデフォルトにリセット</string>
|
<string name="revanced_settings_import_reset">ReVanced 設定をデフォルトにリセット</string>
|
||||||
<string name="revanced_settings_import_success">%d 個の設定をインポートしました</string>
|
<string name="revanced_settings_import_success">%d 個の設定をインポートしました</string>
|
||||||
<string name="revanced_settings_import_failure_parse">インポート失敗: %s</string>
|
<string name="revanced_settings_import_failure_parse">インポート失敗: %s</string>
|
||||||
<string name="revanced_settings_search_hint">検索設定</string>
|
<string name="revanced_settings_search_hint">ReVanced の設定を検索</string>
|
||||||
<string name="revanced_settings_search_no_results_title">\'%s\' の検索結果は見つかりませんでした</string>
|
<string name="revanced_settings_search_no_results_title">\'%s\' に一致する ReVanced の設定は見つかりませんでした</string>
|
||||||
<string name="revanced_settings_search_no_results_summary">別のキーワードを試してください</string>
|
<string name="revanced_settings_search_no_results_summary">別のキーワードを試してください</string>
|
||||||
<string name="revanced_settings_search_remove_message">検索履歴から削除しますか?</string>
|
<string name="revanced_settings_search_remove_message">検索履歴から削除しますか?</string>
|
||||||
<string name="revanced_show_menu_icons_title">ReVanced 設定にアイコンを表示する</string>
|
<string name="revanced_show_menu_icons_title">ReVanced 設定にアイコンを表示する</string>
|
||||||
@@ -98,9 +100,9 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
|
|||||||
<string name="revanced_restore_old_settings_menus_title">設定メニューを旧バージョンに戻す</string>
|
<string name="revanced_restore_old_settings_menus_title">設定メニューを旧バージョンに戻す</string>
|
||||||
<string name="revanced_restore_old_settings_menus_summary_on">旧バージョンの設定メニューが表示されます</string>
|
<string name="revanced_restore_old_settings_menus_summary_on">旧バージョンの設定メニューが表示されます</string>
|
||||||
<string name="revanced_restore_old_settings_menus_summary_off">通常の設定メニューが表示されます</string>
|
<string name="revanced_restore_old_settings_menus_summary_off">通常の設定メニューが表示されます</string>
|
||||||
<string name="revanced_settings_search_history_title">設定の検索履歴を表示</string>
|
<string name="revanced_settings_search_history_title">設定検索の履歴を表示する</string>
|
||||||
<string name="revanced_settings_search_history_summary_on">設定の検索履歴が表示されています</string>
|
<string name="revanced_settings_search_history_summary_on">設定検索の履歴は表示されます</string>
|
||||||
<string name="revanced_settings_search_history_summary_off">設定の検索履歴は表示されません</string>
|
<string name="revanced_settings_search_history_summary_off">設定検索の履歴は表示されません</string>
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="misc.backgroundplayback.backgroundPlaybackPatch">
|
<patch id="misc.backgroundplayback.backgroundPlaybackPatch">
|
||||||
<string name="revanced_shorts_disable_background_playback_title">ショート動画のバックグラウンド再生を無効にする</string>
|
<string name="revanced_shorts_disable_background_playback_title">ショート動画のバックグラウンド再生を無効にする</string>
|
||||||
@@ -244,7 +246,7 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
|
|||||||
<string name="revanced_hide_ai_generated_video_summary_section_title">「AI 生成による動画の要約」を非表示</string>
|
<string name="revanced_hide_ai_generated_video_summary_section_title">「AI 生成による動画の要約」を非表示</string>
|
||||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">動画の要約セクションは表示されません</string>
|
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">動画の要約セクションは表示されません</string>
|
||||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">動画の要約セクションは表示されます</string>
|
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">動画の要約セクションは表示されます</string>
|
||||||
<string name="revanced_hide_ask_section_title">質問ボタンを非表示</string>
|
<string name="revanced_hide_ask_section_title">質問セクションを非表示</string>
|
||||||
<string name="revanced_hide_ask_section_summary_on">質問セクションは表示されません</string>
|
<string name="revanced_hide_ask_section_summary_on">質問セクションは表示されません</string>
|
||||||
<string name="revanced_hide_ask_section_summary_off">質問セクションは表示されます</string>
|
<string name="revanced_hide_ask_section_summary_off">質問セクションは表示されます</string>
|
||||||
<string name="revanced_hide_attributes_section_title">関連情報を非表示</string>
|
<string name="revanced_hide_attributes_section_title">関連情報を非表示</string>
|
||||||
@@ -368,9 +370,6 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
|
|||||||
|
|
||||||
この機能は、古いデバイスでのみ利用できます"</string>
|
この機能は、古いデバイスでのみ利用できます"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">全画面広告は、アプリ起動時に表示されます</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">全画面広告は、アプリ起動時に表示されます</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">ボタン付き広告を非表示</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">ボタン付き広告は表示されません</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">ボタン付き広告は表示されます</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">「プロモーションを含みます」ボタンを非表示</string>
|
<string name="revanced_hide_paid_promotion_label_title">「プロモーションを含みます」ボタンを非表示</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">「プロモーションを含みます」ボタンはプレーヤー画面に表示されません</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">「プロモーションを含みます」ボタンはプレーヤー画面に表示されません</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">「プロモーションを含みます」ボタンはプレーヤー画面に表示されます</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">「プロモーションを含みます」ボタンはプレーヤー画面に表示されます</string>
|
||||||
@@ -1099,11 +1098,6 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s 秒</string>
|
<string name="revanced_sb_stats_saved_second_format">%s 秒</string>
|
||||||
<string name="revanced_sb_color_opacity_label">透明度:</string>
|
<string name="revanced_sb_color_opacity_label">透明度:</string>
|
||||||
<string name="revanced_sb_color_dot_label">色:</string>
|
<string name="revanced_sb_color_dot_label">色:</string>
|
||||||
<string name="revanced_sb_color_changed">色を変更しました</string>
|
|
||||||
<string name="revanced_sb_color_reset">色がリセットされました</string>
|
|
||||||
<string name="revanced_sb_color_invalid">色の値が無効です</string>
|
|
||||||
<string name="revanced_sb_reset_color">色をリセット</string>
|
|
||||||
<string name="revanced_sb_reset">リセット</string>
|
|
||||||
<string name="revanced_sb_about_title">SponsorBlock について</string>
|
<string name="revanced_sb_about_title">SponsorBlock について</string>
|
||||||
<string name="revanced_sb_about_api_summary">SponsorBlock APIによって提供されるデータです。詳細はこちらをタップしてください。</string>
|
<string name="revanced_sb_about_api_summary">SponsorBlock APIによって提供されるデータです。詳細はこちらをタップしてください。</string>
|
||||||
</patch>
|
</patch>
|
||||||
@@ -1167,7 +1161,7 @@ Automotive レイアウト
|
|||||||
<string name="revanced_change_start_page_always_summary_on">"スタート画面の変更は常時適用されます
|
<string name="revanced_change_start_page_always_summary_on">"スタート画面の変更は常時適用されます
|
||||||
|
|
||||||
制限事項: ツールバーの [戻る] ボタンが機能しない可能性があります"</string>
|
制限事項: ツールバーの [戻る] ボタンが機能しない可能性があります"</string>
|
||||||
<string name="revanced_change_start_page_always_summary_off">スタート画面の変更はアプリ起動時にのみ適用されます</string>
|
<string name="revanced_change_start_page_always_summary_off">スタート画面の変更は、アプリ起動時にのみ適用されます</string>
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="layout.startupshortsreset.disableResumingShortsOnStartupPatch">
|
<patch id="layout.startupshortsreset.disableResumingShortsOnStartupPatch">
|
||||||
<string name="revanced_disable_resuming_shorts_player_title">ショート動画プレーヤーの再開を無効にする</string>
|
<string name="revanced_disable_resuming_shorts_player_title">ショート動画プレーヤーの再開を無効にする</string>
|
||||||
@@ -1296,8 +1290,8 @@ Automotive レイアウト
|
|||||||
</patch>
|
</patch>
|
||||||
<patch id="misc.announcements.announcementsPatch">
|
<patch id="misc.announcements.announcementsPatch">
|
||||||
<string name="revanced_announcements_title">ReVanced のお知らせを表示する</string>
|
<string name="revanced_announcements_title">ReVanced のお知らせを表示する</string>
|
||||||
<string name="revanced_announcements_summary_on">アプリ起動時にお知らせが表示されます</string>
|
<string name="revanced_announcements_summary_on">お知らせは、アプリ起動時に表示されます</string>
|
||||||
<string name="revanced_announcements_summary_off">アプリ起動時にお知らせは表示されません</string>
|
<string name="revanced_announcements_summary_off">お知らせは、アプリ起動時に表示されません</string>
|
||||||
<string name="revanced_announcements_enabled_summary">アプリ起動時にお知らせを表示する</string>
|
<string name="revanced_announcements_enabled_summary">アプリ起動時にお知らせを表示する</string>
|
||||||
<string name="revanced_announcements_connection_failed">お知らせの取得に失敗しました</string>
|
<string name="revanced_announcements_connection_failed">お知らせの取得に失敗しました</string>
|
||||||
<string name="revanced_announcements_dialog_dismiss">閉じる</string>
|
<string name="revanced_announcements_dialog_dismiss">閉じる</string>
|
||||||
|
|||||||
@@ -21,20 +21,22 @@ Second \"item\" text"</string>
|
|||||||
<resources>
|
<resources>
|
||||||
<app id="shared">
|
<app id="shared">
|
||||||
<patch id="misc.checks.checkEnvironmentPatch">
|
<patch id="misc.checks.checkEnvironmentPatch">
|
||||||
<string name="revanced_check_environment_failed_title">환경 검사에 실패함</string>
|
<string name="revanced_check_environment_failed_title">환경 검사에 실패하였습니다</string>
|
||||||
<string name="revanced_check_environment_dialog_open_official_source_button">공식 홈페이지 열기</string>
|
<string name="revanced_check_environment_dialog_open_official_source_button">공식 홈페이지 열기</string>
|
||||||
<string name="revanced_check_environment_dialog_ignore_button">닫기</string>
|
<string name="revanced_check_environment_dialog_ignore_button">닫기</string>
|
||||||
<string name="revanced_check_environment_failed_message"><h5>이 앱은 사용자가 패치하지 않은 것 같습니다.</h5><br>이 앱은 제대로 작동하지 않을 수 있으며, <b>사용 시 해롭거나 심지어 위험할 수도 있습니다</b>.<br><br>이러한 검사는 이 앱이 사전에 패치되었거나 다른 사람으로부터 받은 것임을 의미합니다:<br><br><small>%1$s</small><br>검증되고 안전한 앱을 사용하고 있는지 확인하려면 <b>이 앱을 제거하고 직접 패치하는 것</b>을 강력히 권장합니다.<p><br>이 경고는 두 번만 표시됩니다.</string>
|
<string name="revanced_check_environment_failed_message"><h5>이 앱은 사용자가 패치하지 않은 것 같습니다.</h5><br>이 앱은 제대로 작동하지 않을 수 있으며, <b>사용 시 해롭거나 심지어 위험할 수도 있습니다</b>.<br><br>이러한 검사는 이 앱이 사전에 패치되었거나 다른 사람으로부터 받은 것임을 의미합니다:<br><br><small>%1$s</small><br>검증되고 안전한 앱을 사용하고 있는지 확인하려면 <b>이 앱을 삭제하고 직접 패치하는 것</b>을 강력히 권장합니다.<p><br>이 경고는 두 번만 표시됩니다.</string>
|
||||||
<string name="revanced_check_environment_not_same_patching_device">다른 기기에서 패치됨</string>
|
<string name="revanced_check_environment_not_same_patching_device">다른 기기에서 패치되었습니다</string>
|
||||||
<string name="revanced_check_environment_manager_not_expected_installer">ReVanced Manager에 의해 설치되지 않음</string>
|
<string name="revanced_check_environment_manager_not_expected_installer">ReVanced Manager에 의해 설치되지 않았습니다</string>
|
||||||
<string name="revanced_check_environment_not_near_patch_time">10분 이상 전에 패치됨</string>
|
<string name="revanced_check_environment_not_near_patch_time">10분 이상 전에 패치되었습니다</string>
|
||||||
<string name="revanced_check_environment_not_near_patch_time_days">%s 일 전에 패치됨</string>
|
<string name="revanced_check_environment_not_near_patch_time_days">%s 일 전에 패치되었습니다</string>
|
||||||
<string name="revanced_check_environment_not_near_patch_time_invalid">APK 빌드 날짜가 손상됨</string>
|
<string name="revanced_check_environment_not_near_patch_time_invalid">APK 빌드 날짜가 손상되었습니다</string>
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="misc.settings.settingsResourcePatch">
|
<patch id="misc.settings.settingsResourcePatch">
|
||||||
<string name="revanced_settings_submenu_title">설정</string>
|
<string name="revanced_settings_submenu_title">설정</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">계속하시겠습니까?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">계속하시겠습니까?</string>
|
||||||
<string name="revanced_settings_reset">초기화</string>
|
<string name="revanced_settings_reset">초기화</string>
|
||||||
|
<string name="revanced_settings_reset_color">색상 초기화</string>
|
||||||
|
<string name="revanced_settings_color_invalid">잘못된 색상입니다</string>
|
||||||
<string name="revanced_settings_restart_title">새로고침 및 다시 시작</string>
|
<string name="revanced_settings_restart_title">새로고침 및 다시 시작</string>
|
||||||
<string name="revanced_settings_restart">다시 시작</string>
|
<string name="revanced_settings_restart">다시 시작</string>
|
||||||
<string name="revanced_settings_import">가져오기</string>
|
<string name="revanced_settings_import">가져오기</string>
|
||||||
@@ -44,8 +46,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_import_failure_parse">설정을 가져올 수 없습니다: %s</string>
|
<string name="revanced_settings_import_failure_parse">설정을 가져올 수 없습니다: %s</string>
|
||||||
<string name="revanced_settings_search_hint">설정 검색</string>
|
<string name="revanced_settings_search_hint">설정 검색</string>
|
||||||
<string name="revanced_settings_search_no_results_title">\'%s\'에 대한 검색 결과가 없습니다</string>
|
<string name="revanced_settings_search_no_results_title">\'%s\'에 대한 검색 결과가 없습니다</string>
|
||||||
<string name="revanced_settings_search_no_results_summary">다른 키워드를 사용해 보세요</string>
|
<string name="revanced_settings_search_no_results_summary">다른 키워드를 검색해 보세요</string>
|
||||||
<string name="revanced_settings_search_remove_message">검색 기록에서 제거하시겠습니까?</string>
|
<string name="revanced_settings_search_remove_message">검색 기록에서 삭제하시겠습니까?</string>
|
||||||
<string name="revanced_show_menu_icons_title">ReVanced 설정 아이콘 표시하기</string>
|
<string name="revanced_show_menu_icons_title">ReVanced 설정 아이콘 표시하기</string>
|
||||||
<string name="revanced_show_menu_icons_summary_on">설정 아이콘을 표시합니다</string>
|
<string name="revanced_show_menu_icons_summary_on">설정 아이콘을 표시합니다</string>
|
||||||
<string name="revanced_show_menu_icons_summary_off">설정 아이콘을 표시하지 않습니다</string>
|
<string name="revanced_show_menu_icons_summary_off">설정 아이콘을 표시하지 않습니다</string>
|
||||||
@@ -98,8 +100,8 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배
|
|||||||
<string name="revanced_restore_old_settings_menus_summary_on">이전 설정 메뉴를 표시합니다</string>
|
<string name="revanced_restore_old_settings_menus_summary_on">이전 설정 메뉴를 표시합니다</string>
|
||||||
<string name="revanced_restore_old_settings_menus_summary_off">이전 설정 메뉴를 표시하지 않습니다</string>
|
<string name="revanced_restore_old_settings_menus_summary_off">이전 설정 메뉴를 표시하지 않습니다</string>
|
||||||
<string name="revanced_settings_search_history_title">설정 검색 기록 표시하기</string>
|
<string name="revanced_settings_search_history_title">설정 검색 기록 표시하기</string>
|
||||||
<string name="revanced_settings_search_history_summary_on">설정 검색 기록이 표시됩니다</string>
|
<string name="revanced_settings_search_history_summary_on">설정 검색 기록을 표시합니다</string>
|
||||||
<string name="revanced_settings_search_history_summary_off">설정 검색 기록이 표시되지 않습니다</string>
|
<string name="revanced_settings_search_history_summary_off">설정 검색 기록을 표시하지 않습니다</string>
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="misc.backgroundplayback.backgroundPlaybackPatch">
|
<patch id="misc.backgroundplayback.backgroundPlaybackPatch">
|
||||||
<string name="revanced_shorts_disable_background_playback_title">Shorts 백그라운드 재생 비활성화하기</string>
|
<string name="revanced_shorts_disable_background_playback_title">Shorts 백그라운드 재생 비활성화하기</string>
|
||||||
@@ -166,8 +168,8 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배
|
|||||||
<string name="revanced_hide_notify_me_button_summary_off">\'알림 받기\' 버튼이 표시됩니다</string>
|
<string name="revanced_hide_notify_me_button_summary_off">\'알림 받기\' 버튼이 표시됩니다</string>
|
||||||
<!-- 'People also watched' and 'You might also like' should be translated using the same localized wording YouTube displays. -->
|
<!-- 'People also watched' and 'You might also like' should be translated using the same localized wording YouTube displays. -->
|
||||||
<string name="revanced_hide_search_result_recommendation_labels_title">동영상 추천 라벨 숨기기</string>
|
<string name="revanced_hide_search_result_recommendation_labels_title">동영상 추천 라벨 숨기기</string>
|
||||||
<string name="revanced_hide_search_result_recommendation_labels_summary_on">다음 동영상 추천 라벨이 숨겨집니다\n• 시청자가 이 동영상도 시청함\n• 내가 좋아할 만한 동영상</string>
|
<string name="revanced_hide_search_result_recommendation_labels_summary_on">다음 동영상 추천 라벨이 숨겨집니다:\n• 시청자가 이 동영상도 시청함\n• 내가 좋아할 만한 동영상</string>
|
||||||
<string name="revanced_hide_search_result_recommendation_labels_summary_off">다음 동영상 추천 라벨이 표시됩니다\n• 시청자가 이 동영상도 시청함\n• 내가 좋아할 만한 동영상</string>
|
<string name="revanced_hide_search_result_recommendation_labels_summary_off">다음 동영상 추천 라벨이 표시됩니다:\n• 시청자가 이 동영상도 시청함\n• 내가 좋아할 만한 동영상</string>
|
||||||
<!-- 'Show more' should be translated with the same localized wording that YouTube displays.
|
<!-- 'Show more' should be translated with the same localized wording that YouTube displays.
|
||||||
This button usually appears when searching for a YT creator. -->
|
This button usually appears when searching for a YT creator. -->
|
||||||
<string name="revanced_hide_show_more_button_title">\'자세히 보기\' 버튼 숨기기</string>
|
<string name="revanced_hide_show_more_button_title">\'자세히 보기\' 버튼 숨기기</string>
|
||||||
@@ -245,7 +247,7 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배
|
|||||||
<string name="revanced_hide_ai_generated_video_summary_section_title">AI 생성 동영상 요약 섹션 숨기기</string>
|
<string name="revanced_hide_ai_generated_video_summary_section_title">AI 생성 동영상 요약 섹션 숨기기</string>
|
||||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">AI 생성 동영상 요약 섹션이 숨겨집니다</string>
|
<string name="revanced_hide_ai_generated_video_summary_section_summary_on">AI 생성 동영상 요약 섹션이 숨겨집니다</string>
|
||||||
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">AI 생성 동영상 요약 섹션이 표시됩니다</string>
|
<string name="revanced_hide_ai_generated_video_summary_section_summary_off">AI 생성 동영상 요약 섹션이 표시됩니다</string>
|
||||||
<string name="revanced_hide_ask_section_title">요청 버튼 숨기기</string>
|
<string name="revanced_hide_ask_section_title">요청 섹션 숨기기</string>
|
||||||
<string name="revanced_hide_ask_section_summary_on">요청 섹션이 숨겨집니다</string>
|
<string name="revanced_hide_ask_section_summary_on">요청 섹션이 숨겨집니다</string>
|
||||||
<string name="revanced_hide_ask_section_summary_off">요청 섹션이 표시됩니다</string>
|
<string name="revanced_hide_ask_section_summary_off">요청 섹션이 표시됩니다</string>
|
||||||
<string name="revanced_hide_attributes_section_title">속성 섹션 숨기기</string>
|
<string name="revanced_hide_attributes_section_title">속성 섹션 숨기기</string>
|
||||||
@@ -368,9 +370,6 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배
|
|||||||
|
|
||||||
이 설정은 구형 기기에서만 사용할 수 있습니다"</string>
|
이 설정은 구형 기기에서만 사용할 수 있습니다"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">전체 화면 광고가 표시됩니다</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">전체 화면 광고가 표시됩니다</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">버튼형 광고 숨기기</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">버튼형 광고가 숨겨집니다</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">버튼형 광고가 표시됩니다</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">유료 광고 포함 라벨 숨기기</string>
|
<string name="revanced_hide_paid_promotion_label_title">유료 광고 포함 라벨 숨기기</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">유료 광고 포함 라벨이 숨겨집니다</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">유료 광고 포함 라벨이 숨겨집니다</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">유료 광고 포함 라벨이 표시됩니다</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">유료 광고 포함 라벨이 표시됩니다</string>
|
||||||
@@ -423,9 +422,9 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배
|
|||||||
<string name="revanced_copy_video_url_timestamp_summary_off">버튼을 표시하지 않습니다</string>
|
<string name="revanced_copy_video_url_timestamp_summary_off">버튼을 표시하지 않습니다</string>
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="interaction.dialog.removeViewerDiscretionDialogPatch">
|
<patch id="interaction.dialog.removeViewerDiscretionDialogPatch">
|
||||||
<string name="revanced_remove_viewer_discretion_dialog_title">시청 경고 다이얼로그 제거하기</string>
|
<string name="revanced_remove_viewer_discretion_dialog_title">시청 경고 다이얼로그 삭제하기</string>
|
||||||
<string name="revanced_remove_viewer_discretion_dialog_summary_on">다음 동영상을 시청하기 전에 표시되는 시청 경고 다이얼로그를 제거합니다\n• 연령 제한 동영상\n• 자살 또는 자해와 관련된 동영상, etc.</string>
|
<string name="revanced_remove_viewer_discretion_dialog_summary_on">다음 동영상을 시청하기 전에 표시되는 시청 경고 다이얼로그를 삭제합니다:\n• 연령 제한 동영상\n• 자살 또는 자해와 관련된 동영상, etc.</string>
|
||||||
<string name="revanced_remove_viewer_discretion_dialog_summary_off">다음 동영상을 시청하기 전에 표시되는 시청 경고 다이얼로그를 제거하지 않습니다\n• 연령 제한 동영상\n• 자살 또는 자해와 관련된 동영상, etc.</string>
|
<string name="revanced_remove_viewer_discretion_dialog_summary_off">다음 동영상을 시청하기 전에 표시되는 시청 경고 다이얼로그를 삭제하지 않습니다:\n• 연령 제한 동영상\n• 자살 또는 자해와 관련된 동영상, etc.</string>
|
||||||
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">이 설정은 다이얼로그를 자동으로 허용하기만 하며 연령 제한(성인인증 절차)을 우회할 수 없습니다.</string>
|
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">이 설정은 다이얼로그를 자동으로 허용하기만 하며 연령 제한(성인인증 절차)을 우회할 수 없습니다.</string>
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="interaction.downloads.downloadsResourcePatch">
|
<patch id="interaction.downloads.downloadsResourcePatch">
|
||||||
@@ -488,13 +487,13 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배
|
|||||||
<string name="revanced_swipe_volume_sensitivity_title">볼륨 스와이프 민감도</string>
|
<string name="revanced_swipe_volume_sensitivity_title">볼륨 스와이프 민감도</string>
|
||||||
<string name="revanced_swipe_volume_sensitivity_summary">스와이프할 때마다 볼륨이 얼마나 변경되는지를 지정할 수 있습니다</string>
|
<string name="revanced_swipe_volume_sensitivity_summary">스와이프할 때마다 볼륨이 얼마나 변경되는지를 지정할 수 있습니다</string>
|
||||||
<string name="revanced_swipe_overlay_style_title">스와이프 오버레이 스타일</string>
|
<string name="revanced_swipe_overlay_style_title">스와이프 오버레이 스타일</string>
|
||||||
<string name="revanced_swipe_overlay_style_entry_1">가로 오버레이</string>
|
<string name="revanced_swipe_overlay_style_entry_1">가로</string>
|
||||||
<string name="revanced_swipe_overlay_style_entry_2">가로 오버레이 (최소화 - 상단)</string>
|
<string name="revanced_swipe_overlay_style_entry_2">가로 (최소화 - 상단)</string>
|
||||||
<string name="revanced_swipe_overlay_style_entry_3">가로 오버레이 (최소화 - 중앙)</string>
|
<string name="revanced_swipe_overlay_style_entry_3">가로 (최소화 - 중앙)</string>
|
||||||
<string name="revanced_swipe_overlay_style_entry_4">원형 오버레이</string>
|
<string name="revanced_swipe_overlay_style_entry_4">원형</string>
|
||||||
<string name="revanced_swipe_overlay_style_entry_5">원형 오버레이 (최소화)</string>
|
<string name="revanced_swipe_overlay_style_entry_5">원형 (최소화)</string>
|
||||||
<string name="revanced_swipe_overlay_style_entry_6">세로 오버레이</string>
|
<string name="revanced_swipe_overlay_style_entry_6">세로</string>
|
||||||
<string name="revanced_swipe_overlay_style_entry_7">세로 오버레이 (최소화)</string>
|
<string name="revanced_swipe_overlay_style_entry_7">세로 (최소화)</string>
|
||||||
<string name="revanced_swipe_change_video_title">스와이프 제스처로 동영상 전환 활성화하기</string>
|
<string name="revanced_swipe_change_video_title">스와이프 제스처로 동영상 전환 활성화하기</string>
|
||||||
<string name="revanced_swipe_change_video_summary_on">전체 화면 중앙에서 위로/아래로 스와이프하여 다음/이전 동영상으로 전환합니다</string>
|
<string name="revanced_swipe_change_video_summary_on">전체 화면 중앙에서 위로/아래로 스와이프하여 다음/이전 동영상으로 전환합니다</string>
|
||||||
<string name="revanced_swipe_change_video_summary_off">전체 화면 중앙에서 위로/아래로 스와이프하여 다음/이전 동영상으로 전환하지 않습니다</string>
|
<string name="revanced_swipe_change_video_summary_off">전체 화면 중앙에서 위로/아래로 스와이프하여 다음/이전 동영상으로 전환하지 않습니다</string>
|
||||||
@@ -685,8 +684,8 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배
|
|||||||
</patch>
|
</patch>
|
||||||
<patch id="layout.hide.rollingnumber.disableRollingNumberAnimationPatch">
|
<patch id="layout.hide.rollingnumber.disableRollingNumberAnimationPatch">
|
||||||
<string name="revanced_disable_rolling_number_animations_title">롤링 넘버 애니메이션 비활성화하기</string>
|
<string name="revanced_disable_rolling_number_animations_title">롤링 넘버 애니메이션 비활성화하기</string>
|
||||||
<string name="revanced_disable_rolling_number_animations_summary_on">다음 롤링 넘버 애니메이션을 비활성화합니다\n• 조회수, 시청자 수 롤링 애니메이션 (플레이어 하단)\n• 좋아요 수, 조회수 롤링 애니메이션 (동영상 설명)</string>
|
<string name="revanced_disable_rolling_number_animations_summary_on">다음 롤링 넘버 애니메이션을 비활성화합니다:\n• 조회수, 시청자 수 롤링 애니메이션 (플레이어 하단)\n• 좋아요 수, 조회수 롤링 애니메이션 (동영상 설명)</string>
|
||||||
<string name="revanced_disable_rolling_number_animations_summary_off">다음 롤링 넘버 애니메이션을 활성화합니다\n• 조회수, 시청자 수 롤링 애니메이션 (플레이어 하단)\n• 좋아요 수, 조회수 롤링 애니메이션 (동영상 설명)</string>
|
<string name="revanced_disable_rolling_number_animations_summary_off">다음 롤링 넘버 애니메이션을 활성화합니다:\n• 조회수, 시청자 수 롤링 애니메이션 (플레이어 하단)\n• 좋아요 수, 조회수 롤링 애니메이션 (동영상 설명)</string>
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="layout.hide.seekbar.hideSeekbarPatch">
|
<patch id="layout.hide.seekbar.hideSeekbarPatch">
|
||||||
<string name="revanced_hide_seekbar_title">동영상 플레이어 재생바 숨기기</string>
|
<string name="revanced_hide_seekbar_title">동영상 플레이어 재생바 숨기기</string>
|
||||||
@@ -1099,11 +1098,6 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s 초</string>
|
<string name="revanced_sb_stats_saved_second_format">%s 초</string>
|
||||||
<string name="revanced_sb_color_opacity_label">불투명도:</string>
|
<string name="revanced_sb_color_opacity_label">불투명도:</string>
|
||||||
<string name="revanced_sb_color_dot_label">색상:</string>
|
<string name="revanced_sb_color_dot_label">색상:</string>
|
||||||
<string name="revanced_sb_color_changed">설정한 색상을 적용하였습니다</string>
|
|
||||||
<string name="revanced_sb_color_reset">색상을 초기화하였습니다</string>
|
|
||||||
<string name="revanced_sb_color_invalid">잘못된 헥스 코드입니다</string>
|
|
||||||
<string name="revanced_sb_reset_color">색상 초기화</string>
|
|
||||||
<string name="revanced_sb_reset">초기화</string>
|
|
||||||
<string name="revanced_sb_about_title">정보</string>
|
<string name="revanced_sb_about_title">정보</string>
|
||||||
<string name="revanced_sb_about_api_summary">건너뛸 구간의 데이터는 SponsorBlock API에 의해 제공됩니다. 자세한 내용을 보려면 여기를 누르세요</string>
|
<string name="revanced_sb_about_api_summary">건너뛸 구간의 데이터는 SponsorBlock API에 의해 제공됩니다. 자세한 내용을 보려면 여기를 누르세요</string>
|
||||||
</patch>
|
</patch>
|
||||||
@@ -1332,7 +1326,7 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요"</string>
|
|||||||
<string name="microg_settings_summary">알림 수신을 위한 클라우드 메시징을 설정할 수 있습니다</string>
|
<string name="microg_settings_summary">알림 수신을 위한 클라우드 메시징을 설정할 수 있습니다</string>
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="misc.gms.accountCredentialsInvalidTextPatch">
|
<patch id="misc.gms.accountCredentialsInvalidTextPatch">
|
||||||
<string name="microg_offline_account_login_error">최근에 계정 로그인 정보를 변경했다면 MicroG를 제거하고 다시 설치하세요.</string>
|
<string name="microg_offline_account_login_error">최근에 계정 로그인 정보를 변경했다면 MicroG를 삭제하고 다시 설치하세요.</string>
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="misc.links.bypassURLRedirectsPatch">
|
<patch id="misc.links.bypassURLRedirectsPatch">
|
||||||
<string name="revanced_bypass_url_redirects_title">리다이렉션 없이 링크 바로 열기</string>
|
<string name="revanced_bypass_url_redirects_title">리다이렉션 없이 링크 바로 열기</string>
|
||||||
@@ -1345,9 +1339,9 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요"</string>
|
|||||||
<string name="revanced_external_browser_summary_off">앱 내에서 외부 링크를 열 때, 내부 브라우저를 사용합니다</string>
|
<string name="revanced_external_browser_summary_off">앱 내에서 외부 링크를 열 때, 내부 브라우저를 사용합니다</string>
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="misc.privacy.removeTrackingQueryParameterPatch">
|
<patch id="misc.privacy.removeTrackingQueryParameterPatch">
|
||||||
<string name="revanced_remove_tracking_query_parameter_title">추적 쿼리를 제거한 링크 공유하기</string>
|
<string name="revanced_remove_tracking_query_parameter_title">추적 쿼리를 삭제한 링크 공유하기</string>
|
||||||
<string name="revanced_remove_tracking_query_parameter_summary_on">링크를 공유할 때, URL에서 추적 쿼리 매개변수를 제거합니다 (URL의 뒷부분 \'?si=...\' 이 제거됨)</string>
|
<string name="revanced_remove_tracking_query_parameter_summary_on">링크를 공유할 때, URL에서 추적 쿼리 매개변수를 삭제합니다 (URL의 뒷부분 \'?si=...\' 이 삭제됨)</string>
|
||||||
<string name="revanced_remove_tracking_query_parameter_summary_off">링크를 공유할 때, URL에서 추적 쿼리 매개변수를 제거하지 않습니다</string>
|
<string name="revanced_remove_tracking_query_parameter_summary_off">링크를 공유할 때, URL에서 추적 쿼리 매개변수를 삭제하지 않습니다</string>
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="misc.zoomhaptics.zoomHapticsPatch">
|
<patch id="misc.zoomhaptics.zoomHapticsPatch">
|
||||||
<string name="revanced_disable_zoom_haptics_title">동영상을 확대할 때, 진동 피드백 비활성화하기</string>
|
<string name="revanced_disable_zoom_haptics_title">동영상을 확대할 때, 진동 피드백 비활성화하기</string>
|
||||||
@@ -1428,8 +1422,8 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요"</string>
|
|||||||
<string name="revanced_spoof_video_streams_user_dialog_message">이 설정을 비활성화하면 동영상 재생 문제가 발생할 수 있습니다.</string>
|
<string name="revanced_spoof_video_streams_user_dialog_message">이 설정을 비활성화하면 동영상 재생 문제가 발생할 수 있습니다.</string>
|
||||||
<string name="revanced_spoof_video_streams_client_type_title">기본 클라이언트</string>
|
<string name="revanced_spoof_video_streams_client_type_title">기본 클라이언트</string>
|
||||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">iOS AVC (H.264) 강제로 활성화하기</string>
|
<string name="revanced_spoof_video_streams_ios_force_avc_title">iOS AVC (H.264) 강제로 활성화하기</string>
|
||||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">동영상 코덱을 AVC (H.264)로 강제로 활성화합니다\n\n• 일부 VP9 코덱 동영상에서 제거되었던 화질 값이 표시될 수 있습니다\n• 최대 화질 값이 1080p이므로, 초고화질 동영상을 재생할 수 없습니다\n• HDR 동영상을 재생할 수 없습니다</string>
|
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">동영상 코덱을 AVC (H.264)로 강제로 활성화합니다\n\n• 일부 VP9 코덱 동영상에서 삭제되었던 화질 값이 표시될 수 있습니다\n• 최대 화질 값이 1080p이므로, 초고화질 동영상을 재생할 수 없습니다\n• HDR 동영상을 재생할 수 없습니다</string>
|
||||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">동영상 코덱을 자동으로 결정합니다\n\n• 예전에 업로드된 동영상을 재생했는데 VP9 코덱 응답을 받았을 경우, 일부 화질값이 제거되어 360p와 1080p(Premium 기능)만 선택가능할 수 있거나 화질 메뉴를 선택불가능할 수 있습니다</string>
|
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">동영상 코덱을 자동으로 결정합니다\n\n• 예전에 업로드된 동영상을 재생했는데 VP9 코덱 응답을 받았을 경우, 일부 화질값이 삭제되어 360p와 1080p(Premium 기능)만 선택가능할 수 있거나 화질 메뉴를 선택불가능할 수 있습니다</string>
|
||||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"이 설정를 활성화하면 배터리 수명이 향상되고, 동영상 재생 끊김 문제가 해결될 수 있습니다.
|
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"이 설정를 활성화하면 배터리 수명이 향상되고, 동영상 재생 끊김 문제가 해결될 수 있습니다.
|
||||||
|
|
||||||
AVC의 최대 화질 값은 1080p이고, OPUS 코덱을 사용불가 및 HDR 동영상을 재생할 수 없으며, 동영상을 재생했을 경우에는 VP9 또는 AV1보다 더 많은 모바일 데이터를 사용되오니 주의하세요."</string>
|
AVC의 최대 화질 값은 1080p이고, OPUS 코덱을 사용불가 및 HDR 동영상을 재생할 수 없으며, 동영상을 재생했을 경우에는 VP9 또는 AV1보다 더 많은 모바일 데이터를 사용되오니 주의하세요."</string>
|
||||||
@@ -1469,11 +1463,11 @@ AVC의 최대 화질 값은 1080p이고, OPUS 코덱을 사용불가 및 HDR 동
|
|||||||
<string name="revanced_block_video_ads_summary_off">동영상 광고를 차단하지 않습니다</string>
|
<string name="revanced_block_video_ads_summary_off">동영상 광고를 차단하지 않습니다</string>
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="chat.antidelete.showDeletedMessagesPatch">
|
<patch id="chat.antidelete.showDeletedMessagesPatch">
|
||||||
<string name="revanced_deleted_msg">메시지를 제거합니다</string>
|
<string name="revanced_deleted_msg">메시지를 삭제합니다</string>
|
||||||
<string name="revanced_show_deleted_messages_title">제거된 메시지 표시하기</string>
|
<string name="revanced_show_deleted_messages_title">삭제된 메시지 표시하기</string>
|
||||||
<string name="revanced_show_deleted_messages_entry_1">제거된 메시지 표시하지 않기</string>
|
<string name="revanced_show_deleted_messages_entry_1">삭제된 메시지 표시하지 않기</string>
|
||||||
<string name="revanced_show_deleted_messages_entry_2">스포일러 뒤에 제거된 메시지 숨기기</string>
|
<string name="revanced_show_deleted_messages_entry_2">스포일러 뒤에 삭제된 메시지 숨기기</string>
|
||||||
<string name="revanced_show_deleted_messages_entry_3">제거된 메시지를 줄이 그어진 텍스트로 표시하기</string>
|
<string name="revanced_show_deleted_messages_entry_3">삭제된 메시지를 줄이 그어진 텍스트로 표시하기</string>
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="chat.autoclaim.autoClaimChannelPointsPatch">
|
<patch id="chat.autoclaim.autoClaimChannelPointsPatch">
|
||||||
<string name="revanced_auto_claim_channel_points_title">채널 포인트 자동 적립하기</string>
|
<string name="revanced_auto_claim_channel_points_title">채널 포인트 자동 적립하기</string>
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Second \"item\" text"</string>
|
|||||||
<string name="revanced_settings_submenu_title">Nustatymai</string>
|
<string name="revanced_settings_submenu_title">Nustatymai</string>
|
||||||
<string name="revanced_settings_confirm_user_dialog_title">Ar norite tęsti?</string>
|
<string name="revanced_settings_confirm_user_dialog_title">Ar norite tęsti?</string>
|
||||||
<string name="revanced_settings_reset">Atstatyti</string>
|
<string name="revanced_settings_reset">Atstatyti</string>
|
||||||
|
<string name="revanced_settings_reset_color">Atkurti spalvą</string>
|
||||||
|
<string name="revanced_settings_color_invalid">Neteisinga spalva</string>
|
||||||
<string name="revanced_settings_restart_title">Atnaujinti ir paleisti iš naujo</string>
|
<string name="revanced_settings_restart_title">Atnaujinti ir paleisti iš naujo</string>
|
||||||
<string name="revanced_settings_restart">Paleisti iš naujo</string>
|
<string name="revanced_settings_restart">Paleisti iš naujo</string>
|
||||||
<string name="revanced_settings_import">Importuoti</string>
|
<string name="revanced_settings_import">Importuoti</string>
|
||||||
@@ -365,9 +367,6 @@ Apribojimai
|
|||||||
|
|
||||||
Ši funkcija yra prieinama tik senesniuose įrenginiuose"</string>
|
Ši funkcija yra prieinama tik senesniuose įrenginiuose"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary_off">Viso ekrano reklamos yra rodomos</string>
|
<string name="revanced_hide_fullscreen_ads_summary_off">Viso ekrano reklamos yra rodomos</string>
|
||||||
<string name="revanced_hide_buttoned_ads_title">Slėpti reklamas su mygtukais</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_on">Reklamos su mygtukais yra paslėptos</string>
|
|
||||||
<string name="revanced_hide_buttoned_ads_summary_off">Reklamos su mygtukais yra rodomos</string>
|
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Slėpti apmokėtos reklamos etiketę</string>
|
<string name="revanced_hide_paid_promotion_label_title">Slėpti apmokėtos reklamos etiketę</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_on">Apmokėtos reklamos etiketė yra paslėpta</string>
|
<string name="revanced_hide_paid_promotion_label_summary_on">Apmokėtos reklamos etiketė yra paslėpta</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary_off">Apmokėtos reklamos etiketė yra rodoma</string>
|
<string name="revanced_hide_paid_promotion_label_summary_off">Apmokėtos reklamos etiketė yra rodoma</string>
|
||||||
@@ -1098,11 +1097,6 @@ Ar paruošta pateikti?"</string>
|
|||||||
<string name="revanced_sb_stats_saved_second_format">%s sekundės</string>
|
<string name="revanced_sb_stats_saved_second_format">%s sekundės</string>
|
||||||
<string name="revanced_sb_color_opacity_label">Neskaidrumas:</string>
|
<string name="revanced_sb_color_opacity_label">Neskaidrumas:</string>
|
||||||
<string name="revanced_sb_color_dot_label">Spalva:</string>
|
<string name="revanced_sb_color_dot_label">Spalva:</string>
|
||||||
<string name="revanced_sb_color_changed">Spalva pakeista</string>
|
|
||||||
<string name="revanced_sb_color_reset">Spalva atstatyta</string>
|
|
||||||
<string name="revanced_sb_color_invalid">Netinkamas spalvos kodas</string>
|
|
||||||
<string name="revanced_sb_reset_color">Atstatyti spalvą</string>
|
|
||||||
<string name="revanced_sb_reset">Atstatyti</string>
|
|
||||||
<string name="revanced_sb_about_title">Apie</string>
|
<string name="revanced_sb_about_title">Apie</string>
|
||||||
<string name="revanced_sb_about_api_summary">Duomenys pateikiami per \"SponsorBlock\" API. Bakstelėkite čia, kad sužinotumėte daugiau ir pamatytumėte atsisiuntimus kitoms platformoms</string>
|
<string name="revanced_sb_about_api_summary">Duomenys pateikiami per \"SponsorBlock\" API. Bakstelėkite čia, kad sužinotumėte daugiau ir pamatytumėte atsisiuntimus kitoms platformoms</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user