Compare commits

..

37 Commits

Author SHA1 Message Date
semantic-release-bot
f177eae385 chore: Release v5.46.0-dev.6 [skip ci]
# [5.46.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.5...v5.46.0-dev.6) (2025-11-08)

### Features

* **YouTube - Debugging:** Add setting to block experimental client flags ([#6196](https://github.com/ReVanced/revanced-patches/issues/6196)) ([2e9d695](2e9d6959c9))
2025-11-08 08:07:41 +00:00
MarcaD
2e9d6959c9 feat(YouTube - Debugging): Add setting to block experimental client flags (#6196) 2025-11-08 10:01:46 +02:00
semantic-release-bot
81f83690d6 chore: Release v5.46.0-dev.5 [skip ci]
# [5.46.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.4...v5.46.0-dev.5) (2025-11-07)

### Bug Fixes

* **Duolingo - Disable ads:** Constrain patch to last working app target ([f238ae9](f238ae9895))
* **Instagram - Hide navigation buttons:** Constrain patch to last working app target ([e030e9c](e030e9c07a))
* **Spotify - Hide Create button:** Remove obsolete patch that is no longer needed ([#6252](https://github.com/ReVanced/revanced-patches/issues/6252)) ([59d85b2](59d85b28a7))
2025-11-07 11:39:00 +00:00
LisoUseInAIKyrios
f1bd6848c9 chore(deps-dev): Revert bump semantic-release from 24.2.9 to 25.0.1 (#6204)
This reverts commit 55e1a6784b.
2025-11-07 13:36:18 +02:00
LisoUseInAIKyrios
59d85b28a7 fix(Spotify - Hide Create button): Remove obsolete patch that is no longer needed (#6252) 2025-11-07 13:29:34 +02:00
LisoUseInAIKyrios
f238ae9895 fix(Duolingo - Disable ads): Constrain patch to last working app target 2025-11-07 13:27:31 +02:00
LisoUseInAIKyrios
e030e9c07a fix(Instagram - Hide navigation buttons): Constrain patch to last working app target 2025-11-07 13:25:24 +02:00
dependabot[bot]
5029e979be chore(deps): Bump actions/upload-artifact from 4 to 5 (#6201) 2025-11-07 09:34:24 +02:00
dependabot[bot]
55e1a6784b chore(deps-dev): Bump semantic-release from 24.2.9 to 25.0.1 (#6204) 2025-11-07 09:33:23 +02:00
dependabot[bot]
0cad5e73f0 chore(deps): Bump actions/setup-node from 5 to 6 (#6200) 2025-11-07 09:33:05 +02:00
semantic-release-bot
ce503d5b58 chore: Release v5.46.0-dev.4 [skip ci]
# [5.46.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.3...v5.46.0-dev.4) (2025-11-07)

### Bug Fixes

* **YouTube - Check watch history domain name resolution:** Fix false positive warning message if the internet connection fails halfway into the DNS check ([5726353](57263538c7))
2025-11-07 07:17:59 +00:00
LisoUseInAIKyrios
57263538c7 fix(YouTube - Check watch history domain name resolution): Fix false positive warning message if the internet connection fails halfway into the DNS check 2025-11-07 09:14:21 +02:00
semantic-release-bot
70f4955e89 chore: Release v5.46.0-dev.3 [skip ci]
# [5.46.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.2...v5.46.0-dev.3) (2025-11-06)

### Bug Fixes

* **YouTube - Hide layout components:** Fix "Hide Hype points" ([#6247](https://github.com/ReVanced/revanced-patches/issues/6247)) ([5821440](582144026d))
2025-11-06 12:12:38 +00:00
ILoveOpenSourceApplications
582144026d fix(YouTube - Hide layout components): Fix "Hide Hype points" (#6247) 2025-11-06 14:09:43 +02:00
github-actions[bot]
d80892cc0e chore: Sync translations (#6248) 2025-11-06 14:09:25 +02:00
semantic-release-bot
6c4b931b8a chore: Release v5.46.0-dev.2 [skip ci]
# [5.46.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.1...v5.46.0-dev.2) (2025-11-04)

### Bug Fixes

* **YouTube - Settings:** Resolve settings search crash when searching for specific words ([#6231](https://github.com/ReVanced/revanced-patches/issues/6231)) ([76dcfae](76dcfaefd8))
2025-11-04 13:03:33 +00:00
MarcaD
76dcfaefd8 fix(YouTube - Settings): Resolve settings search crash when searching for specific words (#6231) 2025-11-04 14:59:43 +02:00
github-actions[bot]
e4f52343c0 chore: Sync translations (#6239) 2025-11-04 14:59:20 +02:00
semantic-release-bot
1196b1a147 chore: Release v5.46.0-dev.1 [skip ci]
# [5.46.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.45.0...v5.46.0-dev.1) (2025-11-04)

### Features

* **YouTube - Hide layout components:** Add "Hide Hype points" ([#6230](https://github.com/ReVanced/revanced-patches/issues/6230)) ([a52c015](a52c0153b1))
* **YouTube - Hide player flyout menu items:** Add "Hide Listen with YouTube Music" ([#6232](https://github.com/ReVanced/revanced-patches/issues/6232)) ([858edbf](858edbf3e7))
2025-11-04 07:10:24 +00:00
ILoveOpenSourceApplications
858edbf3e7 feat(YouTube - Hide player flyout menu items): Add "Hide Listen with YouTube Music" (#6232) 2025-11-04 09:07:11 +02:00
ILoveOpenSourceApplications
a52c0153b1 feat(YouTube - Hide layout components): Add "Hide Hype points" (#6230) 2025-11-04 09:05:28 +02:00
semantic-release-bot
cd9ef81354 chore: Release v5.45.0 [skip ci]
# [5.45.0](https://github.com/ReVanced/revanced-patches/compare/v5.44.0...v5.45.0) (2025-11-01)

### Bug Fixes

* **Instagram:** Update failing fingerprints on newer versions ([#6181](https://github.com/ReVanced/revanced-patches/issues/6181)) ([c73a03c](c73a03c9e1))
* **TikTok - Downloads:** Fix download path setting  ([#6191](https://github.com/ReVanced/revanced-patches/issues/6191)) ([3e4990a](3e4990afff))
* **YouTube - Change header:** Do not mirror header graphic with RTL languages ([a0c5604](a0c5604951))
* **YouTube - Force original audio:** Fall back to visionOS and not Android Studio if Android VR is not available ([6d01863](6d01863ec7))
* **YouTube - Spoof video streams:** Remove spoof stream audio selector that no longer works ([292fae4](292fae440c))
* **YouTube Music - Hide category bar:** Correctly hide the category bar in newer app targets ([#6175](https://github.com/ReVanced/revanced-patches/issues/6175)) ([13cf172](13cf1724bf))

### Features

* **Spoof video streams:** Add experimental "Android No SDK" client type ([5f23bfe](5f23bfe833))
* **TikTok:** Add `Sanitize sharing links` patch ([#6176](https://github.com/ReVanced/revanced-patches/issues/6176)) ([ef44eaa](ef44eaa119))
* **YouTube - Change Header:** Use SVG for header logo ([#6178](https://github.com/ReVanced/revanced-patches/issues/6178)) ([e9f45ce](e9f45ce926))
2025-11-01 15:36:32 +00:00
LisoUseInAIKyrios
1b2cd64a86 chore: Merge branch dev to main (#6174) 2025-11-01 16:32:23 +01:00
semantic-release-bot
0c03599f07 chore: Release v5.45.0-dev.6 [skip ci]
# [5.45.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.45.0-dev.5...v5.45.0-dev.6) (2025-11-01)

### Features

* **Spoof video streams:** Add experimental "Android No SDK" client type ([5f23bfe](5f23bfe833))
2025-11-01 08:25:19 +00:00
LisoUseInAIKyrios
5f23bfe833 feat(Spoof video streams): Add experimental "Android No SDK" client type 2025-11-01 09:19:49 +01:00
github-actions[bot]
2cf8f0e636 chore: Sync translations (#6197) 2025-11-01 09:17:01 +01:00
semantic-release-bot
c17cf98c7e chore: Release v5.45.0-dev.5 [skip ci]
# [5.45.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.45.0-dev.4...v5.45.0-dev.5) (2025-11-01)

### Bug Fixes

* **TikTok - Downloads:** Fix download path setting  ([#6191](https://github.com/ReVanced/revanced-patches/issues/6191)) ([3e4990a](3e4990afff))
* **YouTube - Spoof video streams:** Remove spoof stream audio selector that no longer works ([292fae4](292fae440c))
2025-11-01 07:36:49 +00:00
hxreborn
3e4990afff fix(TikTok - Downloads): Fix download path setting (#6191) 2025-11-01 08:32:26 +01:00
LisoUseInAIKyrios
292fae440c fix(YouTube - Spoof video streams): Remove spoof stream audio selector that no longer works 2025-11-01 08:31:17 +01:00
semantic-release-bot
12e7c0943a chore: Release v5.45.0-dev.4 [skip ci]
# [5.45.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.45.0-dev.3...v5.45.0-dev.4) (2025-10-30)

### Bug Fixes

* **YouTube - Change header:** Do not mirror header graphic with RTL languages ([a0c5604](a0c5604951))
2025-10-30 08:32:28 +00:00
LisoUseInAIKyrios
a0c5604951 fix(YouTube - Change header): Do not mirror header graphic with RTL languages 2025-10-30 09:27:27 +01:00
LisoUseInAIKyrios
38d9299dfe chore: Add branding license text file (#6179) 2025-10-30 09:26:18 +01:00
semantic-release-bot
dfdbbfa047 chore: Release v5.45.0-dev.3 [skip ci]
# [5.45.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.45.0-dev.2...v5.45.0-dev.3) (2025-10-27)

### Features

* **YouTube - Change Header:** Use SVG for header logo ([#6178](https://github.com/ReVanced/revanced-patches/issues/6178)) ([e9f45ce](e9f45ce926))
2025-10-27 17:14:52 +00:00
MarcaD
e9f45ce926 feat(YouTube - Change Header): Use SVG for header logo (#6178)
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
2025-10-27 21:10:49 +04:00
semantic-release-bot
1b38b1a3c8 chore: Release v5.45.0-dev.2 [skip ci]
# [5.45.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.45.0-dev.1...v5.45.0-dev.2) (2025-10-26)

### Bug Fixes

* **YouTube - Force original audio:** Fall back to visionOS and not Android Studio if Android VR is not available ([6d01863](6d01863ec7))
* **YouTube Music - Hide category bar:** Correctly hide the category bar in newer app targets ([#6175](https://github.com/ReVanced/revanced-patches/issues/6175)) ([13cf172](13cf1724bf))
2025-10-26 15:27:23 +00:00
MarcaD
13cf1724bf fix(YouTube Music - Hide category bar): Correctly hide the category bar in newer app targets (#6175) 2025-10-26 19:23:40 +04:00
LisoUseInAIKyrios
6d01863ec7 fix(YouTube - Force original audio): Fall back to visionOS and not Android Studio if Android VR is not available 2025-10-26 19:23:04 +04:00
188 changed files with 2416 additions and 1314 deletions

View File

@@ -29,7 +29,7 @@ jobs:
run: ./gradlew :patches:buildAndroid --no-daemon
- name: Upload artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: revanced-patches
path: patches/build/libs

View File

@@ -35,7 +35,7 @@ jobs:
run: ./gradlew :patches:buildAndroid clean
- name: Setup Node.js
uses: actions/setup-node@v5
uses: actions/setup-node@v6
with:
node-version: 'lts/*'
cache: 'npm'

View File

@@ -1,3 +1,104 @@
# [5.46.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.5...v5.46.0-dev.6) (2025-11-08)
### Features
* **YouTube - Debugging:** Add setting to block experimental client flags ([#6196](https://github.com/ReVanced/revanced-patches/issues/6196)) ([2e9d695](https://github.com/ReVanced/revanced-patches/commit/2e9d6959c94df7588b9e34b18770e9f437e91926))
# [5.46.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.4...v5.46.0-dev.5) (2025-11-07)
### Bug Fixes
* **Duolingo - Disable ads:** Constrain patch to last working app target ([f238ae9](https://github.com/ReVanced/revanced-patches/commit/f238ae9895000f01d1dccb800cc8efde0d5362bd))
* **Instagram - Hide navigation buttons:** Constrain patch to last working app target ([e030e9c](https://github.com/ReVanced/revanced-patches/commit/e030e9c07a7748e117ac44f6776a9f6317b20623))
* **Spotify - Hide Create button:** Remove obsolete patch that is no longer needed ([#6252](https://github.com/ReVanced/revanced-patches/issues/6252)) ([59d85b2](https://github.com/ReVanced/revanced-patches/commit/59d85b28a7fcb285ff5f2bb6ae654020d76b2019))
# [5.46.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.3...v5.46.0-dev.4) (2025-11-07)
### Bug Fixes
* **YouTube - Check watch history domain name resolution:** Fix false positive warning message if the internet connection fails halfway into the DNS check ([5726353](https://github.com/ReVanced/revanced-patches/commit/57263538c79f5a561c449229ac8e068c641285d3))
# [5.46.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.2...v5.46.0-dev.3) (2025-11-06)
### Bug Fixes
* **YouTube - Hide layout components:** Fix "Hide Hype points" ([#6247](https://github.com/ReVanced/revanced-patches/issues/6247)) ([5821440](https://github.com/ReVanced/revanced-patches/commit/582144026d28e57bb7adcbba39244f3c7cdbc0f3))
# [5.46.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.1...v5.46.0-dev.2) (2025-11-04)
### Bug Fixes
* **YouTube - Settings:** Resolve settings search crash when searching for specific words ([#6231](https://github.com/ReVanced/revanced-patches/issues/6231)) ([76dcfae](https://github.com/ReVanced/revanced-patches/commit/76dcfaefd8679e45a70f265b0239436e60c055cf))
# [5.46.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.45.0...v5.46.0-dev.1) (2025-11-04)
### Features
* **YouTube - Hide layout components:** Add "Hide Hype points" ([#6230](https://github.com/ReVanced/revanced-patches/issues/6230)) ([a52c015](https://github.com/ReVanced/revanced-patches/commit/a52c0153b12c3f6f0ad260e03d2e9850c0466392))
* **YouTube - Hide player flyout menu items:** Add "Hide Listen with YouTube Music" ([#6232](https://github.com/ReVanced/revanced-patches/issues/6232)) ([858edbf](https://github.com/ReVanced/revanced-patches/commit/858edbf3e7f394fcc766d767c8dc54cf5ba24370))
# [5.45.0](https://github.com/ReVanced/revanced-patches/compare/v5.44.0...v5.45.0) (2025-11-01)
### Bug Fixes
* **Instagram:** Update failing fingerprints on newer versions ([#6181](https://github.com/ReVanced/revanced-patches/issues/6181)) ([c73a03c](https://github.com/ReVanced/revanced-patches/commit/c73a03c9e18a12262939c974cdf16221221d1487))
* **TikTok - Downloads:** Fix download path setting ([#6191](https://github.com/ReVanced/revanced-patches/issues/6191)) ([3e4990a](https://github.com/ReVanced/revanced-patches/commit/3e4990afff4c86b93970b153db713ad0f813124d))
* **YouTube - Change header:** Do not mirror header graphic with RTL languages ([a0c5604](https://github.com/ReVanced/revanced-patches/commit/a0c56049510ce040e1ccd49257864672c343344d))
* **YouTube - Force original audio:** Fall back to visionOS and not Android Studio if Android VR is not available ([6d01863](https://github.com/ReVanced/revanced-patches/commit/6d01863ec70617d9abc864ce6686ed9764dd151d))
* **YouTube - Spoof video streams:** Remove spoof stream audio selector that no longer works ([292fae4](https://github.com/ReVanced/revanced-patches/commit/292fae440c6d5694c5e84407becec2d91f1fd156))
* **YouTube Music - Hide category bar:** Correctly hide the category bar in newer app targets ([#6175](https://github.com/ReVanced/revanced-patches/issues/6175)) ([13cf172](https://github.com/ReVanced/revanced-patches/commit/13cf1724bf2f946c7129cab0db96721c90f9fe89))
### Features
* **Spoof video streams:** Add experimental "Android No SDK" client type ([5f23bfe](https://github.com/ReVanced/revanced-patches/commit/5f23bfe833c6e01617a7dbc5325b4a3fb931e53e))
* **TikTok:** Add `Sanitize sharing links` patch ([#6176](https://github.com/ReVanced/revanced-patches/issues/6176)) ([ef44eaa](https://github.com/ReVanced/revanced-patches/commit/ef44eaa119b9d6c5faec051e22d20f883d0da4f1))
* **YouTube - Change Header:** Use SVG for header logo ([#6178](https://github.com/ReVanced/revanced-patches/issues/6178)) ([e9f45ce](https://github.com/ReVanced/revanced-patches/commit/e9f45ce92695d5857473ff71c14b190bded28a73))
# [5.45.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.45.0-dev.5...v5.45.0-dev.6) (2025-11-01)
### Features
* **Spoof video streams:** Add experimental "Android No SDK" client type ([5f23bfe](https://github.com/ReVanced/revanced-patches/commit/5f23bfe833c6e01617a7dbc5325b4a3fb931e53e))
# [5.45.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.45.0-dev.4...v5.45.0-dev.5) (2025-11-01)
### Bug Fixes
* **TikTok - Downloads:** Fix download path setting ([#6191](https://github.com/ReVanced/revanced-patches/issues/6191)) ([3e4990a](https://github.com/ReVanced/revanced-patches/commit/3e4990afff4c86b93970b153db713ad0f813124d))
* **YouTube - Spoof video streams:** Remove spoof stream audio selector that no longer works ([292fae4](https://github.com/ReVanced/revanced-patches/commit/292fae440c6d5694c5e84407becec2d91f1fd156))
# [5.45.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.45.0-dev.3...v5.45.0-dev.4) (2025-10-30)
### Bug Fixes
* **YouTube - Change header:** Do not mirror header graphic with RTL languages ([a0c5604](https://github.com/ReVanced/revanced-patches/commit/a0c56049510ce040e1ccd49257864672c343344d))
# [5.45.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.45.0-dev.2...v5.45.0-dev.3) (2025-10-27)
### Features
* **YouTube - Change Header:** Use SVG for header logo ([#6178](https://github.com/ReVanced/revanced-patches/issues/6178)) ([e9f45ce](https://github.com/ReVanced/revanced-patches/commit/e9f45ce92695d5857473ff71c14b190bded28a73))
# [5.45.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.45.0-dev.1...v5.45.0-dev.2) (2025-10-26)
### Bug Fixes
* **YouTube - Force original audio:** Fall back to visionOS and not Android Studio if Android VR is not available ([6d01863](https://github.com/ReVanced/revanced-patches/commit/6d01863ec70617d9abc864ce6686ed9764dd151d))
* **YouTube Music - Hide category bar:** Correctly hide the category bar in newer app targets ([#6175](https://github.com/ReVanced/revanced-patches/issues/6175)) ([13cf172](https://github.com/ReVanced/revanced-patches/commit/13cf1724bf2f946c7129cab0db96721c90f9fe89))
# [5.45.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.44.0...v5.45.0-dev.1) (2025-10-26)

View File

@@ -19,6 +19,6 @@ public class HideCastButtonPatch {
* Injection point
*/
public static void hideCastButton(View view) {
hideViewBy0dpUnderCondition(Settings.HIDE_CAST_BUTTON.get(), view);
hideViewBy0dpUnderCondition(Settings.HIDE_CAST_BUTTON, view);
}
}

View File

@@ -1,5 +1,8 @@
package app.revanced.extension.music.patches;
import static app.revanced.extension.shared.Utils.hideViewBy0dpUnderCondition;
import android.view.View;
import app.revanced.extension.music.settings.Settings;
@SuppressWarnings("unused")
@@ -8,7 +11,7 @@ public class HideCategoryBarPatch {
/**
* Injection point
*/
public static boolean hideCategoryBar() {
return Settings.HIDE_CATEGORY_BAR.get();
public static void hideCategoryBar(View view) {
hideViewBy0dpUnderCondition(Settings.HIDE_CATEGORY_BAR, view);
}
}

View File

@@ -1,6 +1,7 @@
package app.revanced.extension.music.patches.spoof;
import static app.revanced.extension.music.settings.Settings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE;
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_NO_SDK;
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_VR_1_43_32;
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_VR_1_61_48;
import static app.revanced.extension.shared.spoof.ClientType.VISIONOS;
@@ -18,8 +19,9 @@ public class SpoofVideoStreamsPatch {
public static void setClientOrderToUse() {
List<ClientType> availableClients = List.of(
ANDROID_VR_1_43_32,
ANDROID_VR_1_61_48,
VISIONOS
ANDROID_NO_SDK,
VISIONOS,
ANDROID_VR_1_61_48
);
app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.setClientsToUse(

View File

@@ -16,6 +16,7 @@ import java.util.Arrays;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.ui.Dim;
import com.amazon.video.sdk.player.Player;
@@ -64,9 +65,8 @@ public class PlaybackSpeedPatch {
SpeedIconDrawable speedIcon = new SpeedIconDrawable();
speedButton.setImageDrawable(speedIcon);
int buttonSize = Utils.dipToPixels(48);
speedButton.setMinimumWidth(buttonSize);
speedButton.setMinimumHeight(buttonSize);
speedButton.setMinimumWidth(Dim.dp48);
speedButton.setMinimumHeight(Dim.dp48);
return speedButton;
}
@@ -197,11 +197,11 @@ class SpeedIconDrawable extends Drawable {
@Override
public int getIntrinsicWidth() {
return Utils.dipToPixels(32);
return Dim.dp32;
}
@Override
public int getIntrinsicHeight() {
return Utils.dipToPixels(32);
return Dim.dp32;
}
}

View File

@@ -23,9 +23,7 @@ import android.os.Looper;
import android.preference.Preference;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.util.DisplayMetrics;
import android.util.Pair;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
@@ -45,6 +43,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.text.Bidi;
import java.text.Collator;
import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -61,6 +61,7 @@ import app.revanced.extension.shared.settings.AppLanguage;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.settings.BooleanSetting;
import app.revanced.extension.shared.settings.preference.ReVancedAboutPreference;
import app.revanced.extension.shared.ui.Dim;
@SuppressWarnings("NewApi")
public class Utils {
@@ -79,6 +80,15 @@ public class Utils {
@Nullable
private static Boolean isDarkModeEnabled;
// Cached Collator instance with its locale.
@Nullable
private static Locale cachedCollatorLocale;
@Nullable
private static Collator cachedCollator;
private static final Pattern PUNCTUATION_PATTERN = Pattern.compile("\\p{P}+");
private static final Pattern DIACRITICS_PATTERN = Pattern.compile("\\p{M}");
private Utils() {
} // utility class
@@ -790,13 +800,10 @@ public class Utils {
public static void setDialogWindowParameters(Window window, int gravity, int yOffsetDip, int widthPercentage, boolean dimAmount) {
WindowManager.LayoutParams params = window.getAttributes();
DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
int portraitWidth = Math.min(displayMetrics.widthPixels, displayMetrics.heightPixels);
params.width = (int) (portraitWidth * (widthPercentage / 100.0f)); // Set width based on parameters.
params.width = Dim.pctPortraitWidth(widthPercentage);
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.gravity = gravity;
params.y = yOffsetDip > 0 ? dipToPixels(yOffsetDip) : 0;
params.y = yOffsetDip > 0 ? Dim.dp(yOffsetDip) : 0;
if (dimAmount) {
params.dimAmount = 0f;
}
@@ -805,18 +812,6 @@ public class Utils {
window.setBackgroundDrawable(null); // Remove default dialog background
}
/**
* Creates an array of corner radii for a rounded rectangle shape.
*
* @param dp Radius in density-independent pixels (dip) to apply to all corners.
* @return An array of eight float values representing the corner radii
* (top-left, top-right, bottom-right, bottom-left).
*/
public static float[] createCornerRadii(float dp) {
final float radius = dipToPixels(dp);
return new float[]{radius, radius, radius, radius, radius, radius, radius, radius};
}
/**
* Sets the theme light color used by the app.
*/
@@ -976,30 +971,60 @@ public class Utils {
}
}
private static final Pattern punctuationPattern = Pattern.compile("\\p{P}+");
/**
* Strips all punctuation and converts to lower case. A null parameter returns an empty string.
* Removes punctuation and converts text to lowercase. Returns an empty string if input is null.
*/
public static String removePunctuationToLowercase(@Nullable CharSequence original) {
if (original == null) return "";
return punctuationPattern.matcher(original).replaceAll("")
return PUNCTUATION_PATTERN.matcher(original).replaceAll("")
.toLowerCase(BaseSettings.REVANCED_LANGUAGE.get().getLocale());
}
/**
* Sort a PreferenceGroup and all it's sub groups by title or key.
* Normalizes text for search: applies NFD, removes diacritics, and lowercases (locale-neutral).
* Returns an empty string if input is null.
*/
public static String normalizeTextToLowercase(@Nullable CharSequence original) {
if (original == null) return "";
return DIACRITICS_PATTERN.matcher(Normalizer.normalize(original, Normalizer.Form.NFD))
.replaceAll("").toLowerCase(Locale.ROOT);
}
/**
* Returns a cached Collator for the current locale, or creates a new one if locale changed.
*/
private static Collator getCollator() {
Locale currentLocale = BaseSettings.REVANCED_LANGUAGE.get().getLocale();
if (cachedCollator == null || !currentLocale.equals(cachedCollatorLocale)) {
cachedCollatorLocale = currentLocale;
cachedCollator = Collator.getInstance(currentLocale);
cachedCollator.setStrength(Collator.SECONDARY); // Case-insensitive, diacritic-insensitive.
}
return cachedCollator;
}
/**
* Sorts a {@link PreferenceGroup} and all nested subgroups by title or key.
* <p>
* Sort order is determined by the preferences key {@link Sort} suffix.
* The sort order is controlled by the {@link Sort} suffix present in the preference key.
* Preferences without a key or without a {@link Sort} suffix remain in their original order.
* <p>
* If a preference has no key or no {@link Sort} suffix,
* then the preferences are left unsorted.
* Sorting is performed using {@link Collator} with the current user locale,
* ensuring correct alphabetical ordering for all supported languages
* (e.g., Ukrainian "і", German "ß", French accented characters, etc.).
*
* @param group the {@link PreferenceGroup} to sort
*/
@SuppressWarnings("deprecation")
public static void sortPreferenceGroups(PreferenceGroup group) {
Sort groupSort = Sort.fromKey(group.getKey(), Sort.UNSORTED);
List<Pair<String, Preference>> preferences = new ArrayList<>();
// Get cached Collator for locale-aware string comparison.
Collator collator = getCollator();
for (int i = 0, prefCount = group.getPreferenceCount(); i < prefCount; i++) {
Preference preference = group.getPreference(i);
@@ -1030,10 +1055,11 @@ public class Utils {
preferences.add(new Pair<>(sortValue, preference));
}
//noinspection ComparatorCombinators
// Sort the list using locale-specific collation rules.
Collections.sort(preferences, (pair1, pair2)
-> pair1.first.compareTo(pair2.first));
-> collator.compare(pair1.first, pair2.first));
// Reassign order values to reflect the new sorted sequence
int index = 0;
for (Pair<String, Preference> pair : preferences) {
int order = index++;
@@ -1090,42 +1116,6 @@ public class Utils {
return getResourceColor(colorString);
}
/**
* Converts dip value to actual device pixels.
*
* @param dip The density-independent pixels value.
* @return The device pixel value.
*/
public static int dipToPixels(float dip) {
return (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dip,
Resources.getSystem().getDisplayMetrics()
);
}
/**
* Converts a percentage of the screen height to actual device pixels.
*
* @param percentage The percentage of the screen height (e.g., 30 for 30%).
* @return The device pixel value corresponding to the percentage of screen height.
*/
public static int percentageHeightToPixels(int percentage) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return (int) (metrics.heightPixels * (percentage / 100.0f));
}
/**
* Converts a percentage of the screen width to actual device pixels.
*
* @param percentage The percentage of the screen width (e.g., 30 for 30%).
* @return The device pixel value corresponding to the percentage of screen width.
*/
public static int percentageWidthToPixels(int percentage) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return (int) (metrics.widthPixels * (percentage / 100.0f));
}
/**
* Uses {@link #adjustColorBrightness(int, float)} depending if light or dark mode is active.
*/

View File

@@ -61,7 +61,11 @@ public class CheckWatchHistoryDomainNameResolutionPatch {
// Prevent this false positive by verify youtube.com resolves.
// If youtube.com does not resolve, then it's not a watch history domain resolving error
// because the entire app will not work since no domains are resolving.
if (!domainResolvesToValidIP("youtube.com")
String domainYouTube = "youtube.com";
if (!domainResolvesToValidIP(domainYouTube)
|| domainResolvesToValidIP(HISTORY_TRACKING_ENDPOINT)
// Check multiple times, so a false positive from a flaky connection is almost impossible.
|| !domainResolvesToValidIP(domainYouTube)
|| domainResolvesToValidIP(HISTORY_TRACKING_ENDPOINT)) {
return;
}

View File

@@ -150,14 +150,14 @@ public class CustomBrandingPatch {
}
for (ComponentName disable : componentsToDisable) {
// Use info logging because if the alias status become corrupt the app cannot launch.
Logger.printInfo(() -> "Disabling: " + disable.getClassName());
pm.setComponentEnabledSetting(disable,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
}
// Use info logging because if the alias status become corrupt the app cannot launch.
ComponentName componentToEnableFinal = componentToEnable;
Logger.printInfo(() -> "Enabling: " + componentToEnableFinal.getClassName());
pm.setComponentEnabledSetting(componentToEnable,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
} catch (Exception ex) {

View File

@@ -1,5 +1,9 @@
package app.revanced.extension.shared.patches;
import static java.lang.Boolean.TRUE;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -21,12 +25,28 @@ public final class EnableDebuggingPatch {
? new ConcurrentHashMap<>(800, 0.5f, 1)
: null;
private static final Set<Long> DISABLED_FEATURE_FLAGS = parseFlags(BaseSettings.DISABLED_FEATURE_FLAGS.get());
// Log all disabled flags on app startup.
static {
if (LOG_FEATURE_FLAGS && !DISABLED_FEATURE_FLAGS.isEmpty()) {
StringBuilder sb = new StringBuilder("Disabled feature flags:\n");
for (Long flag : DISABLED_FEATURE_FLAGS) {
sb.append(" ").append(flag).append('\n');
}
Logger.printDebug(sb::toString);
}
}
/**
* Injection point.
*/
public static boolean isBooleanFeatureFlagEnabled(boolean value, Long flag) {
if (LOG_FEATURE_FLAGS && value) {
if (featureFlags.putIfAbsent(flag, true) == null) {
if (DISABLED_FEATURE_FLAGS.contains(flag)) {
return false;
}
if (featureFlags.putIfAbsent(flag, TRUE) == null) {
Logger.printDebug(() -> "boolean feature is enabled: " + flag);
}
}
@@ -70,10 +90,44 @@ public final class EnableDebuggingPatch {
if (LOG_FEATURE_FLAGS && !defaultValue.equals(value)) {
if (featureFlags.putIfAbsent(flag, true) == null) {
Logger.printDebug(() -> " string feature is enabled: " + flag
+ " value: " + value + (defaultValue.isEmpty() ? "" : " default: " + defaultValue));
+ " value: " + value + (defaultValue.isEmpty() ? "" : " default: " + defaultValue));
}
}
return value;
}
/**
* Get all logged feature flags.
* @return Set of all known flags
*/
public static Set<Long> getAllLoggedFlags() {
if (featureFlags != null) {
return new HashSet<>(featureFlags.keySet());
}
return new HashSet<>();
}
/**
* Public method for parsing flags.
* @param flags String containing newline-separated flag IDs
* @return Set of parsed flag IDs
*/
public static Set<Long> parseFlags(String flags) {
Set<Long> parsedFlags = new HashSet<>();
if (!flags.isBlank()) {
for (String flag : flags.split("\n")) {
String trimmedFlag = flag.trim();
if (trimmedFlag.isEmpty()) continue; // Skip empty lines.
try {
parsedFlags.add(Long.parseLong(trimmedFlag));
} catch (NumberFormatException e) {
Logger.printException(() -> "Invalid flag ID: " + flag);
}
}
}
return parsedFlags;
}
}

View File

@@ -7,7 +7,6 @@ import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.preference.PreferenceFragment;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
@@ -16,6 +15,7 @@ import android.widget.Toolbar;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.preference.ToolbarPreferenceFragment;
import app.revanced.extension.shared.ui.Dim;
/**
* Base class for hooking activities to inject a custom PreferenceFragment with a toolbar.
@@ -109,13 +109,12 @@ public abstract class BaseActivityHook extends Activity {
toolbar.setNavigationOnClickListener(getNavigationClickListener(activity));
toolbar.setTitle(STRING_REVANCED_SETTINGS_TITLE);
final int margin = Utils.dipToPixels(16);
toolbar.setTitleMarginStart(margin);
toolbar.setTitleMarginEnd(margin);
toolbar.setTitleMarginStart(Dim.dp16);
toolbar.setTitleMarginEnd(Dim.dp16);
TextView toolbarTextView = Utils.getChildView(toolbar, false, view -> view instanceof TextView);
if (toolbarTextView != null) {
toolbarTextView.setTextColor(Utils.getAppForegroundColor());
toolbarTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
toolbarTextView.setTextSize(20);
}
setToolbarLayoutParams(toolbar);

View File

@@ -4,7 +4,6 @@ import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
import static app.revanced.extension.shared.patches.CustomBrandingPatch.BrandingTheme;
import static app.revanced.extension.shared.settings.Setting.parent;
import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.AudioStreamLanguageOverrideAvailability;
/**
* Settings shared across multiple apps.
@@ -34,7 +33,6 @@ public class BaseSettings {
//
public static final BooleanSetting SPOOF_VIDEO_STREAMS = new BooleanSetting("revanced_spoof_video_streams", TRUE, true, "revanced_spoof_video_streams_user_dialog_message");
public static final EnumSetting<AppLanguage> SPOOF_VIDEO_STREAMS_LANGUAGE = new EnumSetting<>("revanced_spoof_video_streams_language", AppLanguage.DEFAULT, new AudioStreamLanguageOverrideAvailability());
public static final BooleanSetting SPOOF_STREAMING_DATA_STATS_FOR_NERDS = new BooleanSetting("revanced_spoof_streaming_data_stats_for_nerds", TRUE, parent(SPOOF_VIDEO_STREAMS));
public static final BooleanSetting SANITIZE_SHARED_LINKS = new BooleanSetting("revanced_sanitize_sharing_links", TRUE);
@@ -44,4 +42,6 @@ public class BaseSettings {
public static final EnumSetting<BrandingTheme> CUSTOM_BRANDING_ICON = new EnumSetting<>("revanced_custom_branding_icon", BrandingTheme.ORIGINAL, true);
public static final IntegerSetting CUSTOM_BRANDING_NAME = new IntegerSetting("revanced_custom_branding_name", 1, true);
public static final StringSetting DISABLED_FEATURE_FLAGS = new StringSetting("revanced_disabled_feature_flags", "", true, parent(DEBUG));
}

View File

@@ -392,10 +392,13 @@ public abstract class Setting<T> {
/**
* Get the parent Settings that this setting depends on.
* @return List of parent Settings (e.g., BooleanSetting or EnumSetting), or empty list if no dependencies exist.
* @return List of parent Settings, or empty list if no dependencies exist.
* Defensive: handles null availability or missing getParentSettings() override.
*/
public List<Setting<?>> getParentSettings() {
return availability == null ? Collections.emptyList() : availability.getParentSettings();
return availability == null
? Collections.emptyList()
: Objects.requireNonNullElse(availability.getParentSettings(), Collections.emptyList());
}
/**

View File

@@ -1,7 +1,6 @@
package app.revanced.extension.shared.settings.preference;
import static app.revanced.extension.shared.StringRef.str;
import static app.revanced.extension.shared.Utils.dipToPixels;
import static app.revanced.extension.shared.Utils.getResourceIdentifierOrThrow;
import android.app.Dialog;
@@ -37,6 +36,7 @@ import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.shared.settings.StringSetting;
import app.revanced.extension.shared.ui.ColorDot;
import app.revanced.extension.shared.ui.CustomDialog;
import app.revanced.extension.shared.ui.Dim;
/**
* A custom preference for selecting a color via a hexadecimal code or a color picker dialog.
@@ -310,11 +310,8 @@ public class ColorPickerPreference extends EditTextPreference {
inputLayout.setGravity(Gravity.CENTER_VERTICAL);
dialogColorDot = new View(context);
LinearLayout.LayoutParams previewParams = new LinearLayout.LayoutParams(
dipToPixels(20),
dipToPixels(20)
);
previewParams.setMargins(dipToPixels(16), 0, dipToPixels(10), 0);
LinearLayout.LayoutParams previewParams = new LinearLayout.LayoutParams(Dim.dp20,Dim.dp20);
previewParams.setMargins(Dim.dp16, 0, Dim.dp10, 0);
dialogColorDot.setLayoutParams(previewParams);
inputLayout.addView(dialogColorDot);
updateDialogColorDot();

View File

@@ -1,6 +1,5 @@
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;
@@ -21,6 +20,7 @@ import androidx.annotation.ColorInt;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.ui.Dim;
/**
* A custom color picker view that allows the user to select a color using a hue slider, a saturation-value selector
@@ -54,28 +54,28 @@ public class ColorPickerView extends View {
}
/** Expanded touch area for the hue and opacity bars to increase the touch-sensitive area. */
public static final float TOUCH_EXPANSION = dipToPixels(20f);
public static final float TOUCH_EXPANSION = Dim.dp20;
/** Margin between different areas of the view (saturation-value selector, hue bar, and opacity slider). */
private static final float MARGIN_BETWEEN_AREAS = dipToPixels(24);
private static final float MARGIN_BETWEEN_AREAS = Dim.dp24;
/** Padding around the view. */
private static final float VIEW_PADDING = dipToPixels(16);
private static final float VIEW_PADDING = Dim.dp16;
/** Height of the hue bar. */
private static final float HUE_BAR_HEIGHT = dipToPixels(12);
private static final float HUE_BAR_HEIGHT = Dim.dp12;
/** Height of the opacity slider. */
private static final float OPACITY_BAR_HEIGHT = dipToPixels(12);
private static final float OPACITY_BAR_HEIGHT = Dim.dp12;
/** Corner radius for the hue bar. */
private static final float HUE_CORNER_RADIUS = dipToPixels(6);
private static final float HUE_CORNER_RADIUS = Dim.dp6;
/** Corner radius for the opacity slider. */
private static final float OPACITY_CORNER_RADIUS = dipToPixels(6);
private static final float OPACITY_CORNER_RADIUS = Dim.dp6;
/** Radius of the selector handles. */
private static final float SELECTOR_RADIUS = dipToPixels(12);
private static final float SELECTOR_RADIUS = Dim.dp12;
/** Stroke width for the selector handle outlines. */
private static final float SELECTOR_STROKE_WIDTH = 8;
@@ -202,7 +202,7 @@ public class ColorPickerView extends View {
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final float DESIRED_ASPECT_RATIO = 0.8f; // height = width * 0.8
final int minWidth = dipToPixels(250);
final int minWidth = Dim.dp(250);
final int minHeight = (int) (minWidth * DESIRED_ASPECT_RATIO) + (int) (HUE_BAR_HEIGHT + MARGIN_BETWEEN_AREAS)
+ (opacitySliderEnabled ? (int) (OPACITY_BAR_HEIGHT + MARGIN_BETWEEN_AREAS) : 0);

View File

@@ -0,0 +1,621 @@
package app.revanced.extension.shared.settings.preference;
import static app.revanced.extension.shared.StringRef.str;
import static app.revanced.extension.shared.Utils.getResourceIdentifierOrThrow;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.preference.Preference;
import android.text.Editable;
import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Pair;
import android.util.SparseBooleanArray;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Space;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.patches.EnableDebuggingPatch;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.ui.CustomDialog;
import app.revanced.extension.shared.ui.Dim;
/**
* A custom preference that opens a dialog for managing feature flags.
* Allows moving boolean flags between active and blocked states with advanced selection.
*/
@SuppressWarnings({"deprecation", "unused"})
public class FeatureFlagsManagerPreference extends Preference {
private static final int DRAWABLE_REVANCED_SETTINGS_SELECT_ALL =
getResourceIdentifierOrThrow("revanced_settings_select_all", "drawable");
private static final int DRAWABLE_REVANCED_SETTINGS_DESELECT_ALL =
getResourceIdentifierOrThrow("revanced_settings_deselect_all", "drawable");
private static final int DRAWABLE_REVANCED_SETTINGS_COPY_ALL =
getResourceIdentifierOrThrow("revanced_settings_copy_all", "drawable");
private static final int DRAWABLE_REVANCED_SETTINGS_ARROW_RIGHT_ONE =
getResourceIdentifierOrThrow("revanced_settings_arrow_right_one", "drawable");
private static final int DRAWABLE_REVANCED_SETTINGS_ARROW_RIGHT_DOUBLE =
getResourceIdentifierOrThrow("revanced_settings_arrow_right_double", "drawable");
private static final int DRAWABLE_REVANCED_SETTINGS_ARROW_LEFT_ONE =
getResourceIdentifierOrThrow("revanced_settings_arrow_left_one", "drawable");
private static final int DRAWABLE_REVANCED_SETTINGS_ARROW_LEFT_DOUBLE =
getResourceIdentifierOrThrow("revanced_settings_arrow_left_double", "drawable");
/**
* Flags to hide from the UI.
*/
private static final Set<Long> FLAGS_TO_IGNORE = Set.of(
45386834L // 'You' tab settings icon.
);
/**
* Tracks state for range selection in ListView.
*/
private static class ListViewSelectionState {
int lastClickedPosition = -1; // Position of the last clicked item.
boolean isRangeSelecting = false; // True while a range is being selected.
}
/**
* Helper class to pass ListView and Adapter together.
*/
private record ColumnViews(ListView listView, FlagAdapter adapter) {}
{
setOnPreferenceClickListener(pref -> {
showFlagsManagerDialog();
return true;
});
}
public FeatureFlagsManagerPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public FeatureFlagsManagerPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public FeatureFlagsManagerPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FeatureFlagsManagerPreference(Context context) {
super(context);
}
/**
* Shows the main dialog for managing feature flags.
*/
private void showFlagsManagerDialog() {
if (!BaseSettings.DEBUG.get()) {
Utils.showToastShort(str("revanced_debug_logs_disabled"));
return;
}
Context context = getContext();
// Load all known and disabled flags.
TreeSet<Long> allKnownFlags = new TreeSet<>(EnableDebuggingPatch.getAllLoggedFlags());
allKnownFlags.removeAll(FLAGS_TO_IGNORE);
TreeSet<Long> disabledFlags = new TreeSet<>(EnableDebuggingPatch.parseFlags(
BaseSettings.DISABLED_FEATURE_FLAGS.get()));
disabledFlags.removeAll(FLAGS_TO_IGNORE);
if (allKnownFlags.isEmpty() && disabledFlags.isEmpty()) {
// String does not need to be localized because it's basically impossible
// to reach the settings menu without encountering at least 1 flag.
Utils.showToastShort("No feature flags logged yet");
return;
}
TreeSet<Long> availableFlags = new TreeSet<>(allKnownFlags);
availableFlags.removeAll(disabledFlags);
TreeSet<Long> blockedFlags = new TreeSet<>(disabledFlags);
Pair<Dialog, LinearLayout> dialogPair = CustomDialog.create(
context,
getTitle() != null ? getTitle().toString() : "",
null,
null,
str("revanced_settings_save"),
() -> saveFlags(blockedFlags),
() -> {},
str("revanced_settings_reset"),
this::resetFlags,
true
);
LinearLayout mainLayout = dialogPair.second;
LinearLayout.LayoutParams contentParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, 0, 1.0f);
// Insert content before the dialog button row.
View contentView = createContentView(context, availableFlags, blockedFlags);
mainLayout.addView(contentView, mainLayout.getChildCount() - 1, contentParams);
Dialog dialog = dialogPair.first;
dialog.show();
Window window = dialog.getWindow();
if (window != null) {
Utils.setDialogWindowParameters(window, Gravity.CENTER, 0, 100, false);
}
}
/**
* Creates the main content view with two columns.
*/
private View createContentView(Context context, TreeSet<Long> availableFlags, TreeSet<Long> blockedFlags) {
LinearLayout contentLayout = new LinearLayout(context);
contentLayout.setOrientation(LinearLayout.VERTICAL);
// Headers.
TextView availableHeader = createHeader(context, "revanced_debug_feature_flags_manager_active_header");
TextView blockedHeader = createHeader(context, "revanced_debug_feature_flags_manager_blocked_header");
LinearLayout headersLayout = new LinearLayout(context);
headersLayout.setOrientation(LinearLayout.HORIZONTAL);
headersLayout.addView(availableHeader, new LinearLayout.LayoutParams(
0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
headersLayout.addView(blockedHeader, new LinearLayout.LayoutParams(
0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
// Columns.
View leftColumn = createColumn(context, availableFlags, availableHeader);
View rightColumn = createColumn(context, blockedFlags, blockedHeader);
ColumnViews leftViews = (ColumnViews) leftColumn.getTag();
ColumnViews rightViews = (ColumnViews) rightColumn.getTag();
updateHeaderCount(availableHeader, leftViews.adapter);
updateHeaderCount(blockedHeader, rightViews.adapter);
// Main columns layout.
LinearLayout columnsLayout = new LinearLayout(context);
columnsLayout.setOrientation(LinearLayout.HORIZONTAL);
columnsLayout.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f));
columnsLayout.addView(leftColumn, new LinearLayout.LayoutParams(
0, ViewGroup.LayoutParams.MATCH_PARENT, 1f));
Space spaceBetweenColumns = new Space(context);
spaceBetweenColumns.setLayoutParams(new LinearLayout.LayoutParams(Dim.dp8, ViewGroup.LayoutParams.MATCH_PARENT));
columnsLayout.addView(spaceBetweenColumns);
columnsLayout.addView(rightColumn, new LinearLayout.LayoutParams(
0, ViewGroup.LayoutParams.MATCH_PARENT, 1f));
// Move buttons below columns.
Pair<LinearLayout, LinearLayout> moveButtons = createMoveButtons(context,
leftViews.listView, rightViews.listView,
availableFlags, blockedFlags, availableHeader, blockedHeader);
// Layout for buttons row.
LinearLayout buttonsRow = new LinearLayout(context);
buttonsRow.setOrientation(LinearLayout.HORIZONTAL);
buttonsRow.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
buttonsRow.addView(moveButtons.first, new LinearLayout.LayoutParams(
0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
Space spaceBetweenButtons = new Space(context);
spaceBetweenButtons.setLayoutParams(new LinearLayout.LayoutParams(Dim.dp8, ViewGroup.LayoutParams.WRAP_CONTENT));
buttonsRow.addView(spaceBetweenButtons);
buttonsRow.addView(moveButtons.second, new LinearLayout.LayoutParams(
0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
contentLayout.addView(headersLayout);
contentLayout.addView(columnsLayout);
contentLayout.addView(buttonsRow);
return contentLayout;
}
/**
* Creates a header TextView.
*/
private TextView createHeader(Context context, String tag) {
TextView textview = new TextView(context);
textview.setTag(tag);
textview.setTextSize(16);
textview.setTextColor(Utils.getAppForegroundColor());
textview.setGravity(Gravity.CENTER);
return textview;
}
/**
* Creates a single column (search + buttons + list).
*/
private View createColumn(Context context, TreeSet<Long> flags, TextView countText) {
LinearLayout wrapper = new LinearLayout(context);
wrapper.setOrientation(LinearLayout.VERTICAL);
Pair<ListView, FlagAdapter> pair = createListView(context, flags, countText);
ListView listView = pair.first;
FlagAdapter adapter = pair.second;
EditText search = createSearchBox(context, adapter, listView, countText);
LinearLayout buttons = createActionButtons(context, listView, adapter);
listView.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f));
ShapeDrawable background = new ShapeDrawable(new RoundRectShape(
Dim.roundedCorners(10), null, null));
background.getPaint().setColor(Utils.getEditTextBackground());
listView.setPadding(0, Dim.dp4, 0, Dim.dp4);
listView.setBackground(background);
listView.setOverScrollMode(View.OVER_SCROLL_NEVER);
wrapper.addView(search);
wrapper.addView(buttons);
wrapper.addView(listView);
// Save references for move buttons.
wrapper.setTag(new ColumnViews(listView, adapter));
return wrapper;
}
/**
* Updates the header text with the current count.
*/
private void updateHeaderCount(TextView header, FlagAdapter adapter) {
header.setText(str((String) header.getTag(), adapter.getCount()));
}
/**
* Creates a search box that filters the list.
*/
@SuppressLint("ClickableViewAccessibility")
private EditText createSearchBox(Context context, FlagAdapter adapter, ListView listView, TextView countText) {
EditText search = new EditText(context);
search.setInputType(InputType.TYPE_CLASS_NUMBER);
search.setTextSize(16);
search.setHint(str("revanced_debug_feature_flags_manager_search_hint"));
search.setHapticFeedbackEnabled(false);
search.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
search.addTextChangedListener(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) {
adapter.setSearchQuery(s.toString());
listView.clearChoices();
updateHeaderCount(countText, adapter);
Drawable clearIcon = context.getResources().getDrawable(android.R.drawable.ic_menu_close_clear_cancel);
clearIcon.setBounds(0, 0, Dim.dp20, Dim.dp20);
search.setCompoundDrawables(null, null, TextUtils.isEmpty(s) ? null : clearIcon, null);
}
@Override public void afterTextChanged(Editable s) {}
});
search.setOnTouchListener((v, event) -> {
if (event.getAction() == MotionEvent.ACTION_UP) {
Drawable[] compoundDrawables = search.getCompoundDrawables();
if (compoundDrawables[2] != null &&
event.getRawX() >= (search.getRight() - compoundDrawables[2].getBounds().width())) {
search.setText("");
return true;
}
}
return false;
});
return search;
}
/**
* Creates action buttons.
*/
private LinearLayout createActionButtons(Context context, ListView listView, FlagAdapter adapter) {
LinearLayout row = new LinearLayout(context);
row.setOrientation(LinearLayout.HORIZONTAL);
row.setGravity(Gravity.CENTER);
row.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
ImageButton selectAll = createButton(context, DRAWABLE_REVANCED_SETTINGS_SELECT_ALL,
() -> {
for (int i = 0, count = adapter.getCount(); i < count; i++) {
listView.setItemChecked(i, true);
}
});
ImageButton clearAll = createButton(context, DRAWABLE_REVANCED_SETTINGS_DESELECT_ALL,
() -> {
listView.clearChoices();
adapter.notifyDataSetChanged();
});
ImageButton copy = createButton(context, DRAWABLE_REVANCED_SETTINGS_COPY_ALL,
() -> {
List<String> items = new ArrayList<>();
SparseBooleanArray checked = listView.getCheckedItemPositions();
if (checked.size() > 0) {
for (int i = 0, count = adapter.getCount(); i < count; i++) {
if (checked.get(i)) {
items.add(adapter.getItem(i));
}
}
} else {
for (Long flag : adapter.getFullFlags()) {
items.add(String.valueOf(flag));
}
}
Utils.setClipboard(TextUtils.join("\n", items));
Utils.showToastShort(str("revanced_debug_feature_flags_manager_toast_copied"));
});
row.addView(selectAll);
row.addView(clearAll);
row.addView(copy);
return row;
}
/**
* Creates the move buttons (left and right groups).
*/
private Pair<LinearLayout, LinearLayout> createMoveButtons(Context context,
ListView availableListView, ListView blockedListView,
TreeSet<Long> availableFlags, TreeSet<Long> blockedFlags,
TextView availableCountText, TextView blockedCountText) {
// Left group: >> >
LinearLayout leftButtons = new LinearLayout(context);
leftButtons.setOrientation(LinearLayout.HORIZONTAL);
leftButtons.setGravity(Gravity.CENTER);
ImageButton moveAllRight = createButton(context, DRAWABLE_REVANCED_SETTINGS_ARROW_RIGHT_DOUBLE,
() -> moveFlags(availableListView, blockedListView, availableFlags, blockedFlags,
availableCountText, blockedCountText, true));
ImageButton moveOneRight = createButton(context, DRAWABLE_REVANCED_SETTINGS_ARROW_RIGHT_ONE,
() -> moveFlags(availableListView, blockedListView, availableFlags, blockedFlags,
availableCountText, blockedCountText, false));
leftButtons.addView(moveAllRight);
leftButtons.addView(moveOneRight);
// Right group: < <<
LinearLayout rightButtons = new LinearLayout(context);
rightButtons.setOrientation(LinearLayout.HORIZONTAL);
rightButtons.setGravity(Gravity.CENTER);
ImageButton moveOneLeft = createButton(context, DRAWABLE_REVANCED_SETTINGS_ARROW_LEFT_ONE,
() -> moveFlags(blockedListView, availableListView, blockedFlags, availableFlags,
blockedCountText, availableCountText, false));
ImageButton moveAllLeft = createButton(context, DRAWABLE_REVANCED_SETTINGS_ARROW_LEFT_DOUBLE,
() -> moveFlags(blockedListView, availableListView, blockedFlags, availableFlags,
blockedCountText, availableCountText, true));
rightButtons.addView(moveOneLeft);
rightButtons.addView(moveAllLeft);
return new Pair<>(leftButtons, rightButtons);
}
/**
* Creates a styled ImageButton.
*/
@SuppressLint("ResourceType")
private ImageButton createButton(Context context, int drawableResId, Runnable action) {
ImageButton button = new ImageButton(context);
button.setImageResource(drawableResId);
button.setScaleType(ImageView.ScaleType.CENTER);
int[] attrs = {android.R.attr.selectableItemBackgroundBorderless};
try (TypedArray ripple = context.obtainStyledAttributes(attrs)) {
button.setBackgroundDrawable(ripple.getDrawable(0));
}
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(Dim.dp32, Dim.dp32);
params.setMargins(Dim.dp8, Dim.dp8, Dim.dp8, Dim.dp8);
button.setLayoutParams(params);
button.setOnClickListener(v -> action.run());
return button;
}
/**
* Custom adapter with search filtering.
*/
private static class FlagAdapter extends ArrayAdapter<String> {
private final TreeSet<Long> fullFlags;
private String searchQuery = "";
public FlagAdapter(Context context, TreeSet<Long> fullFlags) {
super(context, android.R.layout.simple_list_item_multiple_choice, new ArrayList<>());
this.fullFlags = fullFlags;
updateFiltered();
}
public void setSearchQuery(String query) {
searchQuery = query == null ? "" : query.trim();
updateFiltered();
}
private void updateFiltered() {
clear();
for (Long flag : fullFlags) {
String flagString = String.valueOf(flag);
if (searchQuery.isEmpty() || flagString.contains(searchQuery)) {
add(flagString);
}
}
notifyDataSetChanged();
}
public void refresh() {
updateFiltered();
}
public List<Long> getFullFlags() {
return new ArrayList<>(fullFlags);
}
}
/**
* Creates a ListView with filtering, multi-select, and range selection.
*/
@SuppressLint("ClickableViewAccessibility")
private Pair<ListView, FlagAdapter> createListView(Context context,
TreeSet<Long> flags, TextView countText) {
ListView listView = new ListView(context);
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
listView.setDividerHeight(0);
FlagAdapter adapter = new FlagAdapter(context, flags);
listView.setAdapter(adapter);
final ListViewSelectionState state = new ListViewSelectionState();
listView.setOnItemClickListener((parent, view, position, id) -> {
if (!state.isRangeSelecting) {
state.lastClickedPosition = position;
} else {
state.isRangeSelecting = false;
}
});
listView.setOnItemLongClickListener((parent, view, position, id) -> {
if (state.lastClickedPosition == -1) {
listView.setItemChecked(position, true);
state.lastClickedPosition = position;
} else {
int start = Math.min(state.lastClickedPosition, position);
int end = Math.max(state.lastClickedPosition, position);
for (int i = start; i <= end; i++) {
listView.setItemChecked(i, true);
}
state.isRangeSelecting = true;
}
return true;
});
listView.setOnTouchListener((view, event) -> {
if (event.getAction() == MotionEvent.ACTION_UP && state.isRangeSelecting) {
state.isRangeSelecting = false;
}
return false;
});
return new Pair<>(listView, adapter);
}
/**
* Moves selected or all flags from one list to another.
*
* @param fromListView Source ListView.
* @param toListView Destination ListView.
* @param fromFlags Source flag set.
* @param toFlags Destination flag set.
* @param fromCountText Header showing count of source items.
* @param toCountText Header showing count of destination items.
* @param moveAll If true, move all items; if false, move only selected.
*/
private void moveFlags(ListView fromListView, ListView toListView,
TreeSet<Long> fromFlags, TreeSet<Long> toFlags,
TextView fromCountText, TextView toCountText,
boolean moveAll) {
if (fromListView == null || toListView == null) return;
List<Long> flagsToMove = new ArrayList<>();
FlagAdapter fromAdapter = (FlagAdapter) fromListView.getAdapter();
if (moveAll) {
flagsToMove.addAll(fromFlags);
} else {
SparseBooleanArray checked = fromListView.getCheckedItemPositions();
for (int i = 0, count = fromAdapter.getCount(); i < count; i++) {
if (checked.get(i)) {
String item = fromAdapter.getItem(i);
if (item != null) {
flagsToMove.add(Long.parseLong(item));
}
}
}
}
if (flagsToMove.isEmpty()) return;
for (Long flag : flagsToMove) {
fromFlags.remove(flag);
toFlags.add(flag);
}
// Clear selections before refreshing.
fromListView.clearChoices();
toListView.clearChoices();
// Refresh both adapters.
fromAdapter.refresh();
((FlagAdapter) toListView.getAdapter()).refresh();
// Update headers.
updateHeaderCount(fromCountText, fromAdapter);
updateHeaderCount(toCountText, (FlagAdapter) toListView.getAdapter());
}
/**
* Saves blocked flags to settings.
*/
private void saveFlags(TreeSet<Long> blockedFlags) {
StringBuilder flagsString = new StringBuilder();
for (Long flag : blockedFlags) {
if (flagsString.length() > 0) {
flagsString.append("\n");
}
flagsString.append(flag);
}
BaseSettings.DISABLED_FEATURE_FLAGS.save(flagsString.toString());
Utils.showToastShort(str("revanced_debug_feature_flags_manager_toast_saved"));
Logger.printDebug(() -> "Feature flags saved. Blocked: " + blockedFlags.size());
AbstractPreferenceFragment.showRestartDialog(getContext());
}
/**
* Resets all blocked flags.
*/
private void resetFlags() {
BaseSettings.DISABLED_FEATURE_FLAGS.save("");
Utils.showToastShort(str("revanced_debug_feature_flags_manager_toast_reset"));
AbstractPreferenceFragment.showRestartDialog(getContext());
}
}

View File

@@ -11,7 +11,6 @@ import android.preference.Preference;
import android.text.InputType;
import android.util.AttributeSet;
import android.util.Pair;
import android.util.TypedValue;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.LinearLayout;
@@ -20,6 +19,7 @@ import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.shared.ui.CustomDialog;
import app.revanced.extension.shared.ui.Dim;
@SuppressWarnings({"unused", "deprecation"})
public class ImportExportPreference extends EditTextPreference implements Preference.OnPreferenceClickListener {
@@ -35,7 +35,7 @@ public class ImportExportPreference extends EditTextPreference implements Prefer
editText.setAutofillHints((String) null);
}
editText.setInputType(editText.getInputType() | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
editText.setTextSize(TypedValue.COMPLEX_UNIT_PT, 7); // Use a smaller font to reduce text wrap.
editText.setTextSize(14);
setOnPreferenceClickListener(this);
}

View File

@@ -1,7 +1,6 @@
package app.revanced.extension.shared.settings.preference;
import static app.revanced.extension.shared.StringRef.str;
import static app.revanced.extension.shared.Utils.dipToPixels;
import static app.revanced.extension.shared.requests.Route.Method.GET;
import android.annotation.SuppressLint;
@@ -41,6 +40,7 @@ import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.requests.Requester;
import app.revanced.extension.shared.requests.Route;
import app.revanced.extension.shared.ui.Dim;
/**
* Opens a dialog showing official links.
@@ -222,11 +222,10 @@ class WebViewDialog extends Dialog {
LinearLayout mainLayout = new LinearLayout(getContext());
mainLayout.setOrientation(LinearLayout.VERTICAL);
final int padding = dipToPixels(10);
mainLayout.setPadding(padding, padding, padding, padding);
mainLayout.setPadding(Dim.dp10, Dim.dp10, Dim.dp10, Dim.dp10);
// Set rounded rectangle background.
ShapeDrawable mainBackground = new ShapeDrawable(new RoundRectShape(
Utils.createCornerRadii(28), null, null));
Dim.roundedCorners(28), null, null));
mainBackground.getPaint().setColor(Utils.getDialogBackgroundColor());
mainLayout.setBackground(mainBackground);

View File

@@ -8,7 +8,6 @@ import android.os.Build;
import android.preference.Preference;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.util.TypedValue;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowInsets;
@@ -20,6 +19,7 @@ import androidx.annotation.Nullable;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.BaseActivityHook;
import app.revanced.extension.shared.ui.Dim;
@SuppressWarnings({"deprecation", "NewApi"})
public class ToolbarPreferenceFragment extends AbstractPreferenceFragment {
@@ -88,14 +88,13 @@ public class ToolbarPreferenceFragment extends AbstractPreferenceFragment {
toolbar.setNavigationIcon(getBackButtonDrawable());
toolbar.setNavigationOnClickListener(view -> preferenceScreenDialog.dismiss());
final int margin = Utils.dipToPixels(16);
toolbar.setTitleMargin(margin, 0, margin, 0);
toolbar.setTitleMargin(Dim.dp16, 0, Dim.dp16, 0);
TextView toolbarTextView = Utils.getChildView(toolbar,
true, TextView.class::isInstance);
if (toolbarTextView != null) {
toolbarTextView.setTextColor(Utils.getAppForegroundColor());
toolbarTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
toolbarTextView.setTextSize(20);
}
// Allow package-specific toolbar customization.

View File

@@ -75,7 +75,7 @@ public abstract class BaseSearchResultItem {
// Shared method for highlighting text with search query.
protected static CharSequence highlightSearchQuery(CharSequence text, Pattern queryPattern) {
if (TextUtils.isEmpty(text)) return text;
if (TextUtils.isEmpty(text) || queryPattern == null) return text;
final int adjustedColor = Utils.adjustColorBrightness(
Utils.getAppBackgroundColor(), 0.95f, 1.20f);
@@ -84,7 +84,10 @@ public abstract class BaseSearchResultItem {
Matcher matcher = queryPattern.matcher(text);
while (matcher.find()) {
spannable.setSpan(highlightSpan, matcher.start(), matcher.end(),
int start = matcher.start();
int end = matcher.end();
if (start == end) continue; // Skip zero matches.
spannable.setSpan(highlightSpan, start, end,
SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE);
}
@@ -224,10 +227,14 @@ public abstract class BaseSearchResultItem {
return searchBuilder.toString();
}
/**
* Appends normalized searchable text to the builder.
* Uses full Unicode normalization for accurate search across all languages.
*/
private void appendText(StringBuilder builder, CharSequence text) {
if (!TextUtils.isEmpty(text)) {
if (builder.length() > 0) builder.append(" ");
builder.append(Utils.removePunctuationToLowercase(text));
builder.append(Utils.normalizeTextToLowercase(text));
}
}
@@ -272,7 +279,7 @@ public abstract class BaseSearchResultItem {
*/
@Override
boolean matchesQuery(String query) {
return searchableText.contains(Utils.removePunctuationToLowercase(query));
return searchableText.contains(Utils.normalizeTextToLowercase(query));
}
/**

View File

@@ -484,7 +484,7 @@ public abstract class BaseSearchResultsAdapter extends ArrayAdapter<BaseSearchRe
return -1;
}
for (int i = 0; i < adapter.getCount(); i++) {
for (int i = 0, count = adapter.getCount(); i < count; i++) {
Object item = adapter.getItem(i);
if (item == targetPreference) {
return i;
@@ -522,8 +522,8 @@ public abstract class BaseSearchResultsAdapter extends ArrayAdapter<BaseSearchRe
if (currentAnimator != null && currentAnimator.isRunning()) {
currentAnimator.cancel();
}
int startColor = Utils.getAppBackgroundColor();
int highlightColor = Utils.adjustColorBrightness(
final int startColor = Utils.getAppBackgroundColor();
final int highlightColor = Utils.adjustColorBrightness(
startColor,
Utils.isDarkModeEnabled() ? 1.25f : 0.8f
);
@@ -566,7 +566,7 @@ public abstract class BaseSearchResultsAdapter extends ArrayAdapter<BaseSearchRe
}
// First search on current level.
for (int i = 0; i < group.getPreferenceCount(); i++) {
for (int i = 0, count = group.getPreferenceCount(); i < count; i++) {
Preference pref = group.getPreference(i);
if (key.equals(pref.getKey())) {
return pref;

View File

@@ -13,7 +13,6 @@ import android.preference.PreferenceCategory;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
@@ -45,6 +44,7 @@ import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.shared.settings.preference.ColorPickerPreference;
import app.revanced.extension.shared.settings.preference.CustomDialogListPreference;
import app.revanced.extension.shared.settings.preference.NoTitlePreferenceCategory;
import app.revanced.extension.shared.ui.Dim;
/**
* Abstract controller for managing the overlay search view in ReVanced settings.
@@ -123,7 +123,7 @@ public abstract class BaseSearchViewController {
searchView.setQueryHint(str("revanced_settings_search_hint"));
// Set text size.
searchEditText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
searchEditText.setTextSize(16);
// Set cursor color.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
@@ -149,7 +149,7 @@ public abstract class BaseSearchViewController {
// Create cursor drawable.
GradientDrawable cursorDrawable = new GradientDrawable();
cursorDrawable.setShape(GradientDrawable.RECTANGLE);
cursorDrawable.setSize(Utils.dipToPixels(2), -1); // Width: 2dp, Height: match text height.
cursorDrawable.setSize(Dim.dp2, -1); // Width: 2dp, Height: match text height.
cursorDrawable.setColor(cursorColor);
// Set cursor drawable.
@@ -164,7 +164,7 @@ public abstract class BaseSearchViewController {
overlayContainer = new FrameLayout(activity);
overlayContainer.setVisibility(View.GONE);
overlayContainer.setBackgroundColor(Utils.getAppBackgroundColor());
overlayContainer.setElevation(Utils.dipToPixels(8));
overlayContainer.setElevation(Dim.dp8);
// Container for search results.
FrameLayout searchResultsContainer = new FrameLayout(activity);
@@ -450,7 +450,7 @@ public abstract class BaseSearchViewController {
filteredSearchItems.clear();
String queryLower = Utils.removePunctuationToLowercase(query);
String queryLower = Utils.normalizeTextToLowercase(query);
Pattern queryPattern = Pattern.compile(Pattern.quote(queryLower), Pattern.CASE_INSENSITIVE);
// Clear highlighting only for items that were previously visible.
@@ -669,7 +669,7 @@ public abstract class BaseSearchViewController {
protected static GradientDrawable createBackgroundDrawable() {
GradientDrawable background = new GradientDrawable();
background.setShape(GradientDrawable.RECTANGLE);
background.setCornerRadius(Utils.dipToPixels(28));
background.setCornerRadius(Dim.dp28);
background.setColor(getSearchViewBackground());
return background;
}

View File

@@ -54,6 +54,33 @@ public enum ClientType {
ANDROID_VR_1_61_48.supportsMultiAudioTracks,
"Android VR 1.43"
),
/**
* Video not playable: Paid / Movie / Private / Age-restricted.
* Note: The 'Authorization' key must be excluded from the header.
*
* According to TeamNewPipe in 2022, if the 'androidSdkVersion' field is missing,
* the GVS did not return a valid response:
* [NewPipe#8713 (comment)](https://github.com/TeamNewPipe/NewPipe/issues/8713#issuecomment-1207443550).
*
* According to the latest commit in yt-dlp, the GVS returns a valid response
* even if the 'androidSdkVersion' field is missing:
* [yt-dlp#14693](https://github.com/yt-dlp/yt-dlp/pull/14693).
*
* For some reason, PoToken is not required.
*/
ANDROID_NO_SDK(
3,
"ANDROID",
"",
"",
"",
Build.VERSION.RELEASE,
"20.05.46",
"com.google.android.youtube/20.05.46 (Linux; U; Android " + Build.VERSION.RELEASE + ") gzip",
false,
true,
"Android No SDK"
),
/**
* Cannot play livestreams and lacks HDR, but can play videos with music and labeled "for children".
* <a href="https://dumps.tadiphone.dev/dumps/google/barbet">Google Pixel 9 Pro Fold</a>

View File

@@ -14,19 +14,11 @@ import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.AppLanguage;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.shared.spoof.requests.StreamingDataRequest;
@SuppressWarnings("unused")
public class SpoofVideoStreamsPatch {
public static final class AudioStreamLanguageOverrideAvailability implements Setting.Availability {
@Override
public boolean isAvailable() {
return BaseSettings.SPOOF_VIDEO_STREAMS.get() && !preferredClient.useAuth;
}
}
/**
* Domain used for internet connectivity verification.
* It has an empty response body and is only used to check for a 204 response code.
@@ -62,8 +54,7 @@ public class SpoofVideoStreamsPatch {
}
/**
* @param language Language override for non-authenticated requests. If this is null then
* {@link BaseSettings#SPOOF_VIDEO_STREAMS_LANGUAGE} is used.
* @param language Language override for non-authenticated requests.
*/
public static void setLanguageOverride(@Nullable AppLanguage language) {
languageOverride = language;

View File

@@ -1,7 +1,5 @@
package app.revanced.extension.shared.spoof.requests;
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_VR_1_43_32;
import org.json.JSONException;
import org.json.JSONObject;
@@ -13,7 +11,6 @@ import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.requests.Requester;
import app.revanced.extension.shared.requests.Route;
import app.revanced.extension.shared.settings.AppLanguage;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.shared.spoof.ClientType;
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
@@ -44,7 +41,7 @@ final class PlayerRoutes {
AppLanguage language = SpoofVideoStreamsPatch.getLanguageOverride();
if (language == null) {
// Force original audio has not overrode the language.
language = BaseSettings.SPOOF_VIDEO_STREAMS_LANGUAGE.get();
language = AppLanguage.DEFAULT;
}
//noinspection ExtractMethodRecommender
Locale streamLocale = language.getLocale();

View File

@@ -1,7 +1,6 @@
package app.revanced.extension.shared.ui;
import static app.revanced.extension.shared.Utils.adjustColorBrightness;
import static app.revanced.extension.shared.Utils.dipToPixels;
import static app.revanced.extension.shared.Utils.getAppBackgroundColor;
import static app.revanced.extension.shared.Utils.isDarkModeEnabled;
import static app.revanced.extension.shared.settings.preference.ColorPickerPreference.DISABLED_ALPHA;
@@ -13,7 +12,7 @@ import android.view.View;
import androidx.annotation.ColorInt;
public class ColorDot {
private static final int STROKE_WIDTH = dipToPixels(1.5f); // Stroke width in dp.
private static final int STROKE_WIDTH = Dim.dp(1.5f);
/**
* Creates a circular drawable with a main fill and a stroke.
@@ -55,7 +54,7 @@ public class ColorDot {
targetView.setAlpha(enabled ? 1.0f : DISABLED_ALPHA);
if (!isDarkModeEnabled()) {
targetView.setClipToOutline(true);
targetView.setElevation(dipToPixels(2));
targetView.setElevation(Dim.dp2);
}
}
}

View File

@@ -1,7 +1,5 @@
package app.revanced.extension.shared.ui;
import static app.revanced.extension.shared.Utils.dipToPixels;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
@@ -37,7 +35,6 @@ public class CustomDialog {
private final Context context;
private final Dialog dialog;
private final LinearLayout mainLayout;
private final int dip4, dip8, dip16, dip24, dip36;
/**
* Creates a custom dialog with a styled layout, including a title, message, buttons, and an optional EditText.
@@ -93,13 +90,6 @@ public class CustomDialog {
this.dialog = new Dialog(context);
this.dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); // Remove default title bar.
// Preset size constants.
dip4 = dipToPixels(4);
dip8 = dipToPixels(8);
dip16 = dipToPixels(16);
dip24 = dipToPixels(24);
dip36 = dipToPixels(36);
// Create main layout.
mainLayout = createMainLayout();
addTitle(title);
@@ -122,11 +112,11 @@ public class CustomDialog {
private LinearLayout createMainLayout() {
LinearLayout layout = new LinearLayout(context);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setPadding(dip24, dip16, dip24, dip24);
layout.setPadding(Dim.dp24, Dim.dp16, Dim.dp24, Dim.dp24);
// Set rounded rectangle background.
ShapeDrawable background = new ShapeDrawable(new RoundRectShape(
Utils.createCornerRadii(28), null, null));
Dim.roundedCorners(28), null, null));
// Dialog background.
background.getPaint().setColor(Utils.getDialogBackgroundColor());
layout.setBackground(background);
@@ -152,7 +142,7 @@ public class CustomDialog {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
params.setMargins(0, 0, 0, dip16);
params.setMargins(0, 0, 0, Dim.dp16);
titleView.setLayoutParams(params);
mainLayout.addView(titleView);
@@ -180,9 +170,9 @@ public class CustomDialog {
// EditText (if provided).
if (editText != null) {
ShapeDrawable background = new ShapeDrawable(new RoundRectShape(
Utils.createCornerRadii(10), null, null));
Dim.roundedCorners(10), null, null));
background.getPaint().setColor(Utils.getEditTextBackground());
scrollView.setPadding(dip8, dip8, dip8, dip8);
scrollView.setPadding(Dim.dp8, Dim.dp8, Dim.dp8, Dim.dp8);
scrollView.setBackground(background);
scrollView.setClipToOutline(true);
@@ -241,7 +231,7 @@ public class CustomDialog {
LinearLayout.LayoutParams buttonContainerParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
buttonContainerParams.setMargins(0, dip16, 0, 0);
buttonContainerParams.setMargins(0, Dim.dp16, 0, 0);
buttonContainer.setLayoutParams(buttonContainerParams);
List<Button> buttons = new ArrayList<>();
@@ -289,12 +279,12 @@ public class CustomDialog {
button.setEllipsize(TextUtils.TruncateAt.END);
button.setGravity(Gravity.CENTER);
// Set internal padding.
button.setPadding(dip16, 0, dip16, 0);
button.setPadding(Dim.dp16, 0, Dim.dp16, 0);
// Background color for OK button (inversion).
// Background color for Cancel or Neutral buttons.
ShapeDrawable background = new ShapeDrawable(new RoundRectShape(
Utils.createCornerRadii(20), null, null));
Dim.roundedCorners(20), null, null));
background.getPaint().setColor(isOkButton
? Utils.getOkButtonBackgroundColor()
: Utils.getCancelOrNeutralButtonBackgroundColor());
@@ -331,20 +321,19 @@ public class CustomDialog {
if (buttons.isEmpty()) return;
// Check if buttons fit in one row.
int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
int totalWidth = 0;
for (Integer width : buttonWidths) {
totalWidth += width;
}
if (buttonWidths.size() > 1) {
// Add margins for gaps.
totalWidth += (buttonWidths.size() - 1) * dip8;
totalWidth += (buttonWidths.size() - 1) * Dim.dp8;
}
// Single button: stretch to full width.
if (buttons.size() == 1) {
layoutSingleButton(buttonContainer, buttons.get(0));
} else if (totalWidth <= screenWidth * 0.8) {
} else if (totalWidth <= Dim.pctWidth(80)) {
// Single row: Neutral, Cancel, OK.
layoutButtonsInRow(buttonContainer, buttons, buttonWidths);
} else {
@@ -369,7 +358,7 @@ public class CustomDialog {
button.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
dip36));
Dim.dp36));
singleContainer.addView(button);
buttonContainer.addView(singleContainer);
}
@@ -405,17 +394,17 @@ public class CustomDialog {
if (parent != null) parent.removeView(button);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
0, dip36, buttonWidths.get(i));
0, Dim.dp36, buttonWidths.get(i));
// Set margins based on button type and combination.
if (buttons.size() == 2) {
// Neutral + OK or Cancel + OK.
params.setMargins(i == 0 ? 0 : dip4, 0, i == 0 ? dip4 : 0, 0);
params.setMargins(i == 0 ? 0 : Dim.dp4, 0, i == 0 ? Dim.dp4 : 0, 0);
} else if (buttons.size() == 3) {
// Neutral.
// Cancel.
// OK.
params.setMargins(i == 0 ? 0 : dip4, 0, i == 2 ? 0 : dip4, 0);
params.setMargins(i == 0 ? 0 : Dim.dp4, 0, i == 2 ? 0 : Dim.dp4, 0);
}
button.setLayoutParams(params);
@@ -447,14 +436,14 @@ public class CustomDialog {
singleContainer.setGravity(Gravity.CENTER);
singleContainer.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
dip36));
Dim.dp36));
ViewGroup parent = (ViewGroup) button.getParent();
if (parent != null) parent.removeView(button);
button.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
dip36));
Dim.dp36));
singleContainer.addView(button);
buttonContainer.addView(singleContainer);
@@ -463,7 +452,7 @@ public class CustomDialog {
View spacer = new View(context);
LinearLayout.LayoutParams spacerParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
dip8);
Dim.dp8);
spacer.setLayoutParams(spacerParams);
buttonContainer.addView(spacer);
}

View File

@@ -0,0 +1,89 @@
package app.revanced.extension.shared.ui;
import android.content.res.Resources;
import android.util.DisplayMetrics;
import android.util.TypedValue;
/**
* Utility class for converting design units (dp) and screen percentages to pixels.
*/
public final class Dim {
private Dim() {} // Prevent instantiation.
private static final DisplayMetrics METRICS = Resources.getSystem().getDisplayMetrics();
public static final int SCREEN_WIDTH = METRICS.widthPixels;
public static final int SCREEN_HEIGHT = METRICS.heightPixels;
// DP constants (density-independent pixels).
public static final int dp1 = dp(1);
public static final int dp2 = dp(2);
public static final int dp4 = dp(4);
public static final int dp6 = dp(6);
public static final int dp7 = dp(7);
public static final int dp8 = dp(8);
public static final int dp10 = dp(10);
public static final int dp12 = dp(12);
public static final int dp16 = dp(16);
public static final int dp20 = dp(20);
public static final int dp24 = dp(24);
public static final int dp28 = dp(28);
public static final int dp32 = dp(32);
public static final int dp36 = dp(36);
public static final int dp40 = dp(40);
public static final int dp48 = dp(48);
/**
* Converts dp (density-independent pixels) to actual device pixels.
* Uses Android's official TypedValue.applyDimension() for accurate rounding.
*
* @param dp The dp value to convert (supports float, e.g. 1.2f).
* @return The equivalent pixel value as int.
*/
public static int dp(float dp) {
return (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, dp, METRICS);
}
/**
* Converts a percentage of the screen height to pixels.
*
* @param percent The percentage (0100).
* @return The pixel value corresponding to the percentage of screen height.
*/
public static int pctHeight(int percent) {
return (SCREEN_HEIGHT * percent) / 100;
}
/**
* Converts a percentage of the screen width to pixels.
*
* @param percent The percentage (0100).
* @return The pixel value corresponding to the percentage of screen width.
*/
public static int pctWidth(int percent) {
return (SCREEN_WIDTH * percent) / 100;
}
/**
* Converts a percentage of the screen's portrait width (min side) to pixels.
*
* @param percent The percentage (0100).
* @return The pixel value.
*/
public static int pctPortraitWidth(int percent) {
final int portraitWidth = Math.min(SCREEN_WIDTH, SCREEN_HEIGHT);
return (int) (portraitWidth * (percent / 100.0f));
}
/**
* Creates an array of corner radii for a rounded rectangle.
* All corners use the same radius.
*
* @param dp radius in density-independent pixels
* @return array of 8 floats: [top-left-x, top-left-y, top-right-x, top-right-y, ...]
*/
public static float[] roundedCorners(float dp) {
final float r = dp(dp);
return new float[]{r, r, r, r, r, r, r, r};
}
}

View File

@@ -1,7 +1,5 @@
package app.revanced.extension.shared.ui;
import static app.revanced.extension.shared.Utils.dipToPixels;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
@@ -63,9 +61,8 @@ public class SheetBottomDialog {
// Add top spacer.
View spacer = new View(context);
final int dip40 = dipToPixels(40);
LinearLayout.LayoutParams spacerParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, dip40);
LinearLayout.LayoutParams.MATCH_PARENT, Dim.dp40);
spacer.setLayoutParams(spacerParams);
spacer.setClickable(true);
dragContainer.addView(spacer);
@@ -105,20 +102,15 @@ public class SheetBottomDialog {
* @return A configured {@link DraggableLinearLayout} with a handle bar and styled background.
*/
public static DraggableLinearLayout createMainLayout(@NonNull Context context, @Nullable Integer backgroundColor) {
// Preset size constants.
final int dip4 = dipToPixels(4); // Handle bar height.
final int dip8 = dipToPixels(8); // Dialog padding.
final int dip40 = dipToPixels(40); // Handle bar width.
DraggableLinearLayout mainLayout = new DraggableLinearLayout(context);
mainLayout.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(dip8, 0, dip8, dip8);
layoutParams.setMargins(Dim.dp8, 0, Dim.dp8, Dim.dp8);
mainLayout.setLayoutParams(layoutParams);
ShapeDrawable background = new ShapeDrawable(new RoundRectShape(
Utils.createCornerRadii(12), null, null));
Dim.roundedCorners(12), null, null));
int color = (backgroundColor != null) ? backgroundColor : Utils.getDialogBackgroundColor();
background.getPaint().setColor(color);
mainLayout.setBackground(background);
@@ -127,14 +119,14 @@ public class SheetBottomDialog {
LinearLayout handleContainer = new LinearLayout(context);
LinearLayout.LayoutParams containerParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
containerParams.setMargins(0, dip8, 0, 0);
containerParams.setMargins(0, Dim.dp8, 0, 0);
handleContainer.setLayoutParams(containerParams);
handleContainer.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
View handleBar = new View(context);
ShapeDrawable handleBackground = new ShapeDrawable(new RoundRectShape(
Utils.createCornerRadii(4), null, null));
Dim.roundedCorners(4), null, null));
handleBackground.getPaint().setColor(Utils.adjustColorBrightness(color, 0.9f, 1.25f));
LinearLayout.LayoutParams handleParams = new LinearLayout.LayoutParams(dip40, dip4);
LinearLayout.LayoutParams handleParams = new LinearLayout.LayoutParams(Dim.dp40, Dim.dp4);
handleBar.setLayoutParams(handleParams);
handleBar.setBackground(handleBackground);

View File

@@ -7,6 +7,7 @@ import app.revanced.extension.spotify.shared.ComponentFilters.StringComponentFil
import java.util.List;
@Deprecated(forRemoval = true)
@SuppressWarnings("unused")
public final class HideCreateButtonPatch {

View File

@@ -17,15 +17,25 @@ public class ChangeHeaderPatch {
DEFAULT(null, null),
REGULAR("ytWordmarkHeader", "yt_ringo2_wordmark_header"),
PREMIUM("ytPremiumWordmarkHeader", "yt_ringo2_premium_wordmark_header"),
REVANCED("revanced_header_logo", "revanced_header_logo"),
REVANCED_MINIMAL("revanced_header_logo_minimal", "revanced_header_logo_minimal"),
CUSTOM("custom_header", "custom_header");
ROUNDED("revanced_header_rounded"),
MINIMAL("revanced_header_minimal"),
CUSTOM("revanced_header_custom"),
// Old enum names for data migration. TODO: Eventually delete these.
@Deprecated
REVANCED(ROUNDED.attributeName),
@Deprecated
REVANCED_MINIMAL(MINIMAL.attributeName);
@Nullable
private final String attributeName;
@Nullable
private final String drawableName;
HeaderLogo(String attributeName) {
this(Objects.requireNonNull(attributeName), Objects.requireNonNull(attributeName));
}
HeaderLogo(@Nullable String attributeName, @Nullable String drawableName) {
this.attributeName = attributeName;
this.drawableName = drawableName;
@@ -42,9 +52,8 @@ public class ChangeHeaderPatch {
final int identifier = Utils.getResourceIdentifier(attributeName, "attr");
if (identifier == 0) {
// Identifier is zero if custom header setting was included in imported settings
// and a custom image was not included during patching.
Logger.printDebug(() -> "Could not find attribute: " + drawableName);
// Should never happen.
Logger.printException(() -> "Could not find attribute: " + drawableName);
Settings.HEADER_LOGO.resetToDefault();
return null;
}
@@ -63,12 +72,14 @@ public class ChangeHeaderPatch {
: "_light");
final int identifier = Utils.getResourceIdentifier(drawableFullName, "drawable");
if (identifier == 0) {
Logger.printDebug(() -> "Could not find drawable: " + drawableFullName);
Settings.HEADER_LOGO.resetToDefault();
return null;
if (identifier != 0) {
return Utils.getContext().getDrawable(identifier);
}
return Utils.getContext().getDrawable(identifier);
// Should never happen.
Logger.printException(() -> "Could not find drawable: " + drawableFullName);
Settings.HEADER_LOGO.resetToDefault();
return null;
}
}

View File

@@ -4,6 +4,7 @@ import android.view.View;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.ui.Dim;
import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused")
@@ -31,7 +32,7 @@ public final class WideSearchbarPatch {
final int paddingRight = searchBarView.getPaddingRight();
final int paddingTop = searchBarView.getPaddingTop();
final int paddingBottom = searchBarView.getPaddingBottom();
final int paddingStart = Utils.dipToPixels(8);
final int paddingStart = Dim.dp8;
if (Utils.isRightToLeftLocale()) {
searchBarView.setPadding(paddingLeft, paddingTop, paddingStart, paddingBottom);

View File

@@ -2,7 +2,6 @@ package app.revanced.extension.youtube.patches.announcements;
import static android.text.Html.FROM_HTML_MODE_COMPACT;
import static app.revanced.extension.shared.StringRef.str;
import static app.revanced.extension.shared.Utils.dipToPixels;
import static app.revanced.extension.youtube.patches.announcements.requests.AnnouncementsRoutes.GET_LATEST_ANNOUNCEMENTS;
import static app.revanced.extension.youtube.patches.announcements.requests.AnnouncementsRoutes.GET_LATEST_ANNOUNCEMENT_IDS;
@@ -24,6 +23,7 @@ import java.time.LocalDateTime;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.requests.Requester;
import app.revanced.extension.shared.ui.Dim;
import app.revanced.extension.youtube.patches.announcements.requests.AnnouncementsRoutes;
import app.revanced.extension.youtube.settings.Settings;
@@ -148,7 +148,7 @@ public final class AnnouncementsPatch {
if (child instanceof TextView childTextView && finalTitle.equals(childTextView.getText().toString())) {
childTextView.setCompoundDrawablesWithIntrinsicBounds(
finalLevel.icon, 0, 0, 0);
childTextView.setCompoundDrawablePadding(dipToPixels(8));
childTextView.setCompoundDrawablePadding(Dim.dp8);
}
}

View File

@@ -17,6 +17,7 @@ final class DescriptionComponentsFilter extends Filter {
private final ByteArrayFilterGroup cellVideoAttribute;
private final StringFilterGroup aiGeneratedVideoSummarySection;
private final StringFilterGroup hypePoints;
public DescriptionComponentsFilter() {
exceptions.addPatterns(
@@ -63,6 +64,11 @@ final class DescriptionComponentsFilter extends Filter {
"how_this_was_made_section"
);
hypePoints = new StringFilterGroup(
Settings.HIDE_HYPE_POINTS,
"hype_points_factoid"
);
macroMarkersCarousel = new StringFilterGroup(
null,
"macro_markers_carousel.e"
@@ -96,6 +102,7 @@ final class DescriptionComponentsFilter extends Filter {
infoCardsSection,
horizontalShelf,
howThisWasMadeSection,
hypePoints,
macroMarkersCarousel,
podcastSection,
transcriptSection
@@ -106,7 +113,7 @@ final class DescriptionComponentsFilter extends Filter {
boolean isFiltered(String identifier, String path, byte[] buffer,
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
if (matchedGroup == aiGeneratedVideoSummarySection) {
if (matchedGroup == aiGeneratedVideoSummarySection || matchedGroup == hypePoints) {
// Only hide if player is open, in case this component is used somewhere else.
return PlayerType.getCurrent().isMaximizedOrFullscreen();
}

View File

@@ -63,12 +63,12 @@ public class PlayerFlyoutMenuItemsFilter extends Filter {
"volume_stable_"
),
new ByteArrayFilterGroup(
Settings.HIDE_PLAYER_FLYOUT_HELP,
"yt_outline_question_circle_"
Settings.HIDE_PLAYER_FLYOUT_LISTEN_WITH_YOUTUBE_MUSIC,
"yt_outline_youtube_music_"
),
new ByteArrayFilterGroup(
Settings.HIDE_PLAYER_FLYOUT_MORE_INFO,
"yt_outline_info_circle_"
Settings.HIDE_PLAYER_FLYOUT_HELP,
"yt_outline_question_circle_"
),
new ByteArrayFilterGroup(
Settings.HIDE_PLAYER_FLYOUT_LOCK_SCREEN,

View File

@@ -1,7 +1,6 @@
package app.revanced.extension.youtube.patches.playback.speed;
import static app.revanced.extension.shared.StringRef.str;
import static app.revanced.extension.shared.Utils.dipToPixels;
import static app.revanced.extension.youtube.videoplayer.PlayerControlButton.fadeInDuration;
import static app.revanced.extension.youtube.videoplayer.PlayerControlButton.getDialogBackgroundColor;
@@ -30,6 +29,7 @@ import java.util.function.Function;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.ui.Dim;
import app.revanced.extension.shared.ui.SheetBottomDialog;
import app.revanced.extension.youtube.patches.VideoInformation;
import app.revanced.extension.youtube.patches.components.PlaybackSpeedMenuFilter;
@@ -264,14 +264,6 @@ public class CustomPlaybackSpeedPatch {
SheetBottomDialog.DraggableLinearLayout mainLayout =
SheetBottomDialog.createMainLayout(context, getDialogBackgroundColor());
// Preset size constants.
final int dip4 = dipToPixels(4);
final int dip8 = dipToPixels(8);
final int dip12 = dipToPixels(12);
final int dip20 = dipToPixels(20);
final int dip32 = dipToPixels(32);
final int dip60 = dipToPixels(60);
// Display current playback speed.
TextView currentSpeedText = new TextView(context);
float currentSpeed = VideoInformation.getPlaybackSpeed();
@@ -283,7 +275,7 @@ public class CustomPlaybackSpeedPatch {
currentSpeedText.setGravity(Gravity.CENTER);
LinearLayout.LayoutParams textParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
textParams.setMargins(0, dip20, 0, 0);
textParams.setMargins(0, Dim.dp20, 0, 0);
currentSpeedText.setLayoutParams(textParams);
// Add current speed text view to main layout.
mainLayout.addView(currentSpeedText);
@@ -294,8 +286,8 @@ public class CustomPlaybackSpeedPatch {
sliderLayout.setGravity(Gravity.CENTER_VERTICAL);
// Create +/- buttons.
Button minusButton = createStyledButton(context, false, dip8, dip8);
Button plusButton = createStyledButton(context, true, dip8, dip8);
Button minusButton = createStyledButton(context, false);
Button plusButton = createStyledButton(context, true);
// Create slider for speed adjustment.
SeekBar speedSlider = new SeekBar(context);
@@ -363,7 +355,7 @@ public class CustomPlaybackSpeedPatch {
gridLayout.setRowCount((int) Math.ceil(customPlaybackSpeeds.length / 5.0));
LinearLayout.LayoutParams gridParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
gridParams.setMargins(dip4, dip12, dip4, dip12); // Speed buttons container.
gridParams.setMargins(Dim.dp4, Dim.dp12, Dim.dp4, Dim.dp12); // Speed buttons container.
gridLayout.setLayoutParams(gridParams);
// For button use 1 digit minimum.
@@ -378,8 +370,8 @@ public class CustomPlaybackSpeedPatch {
GridLayout.LayoutParams containerParams = new GridLayout.LayoutParams();
containerParams.width = 0; // Equal width for columns.
containerParams.columnSpec = GridLayout.spec(GridLayout.UNDEFINED, 1, 1f);
containerParams.setMargins(dip4, 0, dip4, 0); // Button margins.
containerParams.height = dip60; // Fixed height for button and label.
containerParams.setMargins(Dim.dp4, 0, Dim.dp4, 0); // Button margins.
containerParams.height = Dim.dp(60); // Fixed height for button and label.
buttonContainer.setLayoutParams(containerParams);
// Create speed button.
@@ -391,14 +383,14 @@ public class CustomPlaybackSpeedPatch {
speedButton.setGravity(Gravity.CENTER);
ShapeDrawable buttonBackground = new ShapeDrawable(new RoundRectShape(
Utils.createCornerRadii(20), null, null));
Dim.roundedCorners(20), null, null));
buttonBackground.getPaint().setColor(getAdjustedBackgroundColor(false));
speedButton.setBackground(buttonBackground);
speedButton.setPadding(dip4, dip4, dip4, dip4);
speedButton.setPadding(Dim.dp4, Dim.dp4, Dim.dp4, Dim.dp4);
// Center button vertically and stretch horizontally in container.
FrameLayout.LayoutParams buttonParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT, dip32, Gravity.CENTER);
FrameLayout.LayoutParams.MATCH_PARENT, Dim.dp32, Gravity.CENTER);
speedButton.setLayoutParams(buttonParams);
// Add speed buttons view to buttons container layout.
@@ -475,21 +467,18 @@ public class CustomPlaybackSpeedPatch {
*
* @param context The Android context used to create the button.
* @param isPlus True to display a plus symbol, false to display a minus symbol.
* @param marginStart The start margin in pixels (left for LTR, right for RTL).
* @param marginEnd The end margin in pixels (right for LTR, left for RTL).
* @return A configured {@link Button} with the specified styling and layout parameters.
*/
private static Button createStyledButton(Context context, boolean isPlus, int marginStart, int marginEnd) {
private static Button createStyledButton(Context context, boolean isPlus) {
Button button = new Button(context, null, 0); // Disable default theme style.
button.setText(""); // No text on button.
ShapeDrawable background = new ShapeDrawable(new RoundRectShape(
Utils.createCornerRadii(20), null, null));
Dim.roundedCorners(20), null, null));
background.getPaint().setColor(getAdjustedBackgroundColor(false));
button.setBackground(background);
button.setForeground(new OutlineSymbolDrawable(isPlus)); // Plus or minus symbol.
final int dip36 = dipToPixels(36);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(dip36, dip36);
params.setMargins(marginStart, 0, marginEnd, 0); // Set margins.
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(Dim.dp36, Dim.dp36);
params.setMargins(Dim.dp8, 0, Dim.dp8, 0); // Set margins.
button.setLayoutParams(params);
return button;
}
@@ -554,7 +543,7 @@ class OutlineSymbolDrawable extends Drawable {
paint = new Paint(Paint.ANTI_ALIAS_FLAG); // Enable anti-aliasing for smooth rendering.
paint.setColor(Utils.getAppForegroundColor());
paint.setStyle(Paint.Style.STROKE); // Use stroke style for outline.
paint.setStrokeWidth(dipToPixels(1)); // 1dp stroke width.
paint.setStrokeWidth(Dim.dp1); // 1dp stroke width.
}
@Override

View File

@@ -1,6 +1,7 @@
package app.revanced.extension.youtube.patches.spoof;
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_CREATOR;
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_NO_SDK;
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_VR_1_43_32;
import static app.revanced.extension.shared.spoof.ClientType.ANDROID_VR_1_61_48;
import static app.revanced.extension.shared.spoof.ClientType.IPADOS;
@@ -21,6 +22,11 @@ public class SpoofVideoStreamsPatch {
return Settings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.isAvailable()
&& Settings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ANDROID_VR_1_43_32;
}
@Override
public List<Setting<?>> getParentSettings() {
return List.of(Settings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE);
}
}
/**
@@ -38,9 +44,10 @@ public class SpoofVideoStreamsPatch {
}
List<ClientType> availableClients = List.of(
VISIONOS,
ANDROID_CREATOR,
ANDROID_VR_1_43_32,
VISIONOS,
ANDROID_NO_SDK,
IPADOS);
app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.setClientsToUse(

View File

@@ -40,6 +40,7 @@ import java.util.concurrent.TimeoutException;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.ui.Dim;
import app.revanced.extension.youtube.returnyoutubedislike.requests.RYDVoteData;
import app.revanced.extension.youtube.returnyoutubedislike.requests.ReturnYouTubeDislikeApi;
import app.revanced.extension.youtube.settings.Settings;
@@ -124,12 +125,12 @@ public class ReturnYouTubeDislike {
static {
leftSeparatorBounds = new Rect(0, 0,
Utils.dipToPixels(1.2f),
Utils.dipToPixels(14f));
final int middleSeparatorSize = Utils.dipToPixels(3.7f);
Dim.dp(1.2f),
Dim.dp(14f));
final int middleSeparatorSize = Dim.dp(3.7f);
middleSeparatorBounds = new Rect(0, 0, middleSeparatorSize, middleSeparatorSize);
leftSeparatorShapePaddingPixels = Utils.dipToPixels(8.4f);
leftSeparatorShapePaddingPixels = Dim.dp(8.4f);
leftSeparatorShape = new ShapeDrawable(new RectShape());
leftSeparatorShape.setBounds(leftSeparatorBounds);

View File

@@ -2,7 +2,6 @@ package app.revanced.extension.youtube.settings;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
import static app.revanced.extension.shared.settings.Setting.migrateOldSettingToNew;
import static app.revanced.extension.shared.settings.Setting.parent;
import static app.revanced.extension.shared.settings.Setting.parentsAll;
import static app.revanced.extension.shared.settings.Setting.parentsAny;
@@ -17,7 +16,6 @@ import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerH
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerHideSubtextsAvailability;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerHorizontalDragAvailability;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType;
import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerType.MINIMAL;
import static app.revanced.extension.youtube.patches.OpenShortsInRegularPlayerPatch.ShortsPlayerType;
import static app.revanced.extension.youtube.patches.SeekbarThumbnailsPatch.SeekbarThumbnailsHighQualityAvailability;
import static app.revanced.extension.youtube.patches.components.PlayerFlyoutMenuItemsFilter.HideAudioFlyoutMenuAvailability;
@@ -41,7 +39,6 @@ import app.revanced.extension.shared.settings.IntegerSetting;
import app.revanced.extension.shared.settings.LongSetting;
import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.shared.settings.StringSetting;
import app.revanced.extension.shared.settings.preference.SharedPrefCategory;
import app.revanced.extension.shared.spoof.ClientType;
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.DeArrowAvailability;
import app.revanced.extension.youtube.patches.AlternativeThumbnailsPatch.StillImagesAvailability;
@@ -214,6 +211,7 @@ public class Settings extends BaseSettings {
public static final BooleanSetting HIDE_ATTRIBUTES_SECTION = new BooleanSetting("revanced_hide_attributes_section", FALSE);
public static final BooleanSetting HIDE_CHAPTERS_SECTION = new BooleanSetting("revanced_hide_chapters_section", TRUE);
public static final BooleanSetting HIDE_HOW_THIS_WAS_MADE_SECTION = new BooleanSetting("revanced_hide_how_this_was_made_section", FALSE);
public static final BooleanSetting HIDE_HYPE_POINTS = new BooleanSetting("revanced_hide_hype_points", FALSE);
public static final BooleanSetting HIDE_INFO_CARDS_SECTION = new BooleanSetting("revanced_hide_info_cards_section", TRUE);
public static final BooleanSetting HIDE_KEY_CONCEPTS_SECTION = new BooleanSetting("revanced_hide_key_concepts_section", FALSE);
public static final BooleanSetting HIDE_PODCAST_SECTION = new BooleanSetting("revanced_hide_podcast_section", TRUE);
@@ -242,9 +240,9 @@ public class Settings extends BaseSettings {
public static final BooleanSetting HIDE_PLAYER_FLYOUT_AUDIO_TRACK = new BooleanSetting("revanced_hide_player_flyout_audio_track", FALSE, new HideAudioFlyoutMenuAvailability());
public static final BooleanSetting HIDE_PLAYER_FLYOUT_CAPTIONS = new BooleanSetting("revanced_hide_player_flyout_captions", FALSE);
public static final BooleanSetting HIDE_PLAYER_FLYOUT_HELP = new BooleanSetting("revanced_hide_player_flyout_help", TRUE);
public static final BooleanSetting HIDE_PLAYER_FLYOUT_LISTEN_WITH_YOUTUBE_MUSIC = new BooleanSetting("revanced_hide_player_flyout_listen_with_youtube_music", FALSE);
public static final BooleanSetting HIDE_PLAYER_FLYOUT_LOCK_SCREEN = new BooleanSetting("revanced_hide_player_flyout_lock_screen", FALSE);
public static final BooleanSetting HIDE_PLAYER_FLYOUT_LOOP_VIDEO = new BooleanSetting("revanced_hide_player_flyout_loop_video", FALSE);
public static final BooleanSetting HIDE_PLAYER_FLYOUT_MORE_INFO = new BooleanSetting("revanced_hide_player_flyout_more_info", TRUE);
public static final BooleanSetting HIDE_PLAYER_FLYOUT_SLEEP_TIMER = new BooleanSetting("revanced_hide_player_flyout_sleep_timer", FALSE);
public static final BooleanSetting HIDE_PLAYER_FLYOUT_SPEED = new BooleanSetting("revanced_hide_player_flyout_speed", FALSE);
public static final BooleanSetting HIDE_PLAYER_FLYOUT_STABLE_VOLUME = new BooleanSetting("revanced_hide_player_flyout_stable_volume", FALSE);
@@ -452,14 +450,7 @@ public class Settings extends BaseSettings {
public static final StringSetting SB_CATEGORY_UNSUBMITTED_COLOR = new StringSetting("sb_unsubmitted_color", "#FFFFFFFF", false, false);
// Deprecated migrations
private static final BooleanSetting DEPRECATED_AUTO_REPEAT = new BooleanSetting("revanced_auto_repeat", FALSE);
private static final BooleanSetting DEPRECATED_HIDE_PLAYER_BUTTONS = new BooleanSetting("revanced_hide_player_buttons", FALSE, true);
private static final BooleanSetting DEPRECATED_HIDE_PLAYER_FLYOUT_VIDEO_QUALITY_FOOTER = new BooleanSetting("revanced_hide_video_quality_menu_footer", FALSE);
private static final IntegerSetting DEPRECATED_SWIPE_OVERLAY_BACKGROUND_ALPHA = new IntegerSetting("revanced_swipe_overlay_background_alpha", 127);
private static final StringSetting DEPRECATED_SEEKBAR_CUSTOM_COLOR_PRIMARY = new StringSetting("revanced_seekbar_custom_color_value", "#FF0033");
private static final BooleanSetting DEPRECATED_DISABLE_SUGGESTED_VIDEO_END_SCREEN = new BooleanSetting("revanced_disable_suggested_video_end_screen", FALSE);
private static final BooleanSetting DEPRECATED_RESTORE_OLD_VIDEO_QUALITY_MENU = new BooleanSetting("revanced_restore_old_video_quality_menu", TRUE);
private static final BooleanSetting DEPRECATED_AUTO_CAPTIONS = new BooleanSetting("revanced_auto_captions", FALSE);
private static final FloatSetting DEPRECATED_SB_CATEGORY_SPONSOR_OPACITY = new FloatSetting("sb_sponsor_opacity", 0.8f, false, false);
private static final FloatSetting DEPRECATED_SB_CATEGORY_SELF_PROMO_OPACITY = new FloatSetting("sb_selfpromo_opacity", 0.8f, false, false);
@@ -475,17 +466,12 @@ public class Settings extends BaseSettings {
static {
// region Migration
migrateOldSettingToNew(DEPRECATED_AUTO_REPEAT, LOOP_VIDEO);
migrateOldSettingToNew(DEPRECATED_HIDE_PLAYER_BUTTONS, HIDE_PLAYER_PREVIOUS_NEXT_BUTTONS);
migrateOldSettingToNew(DEPRECATED_HIDE_PLAYER_FLYOUT_VIDEO_QUALITY_FOOTER, HIDE_PLAYER_FLYOUT_VIDEO_QUALITY_FOOTER);
migrateOldSettingToNew(DEPRECATED_DISABLE_SUGGESTED_VIDEO_END_SCREEN, HIDE_END_SCREEN_SUGGESTED_VIDEO);
migrateOldSettingToNew(DEPRECATED_RESTORE_OLD_VIDEO_QUALITY_MENU, ADVANCED_VIDEO_QUALITY_MENU);
migrateOldSettingToNew(DEPRECATED_AUTO_CAPTIONS, DISABLE_AUTO_CAPTIONS);
// Migrate renamed enum.
//noinspection deprecation
if (MINIPLAYER_TYPE.get() == MiniplayerType.PHONE) {
MINIPLAYER_TYPE.save(MINIMAL);
// Migrate renamed change header enums.
if (HEADER_LOGO.get() == HeaderLogo.REVANCED) {
HEADER_LOGO.save(HeaderLogo.ROUNDED);
}
if (HEADER_LOGO.get() == HeaderLogo.REVANCED_MINIMAL) {
HEADER_LOGO.save(HeaderLogo.MINIMAL);
}
// Migrate old single color seekbar with a slightly brighter accent color based on the primary.
@@ -512,11 +498,6 @@ public class Settings extends BaseSettings {
DEPRECATED_SEEKBAR_CUSTOM_COLOR_PRIMARY.resetToDefault();
}
if (!DEPRECATED_SWIPE_OVERLAY_BACKGROUND_ALPHA.isSetToDefault()) {
SWIPE_OVERLAY_OPACITY.save(DEPRECATED_SWIPE_OVERLAY_BACKGROUND_ALPHA.get() / 255);
DEPRECATED_SWIPE_OVERLAY_BACKGROUND_ALPHA.resetToDefault();
}
// Old spoof versions that no longer work,
// or is spoofing to a version the same or newer than this app.
if (!SPOOF_APP_VERSION_TARGET.isSetToDefault() &&
@@ -534,13 +515,7 @@ public class Settings extends BaseSettings {
// RYD requires manually migrating old settings since the lack of
// a "revanced_" on the old setting causes duplicate key exceptions during export.
SharedPrefCategory revancedPrefs = Setting.preferences;
Setting.migrateFromOldPreferences(revancedPrefs, RYD_USER_ID, "ryd_user_id");
Setting.migrateFromOldPreferences(revancedPrefs, RYD_ENABLED, "ryd_enabled");
Setting.migrateFromOldPreferences(revancedPrefs, RYD_DISLIKE_PERCENTAGE, "ryd_dislike_percentage");
Setting.migrateFromOldPreferences(revancedPrefs, RYD_COMPACT_LAYOUT, "ryd_compact_layout");
Setting.migrateFromOldPreferences(revancedPrefs, RYD_ESTIMATED_LIKE, "ryd_estimated_like");
Setting.migrateFromOldPreferences(revancedPrefs, RYD_TOAST_ON_CONNECTION_ERROR, "ryd_toast_on_connection_error");
Setting.migrateFromOldPreferences(Setting.preferences, RYD_USER_ID, "ryd_user_id");
// Migrate old saved data. Must be done here before the settings can be used by any other code.
applyOldSbOpacityToColor(SB_CATEGORY_SPONSOR_COLOR, DEPRECATED_SB_CATEGORY_SPONSOR_OPACITY);

View File

@@ -2,7 +2,6 @@ package app.revanced.extension.youtube.settings.preference;
import static app.revanced.extension.shared.StringRef.sf;
import static app.revanced.extension.shared.StringRef.str;
import static app.revanced.extension.shared.Utils.dipToPixels;
import android.app.Dialog;
import android.content.Context;
@@ -15,13 +14,9 @@ import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Pair;
import android.util.TypedValue;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import androidx.annotation.Nullable;
@@ -37,6 +32,7 @@ import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.preference.CustomDialogListPreference;
import app.revanced.extension.shared.ui.CustomDialog;
import app.revanced.extension.shared.ui.Dim;
import app.revanced.extension.youtube.settings.Settings;
/**
@@ -264,42 +260,12 @@ public class ExternalDownloaderPreference extends CustomDialogListPreference {
// Add ListView to content layout with initial height.
LinearLayout.LayoutParams listViewParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
0 // Initial height, will be updated.
);
listViewParams.bottomMargin = dipToPixels(16);
LinearLayout.LayoutParams.MATCH_PARENT, 0, 1.0f);
listViewParams.bottomMargin = Dim.dp16;
contentLayout.addView(listView, listViewParams);
// Add EditText for custom package name.
editText = new EditText(context);
editText.setText(packageName);
editText.setSelection(packageName.length());
editText.setHint(str("revanced_external_downloader_other_item_hint"));
editText.setSingleLine(true); // Restrict EditText to a single line.
editText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
// Set initial EditText state based on selected downloader.
editText.setEnabled(usingCustomDownloader);
editText.addTextChangedListener(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) {
String updatedPackageName = edit.toString().trim();
updateListViewSelection.apply(updatedPackageName);
}
});
ShapeDrawable editTextBackground = new ShapeDrawable(new RoundRectShape(
Utils.createCornerRadii(10), null, null));
editTextBackground.getPaint().setColor(Utils.getEditTextBackground());
final int dip8 = dipToPixels(8);
editText.setPadding(dip8, dip8, dip8, dip8);
editText.setBackground(editTextBackground);
editText.setClipToOutline(true);
editText = createEditText(context, packageName, usingCustomDownloader, updateListViewSelection);
contentLayout.addView(editText);
// Create the custom dialog.
@@ -350,50 +316,59 @@ public class ExternalDownloaderPreference extends CustomDialogListPreference {
);
// Add the content layout directly to the dialog's main layout.
LinearLayout dialogMainLayout = dialogPair.second;
dialogMainLayout.addView(contentLayout, dialogMainLayout.getChildCount() - 1);
LinearLayout mainLayout = dialogPair.second;
LinearLayout.LayoutParams contentParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, 0, 1.0f);
// Update ListView height dynamically based on orientation.
//noinspection ExtractMethodRecommender
Runnable updateListViewHeight = () -> {
int totalHeight = 0;
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter != null) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
final int listAdapterCount = listAdapter.getCount();
for (int i = 0; i < listAdapterCount; i++) {
View item = listAdapter.getView(i, null, listView);
item.measure(
View.MeasureSpec.makeMeasureSpec(metrics.widthPixels, View.MeasureSpec.AT_MOST),
View.MeasureSpec.UNSPECIFIED
);
totalHeight += item.getMeasuredHeight();
}
totalHeight += listView.getDividerHeight() * (listAdapterCount - 1);
// Insert content before the dialog button row.
mainLayout.addView(contentLayout, mainLayout.getChildCount() - 1, contentParams);
Dialog dialog = dialogPair.first;
dialog.show();
}
/**
* Creates and configures the EditText for the custom package name.
*
* @param context Context for creating views.
* @param initialPackageName The package name to pre-fill.
* @param isCustom Whether the "Other" option is selected.
* @param textChangeCallback Callback to run when text changes.
* @return A configured EditText.
*/
private EditText createEditText(Context context,
String initialPackageName, boolean isCustom,
Function<String, Void> textChangeCallback) {
EditText editText = new EditText(context);
editText.setText(initialPackageName);
editText.setSelection(initialPackageName.length());
editText.setHint(str("revanced_external_downloader_other_item_hint"));
editText.setSingleLine(true);
editText.setTextSize(16);
editText.setEnabled(isCustom);
editText.addTextChangedListener(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) {
String updatedPackageName = edit.toString().trim();
textChangeCallback.apply(updatedPackageName);
}
});
final int orientation = context.getResources().getConfiguration().orientation;
if (orientation == android.content.res.Configuration.ORIENTATION_PORTRAIT) {
// In portrait orientation, use WRAP_CONTENT for ListView height.
listViewParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
} else {
// In landscape orientation, limit ListView height to 30% of screen height.
final int maxHeight = Utils.percentageHeightToPixels(30);
listViewParams.height = Math.min(totalHeight, maxHeight);
}
listView.setLayoutParams(listViewParams);
};
ShapeDrawable editTextBackground = new ShapeDrawable(new RoundRectShape(
Dim.roundedCorners(10), null, null));
editTextBackground.getPaint().setColor(Utils.getEditTextBackground());
editText.setPadding(Dim.dp8, Dim.dp8, Dim.dp8, Dim.dp8);
editText.setBackground(editTextBackground);
editText.setClipToOutline(true);
// Initial height calculation.
updateListViewHeight.run();
// Listen for configuration changes (e.g., orientation).
View dialogView = dialogPair.second;
// Recalculate height when layout changes (e.g., orientation change).
dialogView.getViewTreeObserver().addOnGlobalLayoutListener(updateListViewHeight::run);
// Show the dialog.
dialogPair.first.show();
return editText;
}
/**

View File

@@ -1,63 +0,0 @@
package app.revanced.extension.youtube.settings.preference;
import static app.revanced.extension.shared.StringRef.str;
import android.content.Context;
import android.util.AttributeSet;
import app.revanced.extension.shared.settings.preference.SortedListPreference;
import app.revanced.extension.shared.spoof.ClientType;
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings({"deprecation", "unused"})
public class SpoofAudioSelectorListPreference extends SortedListPreference {
private final boolean available;
{
final boolean isAndroidStudio = Settings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.ANDROID_CREATOR;
if (isAndroidStudio || SpoofVideoStreamsPatch.getLanguageOverride() != null) {
available = false;
super.setEnabled(false);
super.setSummary(str(isAndroidStudio
? "revanced_spoof_video_streams_language_android_studio"
: "revanced_spoof_video_streams_language_not_available"));
} else {
available = true;
}
}
public SpoofAudioSelectorListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public SpoofAudioSelectorListPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public SpoofAudioSelectorListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SpoofAudioSelectorListPreference(Context context) {
super(context);
}
@Override
public void setEnabled(boolean enabled) {
if (!available) {
return;
}
super.setEnabled(enabled);
}
@Override
public void setSummary(CharSequence summary) {
if (!available) {
return;
}
super.setSummary(summary);
}
}

View File

@@ -80,29 +80,34 @@ public class SpoofStreamingDataSideEffectsPreference extends Preference {
Logger.printDebug(() -> "Updating spoof stream side effects preference");
setEnabled(BaseSettings.SPOOF_VIDEO_STREAMS.get());
String summary = str("revanced_spoof_video_streams_about_no_audio_tracks");
String summary = "";
switch (clientType) {
case ANDROID_CREATOR ->
summary += '\n' + str("revanced_spoof_video_streams_about_no_stable_volume")
+ '\n' + str("revanced_spoof_video_streams_about_no_av1")
+ '\n' + str("revanced_spoof_video_streams_about_no_force_original_audio");
summary = str("revanced_spoof_video_streams_about_no_audio_tracks")
+ '\n' + str("revanced_spoof_video_streams_about_no_stable_volume")
+ '\n' + str("revanced_spoof_video_streams_about_no_av1")
+ '\n' + str("revanced_spoof_video_streams_about_no_force_original_audio");
// VR 1.61 is not exposed in the UI and should never be reached here.
case ANDROID_VR_1_43_32, ANDROID_VR_1_61_48 ->
summary += '\n' + str("revanced_spoof_video_streams_about_no_stable_volume");
summary = str("revanced_spoof_video_streams_about_no_audio_tracks")
+ '\n' + str("revanced_spoof_video_streams_about_no_stable_volume");
case ANDROID_NO_SDK ->
summary = str("revanced_spoof_video_streams_about_playback_failure");
case IPADOS ->
summary = str("revanced_spoof_video_streams_about_playback_failure")
+ '\n' + str("revanced_spoof_video_streams_about_no_av1");
case VISIONOS ->
summary = str("revanced_spoof_video_streams_about_experimental")
+ '\n' + summary
+ '\n' + str("revanced_spoof_video_streams_about_no_audio_tracks")
+ '\n' + str("revanced_spoof_video_streams_about_no_av1");
default -> Logger.printException(() -> "Unknown client: " + clientType);
}
// Only iPadOS can play children videos in incognito, but it commonly fails at 1 minute
// or doesn't even start playback at all. List the side effect for other clients
// or doesn't start playback at all. List the side effect for other clients
// since they will fall over to iPadOS.
if (clientType != ClientType.IPADOS) {
if (clientType != ClientType.IPADOS && clientType != ClientType.ANDROID_NO_SDK) {
summary += '\n' + str("revanced_spoof_video_streams_about_kids_videos");
}

View File

@@ -1,7 +1,6 @@
package app.revanced.extension.youtube.sponsorblock;
import static app.revanced.extension.shared.StringRef.str;
import static app.revanced.extension.shared.Utils.dipToPixels;
import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.SKIP_AUTOMATICALLY;
import android.annotation.SuppressLint;
@@ -34,6 +33,7 @@ import java.util.Objects;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.ui.Dim;
import app.revanced.extension.youtube.patches.VideoInformation;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.PlayerType;
@@ -82,7 +82,7 @@ public class SegmentPlaybackController {
* Highlight segments have zero length as they are a point in time.
* Draw them on screen using a fixed width bar.
*/
private static final int HIGHLIGHT_SEGMENT_DRAW_BAR_WIDTH = dipToPixels(7);
private static final int HIGHLIGHT_SEGMENT_DRAW_BAR_WIDTH = Dim.dp7;
@Nullable
private static String currentVideoId;
@@ -808,14 +808,12 @@ public class SegmentPlaybackController {
LinearLayout mainLayout = new LinearLayout(currentContext);
mainLayout.setOrientation(LinearLayout.VERTICAL);
final int dip8 = dipToPixels(8);
final int dip16 = dipToPixels(16);
mainLayout.setPadding(dip16, dip8, dip16, dip8);
mainLayout.setPadding(Dim.dp16, Dim.dp8, Dim.dp16, Dim.dp8);
mainLayout.setGravity(Gravity.CENTER);
mainLayout.setMinimumHeight(dipToPixels(48));
mainLayout.setMinimumHeight(Dim.dp48);
ShapeDrawable background = new ShapeDrawable(new RoundRectShape(
Utils.createCornerRadii(20), null, null));
Dim.roundedCorners(20), null, null));
background.getPaint().setColor(Utils.getDialogBackgroundColor());
mainLayout.setBackground(background);

View File

@@ -1,7 +1,6 @@
package app.revanced.extension.youtube.sponsorblock.objects;
import static app.revanced.extension.shared.StringRef.str;
import static app.revanced.extension.shared.Utils.dipToPixels;
import static app.revanced.extension.youtube.sponsorblock.SponsorBlockSettings.migrateOldColorString;
import android.content.Context;
@@ -17,6 +16,7 @@ import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.preference.ColorPickerPreference;
import app.revanced.extension.shared.ui.ColorDot;
import app.revanced.extension.shared.ui.Dim;
@SuppressWarnings("deprecation")
public class SegmentCategoryPreference extends ColorPickerPreference {
@@ -110,7 +110,7 @@ public class SegmentCategoryPreference extends ColorPickerPreference {
}
radioGroup.setOnCheckedChangeListener((group, checkedId) -> selectedDialogEntryIndex = checkedId);
radioGroup.setPadding(dipToPixels(10), 0, dipToPixels(10), dipToPixels(10));
radioGroup.setPadding(Dim.dp10, 0, Dim.dp10, Dim.dp10);
return radioGroup;
}

View File

@@ -15,6 +15,7 @@ import android.widget.FrameLayout;
import android.widget.ImageButton;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.ui.Dim;
import app.revanced.extension.youtube.patches.VideoInformation;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.sponsorblock.SponsorBlockUtils;
@@ -132,9 +133,7 @@ public final class NewSegmentLayout extends FrameLayout {
GradientDrawable backgroundDrawable = new GradientDrawable();
backgroundDrawable.setColor(getResourceColor("skip_ad_button_background_color"));
final float cornerRadius = squareLayout
? 0
: 16 * getResources().getDisplayMetrics().density;
final float cornerRadius = squareLayout ? 0f : Dim.dp16;
backgroundDrawable.setCornerRadius(cornerRadius);
setBackground(backgroundDrawable);
}

View File

@@ -18,7 +18,6 @@ import android.preference.SwitchPreference;
import android.text.InputType;
import android.util.AttributeSet;
import android.util.Pair;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
@@ -34,6 +33,7 @@ import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.shared.settings.preference.CustomDialogListPreference;
import app.revanced.extension.shared.settings.preference.ResettableEditTextPreference;
import app.revanced.extension.shared.ui.CustomDialog;
import app.revanced.extension.shared.ui.Dim;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.sponsorblock.SegmentPlaybackController;
import app.revanced.extension.youtube.sponsorblock.SponsorBlockSettings;
@@ -507,7 +507,7 @@ public class SponsorBlockPreferenceGroup extends PreferenceGroup {
EditText editText = getEditText();
editText.setInputType(editText.getInputType() | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
editText.setTextSize(TypedValue.COMPLEX_UNIT_PT, 7); // Use a smaller font to reduce text wrap.
editText.setTextSize(14);
// Create a custom dialog.
Pair<Dialog, LinearLayout> dialogPair = CustomDialog.create(
@@ -550,7 +550,7 @@ public class SponsorBlockPreferenceGroup extends PreferenceGroup {
| InputType.TYPE_TEXT_FLAG_MULTI_LINE
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
editText.setAutofillHints((String) null);
editText.setTextSize(TypedValue.COMPLEX_UNIT_PT, 8);
editText.setTextSize(14);
// Set preference listeners.
importExport.setOnPreferenceClickListener(preference1 -> {

View File

@@ -1,7 +1,6 @@
package app.revanced.extension.youtube.videoplayer;
import static app.revanced.extension.shared.StringRef.str;
import static app.revanced.extension.shared.Utils.dipToPixels;
import static app.revanced.extension.shared.settings.preference.CustomDialogListPreference.*;
import static app.revanced.extension.youtube.patches.VideoInformation.AUTOMATIC_VIDEO_QUALITY_VALUE;
import static app.revanced.extension.youtube.patches.VideoInformation.VIDEO_QUALITY_PREMIUM_NAME;
@@ -21,6 +20,7 @@ import android.widget.*;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import app.revanced.extension.shared.ui.Dim;
import app.revanced.extension.shared.ui.SheetBottomDialog;
import app.revanced.extension.youtube.shared.PlayerType;
import com.google.android.libraries.youtube.innertube.model.media.VideoQuality;
@@ -214,11 +214,6 @@ public class VideoQualityDialogButton {
}
}
// Preset size constants.
final int dip8 = dipToPixels(8);
final int dip12 = dipToPixels(12);
final int dip16 = dipToPixels(16);
// Create main layout.
SheetBottomDialog.DraggableLinearLayout mainLayout =
SheetBottomDialog.createMainLayout(context, getDialogBackgroundColor());
@@ -269,7 +264,7 @@ public class VideoQualityDialogButton {
LinearLayout.LayoutParams titleParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
titleParams.setMargins(dip12, dip16, 0, dip16);
titleParams.setMargins(Dim.dp12, Dim.dp16, 0, Dim.dp16);
titleView.setLayoutParams(titleParams);
mainLayout.addView(titleView);

View File

@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
org.gradle.parallel = true
android.useAndroidX = true
kotlin.code.style = official
version = 5.45.0-dev.1
version = 5.46.0-dev.6

View File

@@ -18,7 +18,7 @@ val removeShareTargetsPatch = resourcePatch(
document("res/xml/shortcuts.xml")
} catch (_: FileNotFoundException) {
return@execute Logger.getLogger(this::class.java.name).warning(
"The app has no shortcuts. No changes applied.")
"The app has no shortcuts. No changes applied.")
}.use { document ->
val rootNode = document.getNode("shortcuts") as? Element ?: return@use

View File

@@ -9,7 +9,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
val disableAdsPatch = bytecodePatch(
"Disable ads",
) {
compatibleWith("com.duolingo")
// 6.55.3 and higher can show ads after each exercise.
compatibleWith("com.duolingo"("6.54.5"))
execute {
// Couple approaches to remove ads exist:

View File

@@ -4,6 +4,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.booleanOption
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.instagram.misc.extension.sharedExtensionPatch
import app.revanced.patches.shared.PATCH_NAME_HIDE_NAVIGATION_BUTTONS
import app.revanced.util.addInstructionsAtControlFlowLabel
import app.revanced.util.findFreeRegister
import app.revanced.util.getReference
@@ -19,11 +20,11 @@ private const val EXTENSION_CLASS_DESCRIPTOR =
@Suppress("unused")
val hideNavigationButtonsPatch = bytecodePatch(
name = "Hide navigation buttons",
name = PATCH_NAME_HIDE_NAVIGATION_BUTTONS,
description = "Hides navigation bar buttons, such as the Reels and Create button.",
use = false
) {
compatibleWith("com.instagram.android")
compatibleWith("com.instagram.android"("401.0.0.48.79"))
dependsOn(sharedExtensionPatch)

View File

@@ -1,20 +1,16 @@
package app.revanced.patches.music.layout.compactheader
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.AccessFlags
import app.revanced.patcher.fingerprint
import app.revanced.util.literal
internal val constructCategoryBarFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
internal val chipCloudFingerprint = fingerprint {
returns("V")
parameters("Landroid/content/Context;", "L", "L", "L")
opcodes(
Opcode.IPUT_OBJECT,
Opcode.CONST,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.CONST,
Opcode.INVOKE_VIRTUAL
Opcode.CONST_4,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT
)
literal { chipCloud }
}

View File

@@ -1,6 +1,6 @@
package app.revanced.patches.music.layout.compactheader
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.resources.addResources
@@ -8,10 +8,14 @@ import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.patches.music.misc.settings.PreferenceScreen
import app.revanced.patches.music.misc.settings.settingsPatch
import app.revanced.patches.shared.misc.mapping.get
import app.revanced.patches.shared.misc.mapping.resourceMappings
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.util.findFreeRegister
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
internal var chipCloud = -1L
private set
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/music/patches/HideCategoryBarPatch;"
@Suppress("unused")
@@ -33,28 +37,21 @@ val hideCategoryBar = bytecodePatch(
)
execute {
chipCloud = resourceMappings["layout", "chip_cloud"]
addResources("music", "layout.compactheader.hideCategoryBar")
PreferenceScreen.GENERAL.addPreferences(
SwitchPreference("revanced_music_hide_category_bar"),
)
constructCategoryBarFingerprint.method.apply {
val insertIndex = constructCategoryBarFingerprint.patternMatch!!.startIndex
val register = getInstruction<OneRegisterInstruction>(insertIndex - 1).registerA
val freeRegister = findFreeRegister(insertIndex, register)
chipCloudFingerprint.method.apply {
val targetIndex = chipCloudFingerprint.patternMatch!!.endIndex
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstructionsWithLabels(
insertIndex,
"""
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->hideCategoryBar()Z
move-result v$freeRegister
if-eqz v$freeRegister, :show
const/16 v$freeRegister, 0x8
invoke-virtual { v$register, v$freeRegister }, Landroid/view/View;->setVisibility(I)V
:show
nop
"""
addInstruction(
targetIndex + 1,
"invoke-static { v$targetRegister }, $EXTENSION_CLASS_DESCRIPTOR->hideCategoryBar(Landroid/view/View;)V"
)
}
}

View File

@@ -12,3 +12,5 @@ internal const val PATCH_DESCRIPTION_SANITIZE_SHARING_LINKS = "Removes the track
internal const val PATCH_NAME_CHANGE_LINK_SHARING_DOMAIN = "Change link sharing domain"
internal const val PATCH_DESCRIPTION_CHANGE_LINK_SHARING_DOMAIN = "Replaces the domain name of shared links."
internal const val PATCH_NAME_HIDE_NAVIGATION_BUTTONS = "Hide navigation buttons"

View File

@@ -0,0 +1,25 @@
package app.revanced.patches.shared.layout.branding
import app.revanced.patcher.patch.rawResourcePatch
import app.revanced.util.inputStreamFromBundledResource
import java.nio.file.Files
/**
* Copies a branding license text file to the target apk.
*
* This patch must be a dependency for all patches that add ReVanced branding to the target app.
*/
internal val addBrandLicensePatch = rawResourcePatch {
execute {
val brandingLicenseFileName = "LICENSE_REVANCED.TXT"
val inputFileStream = inputStreamFromBundledResource(
"branding-license",
brandingLicenseFileName
)!!
val targetFile = get(brandingLicenseFileName, false).toPath()
Files.copy(inputFileStream, targetFile)
}
}

View File

@@ -36,13 +36,13 @@ import org.w3c.dom.NodeList
import java.io.File
import java.util.logging.Logger
private val mipmapDirectories = arrayOf(
private val mipmapDirectories = mapOf(
// Target app does not have ldpi icons.
"mipmap-mdpi",
"mipmap-hdpi",
"mipmap-xhdpi",
"mipmap-xxhdpi",
"mipmap-xxxhdpi"
"mipmap-mdpi" to "108x108 px",
"mipmap-hdpi" to "162x162 px",
"mipmap-xhdpi" to "216x216 px",
"mipmap-xxhdpi" to "324x324 px",
"mipmap-xxxhdpi" to "432x432 px"
)
private val iconStyleNames = arrayOf(
@@ -104,10 +104,13 @@ internal fun baseCustomBrandingPatch(
Folder with images to use as a custom icon.
The folder must contain one or more of the following folders, depending on the DPI of the device:
${mipmapDirectories.joinToString("\n") { "- $it" }}
${mipmapDirectories.keys.joinToString("\n") { "- $it" }}
Each of the folders must contain all of the following files:
${USER_CUSTOM_ADAPTIVE_FILE_NAMES.joinToString("\n")}
The image dimensions must be as follows:
${mipmapDirectories.map { (dpi, dim) -> "- $dpi: $dim" }.joinToString("\n")}
Optionally, the path contains a 'drawable' folder with any of the monochrome icon files:
$USER_CUSTOM_MONOCHROME_FILE_NAME
@@ -120,6 +123,7 @@ internal fun baseCustomBrandingPatch(
dependsOn(
addResourcesPatch,
resourceMappingPatch,
addBrandLicensePatch,
bytecodePatch {
execute {
mainActivityOnCreateFingerprint.method.addInstruction(
@@ -249,7 +253,7 @@ internal fun baseCustomBrandingPatch(
)
// Copy template icon files.
mipmapDirectories.forEach { dpi ->
mipmapDirectories.keys.forEach { dpi ->
copyResources(
"custom-branding",
ResourceGroup(
@@ -405,23 +409,24 @@ internal fun baseCustomBrandingPatch(
)
}
val sourceFolders = iconPathFile.listFiles { file -> file.isDirectory }
?: throw PatchException("The custom icon path contains no subfolders: " +
iconPathFile.absolutePath)
val resourceDirectory = get("res")
var copiedFiles = false
// For each source folder, copy the files to the target resource directories.
sourceFolders.forEach { dpiSourceFolder ->
iconPathFile.listFiles {
file -> file.isDirectory && file.name in mipmapDirectories
}!!.forEach { dpiSourceFolder ->
val targetDpiFolder = resourceDirectory.resolve(dpiSourceFolder.name)
if (!targetDpiFolder.exists()) return@forEach
if (!targetDpiFolder.exists()) {
// Should never happen.
throw IllegalStateException("Resource not found: $dpiSourceFolder")
}
val customFiles = dpiSourceFolder.listFiles { file ->
file.isFile && file.name in USER_CUSTOM_ADAPTIVE_FILE_NAMES
}!!
if (customFiles.size > 0 && customFiles.size != USER_CUSTOM_ADAPTIVE_FILE_NAMES.size) {
if (customFiles.isNotEmpty() && customFiles.size != USER_CUSTOM_ADAPTIVE_FILE_NAMES.size) {
throw PatchException("Must include all required icon files " +
"but only found " + customFiles.map { it.name })
}
@@ -451,8 +456,9 @@ internal fun baseCustomBrandingPatch(
}
if (!copiedFiles) {
throw PatchException("Could not find any replacement images in " +
"patch option path: " + iconPathFile.absolutePath)
throw PatchException("Expected to find directories and files: "
+ USER_CUSTOM_ADAPTIVE_FILE_NAMES.contentToString()
+ "\nBut none were found in the provided option file path: " + iconPathFile.absolutePath)
}
}

View File

@@ -5,6 +5,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatchBuilder
import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.resourcePatch
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.BasePreference
@@ -13,6 +14,8 @@ import app.revanced.patches.shared.misc.settings.preference.NonInteractivePrefer
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.util.ResourceGroup
import app.revanced.util.copyResources
import app.revanced.util.findInstructionIndicesReversedOrThrow
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
@@ -36,7 +39,27 @@ internal fun enableDebuggingPatch(
description = "Adds options for debugging and exporting ReVanced logs to the clipboard.",
) {
dependsOn(addResourcesPatch)
dependsOn(
addResourcesPatch,
resourcePatch {
execute {
copyResources(
"settings",
ResourceGroup("drawable",
// Action buttons.
"revanced_settings_copy_all.xml",
"revanced_settings_deselect_all.xml",
"revanced_settings_select_all.xml",
// Move buttons.
"revanced_settings_arrow_left_double.xml",
"revanced_settings_arrow_left_one.xml",
"revanced_settings_arrow_right_double.xml",
"revanced_settings_arrow_right_one.xml"
)
)
}
}
)
block()
@@ -64,6 +87,11 @@ internal fun enableDebuggingPatch(
"revanced_debug_logs_clear_buffer",
tag = "app.revanced.extension.shared.settings.preference.ClearLogBufferPreference",
selectable = true
),
NonInteractivePreference(
"revanced_debug_feature_flags_manager",
tag = "app.revanced.extension.shared.settings.preference.FeatureFlagsManagerPreference",
selectable = true
)
)
)

View File

@@ -15,7 +15,7 @@ val disableLicenseCheckPatch = bytecodePatch(
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.")
.warning("Could not find Pairip licensing check. No changes applied.")
}
// Set first parameter (responseCode) to 0 (success status).

View File

@@ -6,6 +6,7 @@ import app.revanced.patcher.patch.resourcePatch
import app.revanced.patches.all.misc.resources.addResource
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.layout.branding.addBrandLicensePatch
import app.revanced.patches.shared.misc.settings.preference.BasePreference
import app.revanced.patches.shared.misc.settings.preference.IntentPreference
import app.revanced.patches.shared.misc.settings.preference.PreferenceCategory
@@ -61,7 +62,11 @@ fun settingsPatch (
rootPreferences: List<Pair<BasePreference, String>>? = null,
preferences: Set<BasePreference>,
) = resourcePatch {
dependsOn(addResourcesPatch, settingsColorPatch)
dependsOn(
addResourcesPatch,
settingsColorPatch,
addBrandLicensePatch
)
execute {
copyResources(

View File

@@ -7,10 +7,12 @@ import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@Deprecated("Obsolete")
internal val navigationBarItemSetClassFingerprint = fingerprint {
strings("NavigationBarItemSet(")
}
@Deprecated("Obsolete")
internal val navigationBarItemSetConstructorFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
// Make sure the method checks whether navigation bar items are null before adding them.
@@ -23,6 +25,7 @@ internal val navigationBarItemSetConstructorFingerprint = fingerprint {
}
}
@Deprecated("Obsolete")
internal val oldNavigationBarAddItemFingerprint = fingerprint {
strings("Bottom navigation tabs exceeds maximum of 5 tabs")
}

View File

@@ -14,11 +14,11 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/spotify/layout/hide/createbutton/HideCreateButtonPatch;"
@Deprecated("Patch no longer works with the latest version of Spotify, " +
"and Spotify has added this functionality to the app")
@Suppress("unused")
val hideCreateButtonPatch = bytecodePatch(
name = "Hide Create button",
description = "Hides the \"Create\" button in the navigation bar. The latest app targets do not need this patch.",
use = false
) {
compatibleWith("com.spotify.music")

View File

@@ -3,14 +3,20 @@ package app.revanced.patches.tiktok.interaction.downloads
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.replaceInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.tiktok.misc.extension.sharedExtensionPatch
import app.revanced.patches.tiktok.misc.settings.settingsPatch
import app.revanced.patches.tiktok.misc.settings.settingsStatusLoadFingerprint
import app.revanced.util.findInstructionIndicesReversedOrThrow
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import app.revanced.util.returnEarly
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/tiktok/download/DownloadsPatch;"
@Suppress("unused")
val downloadsPatch = bytecodePatch(
@@ -28,60 +34,45 @@ val downloadsPatch = bytecodePatch(
)
execute {
aclCommonShareFingerprint.method.replaceInstructions(
0,
"""
const/4 v0, 0x0
return v0
""",
)
aclCommonShare2Fingerprint.method.replaceInstructions(
0,
"""
const/4 v0, 0x2
return v0
""",
)
aclCommonShareFingerprint.method.returnEarly(0)
aclCommonShare2Fingerprint.method.returnEarly(2)
// Download videos without watermark.
aclCommonShare3Fingerprint.method.addInstructionsWithLabels(
0,
"""
invoke-static {}, Lapp/revanced/extension/tiktok/download/DownloadsPatch;->shouldRemoveWatermark()Z
move-result v0
if-eqz v0, :noremovewatermark
const/4 v0, 0x1
return v0
:noremovewatermark
nop
""",
invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->shouldRemoveWatermark()Z
move-result v0
if-eqz v0, :noremovewatermark
const/4 v0, 0x1
return v0
:noremovewatermark
nop
""",
)
// Change the download path patch.
downloadUriFingerprint.method.apply {
val firstIndex = indexOfFirstInstructionOrThrow {
getReference<MethodReference>()?.name == "<init>"
}
val secondIndex = indexOfFirstInstructionOrThrow {
getReference<MethodReference>()?.returnType?.contains("Uri") == true
}
findInstructionIndicesReversedOrThrow {
getReference<FieldReference>().let {
it?.definingClass == "Landroid/os/Environment;" && it.name.startsWith("DIRECTORY_")
}
}.forEach { fieldIndex ->
val pathRegister = getInstruction<OneRegisterInstruction>(fieldIndex).registerA
val builderRegister = getInstruction<FiveRegisterInstruction>(fieldIndex + 1).registerC
addInstructions(
secondIndex,
"""
invoke-static {}, Lapp/revanced/extension/tiktok/download/DownloadsPatch;->getDownloadPath()Ljava/lang/String;
move-result-object v0
""",
)
// Remove 'field load → append → "/Camera/" → append' block.
removeInstructions(fieldIndex, 4)
addInstructions(
firstIndex,
"""
invoke-static {}, Lapp/revanced/extension/tiktok/download/DownloadsPatch;->getDownloadPath()Ljava/lang/String;
move-result-object v0
""",
)
addInstructions(
fieldIndex,
"""
invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->getDownloadPath()Ljava/lang/String;
move-result-object v$pathRegister
invoke-virtual { v$builderRegister, v$pathRegister }, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
""",
)
}
}
settingsStatusLoadFingerprint.method.addInstruction(

View File

@@ -5,6 +5,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.layout.branding.addBrandLicensePatch
import app.revanced.patches.tiktok.misc.extension.sharedExtensionPatch
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction22c
@@ -18,7 +19,7 @@ val settingsPatch = bytecodePatch(
name = "Settings",
description = "Adds ReVanced settings to TikTok.",
) {
dependsOn(sharedExtensionPatch)
dependsOn(sharedExtensionPatch, addBrandLicensePatch)
compatibleWith(
"com.ss.android.ugc.trill"("36.5.4"),

View File

@@ -3,23 +3,13 @@ package app.revanced.patches.viber.misc.navbar
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.patch.booleanOption
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.shared.PATCH_NAME_HIDE_NAVIGATION_BUTTONS
import java.util.logging.Logger
import kotlin.collections.joinToString
private const val instructionsFooter = """
# If we reach this, it means that this tab has been disabled by user
const/4 v0, 0
return v0 # return false as "This tab is not enabled"
# Proceed with default execution
:continue
nop
"""
@Suppress("unused")
val hideNavigationButtonsPatch = bytecodePatch(
name = "Hide navigation buttons",
name = PATCH_NAME_HIDE_NAVIGATION_BUTTONS,
description = "Permanently hides navigation bar buttons, such as Explore and Marketplace.",
use = false
) {
@@ -40,13 +30,21 @@ val hideNavigationButtonsPatch = bytecodePatch(
if (allowedItems.size == AllowedNavigationItems.entries.size) {
return@execute Logger.getLogger(this::class.java.name).warning(
"No hide navigation buttons options are enabled. No changes made."
"No hide navigation buttons options are enabled. No changes applied."
)
}
val injectionInstructions = allowedItems
.map { it.key.buildAllowInstruction() }
.joinToString("\n") + instructionsFooter
.joinToString("\n") + """
# If we reach this, it means that this tab has been disabled by user
const/4 v0, 0
return v0 # return false as "This tab is not enabled"
# Proceed with default execution
:continue
nop
"""
shouldShowTabIdMethodFingerprint
.method
@@ -78,8 +76,8 @@ private enum class AllowedNavigationItems(
fun buildAllowInstruction(): String =
ids.joinToString("\n") { id ->
"""
const/4 v0, $id # If tabId == $id ($itemName), don't hide it
if-eq p1, v0, :continue
const/4 v0, $id # If tabId == $id ($itemName), don't hide it
if-eq p1, v0, :continue
"""
}
}

View File

@@ -9,6 +9,7 @@ import app.revanced.patcher.patch.stringOption
import app.revanced.patcher.util.Document
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.layout.branding.addBrandLicensePatch
import app.revanced.patches.shared.misc.mapping.get
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
import app.revanced.patches.shared.misc.mapping.resourceMappings
@@ -24,15 +25,43 @@ import java.io.File
private val variants = arrayOf("light", "dark")
private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/ChangeHeaderPatch;"
private val targetResourceDirectoryNames = mapOf(
"drawable-hdpi" to "194x72 px",
"drawable-xhdpi" to "258x96 px",
"drawable-xxhdpi" to "387x144 px",
"drawable-xxxhdpi" to "512x192 px"
)
/**
* Header logos built into this patch.
*/
private val logoResourceNames = arrayOf(
"revanced_header_minimal",
"revanced_header_rounded",
)
/**
* Custom header resource/file name.
*/
private const val CUSTOM_HEADER_RESOURCE_NAME = "revanced_header_custom"
/**
* Custom header resource/file names.
*/
private val customHeaderResourceFileNames = variants.map { variant ->
"${CUSTOM_HEADER_RESOURCE_NAME}_$variant.png"
}.toTypedArray()
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/ChangeHeaderPatch;"
private val changeHeaderBytecodePatch = bytecodePatch {
dependsOn(resourceMappingPatch)
dependsOn(
resourceMappingPatch,
addBrandLicensePatch
)
execute {
// Resources are not used during patching, but extension code uses these
// images so verify they exist.
// Verify images exist. Resources are not used during patching but extension code does.
arrayOf(
"yt_ringo2_wordmark_header",
"yt_ringo2_premium_wordmark_header"
@@ -62,28 +91,6 @@ private val changeHeaderBytecodePatch = bytecodePatch {
}
}
private val targetResourceDirectoryNames = mapOf(
"xxxhdpi" to "512px x 192px",
"xxhdpi" to "387px x 144px",
"xhdpi" to "258px x 96px",
"hdpi" to "194px x 72px",
"mdpi" to "129px x 48px"
).mapKeys { (dpi, _) -> "drawable-$dpi" }
/**
* Header logos built into this patch.
*/
private val logoResourceNames = arrayOf(
"revanced_header_logo_minimal",
"revanced_header_logo",
)
/**
* Custom header resource/file name.
*/
private const val CUSTOM_HEADER_RESOURCE_NAME = "custom_header"
@Suppress("unused")
val changeHeaderPatch = resourcePatch(
name = "Change header",
@@ -110,7 +117,7 @@ val changeHeaderPatch = resourcePatch(
${targetResourceDirectoryNames.keys.joinToString("\n") { "- $it" }}
Each of the folders must contain all of the following files:
${variants.joinToString("\n") { variant -> "- ${CUSTOM_HEADER_RESOURCE_NAME}_$variant.png" }}
${customHeaderResourceFileNames.joinToString("\n")}
The image dimensions must be as follows:
${targetResourceDirectoryNames.map { (dpi, dim) -> "- $dpi: $dim" }.joinToString("\n")}
@@ -120,67 +127,41 @@ val changeHeaderPatch = resourcePatch(
execute {
addResources("youtube", "layout.branding.changeHeaderPatch")
fun getLightDarkFileNames(vararg resourceNames: String): Array<String> =
variants.flatMap { variant ->
resourceNames.map { resource -> "${resource}_$variant.png" }
}.toTypedArray()
val logoResourceFileNames = getLightDarkFileNames(*logoResourceNames)
copyResources(
"change-header",
ResourceGroup("drawable-hdpi", *logoResourceFileNames),
ResourceGroup("drawable-mdpi", *logoResourceFileNames),
ResourceGroup("drawable-xhdpi", *logoResourceFileNames),
ResourceGroup("drawable-xxhdpi", *logoResourceFileNames),
ResourceGroup("drawable-xxxhdpi", *logoResourceFileNames),
)
if (custom != null) {
val customFile = File(custom!!)
if (!customFile.exists()) {
throw PatchException("The custom icon path cannot be found: " +
customFile.absolutePath
PreferenceScreen.GENERAL_LAYOUT.addPreferences(
if (custom == null) {
ListPreference("revanced_header_logo")
} else {
ListPreference(
key = "revanced_header_logo",
entriesKey = "revanced_header_logo_custom_entries",
entryValuesKey = "revanced_header_logo_custom_entry_values"
)
}
)
if (!customFile.isDirectory) {
throw PatchException("The custom icon path must be a folder: "
+ customFile.absolutePath)
logoResourceNames.forEach { logo ->
variants.forEach { variant ->
copyResources(
"change-header",
ResourceGroup(
"drawable",
logo + "_" + variant + ".xml"
)
)
}
}
val sourceFolders = customFile.listFiles { file -> file.isDirectory }
?: throw PatchException("The custom icon path contains no subfolders: " +
customFile.absolutePath)
val customResourceFileNames = getLightDarkFileNames(CUSTOM_HEADER_RESOURCE_NAME)
var copiedFiles = false
// For each source folder, copy the files to the target resource directories.
sourceFolders.forEach { dpiSourceFolder ->
val targetDpiFolder = get("res").resolve(dpiSourceFolder.name)
if (!targetDpiFolder.exists()) return@forEach
val customFiles = dpiSourceFolder.listFiles { file ->
file.isFile && file.name in customResourceFileNames
}!!
if (customFiles.size > 0 && customFiles.size != variants.size) {
throw PatchException("Both light/dark mode images " +
"must be specified but only found: " + customFiles.map { it.name })
}
customFiles.forEach { imgSourceFile ->
val imgTargetFile = targetDpiFolder.resolve(imgSourceFile.name)
imgSourceFile.copyTo(imgTargetFile)
copiedFiles = true
}
}
if (!copiedFiles) {
throw PatchException("No custom header images found in " +
"the provided path: " + customFile.absolutePath)
// Copy custom template. Images are only used if settings
// are imported and a custom header is enabled.
targetResourceDirectoryNames.keys.forEach { dpi ->
variants.forEach { variant ->
copyResources(
"change-header",
ResourceGroup(
dpi,
*customHeaderResourceFileNames
)
)
}
}
@@ -199,9 +180,7 @@ val changeHeaderPatch = resourcePatch(
addAttributeReference(logoName)
}
if (custom != null) {
addAttributeReference(CUSTOM_HEADER_RESOURCE_NAME)
}
addAttributeReference(CUSTOM_HEADER_RESOURCE_NAME)
}
// Add custom drawables to all styles that use the regular and premium logo.
@@ -227,22 +206,58 @@ val changeHeaderPatch = resourcePatch(
addDrawableElement(document, logoName, mode)
}
if (custom != null) {
addDrawableElement(document, CUSTOM_HEADER_RESOURCE_NAME, mode)
}
addDrawableElement(document, CUSTOM_HEADER_RESOURCE_NAME, mode)
}
}
PreferenceScreen.GENERAL_LAYOUT.addPreferences(
if (custom == null) {
ListPreference("revanced_header_logo")
} else {
ListPreference(
key = "revanced_header_logo",
entriesKey = "revanced_header_logo_custom_entries",
entryValuesKey = "revanced_header_logo_custom_entry_values"
// Copy user provided images last, so if an exception is thrown due to bad input.
if (custom != null) {
val customFile = File(custom!!.trim())
if (!customFile.exists()) {
throw PatchException("The custom header path cannot be found: " +
customFile.absolutePath
)
}
)
if (!customFile.isDirectory) {
throw PatchException("The custom header path must be a folder: "
+ customFile.absolutePath)
}
var copiedFiles = false
// For each source folder, copy the files to the target resource directories.
customFile.listFiles {
file -> file.isDirectory && file.name in targetResourceDirectoryNames
}!!.forEach { dpiSourceFolder ->
val targetDpiFolder = get("res").resolve(dpiSourceFolder.name)
if (!targetDpiFolder.exists()) {
// Should never happen.
throw IllegalStateException("Resource not found: $dpiSourceFolder")
}
val customFiles = dpiSourceFolder.listFiles { file ->
file.isFile && file.name in customHeaderResourceFileNames
}!!
if (customFiles.isNotEmpty() && customFiles.size != variants.size) {
throw PatchException("Both light/dark mode images " +
"must be specified but only found: " + customFiles.map { it.name })
}
customFiles.forEach { imgSourceFile ->
val imgTargetFile = targetDpiFolder.resolve(imgSourceFile.name)
imgSourceFile.copyTo(target = imgTargetFile, overwrite = true)
copiedFiles = true
}
}
if (!copiedFiles) {
throw PatchException("Expected to find directories and files: "
+ customHeaderResourceFileNames.contentToString()
+ "\nBut none were found in the provided option file path: " + customFile.absolutePath)
}
}
}
}

View File

@@ -147,6 +147,7 @@ val hideLayoutComponentsPatch = bytecodePatch(
SwitchPreference("revanced_hide_chapters_section"),
SwitchPreference("revanced_hide_info_cards_section"),
SwitchPreference("revanced_hide_how_this_was_made_section"),
SwitchPreference("revanced_hide_hype_points"),
SwitchPreference("revanced_hide_key_concepts_section"),
SwitchPreference("revanced_hide_podcast_section"),
SwitchPreference("revanced_hide_transcript_section"),

View File

@@ -45,10 +45,10 @@ val hidePlayerFlyoutMenuPatch = bytecodePatch(
SwitchPreference("revanced_hide_player_flyout_loop_video"),
SwitchPreference("revanced_hide_player_flyout_ambient_mode"),
SwitchPreference("revanced_hide_player_flyout_stable_volume"),
SwitchPreference("revanced_hide_player_flyout_listen_with_youtube_music"),
SwitchPreference("revanced_hide_player_flyout_help"),
SwitchPreference("revanced_hide_player_flyout_speed"),
SwitchPreference("revanced_hide_player_flyout_lock_screen"),
SwitchPreference("revanced_hide_player_flyout_more_info"),
SwitchPreference(
key = "revanced_hide_player_flyout_audio_track",
tag = "app.revanced.extension.youtube.settings.preference.HideAudioFlyoutMenuPreference"

View File

@@ -63,13 +63,6 @@ val spoofVideoStreamsPatch = spoofVideoStreamsPatch(
tag = "app.revanced.extension.youtube.settings.preference.SpoofStreamingDataSideEffectsPreference"
),
SwitchPreference("revanced_spoof_video_streams_av1"),
ListPreference(
key = "revanced_spoof_video_streams_language",
// Language strings are declared in Setting patch.
entriesKey = "revanced_language_entries",
entryValuesKey = "revanced_language_entry_values",
tag = "app.revanced.extension.youtube.settings.preference.SpoofAudioSelectorListPreference"
),
SwitchPreference("revanced_spoof_streaming_data_stats_for_nerds"),
)
)

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -134,9 +134,8 @@ Second \"item\" text"</string>
<!-- 'Ambient mode' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Help & feedback' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Playback speed' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
@@ -257,7 +256,6 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<!-- "Force original audio" should use the same text as revanced_force_original_audio_title -->
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -134,9 +134,8 @@ Second \"item\" text"</string>
<!-- 'Ambient mode' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Help & feedback' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Playback speed' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
@@ -257,7 +256,6 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<!-- "Force original audio" should use the same text as revanced_force_original_audio_title -->
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -328,6 +328,9 @@ Second \"item\" text"</string>
<string name="revanced_hide_how_this_was_made_section_title">إخفاء \'كيف تم إنشاء هذا المحتوى\'</string>
<string name="revanced_hide_how_this_was_made_section_summary_on">تم إخفاء قسم كيف تم إنشاء هذا المحتوى</string>
<string name="revanced_hide_how_this_was_made_section_summary_off">يتم عرض قسم كيف تم إنشاء هذا المحتوى</string>
<string name="revanced_hide_hype_points_title">إخفاء نقاط التشجيع</string>
<string name="revanced_hide_hype_points_summary_on">تم إخفاء نقاط التشجيع</string>
<string name="revanced_hide_hype_points_summary_off">يتم عرض نقاط التشجيع</string>
<string name="revanced_hide_podcast_section_title">إخفاء \'استكشاف البودكاست\'</string>
<string name="revanced_hide_podcast_section_summary_on">تم إخفاء قسم استكشاف البودكاست</string>
<string name="revanced_hide_podcast_section_summary_off">يتم عرض قسم استكشاف البودكاست</string>
@@ -771,15 +774,14 @@ Second \"item\" text"</string>
<string name="revanced_hide_player_flyout_speed_title">إخفاء سرعة التشغيل</string>
<string name="revanced_hide_player_flyout_speed_summary_on">تم إخفاء قائمة سرعة التشغيل</string>
<string name="revanced_hide_player_flyout_speed_summary_off">يتم عرض قائمة سرعة التشغيل</string>
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<string name="revanced_hide_player_flyout_more_info_title">إخفاء المزيد من المعلومات</string>
<string name="revanced_hide_player_flyout_more_info_summary_on">تم إخفاء قائمة المزيد من المعلومات</string>
<string name="revanced_hide_player_flyout_more_info_summary_off">يتم عرض قائمة المزيد من المعلومات</string>
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_lock_screen_title">إخفاء شاشة القفل</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_on">تم إخفاء قائمة شاشة القفل</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_off">يتم عرض قائمة شاشة القفل</string>
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_listen_with_youtube_music_title">إخفاء الاستماع مع YouTube Music</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_on">تم إخفاء قائمة الاستماع مع YouTube Music</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_off">يتم عرض قائمة الاستماع مع YouTube Music</string>
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_audio_track_title">إخفاء المقطع الصوتي</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">تم إخفاء قائمة المقطع الصوتي</string>
@@ -1639,10 +1641,6 @@ Second \"item\" text"</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">عرض في إحصاءات تقنية</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">يتم عرض نوع العميل في إحصاءات تقنية</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">تم إخفاء نوع العميل في إحصاءات تقنية</string>
<string name="revanced_spoof_video_streams_language_title">لغة بث الصوت</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">لتحديد لغة صوتية معينة، قم بإيقاف تشغيل \'فرض لغة الصوت الأصلية\'</string>
<string name="revanced_spoof_video_streams_language_android_studio">اختيار لغة البث غير متاح مع Android Studio</string>
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -135,9 +135,8 @@ Second \"item\" text"</string>
<!-- 'Ambient mode' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Help & feedback' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Playback speed' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
@@ -259,7 +258,6 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<!-- "Force original audio" should use the same text as revanced_force_original_audio_title -->
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -328,6 +328,9 @@ Hər halda, bunu aktivləşdirmə IP ünvanınız kimi bəzi istifadəçi məlum
<string name="revanced_hide_how_this_was_made_section_title">\'Bu kontent necə hazırlanıb\'ı Gizlət</string>
<string name="revanced_hide_how_this_was_made_section_summary_on">Bu məzmunun necə hazırlandığı bölməsi gizlidir</string>
<string name="revanced_hide_how_this_was_made_section_summary_off">Bu məzmunun necə hazırlandığı bölməsi görünür</string>
<string name="revanced_hide_hype_points_title">Hype nöqtələrini gizlət</string>
<string name="revanced_hide_hype_points_summary_on">Hype nöqtələri gizlədilib</string>
<string name="revanced_hide_hype_points_summary_off">Hype nöqtələri göstərilir</string>
<string name="revanced_hide_podcast_section_title">\'Podkastı araşdırın\"-ı Gizlət</string>
<string name="revanced_hide_podcast_section_summary_on">Podkast bölməsin araşdırın gizlidir</string>
<string name="revanced_hide_podcast_section_summary_off">Podkast bölməsin araşdırın görünür</string>
@@ -771,15 +774,14 @@ Bu seçimi dəyişdirmə işə düşmürsə, Gizli rejimə keçməyə çalışı
<string name="revanced_hide_player_flyout_speed_title">\"Oynatma sürəti\"ni gizlət</string>
<string name="revanced_hide_player_flyout_speed_summary_on">Oynatma sürəti menyusu gizlidir</string>
<string name="revanced_hide_player_flyout_speed_summary_off">Oynatma sürəti menyusu göstərilir</string>
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<string name="revanced_hide_player_flyout_more_info_title">\"Daha çox məlumat\"ı gizlət</string>
<string name="revanced_hide_player_flyout_more_info_summary_on">Ətraflı məlumat menyusu gizlidir</string>
<string name="revanced_hide_player_flyout_more_info_summary_off">Ətraflı məlumat menyusu göstərilir</string>
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_lock_screen_title">Kilid ekranını gizlət</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_on">Kilid ekranı menyusu gizlidir</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_off">Kilid ekranı menyusu göstərilir</string>
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_listen_with_youtube_music_title">YouTube Music ilə dinləməni gizlət</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_on">YouTube Music ilə dinlə menyusu gizlədilib</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_off">YouTube Music ilə dinlə menyusu göstərilir</string>
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_audio_track_title">Səs trekini gizlət</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">Səs axını menyusu gizlidir</string>
@@ -1638,10 +1640,6 @@ Video oynatma AV1 ilə ilişə bilər və ya kadrlar buraxıla bilər."</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">İstək üçün Statistikada göstər</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Qəbuledici növü İstək üçün statistikada göstərilir</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Qəbuledici nerd üçün Statistikada gizlidir</string>
<string name="revanced_spoof_video_streams_language_title">Səs yayım dili</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">Xüsusi səs dilini seçmək üçün \"Orijinal səs dilini zorlanı\" qapat</string>
<string name="revanced_spoof_video_streams_language_android_studio">Yayım dili seçimi Android Studio ilə əlçatmazdır</string>
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -328,6 +328,9 @@ Second \"item\" text"</string>
<string name="revanced_hide_how_this_was_made_section_title">Схаваць «Як быў створаны гэты кантэнт»</string>
<string name="revanced_hide_how_this_was_made_section_summary_on">Раздзел «Як быў створаны гэты кантэнт» схаваны</string>
<string name="revanced_hide_how_this_was_made_section_summary_off">Раздзел «Як быў створаны гэты кантэнт» паказаны</string>
<string name="revanced_hide_hype_points_title">Схаваць Hype балы</string>
<string name="revanced_hide_hype_points_summary_on">Hype балы схаваны</string>
<string name="revanced_hide_hype_points_summary_off">Hype балы паказаны</string>
<string name="revanced_hide_podcast_section_title">Схаваць «Пазнаёмцеся з падкастам»</string>
<string name="revanced_hide_podcast_section_summary_on">Раздзел «Пазнаёмцеся з падкастам» схаваны</string>
<string name="revanced_hide_podcast_section_summary_off">Раздзел «Пазнаёмцеся з падкастам» паказаны</string>
@@ -771,15 +774,14 @@ Second \"item\" text"</string>
<string name="revanced_hide_player_flyout_speed_title">Схаваць хуткасць прайгравання</string>
<string name="revanced_hide_player_flyout_speed_summary_on">Меню хуткасці прайгравання схавана</string>
<string name="revanced_hide_player_flyout_speed_summary_off">Адлюструецца меню хуткасці прайгравання</string>
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<string name="revanced_hide_player_flyout_more_info_title">Схаваць Дадатковая інфармацыя</string>
<string name="revanced_hide_player_flyout_more_info_summary_on">Меню дадатковай інфармацыі схавана</string>
<string name="revanced_hide_player_flyout_more_info_summary_off">Паказана меню дадатковай інфармацыі</string>
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_lock_screen_title">Схаваць экран блакіроўкі</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_on">Меню экрана блакіроўкі схавана</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_off">Адлюстроўваецца меню блакіроўкі экрана</string>
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_listen_with_youtube_music_title">Схаваць \'Слухаць у YouTube Music\'</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_on">Меню \'Слухаць у YouTube Music\' схавана</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_off">Меню \'Слухаць у YouTube Music\' паказана</string>
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_audio_track_title">Схаваць гукавую дарожку</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">Меню гукавой дарожкі схавана</string>
@@ -1640,10 +1642,6 @@ Second \"item\" text"</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Паказаць у статыстыцы для спецыялістаў</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Тып кліента адлюстроўваецца ў статыстыцы для спецыялістаў</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Кліент схаваны ў статыстыцы для спецыялістаў</string>
<string name="revanced_spoof_video_streams_language_title">Мова аўдыяпатоку</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">Каб выбраць пэўную мову аўдыё, адключыце \'Прымусовая арыгінальная мова аўдыё\'</string>
<string name="revanced_spoof_video_streams_language_android_studio">Выбар мовы трансляцыі недаступны ў Android Studio</string>
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -328,6 +328,9 @@ Second \"item\" text"</string>
<string name="revanced_hide_how_this_was_made_section_title">Скриване на \"Как е създадено това съдържание\"</string>
<string name="revanced_hide_how_this_was_made_section_summary_on">Секцията \"Как е създадено това съдържание\" е скрита</string>
<string name="revanced_hide_how_this_was_made_section_summary_off">Секцията \"Как е създадено това съдържание\" е показана</string>
<string name="revanced_hide_hype_points_title">Скриване на точките на хайп</string>
<string name="revanced_hide_hype_points_summary_on">Точките на хайп са скрити</string>
<string name="revanced_hide_hype_points_summary_off">Точките на хайп са показани</string>
<string name="revanced_hide_podcast_section_title">Скриване на \"Разгледайте подкаста\"</string>
<string name="revanced_hide_podcast_section_summary_on">Секцията \"Разгледайте подкаста\" е скрита</string>
<string name="revanced_hide_podcast_section_summary_off">Секцията \"Разгледайте подкаста\" е показана</string>
@@ -771,15 +774,14 @@ Second \"item\" text"</string>
<string name="revanced_hide_player_flyout_speed_title">Скриване на скоростта на възпроизвеждане</string>
<string name="revanced_hide_player_flyout_speed_summary_on">Менюто за скорост на видеото е скрито</string>
<string name="revanced_hide_player_flyout_speed_summary_off">Менюто за скорост на видеото се показва</string>
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<string name="revanced_hide_player_flyout_more_info_title">\"Допълнителна информация\"</string>
<string name="revanced_hide_player_flyout_more_info_summary_on">\"Допълнителна информация\" е скрита</string>
<string name="revanced_hide_player_flyout_more_info_summary_off">\"Допълнителна информация\" се показва</string>
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_lock_screen_title">\"Заключен екран\"</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_on">Менюто на заключен екран е скрито</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_off">Менюто на заключен екран се показва</string>
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_listen_with_youtube_music_title">Скриване на Слушане с YouTube Music</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_on">Менюто Слушане с YouTube Music е скрито</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_off">Менюто Слушане с YouTube Music е показано</string>
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_audio_track_title">Избор на Аудио</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">Менюто за избор на Аудио е скрито</string>
@@ -1639,10 +1641,6 @@ Second \"item\" text"</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Poka6i v Statistiki za nerds</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Tipът na klienta se poka6va v Statistiki za nerds</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Klientът e skriт v Statistiki za nerds</string>
<string name="revanced_spoof_video_streams_language_title">Език на аудио потока</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">За да изберете конкретен аудио език, изключете \'Принудително оригинален аудио език\'</string>
<string name="revanced_spoof_video_streams_language_android_studio">Изборът на език на потока не е наличен с Android Studio</string>
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -324,6 +324,9 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
<string name="revanced_hide_how_this_was_made_section_title">\'How this content was made\' লুকান</string>
<string name="revanced_hide_how_this_was_made_section_summary_on">How this content was made বিভাগটি লুকানো আছে</string>
<string name="revanced_hide_how_this_was_made_section_summary_off">How this content was made বিভাগটি দেখানো হয়েছে</string>
<string name="revanced_hide_hype_points_title">হাইপ পয়েন্ট লুকান</string>
<string name="revanced_hide_hype_points_summary_on">হাইপ পয়েন্ট লুকানো আছে</string>
<string name="revanced_hide_hype_points_summary_off">হাইপ পয়েন্ট দেখানো আছে</string>
<string name="revanced_hide_podcast_section_title">\'Explore the podcast\' লুকান</string>
<string name="revanced_hide_podcast_section_summary_on">Explore the podcast বিভাগটি লুকানো আছে</string>
<string name="revanced_hide_podcast_section_summary_off">Explore the podcast বিভাগটি দেখানো হয়েছে</string>
@@ -767,15 +770,14 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
<string name="revanced_hide_player_flyout_speed_title">প্লেব্যাকের স্পিড লুকান</string>
<string name="revanced_hide_player_flyout_speed_summary_on">প্লেব্যাকের স্পিড মেনু লুকিয়ে রয়েছে</string>
<string name="revanced_hide_player_flyout_speed_summary_off">প্লেব্যাকের স্পিড মেনু প্রদর্শিত হয়েছে</string>
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<string name="revanced_hide_player_flyout_more_info_title">আরো তথ্য লুকান</string>
<string name="revanced_hide_player_flyout_more_info_summary_on">আরও তথ্য মেনু লুকানো আছে</string>
<string name="revanced_hide_player_flyout_more_info_summary_off">আরও তথ্য মেনু দেখানো হয়</string>
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_lock_screen_title">লক স্ক্রীন লুকান</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_on">লক স্ক্রীন মেনু লুকানো আছে</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_off">লক স্ক্রিন মেনু দেখানো হয়েছে</string>
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_listen_with_youtube_music_title">ইউটিউব মিউজিক দিয়ে শুনুন লুকান</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_on">ইউটিউব মিউজিক দিয়ে শুনুন মেনু লুকানো আছে</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_off">ইউটিউব মিউজিক দিয়ে শুনুন মেনু দেখানো আছে</string>
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_audio_track_title">অডিও ট্র্যাক লুকান</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">অডিও ট্র্যাক মেনু লুকানো আছে</string>
@@ -1635,10 +1637,6 @@ AV1 সহ ভিডিও প্লেব্যাক আটকে যেতে
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">স্ট্যাটস ফর নার্ডসে দেখান</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">স্ট্যাটস ফর নার্ডসে ক্লায়েন্ট প্রকার দেখানো হবে</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">স্ট্যাটস ফর নার্ডসে ক্লায়েন্ট লুকানো হবে</string>
<string name="revanced_spoof_video_streams_language_title">অডিও স্ট্রিম ভাষা</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">একটি নির্দিষ্ট অডিও ভাষা নির্বাচন করতে, \'মূল অডিও ভাষা জোর করে চালু রাখুন\' বন্ধ করুন</string>
<string name="revanced_spoof_video_streams_language_android_studio">অ্যান্ড্রয়েড স্টুডিও সহ স্ট্রিম ভাষার নির্বাচন উপলব্ধ নেই</string>
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -134,9 +134,8 @@ Second \"item\" text"</string>
<!-- 'Ambient mode' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Help & feedback' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Playback speed' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
@@ -257,7 +256,6 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<!-- "Force original audio" should use the same text as revanced_force_original_audio_title -->
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -134,9 +134,8 @@ Second \"item\" text"</string>
<!-- 'Ambient mode' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Help & feedback' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Playback speed' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
@@ -257,7 +256,6 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<!-- "Force original audio" should use the same text as revanced_force_original_audio_title -->
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -328,6 +328,9 @@ Pokud se Doodle v současné době zobrazuje ve vaší oblasti a toto nastavení
<string name="revanced_hide_how_this_was_made_section_title">Skrýt „Jak tento obsah vznikl“</string>
<string name="revanced_hide_how_this_was_made_section_summary_on">Sekce Jak tento obsah vznikl je skrytá</string>
<string name="revanced_hide_how_this_was_made_section_summary_off">Sekce Jak tento obsah vznikl je zobrazena</string>
<string name="revanced_hide_hype_points_title">Skrýt Hype body</string>
<string name="revanced_hide_hype_points_summary_on">Hype body jsou skryté</string>
<string name="revanced_hide_hype_points_summary_off">Hype body jsou zobrazené</string>
<string name="revanced_hide_podcast_section_title">Skrýt „Prozkoumat podcast“</string>
<string name="revanced_hide_podcast_section_summary_on">Sekce Prozkoumat podcast je skrytá</string>
<string name="revanced_hide_podcast_section_summary_off">Sekce Prozkoumat podcast je zobrazena</string>
@@ -771,15 +774,14 @@ Pokud změna tohoto nastavení nemá žádný účinek, zkuste přepnout do rež
<string name="revanced_hide_player_flyout_speed_title">Skrýt Rychlost přehrávání</string>
<string name="revanced_hide_player_flyout_speed_summary_on">Menu Rychlost přehrávání je skryto</string>
<string name="revanced_hide_player_flyout_speed_summary_off">Menu Rychlost přehrávání je zobrazeno</string>
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<string name="revanced_hide_player_flyout_more_info_title">Skrýt Více informací</string>
<string name="revanced_hide_player_flyout_more_info_summary_on">Menu Více informací je skryto</string>
<string name="revanced_hide_player_flyout_more_info_summary_off">Menu Více informací je zobrazeno</string>
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_lock_screen_title">Skrýt Zamknout obrazovku</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_on">Menu Zamknout obrazovku je skryto</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_off">Menu Zamknout obrazovku je zobrazeno</string>
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_listen_with_youtube_music_title">Skrýt Poslouchat v YouTube Music</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_on">Nabídka Poslouchat v YouTube Music je skrytá</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_off">Nabídka Poslouchat v YouTube Music je zobrazena</string>
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_audio_track_title">Skrýt Zvuková stopa</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">Menu Zvuková stopa je skryto</string>
@@ -1639,10 +1641,6 @@ Přehrávání videa s AV1 se může sekat nebo vypadávat snímky."</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Zobrazit ve statistikách pro nadšence</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Typ klienta se zobrazuje ve statistikách pro nadšence</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Klient je skrytý ve statistikách pro nadšence</string>
<string name="revanced_spoof_video_streams_language_title">Jazyk zvukového streamu</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">Chcete-li vybrat konkrétní zvukový jazyk, vypněte „Vynutit původní zvukový jazyk“</string>
<string name="revanced_spoof_video_streams_language_android_studio">Volba jazyka streamu není k dispozici s Android Studiem</string>
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -328,6 +328,9 @@ Hvis et Doodle vises i øjeblikket i din region, og denne skjuleindstilling er a
<string name="revanced_hide_how_this_was_made_section_title">Skjul \"Hvordan dette indhold blev lavet\"</string>
<string name="revanced_hide_how_this_was_made_section_summary_on">Sektionen Sådan blev dette indhold lavet er skjult</string>
<string name="revanced_hide_how_this_was_made_section_summary_off">Sektionen Sådan blev dette indhold lavet vises</string>
<string name="revanced_hide_hype_points_title">Skjul Hype-point</string>
<string name="revanced_hide_hype_points_summary_on">Hype-point er skjult</string>
<string name="revanced_hide_hype_points_summary_off">Hype-point er vist</string>
<string name="revanced_hide_podcast_section_title">Skjul \"Udforsk podcasten\"</string>
<string name="revanced_hide_podcast_section_summary_on">Sektionen Udforsk podcasten er skjult</string>
<string name="revanced_hide_podcast_section_summary_off">Sektionen Udforsk podcasten vises</string>
@@ -771,15 +774,14 @@ Hvis ændring af denne indstilling ikke træder i kraft, kan du prøve at skifte
<string name="revanced_hide_player_flyout_speed_title">Skjul afspilningshastighed</string>
<string name="revanced_hide_player_flyout_speed_summary_on">Afspilningshastighedsmenu er skjult</string>
<string name="revanced_hide_player_flyout_speed_summary_off">Afspilningshastighed menuen vises</string>
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<string name="revanced_hide_player_flyout_more_info_title">Skjul Mere info</string>
<string name="revanced_hide_player_flyout_more_info_summary_on">Mere info menu er skjult</string>
<string name="revanced_hide_player_flyout_more_info_summary_off">Mere info menu er vist</string>
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_lock_screen_title">Skjul låseskærm</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_on">Menuen Låseskærm er skjult</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_off">Låseskærmsmenuen vises</string>
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_listen_with_youtube_music_title">Skjul Lyt med YouTube Music</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_on">Lyt med YouTube Music-menuen er skjult</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_off">Lyt med YouTube Music-menuen vises</string>
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_audio_track_title">Skjul lydspor</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">Menuen for lydspor er skjult</string>
@@ -1641,10 +1643,6 @@ Videoafspilning med AV1 kan hakke eller tabe billeder."</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Vis i Statistik for nørder</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Klienttypen vises i Statistik for nørder</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Klienten er skjult i Statistik for nørder</string>
<string name="revanced_spoof_video_streams_language_title">Lydstreamsprog</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">For at vælge et specifikt lydsprog, slå \'Gennemtving originalt lydsprog\' fra</string>
<string name="revanced_spoof_video_streams_language_android_studio">Valg af streaming-sprog er ikke tilgængeligt med Android Studio</string>
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -327,6 +327,9 @@ Wenn ein Doodle zurzeit in Ihrer Region angezeigt wird und diese Einstellung zum
<string name="revanced_hide_how_this_was_made_section_title">\"Wie dieser Inhalt erstellt wurde\" ausblenden</string>
<string name="revanced_hide_how_this_was_made_section_summary_on">Der Abschnitt \"Wie dieser Inhalt erstellt wurde\" ist ausgeblendet</string>
<string name="revanced_hide_how_this_was_made_section_summary_off">Der Abschnitt \"Wie dieser Inhalt erstellt wurde\" wird angezeigt</string>
<string name="revanced_hide_hype_points_title">Hype-Punkte ausblenden</string>
<string name="revanced_hide_hype_points_summary_on">Hype-Punkte sind ausgeblendet</string>
<string name="revanced_hide_hype_points_summary_off">Hype-Punkte werden angezeigt</string>
<string name="revanced_hide_podcast_section_title">\'Podcast entdecken\' ausblenden</string>
<string name="revanced_hide_podcast_section_summary_on">Der Abschnitt \"Podcast entdecken\" ist ausgeblendet</string>
<string name="revanced_hide_podcast_section_summary_off">Der Abschnitt \"Podcast entdecken\" wird angezeigt</string>
@@ -768,15 +771,14 @@ Wenn diese Änderung nicht wirksam wird, versuchen Sie, in den Inkognito-Modus z
<string name="revanced_hide_player_flyout_speed_title">Wiedergabegeschwindigkeit ausblenden</string>
<string name="revanced_hide_player_flyout_speed_summary_on">Wiedergabegeschwindigkeit ist ausgeblendet</string>
<string name="revanced_hide_player_flyout_speed_summary_off">Wiedergabegeschwindigkeit wird angezeigt</string>
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<string name="revanced_hide_player_flyout_more_info_title">Mehr Info ausblenden</string>
<string name="revanced_hide_player_flyout_more_info_summary_on">Mehr Info-Menü ist ausgeblendet</string>
<string name="revanced_hide_player_flyout_more_info_summary_off">Mehr Info-Menü wird angezeigt</string>
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_lock_screen_title">Sperrbildschirm ausblenden</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_on">Sperrbildschirm-Menü ist ausgeblendet</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_off">Sperrbildschirm-Menü wird angezeigt</string>
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_listen_with_youtube_music_title">„Mit YouTube Music hören“ ausblenden</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_on">„Mit YouTube Music hören“-Menü ist ausgeblendet</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_off">„Mit YouTube Music hören“-Menü wird angezeigt</string>
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_audio_track_title">Audiospur ausblenden</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">Audiospur-Menü ist ausgeblendet</string>
@@ -1636,10 +1638,6 @@ Die Videowiedergabe mit AV1 kann stottern oder Bilder überspringen."</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">In Statistiken für Nerds anzeigen</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Der Client-Typ wird in den Statistiken für Nerds angezeigt</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Der Client wird in den Statistiken für Nerds ausgeblendet</string>
<string name="revanced_spoof_video_streams_language_title">Audiodatenstromsprache</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">Um eine bestimmte Audiosprache auszuwählen, deaktivieren Sie „Original-Audiosprache erzwingen“</string>
<string name="revanced_spoof_video_streams_language_android_studio">Die Auswahl der Stream-Sprache ist mit Android Studio nicht verfügbar.</string>
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -330,6 +330,9 @@ Second \"item\" text"</string>
<string name="revanced_hide_how_this_was_made_section_title">Ενότητα «Πως δημιουργήθηκε αυτό το περιεχόμενο»</string>
<string name="revanced_hide_how_this_was_made_section_summary_on">Κρυμμένη</string>
<string name="revanced_hide_how_this_was_made_section_summary_off">Εμφανίζεται</string>
<string name="revanced_hide_hype_points_title">Πόντοι Hype</string>
<string name="revanced_hide_hype_points_summary_on">Κρυμμένοι</string>
<string name="revanced_hide_hype_points_summary_off">Εμφανίζονται</string>
<string name="revanced_hide_podcast_section_title">Ενότητα «Εξερευνήστε το podcast»</string>
<string name="revanced_hide_podcast_section_summary_on">Κρυμμένη</string>
<string name="revanced_hide_podcast_section_summary_off">Εμφανίζεται</string>
@@ -773,15 +776,14 @@ Second \"item\" text"</string>
<string name="revanced_hide_player_flyout_speed_title">Μενού «Ταχύτητα αναπαραγωγής»</string>
<string name="revanced_hide_player_flyout_speed_summary_on">Κρυμμένο</string>
<string name="revanced_hide_player_flyout_speed_summary_off">Εμφανίζεται</string>
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<string name="revanced_hide_player_flyout_more_info_title">Μενού «Περισσότερα»</string>
<string name="revanced_hide_player_flyout_more_info_summary_on">Κρυμμένο</string>
<string name="revanced_hide_player_flyout_more_info_summary_off">Εμφανίζεται</string>
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_lock_screen_title">Μενού «Οθόνη κλειδώματος»</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_on">Κρυμμένο</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_off">Εμφανίζεται</string>
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_listen_with_youtube_music_title">Μενού «Ακρόαση με YouTube Music»</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_on">Κρυμμένο</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_off">Εμφανίζεται</string>
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_audio_track_title">Μενού «Κομμάτι ήχου»</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">Κρυμμένο</string>
@@ -1638,10 +1640,6 @@ Second \"item\" text"</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Εμφάνιση στο μενού «Στατιστικά για σπασίκλες»</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Το πρόγραμμα πελάτη εμφανίζεται στο μενού «Στατιστικά για σπασίκλες»</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Το πρόγραμμα πελάτη δεν εμφανίζεται στο μενού «Στατιστικά για σπασίκλες»</string>
<string name="revanced_spoof_video_streams_language_title">Γλώσσα ροής ήχου</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">Για να επιλέξετε μια συγκεκριμένη γλώσσα ήχου, απενεργοποιήστε το «Εξαναγκασμός αρχικής γλώσσας ήχου»</string>
<string name="revanced_spoof_video_streams_language_android_studio">Η επιλογή γλώσσας ροής δεν είναι διαθέσιμη με το Android Studio</string>
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -328,6 +328,9 @@ Si un doodle se está mostrando actualmente en tu región y este ajuste de ocult
<string name="revanced_hide_how_this_was_made_section_title">Ocultar \"Cómo se hizo este contenido\"</string>
<string name="revanced_hide_how_this_was_made_section_summary_on">La sección Cómo se hizo este contenido está oculta</string>
<string name="revanced_hide_how_this_was_made_section_summary_off">Se muestra la sección Cómo se hizo este contenido</string>
<string name="revanced_hide_hype_points_title">Ocultar puntos de Hype</string>
<string name="revanced_hide_hype_points_summary_on">Los puntos de Hype están ocultos</string>
<string name="revanced_hide_hype_points_summary_off">Los puntos de Hype están visibles</string>
<string name="revanced_hide_podcast_section_title">Ocultar \"Explora el pódcast\"</string>
<string name="revanced_hide_podcast_section_summary_on">La sección Explora el pódcast está oculta</string>
<string name="revanced_hide_podcast_section_summary_off">Se muestra la sección Explora el pódcast</string>
@@ -771,15 +774,14 @@ Si cambiar este ajuste no tiene efecto, intenta cambiar al modo incógnito."</st
<string name="revanced_hide_player_flyout_speed_title">Ocultar velocidad de reproducción</string>
<string name="revanced_hide_player_flyout_speed_summary_on">Menú de velocidad de reproducción oculto</string>
<string name="revanced_hide_player_flyout_speed_summary_off">Mostrar menú de velocidad de reproducción</string>
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<string name="revanced_hide_player_flyout_more_info_title">Ocultar Más información</string>
<string name="revanced_hide_player_flyout_more_info_summary_on">El menú Más información está oculto</string>
<string name="revanced_hide_player_flyout_more_info_summary_off">Se muestra el menú Más información</string>
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_lock_screen_title">Ocultar pantalla de bloqueo</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_on">El menú de la pantalla de bloqueo está oculto</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_off">Se muestra el menú de pantalla de bloqueo</string>
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_listen_with_youtube_music_title">Ocultar Escuchar con YouTube Music</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_on">El menú Escuchar con YouTube Music está oculto</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_off">El menú Escuchar con YouTube Music está visible</string>
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_audio_track_title">Ocultar pista de audio</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">El menú de pista de audio está oculto</string>
@@ -1628,10 +1630,6 @@ La reproducción puede tartamudear o perder fotogramas"</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Mostrar en Estadísticas para nerds</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">El tipo de cliente se muestra en Estadísticas para nerds</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">El cliente está oculto en Estadísticas para nerds</string>
<string name="revanced_spoof_video_streams_language_title">Idioma de la transmisión de audio</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">Para seleccionar un idioma de audio específico, desactiva \"Forzar idioma de audio original\"</string>
<string name="revanced_spoof_video_streams_language_android_studio">La selección de idioma de transmisión no está disponible con Android Studio</string>
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -328,6 +328,9 @@ Kui Doodle on teie piirkonnas praegu nähtav ja see peitmise seade on sisse lül
<string name="revanced_hide_how_this_was_made_section_title">Peida \"Kuidas see sisu loodi\"</string>
<string name="revanced_hide_how_this_was_made_section_summary_on">Kuidas see sisu loodi jaotis on peidetud</string>
<string name="revanced_hide_how_this_was_made_section_summary_off">Kuidas see sisu loodi jaotis on kuvatud</string>
<string name="revanced_hide_hype_points_title">Peida Hype\'i punktid</string>
<string name="revanced_hide_hype_points_summary_on">Hype\'i punktid on peidetud</string>
<string name="revanced_hide_hype_points_summary_off">Hype\'i punktid on nähtavad</string>
<string name="revanced_hide_podcast_section_title">Peida \"Avasta taskuhäälingut\"</string>
<string name="revanced_hide_podcast_section_summary_on">Avasta taskuhäälingut jaotis on peidetud</string>
<string name="revanced_hide_podcast_section_summary_off">Avasta taskuhäälingut jaotis on kuvatud</string>
@@ -771,15 +774,14 @@ Kui selle sätte muutmine ei avalda mõju, proovige lülituda Inkognito režiimi
<string name="revanced_hide_player_flyout_speed_title">Peida Esituse kiirus</string>
<string name="revanced_hide_player_flyout_speed_summary_on">Esituse kiiruse menüü on peidetud</string>
<string name="revanced_hide_player_flyout_speed_summary_off">Esituse kiiruse menüü on nähtav</string>
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<string name="revanced_hide_player_flyout_more_info_title">Peida Lisateave</string>
<string name="revanced_hide_player_flyout_more_info_summary_on">Lisateabe menüü on peidetud</string>
<string name="revanced_hide_player_flyout_more_info_summary_off">Lisateabe menüü on nähtav</string>
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_lock_screen_title">Peida Ekraani lukustus</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_on">Ekraani lukustuse menüü on peidetud</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_off">Ekraani lukustuse menüü on nähtav</string>
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_listen_with_youtube_music_title">Peida Kuula YouTube Musicuga</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_on">Kuula YouTube Musicuga menüü on peidetud</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_off">Kuula YouTube Musicuga menüü on nähtav</string>
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_audio_track_title">Peida Helitraek</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">Helitraekide menüü on peidetud</string>
@@ -1639,10 +1641,6 @@ AV1-ga videotaasesitus võib hakitud olla või kaadreid vahele jätta."</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Kuva statistikas \"Nerdide jaoks\"</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Klienditüüp on statistikas \"Nerdide jaoks\" nähtav</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Klient on statistikas \"Nerdide jaoks\" peidetud</string>
<string name="revanced_spoof_video_streams_language_title">Helivoo keel</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">Konkreetse helikeele valimiseks lülita välja \"Sunni algne helikeel\"</string>
<string name="revanced_spoof_video_streams_language_android_studio">Voogedastuse keelevalik ei ole Android Studioga saadaval</string>
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -134,9 +134,8 @@ Second \"item\" text"</string>
<!-- 'Ambient mode' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Help & feedback' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Playback speed' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
@@ -257,7 +256,6 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<!-- "Force original audio" should use the same text as revanced_force_original_audio_title -->
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -181,9 +181,8 @@ Second \"item\" text"</string>
<!-- 'Ambient mode' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Help & feedback' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Playback speed' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
@@ -307,7 +306,6 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<!-- "Force original audio" should use the same text as revanced_force_original_audio_title -->
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -328,6 +328,9 @@ Jos Doodle näkyy tällä hetkellä alueellasi ja tämä piilotusasetus on käyt
<string name="revanced_hide_how_this_was_made_section_title">Piilota \"Miten sisältö on luotu\"</string>
<string name="revanced_hide_how_this_was_made_section_summary_on">Miten sisältö on luotu -osio piilotetaan</string>
<string name="revanced_hide_how_this_was_made_section_summary_off">Miten sisältö on luotu -osio näytetään</string>
<string name="revanced_hide_hype_points_title">Piilota Hype-pisteet</string>
<string name="revanced_hide_hype_points_summary_on">Hype-pisteet piilotetaan</string>
<string name="revanced_hide_hype_points_summary_off">Hype-pisteet näytetään</string>
<string name="revanced_hide_podcast_section_title">Piilota \"Tutustu podcastiin\"</string>
<string name="revanced_hide_podcast_section_summary_on">Tutustu podcastiin -osio piilotetaan</string>
<string name="revanced_hide_podcast_section_summary_off">Tutustu podcastiin -osio näytetään</string>
@@ -771,15 +774,14 @@ Jos tämän asetuksen muuttaminen ei tule voimaan, kokeile vaihtaa Incognito-til
<string name="revanced_hide_player_flyout_speed_title">Piilota Toistonopeus</string>
<string name="revanced_hide_player_flyout_speed_summary_on">Toistonopeusvalikko piilotetaan</string>
<string name="revanced_hide_player_flyout_speed_summary_off">Toistonopeusvalikko näytetään</string>
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<string name="revanced_hide_player_flyout_more_info_title">Piilota Lisätietoja</string>
<string name="revanced_hide_player_flyout_more_info_summary_on">Lisätietoja-valinta piilotetaan</string>
<string name="revanced_hide_player_flyout_more_info_summary_off">Lisätietoja-valinta näytetään </string>
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_lock_screen_title">Piilota Näytön lukitus</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_on">Näytön lukitus -valinta piilotetaan</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_off">Näytön lukitus -valinta näytetään</string>
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_listen_with_youtube_music_title">Piilota Kuuntele YouTube Musicilla</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_on">Kuuntele YouTube Musicilla -valikko on piilotettu</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_off">Kuuntele YouTube Musicilla -valikko on näkyvissä</string>
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_audio_track_title">Piilota Ääniraita</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">Ääniraitavalikko piilotetaan</string>
@@ -1639,10 +1641,6 @@ AV1-videon toisto saattaa pätkiä."</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Näytä teknisissä tiedoissa</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Asiakastyyppi näytetään teknisissä tiedoissa</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Asiakastyyppi piilotetaan teknisissä tiedoissa</string>
<string name="revanced_spoof_video_streams_language_title">Äänivirran kieli</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">Valitaksesi tietyn äänen kielen, poista \"Pakota alkuperäinen äänen kieli\" käytöstä</string>
<string name="revanced_spoof_video_streams_language_android_studio">Striimin kielivalinta ei ole käytettävissä Android Studion kanssa</string>
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -328,6 +328,9 @@ Kung ang isang Doodle ay kasalukuyang ipinapakita sa iyong rehiyon at ang settin
<string name="revanced_hide_how_this_was_made_section_title">Itago ang \'Paano ginawa ang content na ito\'</string>
<string name="revanced_hide_how_this_was_made_section_summary_on">Nakatago ang seksyon ng Paano ginawa ang content na ito</string>
<string name="revanced_hide_how_this_was_made_section_summary_off">Ipinapakita ang seksyon ng Paano ginawa ang content na ito</string>
<string name="revanced_hide_hype_points_title">Itago ang mga Puntos ng Hype</string>
<string name="revanced_hide_hype_points_summary_on">Nakatago ang mga Puntos ng Hype</string>
<string name="revanced_hide_hype_points_summary_off">Ipinapakita ang mga Puntos ng Hype</string>
<string name="revanced_hide_podcast_section_title">Itago ang \'I-explore ang podcast\'</string>
<string name="revanced_hide_podcast_section_summary_on">Nakatago ang seksyon ng I-explore ang podcast</string>
<string name="revanced_hide_podcast_section_summary_off">Ipinapakita ang seksyon ng I-explore ang podcast</string>
@@ -769,15 +772,14 @@ Tandaan: Ang pagpapagana nito ay nagtatago rin ng mga ad ng video"</string>
<string name="revanced_hide_player_flyout_speed_title">Itago ang bilis ng pag-playback</string>
<string name="revanced_hide_player_flyout_speed_summary_on">Nakatago ang menu ng bilis ng pag-playback</string>
<string name="revanced_hide_player_flyout_speed_summary_off">Ang menu ng bilis ng pag-playback ay ipinapakita</string>
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<string name="revanced_hide_player_flyout_more_info_title">Itago ang Higit pang impormasyon</string>
<string name="revanced_hide_player_flyout_more_info_summary_on">Nakatago ang menu ng higit pang impormasyon</string>
<string name="revanced_hide_player_flyout_more_info_summary_off">Ang menu ng higit pang impormasyon ay ipinapakita</string>
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_lock_screen_title">Itago ang Lock screen</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_on">Nakatago ang menu ng lock screen</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_off">Ipinapakita ang menu ng lock screen</string>
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_listen_with_youtube_music_title">Itago ang Makinig gamit ang YouTube Music</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_on">Nakatago ang menu ng Makinig gamit ang YouTube Music</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_off">Ipinapakita ang menu ng Makinig gamit ang YouTube Music</string>
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_audio_track_title">Itago ang Audio track</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">Nakatago ang menu ng audio track</string>
@@ -1637,10 +1639,6 @@ Maaaring mag-stutter o mag-drop ng frames ang pag-playback ng video na may AV1."
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Ipakita sa Mga Istatistika para sa mga nerds</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Ipinapakita ang uri ng kliyente sa Mga Istatistika para sa mga nerds</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Nakatago ang kliyente sa Mga Istatistika para sa mga nerds</string>
<string name="revanced_spoof_video_streams_language_title">Wika ng audio stream</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">Upang pumili ng isang partikular na wika ng audio, i-off ang \'Puwersahin ang orihinal na wika ng audio\'</string>
<string name="revanced_spoof_video_streams_language_android_studio">Hindi available ang pagpili ng wika ng stream sa Android Studio</string>
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -328,6 +328,9 @@ Si un Doodle est actuellement affiché dans votre région et que cette option de
<string name="revanced_hide_how_this_was_made_section_title">Masquer \"Comment ce contenu a été créé\"</string>
<string name="revanced_hide_how_this_was_made_section_summary_on">La section \"Comment ce contenu a été créé\" est masquée</string>
<string name="revanced_hide_how_this_was_made_section_summary_off">La section \"Comment ce contenu a été créé\" est affichée</string>
<string name="revanced_hide_hype_points_title">Masquer les points Boost</string>
<string name="revanced_hide_hype_points_summary_on">Les points Boost sont masqués</string>
<string name="revanced_hide_hype_points_summary_off">Les points Boost sont affichés</string>
<string name="revanced_hide_podcast_section_title">Masquer \"Découvrir le podcast\"</string>
<string name="revanced_hide_podcast_section_summary_on">La section \"Découvrir le podcast\" est masquée</string>
<string name="revanced_hide_podcast_section_summary_off">La section \"Découvrir le podcast\" est affichée</string>
@@ -771,15 +774,14 @@ Si la modification de ce paramètre ne prend pas effet, essayez de passer en mod
<string name="revanced_hide_player_flyout_speed_title">Masquer \"Vitesse de lecture\"</string>
<string name="revanced_hide_player_flyout_speed_summary_on">Le menu Vitesse de lecture est masqué</string>
<string name="revanced_hide_player_flyout_speed_summary_off">Le menu Vitesse de lecture est affiché</string>
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<string name="revanced_hide_player_flyout_more_info_title">Masquer \"Plus d\'infos\"</string>
<string name="revanced_hide_player_flyout_more_info_summary_on">Le menu Plus d\'infos est masqué</string>
<string name="revanced_hide_player_flyout_more_info_summary_off">Le menu Plus d\'infos est affiché</string>
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_lock_screen_title">Masquer \"Verrouiller l\'écran\"</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_on">Le menu Verrouiller l\'écran est masqué</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_off">Le menu Verrouiller l\'écran est affiché</string>
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_listen_with_youtube_music_title">Masquer \"Écouter avec YouTube Music\"</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_on">Le menu Écouter avec YouTube Music est masqué</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_off">Le menu Écouter avec YouTube Music est affiché</string>
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_audio_track_title">Masquer \"Piste audio\"</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">Le menu Piste audio est masqué</string>
@@ -1640,10 +1642,6 @@ La lecture vidéo avec AV1 peut être saccadée et des images peuvent être perd
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Afficher dans les Statistiques avancées</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Le type de client est affiché dans les Statistiques avancées</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Le client est caché dans les Statistiques avancées</string>
<string name="revanced_spoof_video_streams_language_title">Langue du flux audio</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">Pour sélectionner une langue audio spécifique, désactivez \"Forcer la langue audio d\'origine\"</string>
<string name="revanced_spoof_video_streams_language_android_studio">La sélection de la langue du flux n\'est pas disponible avec Android Studio</string>
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -328,6 +328,9 @@ Má tá Doodle á thaispeáint faoi láthair i do réigiún agus má tá an tsu
<string name="revanced_hide_how_this_was_made_section_title">Folaigh \'Conas a rinneadh an t-ábhar seo\'</string>
<string name="revanced_hide_how_this_was_made_section_summary_on">Tá an chuid Conas a rinneadh an t-ábhar seo i bhfolach</string>
<string name="revanced_hide_how_this_was_made_section_summary_off">Taispeántar an chuid Conas a rinneadh an t-ábhar seo</string>
<string name="revanced_hide_hype_points_title">Folaigh pointí Hype</string>
<string name="revanced_hide_hype_points_summary_on">Tá pointí Hype i bhfolach</string>
<string name="revanced_hide_hype_points_summary_off">Taispeántar pointí Hype</string>
<string name="revanced_hide_podcast_section_title">Folaigh \'Déan iniúchadh ar an bpodchraoladh\'</string>
<string name="revanced_hide_podcast_section_summary_on">Tá an chuid Déan iniúchadh ar an bpodchraoladh i bhfolach</string>
<string name="revanced_hide_podcast_section_summary_off">Taispeántar an chuid Déan iniúchadh ar an bpodchraoladh</string>
@@ -769,15 +772,14 @@ Mura dtagann aon athrú ar an socrú seo, bain triail as mód Incognito a chur a
<string name="revanced_hide_player_flyout_speed_title">Folaigh luas athsheinm</string>
<string name="revanced_hide_player_flyout_speed_summary_on">Tá roghchlár luas athsheinm i bhfolach</string>
<string name="revanced_hide_player_flyout_speed_summary_off">Taispeántar roghchlár luas athsheinm</string>
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<string name="revanced_hide_player_flyout_more_info_title">Folaigh Tuilleadh eolais</string>
<string name="revanced_hide_player_flyout_more_info_summary_on">Tá tuilleadh eolais i bhfolach</string>
<string name="revanced_hide_player_flyout_more_info_summary_off">Taispeántar roghchlár tuilleadh eolais</string>
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_lock_screen_title">Folaigh scáileán Glas</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_on">Tá roghchlár scáileán glas i bhfolach</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_off">Taispeántar roghchlár an scáileáin ghlasála</string>
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_listen_with_youtube_music_title">Folaigh Éist le YouTube Music</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_on">Tá roghchlár Éist le YouTube Music i bhfolach</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_off">Taispeántar an roghchlár Éist le YouTube Music</string>
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_audio_track_title">Folaigh Rian Fuaime</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">Tá roghchlár rian fuaime i bhfolach</string>
@@ -1637,10 +1639,6 @@ Dfhéadfadh sé go mbeadh stad nó go gcaillfí frámaí ag athsheinm físe l
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Taispeáin i Staitisticí do nerds</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Taispeántar cineál an chliaint i Staitisticí do nerds</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Tá an cliant curtha i bhfolach i Staitisticí do nerds</string>
<string name="revanced_spoof_video_streams_language_title">Teanga an tsrutha fuaime</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">Chun teanga fuaime ar leith a roghnú, múch \'Fórsaigh teanga fuaime bhunaidh\'</string>
<string name="revanced_spoof_video_streams_language_android_studio">Níl roghnú theanga an tsrutha ar fáil le Android Studio</string>
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -134,9 +134,8 @@ Second \"item\" text"</string>
<!-- 'Ambient mode' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Help & feedback' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Playback speed' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
@@ -257,7 +256,6 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<!-- "Force original audio" should use the same text as revanced_force_original_audio_title -->
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -134,9 +134,8 @@ Second \"item\" text"</string>
<!-- 'Ambient mode' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Help & feedback' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Playback speed' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
@@ -257,7 +256,6 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<!-- "Force original audio" should use the same text as revanced_force_original_audio_title -->
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -136,9 +136,8 @@ Second \"item\" text"</string>
<!-- 'Ambient mode' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Help & feedback' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Playback speed' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
@@ -259,7 +258,6 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<!-- "Force original audio" should use the same text as revanced_force_original_audio_title -->
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -135,9 +135,8 @@ Second \"item\" text"</string>
<!-- 'Ambient mode' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Help & feedback' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Playback speed' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
@@ -258,7 +257,6 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<!-- "Force original audio" should use the same text as revanced_force_original_audio_title -->
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -328,6 +328,9 @@ Ha a Doodle jelenleg a régiódában látható, és ez a rejtés beállítás be
<string name="revanced_hide_how_this_was_made_section_title">A „Hogyan készült ez a tartalom” elrejtése</string>
<string name="revanced_hide_how_this_was_made_section_summary_on">A Hogyan készült ez a tartalom szakasz rejtett</string>
<string name="revanced_hide_how_this_was_made_section_summary_off">A Hogyan készült ez a tartalom szakasz látható</string>
<string name="revanced_hide_hype_points_title">Hype pontok elrejtése</string>
<string name="revanced_hide_hype_points_summary_on">A Hype pontok el vannak rejtve</string>
<string name="revanced_hide_hype_points_summary_off">A Hype pontok láthatóak</string>
<string name="revanced_hide_podcast_section_title">A „Podcast felfedezése” elrejtése</string>
<string name="revanced_hide_podcast_section_summary_on">A Podcast felfedezése szakasz rejtett</string>
<string name="revanced_hide_podcast_section_summary_off">A Podcast felfedezése szakasz látható</string>
@@ -771,15 +774,14 @@ Ha a beállítás módosítása nem lép életbe, próbáljon meg Inkognitó mó
<string name="revanced_hide_player_flyout_speed_title">Lejátszási sebesség elrejtése</string>
<string name="revanced_hide_player_flyout_speed_summary_on">A lejátszási sebesség menü el van rejtve</string>
<string name="revanced_hide_player_flyout_speed_summary_off">A lejátszási sebesség menü látható</string>
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<string name="revanced_hide_player_flyout_more_info_title">További információk elrejtése</string>
<string name="revanced_hide_player_flyout_more_info_summary_on"> A további információ menü el van rejtve</string>
<string name="revanced_hide_player_flyout_more_info_summary_off">A további információ menü megjelenik</string>
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_lock_screen_title">Lezárási képernyő elrejtése</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_on">A lezárási képernyő menü el van rejtve</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_off">A lezárási képernyő menü megjelenik</string>
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_listen_with_youtube_music_title">\"Meghallgatás YouTube Music alkalmazással\" elrejtése</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_on">A(z) \"Meghallgatás YouTube Music alkalmazással\" menü rejtett</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_off">A(z) \"Meghallgatás YouTube Music alkalmazással\" menü megjelenítve</string>
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_audio_track_title">Hangsáv elrejtése</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">A hangsáv menü el van rejtve</string>
@@ -1636,10 +1638,6 @@ Az AV1-es videólejátszás akadozhat vagy képkockákat ejthet."</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Megjelenítés a Statisztikákban</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">A kliens típusa a Statisztikákban látható</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">A kliens el van rejtve a Statisztikákban</string>
<string name="revanced_spoof_video_streams_language_title">Hangfolyam nyelve</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">Egy adott hangsáv nyelv kiválasztásához kapcsold ki az \"Eredeti hangsáv nyelv kikényszerítése\" opciót</string>
<string name="revanced_spoof_video_streams_language_android_studio">Az Android Studio-val nem érhető el a stream nyelvének kiválasztása</string>
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -328,6 +328,9 @@ MicroG-ի համար մարտկոցի օպտիմալացումը անջատել
<string name="revanced_hide_how_this_was_made_section_title">Թաքցնել \"Ինչպես է պատրաստվել այս բովանդակությունը\"</string>
<string name="revanced_hide_how_this_was_made_section_summary_on">Ինչպես է պատրաստվել այս բովանդակությունը բաժինը թաքցված է</string>
<string name="revanced_hide_how_this_was_made_section_summary_off">Ինչպես է պատրաստվել այս բովանդակությունը բաժինը ցուցադրվում է</string>
<string name="revanced_hide_hype_points_title">Թաքցնել Hype միավորները</string>
<string name="revanced_hide_hype_points_summary_on">Hype միավորները թաքնված են</string>
<string name="revanced_hide_hype_points_summary_off">Hype միավորները ցուցադրվում են</string>
<string name="revanced_hide_podcast_section_title">Թաքցնել \"Բացահայտեք փոդքասթը\"</string>
<string name="revanced_hide_podcast_section_summary_on">Բացահայտեք փոդքասթը բաժինը թաքցված է</string>
<string name="revanced_hide_podcast_section_summary_off">Բացահայտեք փոդքասթը բաժինը ցուցադրվում է</string>
@@ -771,15 +774,14 @@ MicroG-ի համար մարտկոցի օպտիմալացումը անջատել
<string name="revanced_hide_player_flyout_speed_title">Վերարտադրման արագությունը թաքցնել</string>
<string name="revanced_hide_player_flyout_speed_summary_on">Վերարտադրման արագության մենյուը թաքցված է</string>
<string name="revanced_hide_player_flyout_speed_summary_off">Վերարտադրման արագության մենյուը երևում է</string>
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<string name="revanced_hide_player_flyout_more_info_title">Լրացուցիչ տեղեկությունը թաքցնել</string>
<string name="revanced_hide_player_flyout_more_info_summary_on">Լրացուցիչ տեղեկությունների մենյուը թաքցված է</string>
<string name="revanced_hide_player_flyout_more_info_summary_off">Լրացուցիչ տեղեկությունների մենյուը երևում է</string>
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_lock_screen_title">Էկրանի արգելափակումը թաքցնել</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_on">Էկրանի արգելափակման մենյուը թաքցված է</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_off">Էկրանի արգելափակման մենյուը երևում է</string>
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_listen_with_youtube_music_title">Թաքցնել Լսել YouTube Music-ով</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_on">Լսել YouTube Music-ով մենյուն թաքցված է</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_off">Լսել YouTube Music-ով մենյուն ցուցադրված է</string>
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_audio_track_title">Աուդիո ձայնագրությունը թաքցնել</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">Աուդիո ձայնագրման մենյուը թաքցված է</string>
@@ -1640,10 +1642,6 @@ AV1-ով տեսանյութի նվագարկումը կարող է ընդհատ
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Ցուցադրել վիճակագրության ակնոցներում</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Հաճախորդի տեսակը ցուցադրվում է վիճակագրության ակնոցներում</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Հաճախորդը թաքնված է վիճակագրության ակնոցներում</string>
<string name="revanced_spoof_video_streams_language_title">Ձայնային հոսքի լեզուն</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">Որոշակի ձայնային լեզու ընտրելու համար անջատեք \'Պարտադրել բնօրինակ ձայնային լեզուն\'</string>
<string name="revanced_spoof_video_streams_language_android_studio">Հոսքի լեզվի ընտրությունը հասանելի չէ Android Studio-ի հետ</string>
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -328,6 +328,9 @@ Jika Doodle saat ini ditampilkan di wilayah Anda dan pengaturan penyembunyi ini
<string name="revanced_hide_how_this_was_made_section_title">Sembunyikan \'Cara konten ini dibuat\'</string>
<string name="revanced_hide_how_this_was_made_section_summary_on">Bagian Cara konten ini dibuat disembunyikan</string>
<string name="revanced_hide_how_this_was_made_section_summary_off">Bagian Cara konten ini dibuat ditampilkan</string>
<string name="revanced_hide_hype_points_title">Sembunyikan Poin Hype</string>
<string name="revanced_hide_hype_points_summary_on">Poin Hype disembunyikan</string>
<string name="revanced_hide_hype_points_summary_off">Poin Hype ditampilkan</string>
<string name="revanced_hide_podcast_section_title">Sembunyikan \'Jelajahi podcast\'</string>
<string name="revanced_hide_podcast_section_summary_on">Bagian Jelajahi podcast disembunyikan</string>
<string name="revanced_hide_podcast_section_summary_off">Bagian Jelajahi podcast ditampilkan</string>
@@ -771,15 +774,14 @@ Jika mengubah setelan ini tidak berpengaruh, coba beralih ke mode Penyamaran."</
<string name="revanced_hide_player_flyout_speed_title">Sembunyikan Kecepatan pemutaran</string>
<string name="revanced_hide_player_flyout_speed_summary_on">Menu kecepatan pemutaran disembunyikan</string>
<string name="revanced_hide_player_flyout_speed_summary_off">Menu kecepatan pemutaran ditampilkan</string>
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<string name="revanced_hide_player_flyout_more_info_title">Sembunyikan Info selengkapnya</string>
<string name="revanced_hide_player_flyout_more_info_summary_on">Menu info selengkapnya disembunyikan</string>
<string name="revanced_hide_player_flyout_more_info_summary_off">Menu info selengkapnya ditampilkan</string>
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_lock_screen_title">Sembunyikan Kunci layar</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_on">Menu kunci layar disembunyikan</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_off">Menu kunci layar ditampilkan</string>
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_listen_with_youtube_music_title">Sembunyikan Dengarkan dengan YouTube Music</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_on">Menu Dengarkan dengan YouTube Music disembunyikan</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_off">Menu Dengarkan dengan YouTube Music ditampilkan</string>
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_audio_track_title">Sembunyikan trek Audio</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">Menu trek audio disembunyikan</string>
@@ -1638,10 +1640,6 @@ Pemutaran video dengan AV1 mungkin tersendat atau kehilangan bingkai."</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Tampilkan di Statistik untuk nerds</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Jenis klien ditampilkan di Statistik untuk nerds</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Klien disembunyikan di Statistik untuk nerds</string>
<string name="revanced_spoof_video_streams_language_title">Bahasa aliran audio</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">Untuk memilih bahasa audio tertentu, matikan \'Paksa bahasa audio asli\'</string>
<string name="revanced_spoof_video_streams_language_android_studio">Pilihan bahasa streaming tidak tersedia dengan Android Studio</string>
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -134,9 +134,8 @@ Second \"item\" text"</string>
<!-- 'Ambient mode' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Help & feedback' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Playback speed' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
@@ -257,7 +256,6 @@ Second \"item\" text"</string>
</patch>
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
<!-- "Force original audio" should use the same text as revanced_force_original_audio_title -->
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
</patch>
</app>
<app id="music">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 ReVanced. Not licensed under GPL. See https://github.com/ReVanced/revanced-branding -->
<!-- Copyright 2024 ReVanced. See https://github.com/ReVanced/revanced-branding -->
<!--
All strings must have a unique path, even if the same string is declared in two different apps.
@@ -328,6 +328,9 @@ Se al momento un Doodle è visibile nella tua regione e questa impostazione nasc
<string name="revanced_hide_how_this_was_made_section_title">Nascondi \"Come è stato realizzato questo contenuto\"</string>
<string name="revanced_hide_how_this_was_made_section_summary_on">La sezione Come è stato realizzato questo contenuto è nascosta</string>
<string name="revanced_hide_how_this_was_made_section_summary_off">La sezione Come è stato realizzato questo contenuto è visibile</string>
<string name="revanced_hide_hype_points_title">Nascondi i punti Hype</string>
<string name="revanced_hide_hype_points_summary_on">I punti Hype sono nascosti</string>
<string name="revanced_hide_hype_points_summary_off">I punti Hype sono mostrati</string>
<string name="revanced_hide_podcast_section_title">Nascondi \"Esplora il podcast\"</string>
<string name="revanced_hide_podcast_section_summary_on">La sezione Esplora il podcast è nascosta</string>
<string name="revanced_hide_podcast_section_summary_off">La sezione Esplora il podcast è visibile</string>
@@ -771,15 +774,14 @@ Se la modifica di questa impostazione non ha effetto, prova a passare alla modal
<string name="revanced_hide_player_flyout_speed_title">Nascondi Velocità di riproduzione</string>
<string name="revanced_hide_player_flyout_speed_summary_on">Il menu Velocità di riproduzione è nascosto</string>
<string name="revanced_hide_player_flyout_speed_summary_off">Il menu Velocità di riproduzione è visibile</string>
<!-- 'More info' should be translated using the same localized wording YouTube displays for the menu item.
This menu only appears for some videos. Translate the name normally if the menu cannot be found. -->
<string name="revanced_hide_player_flyout_more_info_title">Nascondi Maggiori Informazioni</string>
<string name="revanced_hide_player_flyout_more_info_summary_on">Il menu Maggiori Informazioni è nascosto</string>
<string name="revanced_hide_player_flyout_more_info_summary_off">Il menu Maggiori Informazioni è visibile</string>
<!-- 'Lock screen' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_lock_screen_title">Nascondi Blocca schermo</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_on">Il menu Blocca Schermo è nascosto</string>
<string name="revanced_hide_player_flyout_lock_screen_summary_off">Il menu Blocca Schermo è visibile</string>
<!-- 'Listen with YouTube Music' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_listen_with_youtube_music_title">Nascondi Ascolta con YouTube Music</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_on">Il menu Ascolta con YouTube Music è nascosto</string>
<string name="revanced_hide_player_flyout_listen_with_youtube_music_summary_off">Il menu Ascolta con YouTube Music è visualizzato</string>
<!-- 'Audio track' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_audio_track_title">Nascondi Traccia audio</string>
<string name="revanced_hide_player_flyout_audio_track_summary_on">Il menu Traccia audio è nascosto</string>
@@ -1638,10 +1640,6 @@ La riproduzione video con AV1 potrebbe rallentare o perdere fotogrammi."</string
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Mostra nelle statistiche per nerd</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Il tipo di client è mostrato nelle statistiche per nerd</string>
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Il client è nascosto nelle statistiche per nerd</string>
<string name="revanced_spoof_video_streams_language_title">Lingua del flusso audio</string>
<!-- 'Force original audio language' should use the same text as revanced_force_original_audio_title -->
<string name="revanced_spoof_video_streams_language_not_available">Per selezionare una lingua audio specifica, disattiva \'Forza lingua audio originale\'</string>
<string name="revanced_spoof_video_streams_language_android_studio">La selezione della lingua dello stream non è disponibile con Android Studio</string>
</patch>
</app>
<app id="music">

Some files were not shown because too many files have changed in this diff Show More