mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-15 21:52:27 +01:00
Compare commits
49 Commits
v5.35.1-de
...
v5.38.0-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fb94a7a41 | ||
|
|
3776dda710 | ||
|
|
f88b3a5162 | ||
|
|
0eeaf7ad67 | ||
|
|
2726231404 | ||
|
|
9f0558e494 | ||
|
|
01f7bc9f8d | ||
|
|
5e20bd80f1 | ||
|
|
f304c178e2 | ||
|
|
1d65887e01 | ||
|
|
6b6eea8414 | ||
|
|
1db131e90e | ||
|
|
abe3943f98 | ||
|
|
cb6d802de3 | ||
|
|
f11d1ef990 | ||
|
|
3d25da18bc | ||
|
|
fa04c8eecf | ||
|
|
105f6e0e97 | ||
|
|
7d59efe05d | ||
|
|
81ff5576b0 | ||
|
|
9a5c102c0d | ||
|
|
e6c79f1383 | ||
|
|
2a582eced8 | ||
|
|
2db0948bea | ||
|
|
a3ba92e742 | ||
|
|
2a85a3b290 | ||
|
|
eee72208dd | ||
|
|
dcd42454bd | ||
|
|
782353c18a | ||
|
|
b53b870e8f | ||
|
|
09b941abf0 | ||
|
|
678ef4052e | ||
|
|
0abfab79d7 | ||
|
|
61cadf72cd | ||
|
|
e12359b94f | ||
|
|
c001daba4a | ||
|
|
e136f62d6e | ||
|
|
8ec405a359 | ||
|
|
2f4b3a887b | ||
|
|
d1fabb242b | ||
|
|
a53b00dd51 | ||
|
|
850c13e98e | ||
|
|
4310789a26 | ||
|
|
c4a720fbd3 | ||
|
|
3bdb8dbce0 | ||
|
|
4894f33c96 | ||
|
|
7f6093ee66 | ||
|
|
9d4aa5cd16 | ||
|
|
5ace6f587c |
182
CHANGELOG.md
182
CHANGELOG.md
@@ -1,3 +1,185 @@
|
||||
# [5.38.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.38.0-dev.3...v5.38.0-dev.4) (2025-09-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video streams:** Show settings summary if `Force original audio` is enabled ([3776dda](https://github.com/ReVanced/revanced-patches/commit/3776dda710a7780717b7e6f2cdc1333ab67b92fc))
|
||||
|
||||
# [5.38.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.38.0-dev.2...v5.38.0-dev.3) (2025-09-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Spoof video streams:** Add iPadOS client ([2726231](https://github.com/ReVanced/revanced-patches/commit/2726231404384d87f101d825e10a17c944e8f1bd))
|
||||
|
||||
# [5.38.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.38.0-dev.1...v5.38.0-dev.2) (2025-09-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube Music:** Add `Settings` patch ([#5838](https://github.com/ReVanced/revanced-patches/issues/5838)) ([5e20bd8](https://github.com/ReVanced/revanced-patches/commit/5e20bd80f138d7ca94f18857194c46e489c435dc))
|
||||
|
||||
# [5.38.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.37.1-dev.3...v5.38.0-dev.1) (2025-09-15)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Instagram:** Add `Hide explore feed` patch ([#5856](https://github.com/ReVanced/revanced-patches/issues/5856)) ([1d65887](https://github.com/ReVanced/revanced-patches/commit/1d65887e015a067196f5a84db486fff355c96596))
|
||||
|
||||
## [5.37.1-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.37.1-dev.2...v5.37.1-dev.3) (2025-09-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Spoof video streams:** Remove Android TV and iOS TV clients, add experimental VisionOS, add temporary fix for `Force original audio` to work with any spoof client ([#5861](https://github.com/ReVanced/revanced-patches/issues/5861)) ([abe3943](https://github.com/ReVanced/revanced-patches/commit/abe3943f98fd86dcd74c7e07cf65d3c7fc24fef9))
|
||||
|
||||
## [5.37.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.37.1-dev.1...v5.37.1-dev.2) (2025-09-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Instagram - Hide navigation buttons:** Support v397.1.0.52.81 ([#5855](https://github.com/ReVanced/revanced-patches/issues/5855)) ([f11d1ef](https://github.com/ReVanced/revanced-patches/commit/f11d1ef9907082512f139d4ab0e2e9f707de7e48))
|
||||
|
||||
## [5.37.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.37.0...v5.37.1-dev.1) (2025-09-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube Music - Spoof video streams:** Fix playback issues when using a cellular network ([fa04c8e](https://github.com/ReVanced/revanced-patches/commit/fa04c8eecfbdd0b6ed082b464ca9032536d71762))
|
||||
|
||||
# [5.37.0](https://github.com/ReVanced/revanced-patches/compare/v5.36.0...v5.37.0) (2025-09-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Instagram - Hide navigation buttons:** Add constrain to known working version ([e6c79f1](https://github.com/ReVanced/revanced-patches/commit/e6c79f13834c83fef04e4dee5e628cb0b9a27765))
|
||||
* Resolve patching with dev branch ([09b941a](https://github.com/ReVanced/revanced-patches/commit/09b941abf0e8029999565082b02a88b5de507ec4))
|
||||
* **Spotify:** Remove broken `Spoof client` patch ([#5833](https://github.com/ReVanced/revanced-patches/issues/5833)) ([dcd4245](https://github.com/ReVanced/revanced-patches/commit/dcd42454bd5f87dddd720534f6120c4ef90063a3))
|
||||
* **Viber - Hide ads:** Add constrain to known working version ([2db0948](https://github.com/ReVanced/revanced-patches/commit/2db0948beaf2b68391a1fe7f21e92d31c7df61e7))
|
||||
* **YouTube Music - Spoof streaming data:** Fix audio playback stuttering ([#5839](https://github.com/ReVanced/revanced-patches/issues/5839)) ([2a85a3b](https://github.com/ReVanced/revanced-patches/commit/2a85a3b29092729ae16d1fd93803634ce5f08e95))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Viber:** Add `Hide ads` patch ([#5826](https://github.com/ReVanced/revanced-patches/issues/5826)) ([0abfab7](https://github.com/ReVanced/revanced-patches/commit/0abfab79d7cda15bf17c53679fbfffb021662649))
|
||||
|
||||
# [5.37.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.37.0-dev.5...v5.37.0-dev.6) (2025-09-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Instagram - Hide navigation buttons:** Add constrain to known working version ([e6c79f1](https://github.com/ReVanced/revanced-patches/commit/e6c79f13834c83fef04e4dee5e628cb0b9a27765))
|
||||
|
||||
# [5.37.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.37.0-dev.4...v5.37.0-dev.5) (2025-09-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Viber - Hide ads:** Add constrain to known working version ([2db0948](https://github.com/ReVanced/revanced-patches/commit/2db0948beaf2b68391a1fe7f21e92d31c7df61e7))
|
||||
|
||||
# [5.37.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.37.0-dev.3...v5.37.0-dev.4) (2025-09-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube Music - Spoof streaming data:** Fix audio playback stuttering ([#5839](https://github.com/ReVanced/revanced-patches/issues/5839)) ([2a85a3b](https://github.com/ReVanced/revanced-patches/commit/2a85a3b29092729ae16d1fd93803634ce5f08e95))
|
||||
|
||||
# [5.37.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.37.0-dev.2...v5.37.0-dev.3) (2025-09-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Spotify:** Remove broken `Spoof client` patch ([#5833](https://github.com/ReVanced/revanced-patches/issues/5833)) ([dcd4245](https://github.com/ReVanced/revanced-patches/commit/dcd42454bd5f87dddd720534f6120c4ef90063a3))
|
||||
|
||||
# [5.37.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.37.0-dev.1...v5.37.0-dev.2) (2025-09-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Resolve patching with dev branch ([09b941a](https://github.com/ReVanced/revanced-patches/commit/09b941abf0e8029999565082b02a88b5de507ec4))
|
||||
|
||||
# [5.37.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.36.0...v5.37.0-dev.1) (2025-09-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Viber:** Add `Hide ads` patch ([#5826](https://github.com/ReVanced/revanced-patches/issues/5826)) ([0abfab7](https://github.com/ReVanced/revanced-patches/commit/0abfab79d7cda15bf17c53679fbfffb021662649))
|
||||
|
||||
# [5.36.0](https://github.com/ReVanced/revanced-patches/compare/v5.35.0...v5.36.0) (2025-09-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Duolingo - Disable ads:** Support latest app target ([#5782](https://github.com/ReVanced/revanced-patches/issues/5782)) ([88b47ef](https://github.com/ReVanced/revanced-patches/commit/88b47ef414cd073ec3800258b32aceb6f383a411))
|
||||
* **YouTube - Hide layout components:** Hide new type of Playable shelf ([8cd8e59](https://github.com/ReVanced/revanced-patches/commit/8cd8e59bbc3a878269276b8ae5f627b044d157f0))
|
||||
* **YouTube Music:** Resolve playback issues, change recommended app target to `7.29.52` ([#5813](https://github.com/ReVanced/revanced-patches/issues/5813)) ([a53b00d](https://github.com/ReVanced/revanced-patches/commit/a53b00dd514dbe2b3406f3c1013a4f58a7f481c5))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - SponsorBlock:** Add 'Hook' segment category ([#5783](https://github.com/ReVanced/revanced-patches/issues/5783)) ([9d4aa5c](https://github.com/ReVanced/revanced-patches/commit/9d4aa5cd16a6f9e95cf7c626351b46b86ca80efe))
|
||||
|
||||
# [5.36.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.0...v5.36.0-dev.1) (2025-09-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Duolingo - Disable ads:** Support latest app target ([#5782](https://github.com/ReVanced/revanced-patches/issues/5782)) ([88b47ef](https://github.com/ReVanced/revanced-patches/commit/88b47ef414cd073ec3800258b32aceb6f383a411))
|
||||
* **YouTube - Hide layout components:** Hide new type of Playable shelf ([8cd8e59](https://github.com/ReVanced/revanced-patches/commit/8cd8e59bbc3a878269276b8ae5f627b044d157f0))
|
||||
* **YouTube Music:** Resolve playback issues, change recommended app target to `7.29.52` ([#5813](https://github.com/ReVanced/revanced-patches/issues/5813)) ([a53b00d](https://github.com/ReVanced/revanced-patches/commit/a53b00dd514dbe2b3406f3c1013a4f58a7f481c5))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - SponsorBlock:** Add 'Hook' segment category ([#5783](https://github.com/ReVanced/revanced-patches/issues/5783)) ([9d4aa5c](https://github.com/ReVanced/revanced-patches/commit/9d4aa5cd16a6f9e95cf7c626351b46b86ca80efe))
|
||||
|
||||
# [5.36.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.0...v5.36.0-dev.1) (2025-09-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Duolingo - Disable ads:** Support latest app target ([#5782](https://github.com/ReVanced/revanced-patches/issues/5782)) ([88b47ef](https://github.com/ReVanced/revanced-patches/commit/88b47ef414cd073ec3800258b32aceb6f383a411))
|
||||
* **YouTube - Hide layout components:** Hide new type of Playable shelf ([8cd8e59](https://github.com/ReVanced/revanced-patches/commit/8cd8e59bbc3a878269276b8ae5f627b044d157f0))
|
||||
* **YouTube Music:** Resolve playback issues, change recommended app target to `7.29.52` ([#5813](https://github.com/ReVanced/revanced-patches/issues/5813)) ([a53b00d](https://github.com/ReVanced/revanced-patches/commit/a53b00dd514dbe2b3406f3c1013a4f58a7f481c5))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - SponsorBlock:** Add 'Hook' segment category ([#5783](https://github.com/ReVanced/revanced-patches/issues/5783)) ([9d4aa5c](https://github.com/ReVanced/revanced-patches/commit/9d4aa5cd16a6f9e95cf7c626351b46b86ca80efe))
|
||||
|
||||
# [5.36.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.0...v5.36.0-dev.1) (2025-09-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Duolingo - Disable ads:** Support latest app target ([#5782](https://github.com/ReVanced/revanced-patches/issues/5782)) ([88b47ef](https://github.com/ReVanced/revanced-patches/commit/88b47ef414cd073ec3800258b32aceb6f383a411))
|
||||
* **YouTube - Hide layout components:** Hide new type of Playable shelf ([8cd8e59](https://github.com/ReVanced/revanced-patches/commit/8cd8e59bbc3a878269276b8ae5f627b044d157f0))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - SponsorBlock:** Add 'Hook' segment category ([#5783](https://github.com/ReVanced/revanced-patches/issues/5783)) ([9d4aa5c](https://github.com/ReVanced/revanced-patches/commit/9d4aa5cd16a6f9e95cf7c626351b46b86ca80efe))
|
||||
|
||||
# [5.36.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.0...v5.36.0-dev.1) (2025-09-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Duolingo - Disable ads:** Support latest app target ([#5782](https://github.com/ReVanced/revanced-patches/issues/5782)) ([88b47ef](https://github.com/ReVanced/revanced-patches/commit/88b47ef414cd073ec3800258b32aceb6f383a411))
|
||||
* **YouTube - Hide layout components:** Hide new type of Playable shelf ([8cd8e59](https://github.com/ReVanced/revanced-patches/commit/8cd8e59bbc3a878269276b8ae5f627b044d157f0))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - SponsorBlock:** Add 'Hook' segment category ([#5783](https://github.com/ReVanced/revanced-patches/issues/5783)) ([9d4aa5c](https://github.com/ReVanced/revanced-patches/commit/9d4aa5cd16a6f9e95cf7c626351b46b86ca80efe))
|
||||
|
||||
# [5.36.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.1-dev.1...v5.36.0-dev.1) (2025-09-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - SponsorBlock:** Add 'Hook' segment category ([#5783](https://github.com/ReVanced/revanced-patches/issues/5783)) ([2e042c4](https://github.com/ReVanced/revanced-patches/commit/2e042c4b3366fa3daf991d5560fcae991d00ad12))
|
||||
|
||||
## [5.35.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.0...v5.35.1-dev.1) (2025-09-11)
|
||||
|
||||
|
||||
|
||||
8
adsfund.json
Normal file
8
adsfund.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"info": "This is verification file for ads.fund project",
|
||||
"project": {
|
||||
"name": "Revanced Patches",
|
||||
"walletAddress": "0x7ab4091e00363654bf84B34151225742cd92FCE5",
|
||||
"tokenAddress": "0xadf325f255083a3f3d9a9d01ffb3db52a148d802"
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,9 @@
|
||||
dependencies {
|
||||
compileOnly(project(":extensions:shared:library"))
|
||||
compileOnly(project(":extensions:youtube:stub"))
|
||||
compileOnly(libs.annotation)
|
||||
}
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
minSdk = 26
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package app.revanced.extension.music.patches;
|
||||
|
||||
import app.revanced.extension.music.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class HideCategoryBarPatch {
|
||||
|
||||
/**
|
||||
* Injection point
|
||||
*/
|
||||
public static boolean hideCategoryBar() {
|
||||
return Settings.HIDE_CATEGORY_BAR.get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package app.revanced.extension.music.patches;
|
||||
|
||||
import app.revanced.extension.music.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class HideGetPremiumPatch {
|
||||
|
||||
/**
|
||||
* Injection point
|
||||
*/
|
||||
public static boolean hideGetPremiumLabel() {
|
||||
return Settings.HIDE_GET_PREMIUM_LABEL.get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package app.revanced.extension.music.patches;
|
||||
|
||||
import app.revanced.extension.music.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class HideUpgradeButtonPatch {
|
||||
|
||||
/**
|
||||
* Injection point
|
||||
*/
|
||||
public static boolean hideUpgradeButton() {
|
||||
return Settings.HIDE_UPGRADE_BUTTON.get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package app.revanced.extension.music.patches;
|
||||
|
||||
import app.revanced.extension.music.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class HideVideoAdsPatch {
|
||||
|
||||
/**
|
||||
* Injection point
|
||||
*/
|
||||
public static boolean showVideoAds(boolean original) {
|
||||
if (Settings.HIDE_VIDEO_ADS.get()) {
|
||||
return false;
|
||||
}
|
||||
return original;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package app.revanced.extension.music.patches;
|
||||
|
||||
import app.revanced.extension.music.settings.Settings;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class PermanentRepeatPatch {
|
||||
|
||||
/**
|
||||
* Injection point
|
||||
*/
|
||||
public static boolean permanentRepeat() {
|
||||
return Settings.PERMANENT_REPEAT.get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package app.revanced.extension.music.patches.spoof;
|
||||
|
||||
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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import app.revanced.extension.shared.spoof.ClientType;
|
||||
import app.revanced.extension.shared.spoof.requests.StreamingDataRequest;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class SpoofVideoStreamsPatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void setClientOrderToUse() {
|
||||
List<ClientType> availableClients = List.of(
|
||||
ANDROID_VR_1_43_32,
|
||||
ANDROID_VR_1_61_48,
|
||||
VISIONOS
|
||||
);
|
||||
|
||||
StreamingDataRequest.setClientOrderToUse(availableClients, ANDROID_VR_1_43_32);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package app.revanced.extension.music.settings;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.view.View;
|
||||
|
||||
import app.revanced.extension.music.settings.preference.ReVancedPreferenceFragment;
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BaseActivityHook;
|
||||
|
||||
/**
|
||||
* Hooks GoogleApiActivity to inject a custom ReVancedPreferenceFragment with a toolbar.
|
||||
*/
|
||||
public class GoogleApiActivityHook extends BaseActivityHook {
|
||||
/**
|
||||
* Injection point
|
||||
* <p>
|
||||
* Creates an instance of GoogleApiActivityHook for use in static initialization.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static GoogleApiActivityHook createInstance() {
|
||||
// Must touch the Music settings to ensure the class is loaded and
|
||||
// the values can be found when setting the UI preferences.
|
||||
// Logging anything under non debug ensures this is set.
|
||||
Logger.printInfo(() -> "Permanent repeat enabled: " + Settings.PERMANENT_REPEAT.get());
|
||||
|
||||
return new GoogleApiActivityHook();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the fixed theme for the activity.
|
||||
*/
|
||||
@Override
|
||||
protected void customizeActivityTheme(Activity activity) {
|
||||
// Override the default YouTube Music theme to increase start padding of list items.
|
||||
// Custom style located in resources/music/values/style.xml
|
||||
activity.setTheme(Utils.getResourceIdentifier("Theme.ReVanced.YouTubeMusic.Settings", "style"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resource ID for the YouTube Music settings layout.
|
||||
*/
|
||||
@Override
|
||||
protected int getContentViewResourceId() {
|
||||
return Utils.getResourceIdentifier("revanced_music_settings_with_toolbar", "layout");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fixed background color for the toolbar.
|
||||
*/
|
||||
@Override
|
||||
protected int getToolbarBackgroundColor() {
|
||||
return Utils.getResourceColor("ytm_color_black");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the navigation icon with a color filter applied.
|
||||
*/
|
||||
@Override
|
||||
protected Drawable getNavigationIcon() {
|
||||
Drawable navigationIcon = ReVancedPreferenceFragment.getBackButtonDrawable();
|
||||
navigationIcon.setColorFilter(Utils.getAppForegroundColor(), PorterDuff.Mode.SRC_IN);
|
||||
return navigationIcon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the click listener that finishes the activity when the navigation icon is clicked.
|
||||
*/
|
||||
@Override
|
||||
protected View.OnClickListener getNavigationClickListener(Activity activity) {
|
||||
return view -> activity.finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ReVancedPreferenceFragment for the activity.
|
||||
*/
|
||||
@Override
|
||||
protected PreferenceFragment createPreferenceFragment() {
|
||||
return new ReVancedPreferenceFragment();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package app.revanced.extension.music.settings;
|
||||
|
||||
import static java.lang.Boolean.FALSE;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.shared.settings.BooleanSetting;
|
||||
|
||||
public class Settings extends BaseSettings {
|
||||
|
||||
// Ads
|
||||
public static final BooleanSetting HIDE_VIDEO_ADS = new BooleanSetting("revanced_music_hide_video_ads", TRUE, true);
|
||||
public static final BooleanSetting HIDE_GET_PREMIUM_LABEL = new BooleanSetting("revanced_music_hide_get_premium_label", TRUE, true);
|
||||
public static final BooleanSetting HIDE_UPGRADE_BUTTON = new BooleanSetting("revanced_music_hide_upgrade_button", TRUE, true);
|
||||
|
||||
// General
|
||||
public static final BooleanSetting HIDE_CATEGORY_BAR = new BooleanSetting("revanced_music_hide_category_bar", FALSE, true);
|
||||
|
||||
// Player
|
||||
public static final BooleanSetting PERMANENT_REPEAT = new BooleanSetting("revanced_music_play_permanent_repeat", FALSE, true);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package app.revanced.extension.music.settings.preference;
|
||||
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import app.revanced.extension.music.settings.GoogleApiActivityHook;
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.preference.ToolbarPreferenceFragment;
|
||||
|
||||
/**
|
||||
* Preference fragment for ReVanced settings.
|
||||
*/
|
||||
@SuppressWarnings({"deprecation", "NewApi"})
|
||||
public class ReVancedPreferenceFragment extends ToolbarPreferenceFragment {
|
||||
|
||||
/**
|
||||
* Initializes the preference fragment.
|
||||
*/
|
||||
@Override
|
||||
protected void initialize() {
|
||||
super.initialize();
|
||||
|
||||
try {
|
||||
Utils.sortPreferenceGroups(getPreferenceScreen());
|
||||
setPreferenceScreenToolbar(getPreferenceScreen());
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "initialize failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets toolbar for all nested preference screens.
|
||||
*/
|
||||
@Override
|
||||
protected void customizeToolbar(Toolbar toolbar) {
|
||||
GoogleApiActivityHook.setToolbarLayoutParams(toolbar);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package app.revanced.extension.music.spoof;
|
||||
|
||||
/**
|
||||
* @noinspection unused
|
||||
*/
|
||||
public class SpoofClientPatch {
|
||||
private static final int CLIENT_TYPE_ID = 26;
|
||||
private static final String CLIENT_VERSION = "6.21";
|
||||
private static final String DEVICE_MODEL = "iPhone16,2";
|
||||
private static final String OS_VERSION = "17.7.2.21H221";
|
||||
|
||||
public static int getClientId() {
|
||||
return CLIENT_TYPE_ID;
|
||||
}
|
||||
|
||||
public static String getClientVersion() {
|
||||
return CLIENT_VERSION;
|
||||
}
|
||||
|
||||
public static String getClientModel() {
|
||||
return DEVICE_MODEL;
|
||||
}
|
||||
|
||||
public static String getOsVersion() {
|
||||
return OS_VERSION;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
package app.revanced.extension.shared.settings;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
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;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.preference.ToolbarPreferenceFragment;
|
||||
|
||||
/**
|
||||
* Base class for hooking activities to inject a custom PreferenceFragment with a toolbar.
|
||||
* Provides common logic for initializing the activity and setting up the toolbar.
|
||||
*/
|
||||
@SuppressWarnings({"deprecation", "NewApi"})
|
||||
public abstract class BaseActivityHook extends Activity {
|
||||
|
||||
/**
|
||||
* Layout parameters for the toolbar, extracted from the dummy toolbar.
|
||||
*/
|
||||
protected static ViewGroup.LayoutParams toolbarLayoutParams;
|
||||
|
||||
/**
|
||||
* Sets the layout parameters for the toolbar.
|
||||
*/
|
||||
public static void setToolbarLayoutParams(Toolbar toolbar) {
|
||||
if (toolbarLayoutParams != null) {
|
||||
toolbar.setLayoutParams(toolbarLayoutParams);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the activity by setting the theme, content view and injecting a PreferenceFragment.
|
||||
*/
|
||||
public static void initialize(BaseActivityHook hook, Activity activity) {
|
||||
try {
|
||||
hook.customizeActivityTheme(activity);
|
||||
activity.setContentView(hook.getContentViewResourceId());
|
||||
|
||||
// Sanity check.
|
||||
String dataString = activity.getIntent().getDataString();
|
||||
if (!"revanced_settings_intent".equals(dataString)) {
|
||||
Logger.printException(() -> "Unknown intent: " + dataString);
|
||||
return;
|
||||
}
|
||||
|
||||
PreferenceFragment fragment = hook.createPreferenceFragment();
|
||||
hook.createToolbar(activity, fragment);
|
||||
|
||||
activity.getFragmentManager()
|
||||
.beginTransaction()
|
||||
.replace(Utils.getResourceIdentifier("revanced_settings_fragments", "id"), fragment)
|
||||
.commit();
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "initialize failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and configures a toolbar for the activity, replacing a dummy placeholder.
|
||||
*/
|
||||
@SuppressLint("UseCompatLoadingForDrawables")
|
||||
protected void createToolbar(Activity activity, PreferenceFragment fragment) {
|
||||
// Replace dummy placeholder toolbar.
|
||||
// This is required to fix submenu title alignment issue with Android ASOP 15+
|
||||
ViewGroup toolBarParent = activity.findViewById(
|
||||
Utils.getResourceIdentifier("revanced_toolbar_parent", "id"));
|
||||
ViewGroup dummyToolbar = Utils.getChildViewByResourceName(toolBarParent, "revanced_toolbar");
|
||||
toolbarLayoutParams = dummyToolbar.getLayoutParams();
|
||||
toolBarParent.removeView(dummyToolbar);
|
||||
|
||||
// Sets appropriate system navigation bar color for the activity.
|
||||
ToolbarPreferenceFragment.setNavigationBarColor(activity.getWindow());
|
||||
|
||||
Toolbar toolbar = new Toolbar(toolBarParent.getContext());
|
||||
toolbar.setBackgroundColor(getToolbarBackgroundColor());
|
||||
toolbar.setNavigationIcon(getNavigationIcon());
|
||||
toolbar.setNavigationOnClickListener(getNavigationClickListener(activity));
|
||||
toolbar.setTitle(Utils.getResourceIdentifier("revanced_settings_title", "string"));
|
||||
|
||||
final int margin = Utils.dipToPixels(16);
|
||||
toolbar.setTitleMarginStart(margin);
|
||||
toolbar.setTitleMarginEnd(margin);
|
||||
TextView toolbarTextView = Utils.getChildView(toolbar, false, view -> view instanceof TextView);
|
||||
if (toolbarTextView != null) {
|
||||
toolbarTextView.setTextColor(Utils.getAppForegroundColor());
|
||||
toolbarTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
|
||||
}
|
||||
setToolbarLayoutParams(toolbar);
|
||||
|
||||
onPostToolbarSetup(activity, toolbar, fragment);
|
||||
|
||||
toolBarParent.addView(toolbar, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Customizes the activity's theme.
|
||||
*/
|
||||
protected abstract void customizeActivityTheme(Activity activity);
|
||||
|
||||
/**
|
||||
* Returns the resource ID for the content view layout.
|
||||
*/
|
||||
protected abstract int getContentViewResourceId();
|
||||
|
||||
/**
|
||||
* Returns the background color for the toolbar.
|
||||
*/
|
||||
protected abstract int getToolbarBackgroundColor();
|
||||
|
||||
/**
|
||||
* Returns the navigation icon drawable for the toolbar.
|
||||
*/
|
||||
protected abstract Drawable getNavigationIcon();
|
||||
|
||||
/**
|
||||
* Returns the click listener for the toolbar's navigation icon.
|
||||
*/
|
||||
protected abstract View.OnClickListener getNavigationClickListener(Activity activity);
|
||||
|
||||
/**
|
||||
* Creates the PreferenceFragment to be injected into the activity.
|
||||
*/
|
||||
protected PreferenceFragment createPreferenceFragment() {
|
||||
return new ToolbarPreferenceFragment();
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs additional setup after the toolbar is configured.
|
||||
*
|
||||
* @param activity The activity hosting the toolbar.
|
||||
* @param toolbar The configured toolbar.
|
||||
* @param fragment The PreferenceFragment associated with the activity.
|
||||
*/
|
||||
protected void onPostToolbarSetup(Activity activity, Toolbar toolbar, PreferenceFragment fragment) {}
|
||||
}
|
||||
@@ -4,8 +4,8 @@ import static java.lang.Boolean.FALSE;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static app.revanced.extension.shared.settings.Setting.parent;
|
||||
import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.AudioStreamLanguageOverrideAvailability;
|
||||
import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.SpoofiOSAvailability;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.spoof.ClientType;
|
||||
|
||||
/**
|
||||
@@ -31,9 +31,13 @@ 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 SPOOF_VIDEO_STREAMS_IOS_FORCE_AVC = new BooleanSetting("revanced_spoof_video_streams_ios_force_avc", FALSE, true,
|
||||
"revanced_spoof_video_streams_ios_force_avc_user_dialog_message", new SpoofiOSAvailability());
|
||||
// Client type must be last spoof setting due to cyclic references.
|
||||
public static final EnumSetting<ClientType> SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client_type", ClientType.ANDROID_UNPLUGGED, true, parent(SPOOF_VIDEO_STREAMS));
|
||||
public static final EnumSetting<ClientType> SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client_type", ClientType.ANDROID_VR_1_61_48, true, parent(SPOOF_VIDEO_STREAMS));
|
||||
|
||||
static {
|
||||
if (SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS_UNPLUGGED) {
|
||||
Logger.printInfo(() -> "Migrating from iOS Unplugged to iPadOS");
|
||||
SPOOF_VIDEO_STREAMS_CLIENT_TYPE.save(ClientType.IPADOS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package app.revanced.extension.youtube.settings.preference;
|
||||
package app.revanced.extension.shared.settings.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.preference.Preference;
|
||||
import app.revanced.extension.shared.settings.preference.LogBufferManager;
|
||||
|
||||
/**
|
||||
* A custom preference that clears the ReVanced debug log buffer when clicked.
|
||||
@@ -1,9 +1,8 @@
|
||||
package app.revanced.extension.youtube.settings.preference;
|
||||
package app.revanced.extension.shared.settings.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.preference.Preference;
|
||||
import app.revanced.extension.shared.settings.preference.LogBufferManager;
|
||||
|
||||
/**
|
||||
* A custom preference that triggers exporting ReVanced debug logs to the clipboard when clicked.
|
||||
@@ -0,0 +1,150 @@
|
||||
package app.revanced.extension.shared.settings.preference;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Dialog;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.util.TypedValue;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowInsets;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BaseActivityHook;
|
||||
|
||||
@SuppressWarnings({"deprecation", "NewApi"})
|
||||
public class ToolbarPreferenceFragment extends AbstractPreferenceFragment {
|
||||
/**
|
||||
* Sets toolbar for all nested preference screens.
|
||||
*/
|
||||
protected void setPreferenceScreenToolbar(PreferenceScreen parentScreen) {
|
||||
for (int i = 0, count = parentScreen.getPreferenceCount(); i < count; i++) {
|
||||
Preference childPreference = parentScreen.getPreference(i);
|
||||
if (childPreference instanceof PreferenceScreen) {
|
||||
// Recursively set sub preferences.
|
||||
setPreferenceScreenToolbar((PreferenceScreen) childPreference);
|
||||
|
||||
childPreference.setOnPreferenceClickListener(
|
||||
childScreen -> {
|
||||
Dialog preferenceScreenDialog = ((PreferenceScreen) childScreen).getDialog();
|
||||
ViewGroup rootView = (ViewGroup) preferenceScreenDialog
|
||||
.findViewById(android.R.id.content)
|
||||
.getParent();
|
||||
|
||||
// Allow package-specific background customization.
|
||||
customizeDialogBackground(rootView);
|
||||
|
||||
// Fix the system navigation bar color for submenus.
|
||||
setNavigationBarColor(preferenceScreenDialog.getWindow());
|
||||
|
||||
// Fix edge-to-edge screen with Android 15 and YT 19.45+
|
||||
// https://developer.android.com/develop/ui/views/layout/edge-to-edge#system-bars-insets
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
rootView.setOnApplyWindowInsetsListener((v, insets) -> {
|
||||
Insets statusInsets = insets.getInsets(WindowInsets.Type.statusBars());
|
||||
Insets navInsets = insets.getInsets(WindowInsets.Type.navigationBars());
|
||||
Insets cutoutInsets = insets.getInsets(WindowInsets.Type.displayCutout());
|
||||
|
||||
// Apply padding for display cutout in landscape.
|
||||
int leftPadding = cutoutInsets.left;
|
||||
int rightPadding = cutoutInsets.right;
|
||||
int topPadding = statusInsets.top;
|
||||
int bottomPadding = navInsets.bottom;
|
||||
|
||||
v.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
|
||||
return insets;
|
||||
});
|
||||
}
|
||||
|
||||
Toolbar toolbar = new Toolbar(childScreen.getContext());
|
||||
toolbar.setTitle(childScreen.getTitle());
|
||||
toolbar.setNavigationIcon(getBackButtonDrawable());
|
||||
toolbar.setNavigationOnClickListener(view -> preferenceScreenDialog.dismiss());
|
||||
|
||||
final int margin = Utils.dipToPixels(16);
|
||||
toolbar.setTitleMargin(margin, 0, margin, 0);
|
||||
|
||||
TextView toolbarTextView = Utils.getChildView(toolbar,
|
||||
true, TextView.class::isInstance);
|
||||
if (toolbarTextView != null) {
|
||||
toolbarTextView.setTextColor(Utils.getAppForegroundColor());
|
||||
toolbarTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
|
||||
}
|
||||
|
||||
// Allow package-specific toolbar customization.
|
||||
customizeToolbar(toolbar);
|
||||
|
||||
// Allow package-specific post-toolbar setup.
|
||||
onPostToolbarSetup(toolbar, preferenceScreenDialog);
|
||||
|
||||
rootView.addView(toolbar, 0);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the system navigation bar color for the activity.
|
||||
* Applies the background color obtained from {@link Utils#getAppBackgroundColor()} to the navigation bar.
|
||||
* For Android 10 (API 29) and above, enforces navigation bar contrast to ensure visibility.
|
||||
*/
|
||||
public static void setNavigationBarColor(@Nullable Window window) {
|
||||
if (window == null) {
|
||||
Logger.printDebug(() -> "Cannot set navigation bar color, window is null");
|
||||
return;
|
||||
}
|
||||
|
||||
window.setNavigationBarColor(Utils.getAppBackgroundColor());
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
window.setNavigationBarContrastEnforced(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the drawable for the back button.
|
||||
*/
|
||||
@SuppressLint("UseCompatLoadingForDrawables")
|
||||
public static Drawable getBackButtonDrawable() {
|
||||
final int backButtonResource = Utils.getResourceIdentifier(
|
||||
"revanced_settings_toolbar_arrow_left", "drawable");
|
||||
Drawable drawable = Utils.getContext().getResources().getDrawable(backButtonResource);
|
||||
customizeBackButtonDrawable(drawable);
|
||||
return drawable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Customizes the back button drawable.
|
||||
*/
|
||||
protected static void customizeBackButtonDrawable(Drawable drawable) {
|
||||
drawable.setTint(Utils.getAppForegroundColor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows subclasses to customize the dialog's root view background.
|
||||
*/
|
||||
protected void customizeDialogBackground(ViewGroup rootView) {
|
||||
rootView.setBackgroundColor(Utils.getAppBackgroundColor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows subclasses to customize the toolbar.
|
||||
*/
|
||||
protected void customizeToolbar(Toolbar toolbar) {
|
||||
BaseActivityHook.setToolbarLayoutParams(toolbar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows subclasses to perform actions after toolbar setup.
|
||||
*/
|
||||
protected void onPostToolbarSetup(Toolbar toolbar, Dialog preferenceScreenDialog) {}
|
||||
}
|
||||
@@ -2,17 +2,22 @@ package app.revanced.extension.shared.spoof;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
|
||||
@SuppressWarnings("ConstantLocale")
|
||||
public enum ClientType {
|
||||
/**
|
||||
* Video not playable: Kids / Paid / Movie / Private / Age-restricted.
|
||||
* This client can only be used when logged out.
|
||||
*/
|
||||
// https://dumps.tadiphone.dev/dumps/oculus/eureka
|
||||
ANDROID_VR_NO_AUTH(
|
||||
ANDROID_VR_1_61_48(
|
||||
28,
|
||||
"ANDROID_VR",
|
||||
"com.google.android.apps.youtube.vr.oculus",
|
||||
@@ -27,29 +32,32 @@ public enum ClientType {
|
||||
"1.61.48",
|
||||
false,
|
||||
false,
|
||||
"Android VR No auth"
|
||||
"Android VR 1.61"
|
||||
),
|
||||
// Chromecast with Google TV 4K.
|
||||
// https://dumps.tadiphone.dev/dumps/google/kirkwood
|
||||
ANDROID_UNPLUGGED(
|
||||
29,
|
||||
"ANDROID_UNPLUGGED",
|
||||
"com.google.android.apps.youtube.unplugged",
|
||||
"Google",
|
||||
"Google TV Streamer",
|
||||
"Android",
|
||||
"14",
|
||||
"34",
|
||||
"UTT3.240625.001.K5",
|
||||
"132.0.6808.3",
|
||||
"8.49.0",
|
||||
true,
|
||||
true,
|
||||
"Android TV"
|
||||
/**
|
||||
* Uses non adaptive bitrate, which fixes audio stuttering with YT Music.
|
||||
* Does not use AV1.
|
||||
*/
|
||||
ANDROID_VR_1_43_32(
|
||||
ANDROID_VR_1_61_48.id,
|
||||
ANDROID_VR_1_61_48.clientName,
|
||||
Objects.requireNonNull(ANDROID_VR_1_61_48.packageName),
|
||||
ANDROID_VR_1_61_48.deviceMake,
|
||||
ANDROID_VR_1_61_48.deviceModel,
|
||||
ANDROID_VR_1_61_48.osName,
|
||||
ANDROID_VR_1_61_48.osVersion,
|
||||
Objects.requireNonNull(ANDROID_VR_1_61_48.androidSdkVersion),
|
||||
Objects.requireNonNull(ANDROID_VR_1_61_48.buildId),
|
||||
"107.0.5284.2",
|
||||
"1.43.32",
|
||||
ANDROID_VR_1_61_48.requiresAuth,
|
||||
ANDROID_VR_1_61_48.useAuth,
|
||||
"Android VR 1.43"
|
||||
),
|
||||
// Cannot play livestreams and lacks HDR, but can play videos with music and labeled "for children".
|
||||
// Google Pixel 9 Pro Fold
|
||||
// https://dumps.tadiphone.dev/dumps/google/barbet
|
||||
/**
|
||||
* 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>
|
||||
*/
|
||||
ANDROID_CREATOR(
|
||||
14,
|
||||
"ANDROID_CREATOR",
|
||||
@@ -66,58 +74,64 @@ public enum ClientType {
|
||||
true,
|
||||
"Android Creator"
|
||||
),
|
||||
/**
|
||||
* Internal YT client for an unreleased YT client. May stop working at any time.
|
||||
*/
|
||||
VISIONOS(101,
|
||||
"VISIONOS",
|
||||
"Apple",
|
||||
"RealityDevice14,1",
|
||||
"visionOS",
|
||||
"1.3.21O771",
|
||||
"0.1",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15",
|
||||
false,
|
||||
false,
|
||||
"visionOS"
|
||||
),
|
||||
/**
|
||||
* The device machine id for the iPad 6th Gen (iPad7,6).
|
||||
* AV1 hardware decoding is not supported.
|
||||
* See [this GitHub Gist](https://gist.github.com/adamawolf/3048717) for more information.
|
||||
*
|
||||
* Based on Google's actions to date, PoToken may not be required on devices with very low specs.
|
||||
* For example, suppose the User-Agent for a PlayStation 3 (with 256MB of RAM) is used.
|
||||
* Accessing 'Web' (https://www.youtube.com) will redirect to 'TV' (https://www.youtube.com/tv).
|
||||
* 'TV' target devices with very low specs, such as embedded devices, game consoles, and blu-ray players, so PoToken is not required.
|
||||
*
|
||||
* For this reason, the device machine id for the iPad 6th Gen (with 2GB of RAM),
|
||||
* the lowest spec device capable of running iPadOS 17, was used.
|
||||
*/
|
||||
IPADOS(5,
|
||||
"IOS",
|
||||
"Apple",
|
||||
"iPad7,6",
|
||||
"iPadOS",
|
||||
"17.7.10.21H450",
|
||||
"19.22.3",
|
||||
"com.google.ios.youtube/19.22.3 (iPad7,6; U; CPU iPadOS 17_7_10 like Mac OS X; " + Locale.getDefault() + ")",
|
||||
false,
|
||||
false,
|
||||
"iPadOS"
|
||||
),
|
||||
/**
|
||||
* Obsolete and broken client. Here only to migrate data.
|
||||
*/
|
||||
@Deprecated
|
||||
IOS_UNPLUGGED(
|
||||
33,
|
||||
"IOS_UNPLUGGED",
|
||||
"com.google.ios.youtubeunplugged",
|
||||
"Apple",
|
||||
forceAVC()
|
||||
// 11 Pro Max (last device with iOS 13)
|
||||
? "iPhone12,5"
|
||||
// 15 Pro Max
|
||||
: "iPhone16,2",
|
||||
"iPhone16,2",
|
||||
"iOS",
|
||||
forceAVC()
|
||||
// iOS 13 and earlier uses only AVC. 14+ adds VP9 and AV1.
|
||||
? "13.7.17H35"
|
||||
: "18.2.22C152",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
// Version number should be a valid iOS release.
|
||||
// https://www.ipa4fun.com/history/152043/
|
||||
forceAVC()
|
||||
// Some newer versions can also force AVC,
|
||||
// but 6.45 is the last version that supports iOS 13.
|
||||
? "6.45"
|
||||
: "8.49",
|
||||
"18.2.22C152",
|
||||
"8.49",
|
||||
"dummy user-agent",
|
||||
true,
|
||||
true,
|
||||
forceAVC()
|
||||
? "iOS TV Force AVC"
|
||||
: "iOS TV"
|
||||
),
|
||||
ANDROID_VR_AUTH(
|
||||
ANDROID_VR_NO_AUTH.id,
|
||||
ANDROID_VR_NO_AUTH.clientName,
|
||||
ANDROID_VR_NO_AUTH.packageName,
|
||||
ANDROID_VR_NO_AUTH.deviceMake,
|
||||
ANDROID_VR_NO_AUTH.deviceModel,
|
||||
ANDROID_VR_NO_AUTH.osName,
|
||||
ANDROID_VR_NO_AUTH.osVersion,
|
||||
ANDROID_VR_NO_AUTH.androidSdkVersion,
|
||||
ANDROID_VR_NO_AUTH.buildId,
|
||||
ANDROID_VR_NO_AUTH.cronetVersion,
|
||||
ANDROID_VR_NO_AUTH.clientVersion,
|
||||
ANDROID_VR_NO_AUTH.requiresAuth,
|
||||
true,
|
||||
"Android VR Auth"
|
||||
"iOS TV"
|
||||
);
|
||||
|
||||
private static boolean forceAVC() {
|
||||
return BaseSettings.SPOOF_VIDEO_STREAMS_IOS_FORCE_AVC.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* YouTube
|
||||
* <a href="https://github.com/zerodytrash/YouTube-Internal-Clients?tab=readme-ov-file#clients">client type</a>
|
||||
@@ -129,6 +143,7 @@ public enum ClientType {
|
||||
/**
|
||||
* App package name.
|
||||
*/
|
||||
@Nullable
|
||||
private final String packageName;
|
||||
|
||||
/**
|
||||
@@ -198,17 +213,19 @@ public enum ClientType {
|
||||
*/
|
||||
public final String friendlyName;
|
||||
|
||||
@SuppressWarnings("ConstantLocale")
|
||||
/**
|
||||
* Android constructor.
|
||||
*/
|
||||
ClientType(int id,
|
||||
String clientName,
|
||||
String packageName,
|
||||
@NonNull String packageName,
|
||||
String deviceMake,
|
||||
String deviceModel,
|
||||
String osName,
|
||||
String osVersion,
|
||||
@Nullable String androidSdkVersion,
|
||||
@Nullable String buildId,
|
||||
@Nullable String cronetVersion,
|
||||
@NonNull String androidSdkVersion,
|
||||
@NonNull String buildId,
|
||||
@NonNull String cronetVersion,
|
||||
String clientVersion,
|
||||
boolean requiresAuth,
|
||||
boolean useAuth,
|
||||
@@ -229,31 +246,44 @@ public enum ClientType {
|
||||
this.friendlyName = friendlyName;
|
||||
|
||||
Locale defaultLocale = Locale.getDefault();
|
||||
if (androidSdkVersion == null) {
|
||||
// Convert version from '18.2.22C152' into '18_2_22'
|
||||
String userAgentOsVersion = osVersion
|
||||
.replaceAll("(\\d+\\.\\d+\\.\\d+).*", "$1")
|
||||
.replace(".", "_");
|
||||
// https://github.com/mitmproxy/mitmproxy/issues/4836
|
||||
this.userAgent = String.format("%s/%s (%s; U; CPU iOS %s like Mac OS X; %s)",
|
||||
packageName,
|
||||
clientVersion,
|
||||
deviceModel,
|
||||
userAgentOsVersion,
|
||||
defaultLocale
|
||||
);
|
||||
} else {
|
||||
this.userAgent = String.format("%s/%s (Linux; U; Android %s; %s; %s; Build/%s; Cronet/%s)",
|
||||
packageName,
|
||||
clientVersion,
|
||||
osVersion,
|
||||
defaultLocale,
|
||||
deviceModel,
|
||||
Objects.requireNonNull(buildId),
|
||||
Objects.requireNonNull(cronetVersion)
|
||||
);
|
||||
}
|
||||
this.userAgent = String.format("%s/%s (Linux; U; Android %s; %s; %s; Build/%s; Cronet/%s)",
|
||||
packageName,
|
||||
clientVersion,
|
||||
osVersion,
|
||||
defaultLocale,
|
||||
deviceModel,
|
||||
Objects.requireNonNull(buildId),
|
||||
Objects.requireNonNull(cronetVersion)
|
||||
);
|
||||
Logger.printDebug(() -> "userAgent: " + this.userAgent);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantLocale")
|
||||
ClientType(int id,
|
||||
String clientName,
|
||||
String deviceMake,
|
||||
String deviceModel,
|
||||
String osName,
|
||||
String osVersion,
|
||||
String clientVersion,
|
||||
String userAgent,
|
||||
boolean requiresAuth,
|
||||
boolean useAuth,
|
||||
String friendlyName) {
|
||||
this.id = id;
|
||||
this.clientName = clientName;
|
||||
this.deviceMake = deviceMake;
|
||||
this.deviceModel = deviceModel;
|
||||
this.osName = osName;
|
||||
this.osVersion = osVersion;
|
||||
this.clientVersion = clientVersion;
|
||||
this.userAgent = userAgent;
|
||||
this.requiresAuth = requiresAuth;
|
||||
this.useAuth = useAuth;
|
||||
this.friendlyName = friendlyName;
|
||||
this.packageName = null;
|
||||
this.androidSdkVersion = null;
|
||||
this.buildId = null;
|
||||
this.cronetVersion = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import java.util.Map;
|
||||
|
||||
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;
|
||||
@@ -19,13 +20,25 @@ public class SpoofVideoStreamsPatch {
|
||||
private static final boolean SPOOF_STREAMING_DATA = BaseSettings.SPOOF_VIDEO_STREAMS.get();
|
||||
|
||||
private static final boolean FIX_HLS_CURRENT_TIME = SPOOF_STREAMING_DATA
|
||||
&& BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS_UNPLUGGED;
|
||||
&& BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.VISIONOS;
|
||||
|
||||
@Nullable
|
||||
private static volatile AppLanguage languageOverride;
|
||||
|
||||
/**
|
||||
* Any unreachable ip address. Used to intentionally fail requests.
|
||||
* Domain used for internet connectivity verification.
|
||||
* It has an empty response body and is only used to check for a 204 response code.
|
||||
* <p>
|
||||
* If an unreachable IP address (127.0.0.1) is used, no response code is provided.
|
||||
* <p>
|
||||
* YouTube handles unreachable IP addresses without issue.
|
||||
* YouTube Music has an issue with waiting for the Cronet connect timeout of 30s on mobile networks.
|
||||
* <p>
|
||||
* Using a VPN or DNS can temporarily resolve this issue,
|
||||
* But the ideal workaround is to avoid using an unreachable IP address.
|
||||
*/
|
||||
private static final String UNREACHABLE_HOST_URI_STRING = "https://127.0.0.0";
|
||||
private static final Uri UNREACHABLE_HOST_URI = Uri.parse(UNREACHABLE_HOST_URI_STRING);
|
||||
private static final String INTERNET_CONNECTION_CHECK_URI_STRING = "https://www.google.com/gen_204";
|
||||
private static final Uri INTERNET_CONNECTION_CHECK_URI = Uri.parse(INTERNET_CONNECTION_CHECK_URI_STRING);
|
||||
|
||||
/**
|
||||
* @return If this patch was included during patching.
|
||||
@@ -34,10 +47,21 @@ public class SpoofVideoStreamsPatch {
|
||||
return false; // Modified during patching.
|
||||
}
|
||||
|
||||
public static boolean notSpoofingToAndroid() {
|
||||
return !isPatchIncluded()
|
||||
|| !BaseSettings.SPOOF_VIDEO_STREAMS.get()
|
||||
|| BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS_UNPLUGGED;
|
||||
public static boolean spoofingToClientWithNoMultiAudioStreams() {
|
||||
return isPatchIncluded() && BaseSettings.SPOOF_VIDEO_STREAMS.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param language Language override for non-authenticated requests. If this is null then
|
||||
* {@link BaseSettings#SPOOF_VIDEO_STREAMS_LANGUAGE} is used.
|
||||
*/
|
||||
public static void setLanguageOverride(@Nullable AppLanguage language) {
|
||||
languageOverride = language;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static AppLanguage getLanguageOverride() {
|
||||
return languageOverride;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,9 +77,9 @@ public class SpoofVideoStreamsPatch {
|
||||
String path = playerRequestUri.getPath();
|
||||
|
||||
if (path != null && path.contains("get_watch")) {
|
||||
Logger.printDebug(() -> "Blocking 'get_watch' by returning unreachable uri");
|
||||
Logger.printDebug(() -> "Blocking 'get_watch' by returning internet connection check uri");
|
||||
|
||||
return UNREACHABLE_HOST_URI;
|
||||
return INTERNET_CONNECTION_CHECK_URI;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "blockGetWatchRequest failure", ex);
|
||||
@@ -77,9 +101,9 @@ public class SpoofVideoStreamsPatch {
|
||||
String path = originalUri.getPath();
|
||||
|
||||
if (path != null && path.contains("initplayback")) {
|
||||
Logger.printDebug(() -> "Blocking 'initplayback' by clearing query");
|
||||
Logger.printDebug(() -> "Blocking 'initplayback' by returning internet connection check uri");
|
||||
|
||||
return originalUri.buildUpon().clearQuery().build().toString();
|
||||
return INTERNET_CONNECTION_CHECK_URI_STRING;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "blockInitPlaybackRequest failure", ex);
|
||||
@@ -252,16 +276,8 @@ public class SpoofVideoStreamsPatch {
|
||||
public static final class AudioStreamLanguageOverrideAvailability implements Setting.Availability {
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return BaseSettings.SPOOF_VIDEO_STREAMS.get()
|
||||
&& BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.ANDROID_VR_NO_AUTH;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class SpoofiOSAvailability implements Setting.Availability {
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return BaseSettings.SPOOF_VIDEO_STREAMS.get()
|
||||
&& BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS_UNPLUGGED;
|
||||
// Since all current clients are un-authenticated, this works for all spoof clients.
|
||||
return BaseSettings.SPOOF_VIDEO_STREAMS.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
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;
|
||||
|
||||
@@ -10,8 +12,10 @@ import java.util.Locale;
|
||||
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;
|
||||
|
||||
final class PlayerRoutes {
|
||||
static final Route.CompiledRoute GET_STREAMING_DATA = new Route(
|
||||
@@ -37,14 +41,16 @@ final class PlayerRoutes {
|
||||
try {
|
||||
JSONObject context = new JSONObject();
|
||||
|
||||
// Can override default language only if no login is used.
|
||||
// Could use preferred audio for all clients that do not login,
|
||||
// but if this is a fall over client it will set the language even though
|
||||
// the audio language is not selectable in the UI.
|
||||
ClientType userSelectedClient = BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get();
|
||||
Locale streamLocale = userSelectedClient == ClientType.ANDROID_VR_NO_AUTH
|
||||
? BaseSettings.SPOOF_VIDEO_STREAMS_LANGUAGE.get().getLocale()
|
||||
: Locale.getDefault();
|
||||
AppLanguage language = SpoofVideoStreamsPatch.getLanguageOverride();
|
||||
if (language == null || BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ANDROID_VR_1_43_32) {
|
||||
// Force original audio has not overrode the language.
|
||||
// Or if YT has fallen over to the very last client (VR 1.43), then always
|
||||
// use the app language because forcing an audio stream of specific languages
|
||||
// can sometimes fail so it's better to try and load something rather than nothing.
|
||||
language = BaseSettings.SPOOF_VIDEO_STREAMS_LANGUAGE.get();
|
||||
}
|
||||
//noinspection ExtractMethodRecommender
|
||||
Locale streamLocale = language.getLocale();
|
||||
|
||||
JSONObject client = new JSONObject();
|
||||
client.put("deviceMake", clientType.deviceMake);
|
||||
|
||||
@@ -35,21 +35,27 @@ import app.revanced.extension.shared.spoof.ClientType;
|
||||
*/
|
||||
public class StreamingDataRequest {
|
||||
|
||||
private static final ClientType[] CLIENT_ORDER_TO_USE;
|
||||
private static volatile ClientType[] clientOrderToUse = ClientType.values();
|
||||
|
||||
static {
|
||||
ClientType[] allClientTypes = ClientType.values();
|
||||
ClientType preferredClient = BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get();
|
||||
public static void setClientOrderToUse(List<ClientType> availableClients, ClientType preferredClient) {
|
||||
Objects.requireNonNull(preferredClient);
|
||||
|
||||
CLIENT_ORDER_TO_USE = new ClientType[allClientTypes.length];
|
||||
CLIENT_ORDER_TO_USE[0] = preferredClient;
|
||||
int availableClientSize = availableClients.size();
|
||||
if (!availableClients.contains(preferredClient)) {
|
||||
availableClientSize++;
|
||||
}
|
||||
|
||||
clientOrderToUse = new ClientType[availableClientSize];
|
||||
clientOrderToUse[0] = preferredClient;
|
||||
|
||||
int i = 1;
|
||||
for (ClientType c : allClientTypes) {
|
||||
for (ClientType c : availableClients) {
|
||||
if (c != preferredClient) {
|
||||
CLIENT_ORDER_TO_USE[i++] = c;
|
||||
clientOrderToUse[i++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
Logger.printDebug(() -> "Available spoof clients: " + Arrays.toString(clientOrderToUse));
|
||||
}
|
||||
|
||||
private static final String AUTHORIZATION_HEADER = "Authorization";
|
||||
@@ -193,9 +199,9 @@ public class StreamingDataRequest {
|
||||
|
||||
// Retry with different client if empty response body is received.
|
||||
int i = 0;
|
||||
for (ClientType clientType : CLIENT_ORDER_TO_USE) {
|
||||
for (ClientType clientType : clientOrderToUse) {
|
||||
// Show an error if the last client type fails, or if debug is enabled then show for all attempts.
|
||||
final boolean showErrorToast = (++i == CLIENT_ORDER_TO_USE.length) || debugEnabled;
|
||||
final boolean showErrorToast = (++i == clientOrderToUse.length) || debugEnabled;
|
||||
|
||||
HttpURLConnection connection = send(clientType, videoId, playerHeaders, showErrorToast);
|
||||
if (connection != null) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.settings.Setting;
|
||||
import app.revanced.extension.shared.settings.AppLanguage;
|
||||
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@@ -11,16 +11,21 @@ public class ForceOriginalAudioPatch {
|
||||
private static final String DEFAULT_AUDIO_TRACKS_SUFFIX = ".4";
|
||||
|
||||
/**
|
||||
* If the conditions to use this patch were present when the app launched.
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean PATCH_AVAILABLE = SpoofVideoStreamsPatch.notSpoofingToAndroid();
|
||||
|
||||
public static final class ForceOriginalAudioAvailability implements Setting.Availability {
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
// Check conditions of launch and now. Otherwise if spoofing is changed
|
||||
// without a restart the setting will show as available when it's not.
|
||||
return PATCH_AVAILABLE && SpoofVideoStreamsPatch.notSpoofingToAndroid();
|
||||
public static void setPreferredLanguage() {
|
||||
if (Settings.FORCE_ORIGINAL_AUDIO.get()
|
||||
&& SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams()) {
|
||||
// If client spoofing does not use authentication and lacks multi-audio streams,
|
||||
// then can use any language code for the request and if that requested language is
|
||||
// not available YT uses the original audio language. Authenticated requests ignore
|
||||
// the language code and always use the account language. Use a language that is
|
||||
// not auto-dubbed by YouTube: https://support.google.com/youtube/answer/15569972
|
||||
// but the language is also supported natively by the Meta Quest device that
|
||||
// Android VR is spoofing.
|
||||
AppLanguage override = AppLanguage.SV;
|
||||
Logger.printDebug(() -> "Setting language override: " + override);
|
||||
SpoofVideoStreamsPatch.setLanguageOverride(override);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,13 +9,13 @@ import app.revanced.extension.youtube.shared.ShortsPlayerState;
|
||||
public class PlayerFlyoutMenuItemsFilter extends Filter {
|
||||
|
||||
public static final class HideAudioFlyoutMenuAvailability implements Setting.Availability {
|
||||
private static final boolean AVAILABLE_ON_LAUNCH = SpoofVideoStreamsPatch.notSpoofingToAndroid();
|
||||
private static final boolean AVAILABLE_ON_LAUNCH = !SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams();
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
// Check conditions of launch and now. Otherwise if spoofing is changed
|
||||
// without a restart the setting will show as available when it's not.
|
||||
return AVAILABLE_ON_LAUNCH && SpoofVideoStreamsPatch.notSpoofingToAndroid();
|
||||
return AVAILABLE_ON_LAUNCH && !SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
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_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;
|
||||
import static app.revanced.extension.shared.spoof.ClientType.VISIONOS;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.shared.spoof.ClientType;
|
||||
import app.revanced.extension.shared.spoof.requests.StreamingDataRequest;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class SpoofVideoStreamsPatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void setClientOrderToUse() {
|
||||
List<ClientType> availableClients = List.of(
|
||||
ANDROID_VR_1_61_48,
|
||||
VISIONOS,
|
||||
IPADOS,
|
||||
// Creator must be next to last, because livestreams fetch successfully but don't playback.
|
||||
ANDROID_CREATOR,
|
||||
// VR 1.43 must be last as spoof streaming data handles it slightly differently.
|
||||
ANDROID_VR_1_43_32
|
||||
);
|
||||
|
||||
StreamingDataRequest.setClientOrderToUse(availableClients,
|
||||
BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get());
|
||||
}
|
||||
}
|
||||
@@ -1,50 +1,120 @@
|
||||
package app.revanced.extension.youtube.settings;
|
||||
|
||||
import static app.revanced.extension.shared.Utils.getResourceIdentifier;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.util.TypedValue;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.view.View;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
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.BaseActivityHook;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.youtube.patches.VersionCheckPatch;
|
||||
import app.revanced.extension.youtube.patches.spoof.SpoofAppVersionPatch;
|
||||
import app.revanced.extension.youtube.settings.preference.ReVancedPreferenceFragment;
|
||||
|
||||
/**
|
||||
* Hooks LicenseActivity.
|
||||
* <p>
|
||||
* This class is responsible for injecting our own fragment by replacing the LicenseActivity.
|
||||
* Hooks LicenseActivity to inject a custom ReVancedPreferenceFragment with a toolbar and search functionality.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class LicenseActivityHook extends Activity {
|
||||
@SuppressWarnings("deprecation")
|
||||
public class LicenseActivityHook extends BaseActivityHook {
|
||||
|
||||
private static int currentThemeValueOrdinal = -1; // Must initially be a non-valid enum ordinal value.
|
||||
|
||||
private static ViewGroup.LayoutParams toolbarLayoutParams;
|
||||
|
||||
/**
|
||||
* Controller for managing search view components in the toolbar.
|
||||
*/
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
public static SearchViewController searchViewController;
|
||||
|
||||
public static void setToolbarLayoutParams(Toolbar toolbar) {
|
||||
if (toolbarLayoutParams != null) {
|
||||
toolbar.setLayoutParams(toolbarLayoutParams);
|
||||
/**
|
||||
* Injection point
|
||||
* <p>
|
||||
* Creates an instance of LicenseActivityHook for use in static initialization.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static LicenseActivityHook createInstance() {
|
||||
return new LicenseActivityHook();
|
||||
}
|
||||
|
||||
/**
|
||||
* Customizes the activity theme based on dark/light mode.
|
||||
*/
|
||||
@Override
|
||||
protected void customizeActivityTheme(Activity activity) {
|
||||
final var theme = Utils.isDarkModeEnabled()
|
||||
? "Theme.YouTube.Settings.Dark"
|
||||
: "Theme.YouTube.Settings";
|
||||
activity.setTheme(Utils.getResourceIdentifier(theme, "style"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resource ID for the YouTube settings layout.
|
||||
*/
|
||||
@Override
|
||||
protected int getContentViewResourceId() {
|
||||
return Utils.getResourceIdentifier("revanced_settings_with_toolbar", "layout");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the toolbar background color based on dark/light mode.
|
||||
*/
|
||||
@Override
|
||||
protected int getToolbarBackgroundColor() {
|
||||
final String colorName = Utils.isDarkModeEnabled()
|
||||
? "yt_black3"
|
||||
: "yt_white1";
|
||||
return Utils.getColorFromString(colorName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the navigation icon drawable for the toolbar.
|
||||
*/
|
||||
@Override
|
||||
protected Drawable getNavigationIcon() {
|
||||
return ReVancedPreferenceFragment.getBackButtonDrawable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the click listener for the navigation icon.
|
||||
*/
|
||||
@Override
|
||||
protected View.OnClickListener getNavigationClickListener(Activity activity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds search view components to the toolbar for ReVancedPreferenceFragment.
|
||||
*
|
||||
* @param activity The activity hosting the toolbar.
|
||||
* @param toolbar The configured toolbar.
|
||||
* @param fragment The PreferenceFragment associated with the activity.
|
||||
*/
|
||||
@Override
|
||||
protected void onPostToolbarSetup(Activity activity, Toolbar toolbar, PreferenceFragment fragment) {
|
||||
if (fragment instanceof ReVancedPreferenceFragment) {
|
||||
searchViewController = SearchViewController.addSearchViewComponents(
|
||||
activity, toolbar, (ReVancedPreferenceFragment) fragment);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ReVancedPreferenceFragment for the activity.
|
||||
*/
|
||||
@Override
|
||||
protected PreferenceFragment createPreferenceFragment() {
|
||||
return new ReVancedPreferenceFragment();
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* Overrides the ReVanced settings language.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static Context getAttachBaseContext(Context original) {
|
||||
AppLanguage language = BaseSettings.REVANCED_LANGUAGE.get();
|
||||
if (language == AppLanguage.DEFAULT) {
|
||||
@@ -57,6 +127,7 @@ public class LicenseActivityHook extends Activity {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static boolean useCairoSettingsFragment(boolean original) {
|
||||
// Early targets have layout issues and it's better to always force off.
|
||||
if (!VersionCheckPatch.IS_19_34_OR_GREATER) {
|
||||
@@ -80,87 +151,6 @@ public class LicenseActivityHook extends Activity {
|
||||
/**
|
||||
* Injection point.
|
||||
* <p>
|
||||
* Hooks LicenseActivity#onCreate in order to inject our own fragment.
|
||||
*/
|
||||
public static void initialize(Activity licenseActivity) {
|
||||
try {
|
||||
setActivityTheme(licenseActivity);
|
||||
ReVancedPreferenceFragment.setNavigationBarColor(licenseActivity.getWindow());
|
||||
licenseActivity.setContentView(getResourceIdentifier(
|
||||
"revanced_settings_with_toolbar", "layout"));
|
||||
|
||||
// Sanity check.
|
||||
String dataString = licenseActivity.getIntent().getDataString();
|
||||
if (!"revanced_settings_intent".equals(dataString)) {
|
||||
Logger.printException(() -> "Unknown intent: " + dataString);
|
||||
return;
|
||||
}
|
||||
|
||||
PreferenceFragment fragment = new ReVancedPreferenceFragment();
|
||||
createToolbar(licenseActivity, fragment);
|
||||
|
||||
//noinspection deprecation
|
||||
licenseActivity.getFragmentManager()
|
||||
.beginTransaction()
|
||||
.replace(getResourceIdentifier("revanced_settings_fragments", "id"), fragment)
|
||||
.commit();
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "initialize failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("UseCompatLoadingForDrawables")
|
||||
private static void createToolbar(Activity activity, PreferenceFragment fragment) {
|
||||
// Replace dummy placeholder toolbar.
|
||||
// This is required to fix submenu title alignment issue with Android ASOP 15+
|
||||
ViewGroup toolBarParent = activity.findViewById(
|
||||
getResourceIdentifier("revanced_toolbar_parent", "id"));
|
||||
ViewGroup dummyToolbar = Utils.getChildViewByResourceName(toolBarParent, "revanced_toolbar");
|
||||
toolbarLayoutParams = dummyToolbar.getLayoutParams();
|
||||
toolBarParent.removeView(dummyToolbar);
|
||||
|
||||
Toolbar toolbar = new Toolbar(toolBarParent.getContext());
|
||||
toolbar.setBackgroundColor(getToolbarBackgroundColor());
|
||||
toolbar.setNavigationIcon(ReVancedPreferenceFragment.getBackButtonDrawable());
|
||||
toolbar.setTitle(getResourceIdentifier("revanced_settings_title", "string"));
|
||||
|
||||
final int margin = Utils.dipToPixels(16);
|
||||
toolbar.setTitleMarginStart(margin);
|
||||
toolbar.setTitleMarginEnd(margin);
|
||||
TextView toolbarTextView = Utils.getChildView(toolbar, false,
|
||||
view -> view instanceof TextView);
|
||||
if (toolbarTextView != null) {
|
||||
toolbarTextView.setTextColor(Utils.getAppForegroundColor());
|
||||
toolbarTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
|
||||
}
|
||||
setToolbarLayoutParams(toolbar);
|
||||
|
||||
// Add Search bar only for ReVancedPreferenceFragment.
|
||||
if (fragment instanceof ReVancedPreferenceFragment) {
|
||||
searchViewController = SearchViewController.addSearchViewComponents(activity, toolbar, (ReVancedPreferenceFragment) fragment);
|
||||
}
|
||||
|
||||
toolBarParent.addView(toolbar, 0);
|
||||
}
|
||||
|
||||
public static void setActivityTheme(Activity activity) {
|
||||
final var theme = Utils.isDarkModeEnabled()
|
||||
? "Theme.YouTube.Settings.Dark"
|
||||
: "Theme.YouTube.Settings";
|
||||
activity.setTheme(getResourceIdentifier(theme, "style"));
|
||||
}
|
||||
|
||||
public static int getToolbarBackgroundColor() {
|
||||
final String colorName = Utils.isDarkModeEnabled()
|
||||
? "yt_black3"
|
||||
: "yt_white1";
|
||||
|
||||
return Utils.getColorFromString(colorName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*
|
||||
* Updates dark/light mode since YT settings can force light/dark mode
|
||||
* which can differ from the global device settings.
|
||||
*/
|
||||
@@ -173,6 +163,10 @@ public class LicenseActivityHook extends Activity {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles configuration changes, such as orientation, to update the search view.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static void handleConfigurationChanged(Activity activity, Configuration newConfig) {
|
||||
if (searchViewController != null) {
|
||||
searchViewController.handleOrientationChange(newConfig.orientation);
|
||||
|
||||
@@ -12,7 +12,6 @@ import static app.revanced.extension.youtube.patches.ChangeHeaderPatch.HeaderLog
|
||||
import static app.revanced.extension.youtube.patches.ChangeStartPagePatch.ChangeStartPageTypeAvailability;
|
||||
import static app.revanced.extension.youtube.patches.ChangeStartPagePatch.StartPage;
|
||||
import static app.revanced.extension.youtube.patches.ExitFullscreenPatch.FullscreenMode;
|
||||
import static app.revanced.extension.youtube.patches.ForceOriginalAudioPatch.ForceOriginalAudioAvailability;
|
||||
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;
|
||||
@@ -75,7 +74,7 @@ public class Settings extends BaseSettings {
|
||||
"0.25\n0.5\n0.75\n1.0\n1.25\n1.5\n1.75\n2.0\n2.5\n3.0\n4.0\n5.0\n6.0\n7.0\n8.0", true);
|
||||
|
||||
// Audio
|
||||
public static final BooleanSetting FORCE_ORIGINAL_AUDIO = new BooleanSetting("revanced_force_original_audio", FALSE, new ForceOriginalAudioAvailability());
|
||||
public static final BooleanSetting FORCE_ORIGINAL_AUDIO = new BooleanSetting("revanced_force_original_audio", FALSE, true);
|
||||
|
||||
// Ads
|
||||
public static final BooleanSetting HIDE_CREATOR_STORE_SHELF = new BooleanSetting("revanced_hide_creator_store_shelf", TRUE);
|
||||
@@ -436,6 +435,9 @@ public class Settings extends BaseSettings {
|
||||
public static final StringSetting SB_CATEGORY_HIGHLIGHT = new StringSetting("sb_highlight", MANUAL_SKIP.reVancedKeyValue);
|
||||
public static final StringSetting SB_CATEGORY_HIGHLIGHT_COLOR = new StringSetting("sb_highlight_color", "#FF1684");
|
||||
public static final FloatSetting SB_CATEGORY_HIGHLIGHT_OPACITY = new FloatSetting("sb_highlight_opacity", 0.8f);
|
||||
public static final StringSetting SB_CATEGORY_HOOK = new StringSetting("sb_hook", IGNORE.reVancedKeyValue);
|
||||
public static final StringSetting SB_CATEGORY_HOOK_COLOR = new StringSetting("sb_hook_color", "#395699");
|
||||
public static final FloatSetting SB_CATEGORY_HOOK_OPACITY = new FloatSetting("sb_hook_opacity", 0.8f);
|
||||
public static final StringSetting SB_CATEGORY_INTRO = new StringSetting("sb_intro", MANUAL_SKIP.reVancedKeyValue);
|
||||
public static final StringSetting SB_CATEGORY_INTRO_COLOR = new StringSetting("sb_intro_color", "#00FFFF");
|
||||
public static final FloatSetting SB_CATEGORY_INTRO_OPACITY = new FloatSetting("sb_intro_opacity", 0.8f);
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
package app.revanced.extension.youtube.settings.preference;
|
||||
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
|
||||
import android.content.Context;
|
||||
import android.preference.SwitchPreference;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import app.revanced.extension.youtube.patches.ForceOriginalAudioPatch;
|
||||
|
||||
@SuppressWarnings({"deprecation", "unused"})
|
||||
public class ForceOriginalAudioSwitchPreference extends SwitchPreference {
|
||||
|
||||
{
|
||||
if (!ForceOriginalAudioPatch.PATCH_AVAILABLE) {
|
||||
// Show why force audio is not available.
|
||||
String summary = str("revanced_force_original_audio_not_available");
|
||||
setSummary(summary);
|
||||
setSummaryOn(summary);
|
||||
setSummaryOff(summary);
|
||||
}
|
||||
}
|
||||
|
||||
public ForceOriginalAudioSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
public ForceOriginalAudioSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
public ForceOriginalAudioSwitchPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
public ForceOriginalAudioSwitchPreference(Context context) {
|
||||
super(context);
|
||||
}
|
||||
}
|
||||
@@ -12,8 +12,8 @@ import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
|
||||
public class HideAudioFlyoutMenuPreference extends SwitchPreference {
|
||||
|
||||
{
|
||||
// Audio menu is not available if spoofing to Android client type.
|
||||
if (!SpoofVideoStreamsPatch.notSpoofingToAndroid()) {
|
||||
// Audio menu is not available if spoofing to most client types.
|
||||
if (SpoofVideoStreamsPatch.spoofingToClientWithNoMultiAudioStreams()) {
|
||||
String summary = str("revanced_hide_player_flyout_audio_track_not_available");
|
||||
setSummary(summary);
|
||||
setSummaryOn(summary);
|
||||
|
||||
@@ -3,11 +3,7 @@ package app.revanced.extension.youtube.settings.preference;
|
||||
import static app.revanced.extension.shared.StringRef.str;
|
||||
import static app.revanced.extension.shared.Utils.getResourceIdentifier;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Dialog;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceCategory;
|
||||
@@ -17,11 +13,6 @@ import android.preference.SwitchPreference;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.BackgroundColorSpan;
|
||||
import android.util.TypedValue;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowInsets;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
@@ -40,16 +31,16 @@ import java.util.regex.Pattern;
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.shared.Utils;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.shared.settings.preference.AbstractPreferenceFragment;
|
||||
import app.revanced.extension.shared.settings.preference.NoTitlePreferenceCategory;
|
||||
import app.revanced.extension.shared.settings.preference.ToolbarPreferenceFragment;
|
||||
import app.revanced.extension.youtube.settings.LicenseActivityHook;
|
||||
import app.revanced.extension.youtube.sponsorblock.ui.SponsorBlockPreferenceGroup;
|
||||
|
||||
/**
|
||||
* Preference fragment for ReVanced settings.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
|
||||
@SuppressWarnings({"deprecation", "NewApi"})
|
||||
public class ReVancedPreferenceFragment extends ToolbarPreferenceFragment {
|
||||
|
||||
/**
|
||||
* The main PreferenceScreen used to display the current set of preferences.
|
||||
@@ -70,31 +61,6 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
|
||||
*/
|
||||
private final List<AbstractPreferenceSearchData<?>> allPreferences = new ArrayList<>();
|
||||
|
||||
@SuppressLint("UseCompatLoadingForDrawables")
|
||||
public static Drawable getBackButtonDrawable() {
|
||||
final int backButtonResource = getResourceIdentifier("revanced_settings_toolbar_arrow_left", "drawable");
|
||||
Drawable drawable = Utils.getContext().getResources().getDrawable(backButtonResource);
|
||||
drawable.setTint(Utils.getAppForegroundColor());
|
||||
return drawable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the system navigation bar color for the activity.
|
||||
* Applies the background color obtained from {@link Utils#getAppBackgroundColor()} to the navigation bar.
|
||||
* For Android 10 (API 29) and above, enforces navigation bar contrast to ensure visibility.
|
||||
*/
|
||||
public static void setNavigationBarColor(@Nullable Window window) {
|
||||
if (window == null) {
|
||||
Logger.printDebug(() -> "Cannot set navigation bar color, window is null");
|
||||
return;
|
||||
}
|
||||
|
||||
window.setNavigationBarColor(Utils.getAppBackgroundColor());
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
window.setNavigationBarContrastEnforced(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the preference fragment, copying the original screen to allow full restoration.
|
||||
*/
|
||||
@@ -139,8 +105,28 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets toolbar for all nested preference screens.
|
||||
*/
|
||||
@Override
|
||||
protected void customizeToolbar(Toolbar toolbar) {
|
||||
LicenseActivityHook.setToolbarLayoutParams(toolbar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform actions after toolbar setup.
|
||||
*/
|
||||
@Override
|
||||
protected void onPostToolbarSetup(Toolbar toolbar, Dialog preferenceScreenDialog) {
|
||||
if (LicenseActivityHook.searchViewController != null
|
||||
&& LicenseActivityHook.searchViewController.isSearchActive()) {
|
||||
toolbar.post(() -> LicenseActivityHook.searchViewController.closeSearch());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively collects all preferences from the screen or group.
|
||||
*
|
||||
* @param includeDepth Menu depth to start including preferences.
|
||||
* A value of 0 adds all preferences.
|
||||
*/
|
||||
@@ -222,75 +208,6 @@ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment {
|
||||
preferenceScreen.addPreference(noResultsPreference);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets toolbar for all nested preference screens.
|
||||
*/
|
||||
private void setPreferenceScreenToolbar(PreferenceScreen parentScreen) {
|
||||
for (int i = 0, count = parentScreen.getPreferenceCount(); i < count; i++) {
|
||||
Preference childPreference = parentScreen.getPreference(i);
|
||||
if (childPreference instanceof PreferenceScreen) {
|
||||
// Recursively set sub preferences.
|
||||
setPreferenceScreenToolbar((PreferenceScreen) childPreference);
|
||||
|
||||
childPreference.setOnPreferenceClickListener(
|
||||
childScreen -> {
|
||||
Dialog preferenceScreenDialog = ((PreferenceScreen) childScreen).getDialog();
|
||||
ViewGroup rootView = (ViewGroup) preferenceScreenDialog
|
||||
.findViewById(android.R.id.content)
|
||||
.getParent();
|
||||
|
||||
// Fix the system navigation bar color for submenus.
|
||||
setNavigationBarColor(preferenceScreenDialog.getWindow());
|
||||
|
||||
// Fix edge-to-edge screen with Android 15 and YT 19.45+
|
||||
// https://developer.android.com/develop/ui/views/layout/edge-to-edge#system-bars-insets
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
rootView.setOnApplyWindowInsetsListener((v, insets) -> {
|
||||
Insets statusInsets = insets.getInsets(WindowInsets.Type.statusBars());
|
||||
Insets navInsets = insets.getInsets(WindowInsets.Type.navigationBars());
|
||||
Insets cutoutInsets = insets.getInsets(WindowInsets.Type.displayCutout());
|
||||
|
||||
// Apply padding for display cutout in landscape.
|
||||
int leftPadding = cutoutInsets.left;
|
||||
int rightPadding = cutoutInsets.right;
|
||||
int topPadding = statusInsets.top;
|
||||
int bottomPadding = navInsets.bottom;
|
||||
|
||||
v.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
|
||||
return insets;
|
||||
});
|
||||
}
|
||||
|
||||
Toolbar toolbar = new Toolbar(childScreen.getContext());
|
||||
toolbar.setTitle(childScreen.getTitle());
|
||||
toolbar.setNavigationIcon(getBackButtonDrawable());
|
||||
toolbar.setNavigationOnClickListener(view -> preferenceScreenDialog.dismiss());
|
||||
|
||||
final int margin = Utils.dipToPixels(16);
|
||||
toolbar.setTitleMargin(margin, 0, margin, 0);
|
||||
|
||||
TextView toolbarTextView = Utils.getChildView(toolbar,
|
||||
true, TextView.class::isInstance);
|
||||
if (toolbarTextView != null) {
|
||||
toolbarTextView.setTextColor(Utils.getAppForegroundColor());
|
||||
toolbarTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
|
||||
}
|
||||
|
||||
LicenseActivityHook.setToolbarLayoutParams(toolbar);
|
||||
|
||||
if (LicenseActivityHook.searchViewController != null
|
||||
&& LicenseActivityHook.searchViewController.isSearchActive()) {
|
||||
toolbar.post(() -> LicenseActivityHook.searchViewController.closeSearch());
|
||||
}
|
||||
|
||||
rootView.addView(toolbar, 0);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
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.SpoofVideoStreamsPatch;
|
||||
|
||||
@SuppressWarnings({"deprecation", "unused"})
|
||||
public class SpoofAudioSelectorListPreference extends SortedListPreference {
|
||||
|
||||
private final boolean available;
|
||||
|
||||
{
|
||||
if (SpoofVideoStreamsPatch.getLanguageOverride() != null) {
|
||||
available = false;
|
||||
super.setEnabled(false);
|
||||
super.setSummary(str("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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,21 +78,25 @@ public class SpoofStreamingDataSideEffectsPreference extends Preference {
|
||||
Logger.printDebug(() -> "Updating spoof stream side effects preference");
|
||||
setEnabled(BaseSettings.SPOOF_VIDEO_STREAMS.get());
|
||||
|
||||
String key = "revanced_spoof_video_streams_about_" +
|
||||
(clientType == ClientType.IOS_UNPLUGGED
|
||||
? "ios_tv"
|
||||
: "android");
|
||||
String title = str(key + "_title");
|
||||
String summary = str(key + "_summary");
|
||||
setTitle(str("revanced_spoof_video_streams_about_title"));
|
||||
|
||||
// Android VR supports AV1 but all other clients do not.
|
||||
if (clientType != ClientType.ANDROID_VR_AUTH && clientType != ClientType.ANDROID_VR_NO_AUTH) {
|
||||
summary += '\n' + str("revanced_spoof_video_streams_about_no_av1");
|
||||
String summary = str(clientType == ClientType.IPADOS
|
||||
? "revanced_spoof_video_streams_about_ipados_summary"
|
||||
// visionOS has same base side effects as Android VR.
|
||||
: "revanced_spoof_video_streams_about_android_summary");
|
||||
|
||||
if (clientType == ClientType.IPADOS) {
|
||||
summary = str("revanced_spoof_video_streams_about_no_av1")
|
||||
+ '\n' + summary;
|
||||
} else if (clientType == ClientType.VISIONOS) {
|
||||
summary = str("revanced_spoof_video_streams_about_experimental")
|
||||
+ '\n' + summary
|
||||
+ '\n' + str("revanced_spoof_video_streams_about_no_av1")
|
||||
+ '\n' + str("revanced_spoof_video_streams_about_kids_videos");
|
||||
} else {
|
||||
summary += '\n' + str("revanced_spoof_video_streams_about_kids_videos");
|
||||
}
|
||||
|
||||
summary += '\n' + str("revanced_spoof_video_streams_about_kids_videos");
|
||||
|
||||
setTitle(title);
|
||||
setSummary(summary);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import android.graphics.drawable.shapes.RoundRectShape;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Range;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
@@ -167,6 +168,11 @@ public class SegmentPlaybackController {
|
||||
*/
|
||||
private static WeakReference<Dialog> toastDialogRef = new WeakReference<>(null);
|
||||
|
||||
/**
|
||||
* Visibility of the ad progress UI component.
|
||||
*/
|
||||
private static volatile int adProgressTextVisibility = -1;
|
||||
|
||||
static {
|
||||
// Dismiss toast if app changes to PiP while undo skip is shown.
|
||||
PlayerType.getOnChange().addObserver((PlayerType type) -> {
|
||||
@@ -336,6 +342,7 @@ public class SegmentPlaybackController {
|
||||
*/
|
||||
static void executeDownloadSegments(String videoId) {
|
||||
Objects.requireNonNull(videoId);
|
||||
Utils.verifyOffMainThread();
|
||||
|
||||
SponsorSegment[] segments = SBRequester.getSegments(videoId);
|
||||
|
||||
@@ -367,6 +374,35 @@ public class SegmentPlaybackController {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static void setAdProgressTextVisibility(int visibility) {
|
||||
if (adProgressTextVisibility != visibility) {
|
||||
adProgressTextVisibility = visibility;
|
||||
|
||||
Logger.printDebug(() -> {
|
||||
String visibilityMessage = switch (visibility) {
|
||||
case View.VISIBLE -> "VISIBLE";
|
||||
case View.GONE -> "GONE";
|
||||
case View.INVISIBLE -> "INVISIBLE";
|
||||
default -> "UNKNOWN";
|
||||
};
|
||||
return "AdProgressText visibility changed to: " + visibilityMessage;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When a video ad is playing in a regular video player, segments or the Skip button should be hidden.
|
||||
* @return Whether the Ad Progress TextView is visible in the regular video player.
|
||||
*/
|
||||
public static boolean isAdProgressTextVisible() {
|
||||
return adProgressTextVisibility == View.VISIBLE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* Updates SponsorBlock every 1000ms.
|
||||
@@ -376,7 +412,8 @@ public class SegmentPlaybackController {
|
||||
try {
|
||||
if (!Settings.SB_ENABLED.get()
|
||||
|| PlayerType.getCurrent().isNoneOrHidden() // Shorts playback.
|
||||
|| segments == null || segments.length == 0) {
|
||||
|| segments == null || segments.length == 0
|
||||
|| isAdProgressTextVisible()) {
|
||||
return;
|
||||
}
|
||||
Logger.printDebug(() -> "setVideoTime: " + millis);
|
||||
@@ -671,7 +708,14 @@ public class SegmentPlaybackController {
|
||||
// Check for any smaller embedded segments, and count those as auto-skipped.
|
||||
final boolean showSkipToast = Settings.SB_TOAST_ON_SKIP.get();
|
||||
for (SponsorSegment otherSegment : Objects.requireNonNull(segments)) {
|
||||
if (segmentToSkip.end < otherSegment.start) {
|
||||
if (otherSegment.end <= segmentToSkip.start) {
|
||||
// Other segment does not overlap, and is before this skipped segment.
|
||||
// This situation can only happen if a video is opened and adjusted to
|
||||
// a later time in the video where earlier auto skip segments
|
||||
// have not been encountered yet.
|
||||
continue;
|
||||
}
|
||||
if (segmentToSkip.end <= otherSegment.start) {
|
||||
break; // No other segments can be contained.
|
||||
}
|
||||
|
||||
@@ -922,7 +966,8 @@ public class SegmentPlaybackController {
|
||||
public static String appendTimeWithoutSegments(String totalTime) {
|
||||
try {
|
||||
if (Settings.SB_ENABLED.get() && Settings.SB_VIDEO_LENGTH_WITHOUT_SEGMENTS.get()
|
||||
&& !TextUtils.isEmpty(totalTime) && !TextUtils.isEmpty(timeWithoutSegments)) {
|
||||
&& !TextUtils.isEmpty(totalTime) && !TextUtils.isEmpty(timeWithoutSegments)
|
||||
&& !isAdProgressTextVisible()) {
|
||||
// Force LTR layout, to match the same LTR video time/length layout YouTube uses for all languages
|
||||
return "\u202D" + totalTime + timeWithoutSegments; // u202D = left to right override
|
||||
}
|
||||
@@ -983,7 +1028,7 @@ public class SegmentPlaybackController {
|
||||
@SuppressWarnings("unused")
|
||||
public static void drawSponsorTimeBars(final Canvas canvas, final float posY) {
|
||||
try {
|
||||
if (segments == null) return;
|
||||
if (segments == null || isAdProgressTextVisible()) return;
|
||||
final long videoLength = VideoInformation.getVideoLength();
|
||||
if (videoLength <= 0) return;
|
||||
|
||||
|
||||
@@ -52,6 +52,8 @@ public enum SegmentCategory {
|
||||
sf("revanced_sb_skip_button_preview_beginning"), sf("revanced_sb_skip_button_preview_middle"), sf("revanced_sb_skip_button_preview_end"),
|
||||
sf("revanced_sb_skipped_preview_beginning"), sf("revanced_sb_skipped_preview_middle"), sf("revanced_sb_skipped_preview_end"),
|
||||
SB_CATEGORY_PREVIEW, SB_CATEGORY_PREVIEW_COLOR, SB_CATEGORY_PREVIEW_OPACITY),
|
||||
HOOK("hook", sf("revanced_sb_segments_hook"), sf("revanced_sb_segments_hook_sum"), sf("revanced_sb_skip_button_hook"), sf("revanced_sb_skipped_hook"),
|
||||
SB_CATEGORY_HOOK, SB_CATEGORY_HOOK_COLOR, SB_CATEGORY_HOOK_OPACITY),
|
||||
FILLER("filler", sf("revanced_sb_segments_filler"), sf("revanced_sb_segments_filler_sum"), sf("revanced_sb_skip_button_filler"), sf("revanced_sb_skipped_filler"),
|
||||
SB_CATEGORY_FILLER, SB_CATEGORY_FILLER_COLOR, SB_CATEGORY_FILLER_OPACITY),
|
||||
MUSIC_OFFTOPIC("music_offtopic", sf("revanced_sb_segments_nomusic"), sf("revanced_sb_segments_nomusic_sum"), sf("revanced_sb_skip_button_nomusic"), sf("revanced_sb_skipped_nomusic"),
|
||||
@@ -69,6 +71,7 @@ public enum SegmentCategory {
|
||||
INTRO,
|
||||
OUTRO,
|
||||
PREVIEW,
|
||||
HOOK,
|
||||
FILLER,
|
||||
MUSIC_OFFTOPIC,
|
||||
};
|
||||
@@ -81,6 +84,7 @@ public enum SegmentCategory {
|
||||
INTRO,
|
||||
OUTRO,
|
||||
PREVIEW,
|
||||
HOOK,
|
||||
FILLER,
|
||||
MUSIC_OFFTOPIC,
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.sponsorblock.SegmentPlaybackController;
|
||||
import app.revanced.extension.youtube.videoplayer.PlayerControlButton;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@@ -26,7 +27,7 @@ public class CreateSegmentButton {
|
||||
controlsView,
|
||||
"revanced_sb_create_segment_button",
|
||||
null,
|
||||
CreateSegmentButton::shouldBeShown,
|
||||
CreateSegmentButton::isButtonEnabled,
|
||||
v -> SponsorBlockViewController.toggleNewSegmentLayoutVisibility(),
|
||||
null
|
||||
);
|
||||
@@ -56,7 +57,8 @@ public class CreateSegmentButton {
|
||||
if (instance != null) instance.setVisibility(visible, animated);
|
||||
}
|
||||
|
||||
private static boolean shouldBeShown() {
|
||||
return Settings.SB_ENABLED.get() && Settings.SB_CREATE_NEW_SEGMENT.get();
|
||||
private static boolean isButtonEnabled() {
|
||||
return Settings.SB_ENABLED.get() && Settings.SB_CREATE_NEW_SEGMENT.get()
|
||||
&& !SegmentPlaybackController.isAdProgressTextVisible();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public class VotingButton {
|
||||
controlsView,
|
||||
"revanced_sb_voting_button",
|
||||
null,
|
||||
VotingButton::shouldBeShown,
|
||||
VotingButton::isButtonEnabled,
|
||||
v -> SponsorBlockUtils.onVotingClicked(v.getContext()),
|
||||
null
|
||||
);
|
||||
@@ -58,8 +58,9 @@ public class VotingButton {
|
||||
if (instance != null) instance.setVisibility(visible, animated);
|
||||
}
|
||||
|
||||
private static boolean shouldBeShown() {
|
||||
private static boolean isButtonEnabled() {
|
||||
return Settings.SB_ENABLED.get() && Settings.SB_VOTING_BUTTON.get()
|
||||
&& SegmentPlaybackController.videoHasSegments();
|
||||
&& SegmentPlaybackController.videoHasSegments()
|
||||
&& !SegmentPlaybackController.isAdProgressTextVisible();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
|
||||
org.gradle.parallel = true
|
||||
android.useAndroidX = true
|
||||
kotlin.code.style = official
|
||||
version = 5.35.1-dev.1
|
||||
version = 5.38.0-dev.4
|
||||
|
||||
@@ -264,6 +264,10 @@ public final class app/revanced/patches/instagram/ads/HideAdsPatchKt {
|
||||
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/instagram/hide/explore/HideExploreFeedKt {
|
||||
public static final fun getHideExportFeedPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/instagram/hide/navigation/HideNavigationButtonsKt {
|
||||
public static final fun getHideNavigationButtonsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -368,8 +372,9 @@ public final class app/revanced/patches/music/layout/premium/HideGetPremiumPatch
|
||||
public static final fun getHideGetPremiumPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/layout/upgradebutton/RemoveUpgradeButtonPatchKt {
|
||||
public static final fun getRemoveUpgradeButtonPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public final class app/revanced/patches/music/layout/upgradebutton/HideUpgradeButtonPatchKt {
|
||||
public static final fun getHideUpgradeButton ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static final fun getRemoveUpgradeButton ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/misc/androidauto/BypassCertificateChecksPatchKt {
|
||||
@@ -392,14 +397,35 @@ public final class app/revanced/patches/music/misc/gms/GmsCoreSupportPatchKt {
|
||||
public static final fun getGmsCoreSupportPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/misc/spoof/SpoofClientPatchKt {
|
||||
public static final fun getSpoofClientPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public final class app/revanced/patches/music/misc/settings/PreferenceScreen : app/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen {
|
||||
public static final field INSTANCE Lapp/revanced/patches/music/misc/settings/PreferenceScreen;
|
||||
public fun commit (Lapp/revanced/patches/shared/misc/settings/preference/PreferenceScreenPreference;)V
|
||||
public final fun getADS ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
|
||||
public final fun getGENERAL ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
|
||||
public final fun getMISC ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
|
||||
public final fun getPLAYER ()Lapp/revanced/patches/shared/misc/settings/preference/BasePreferenceScreen$Screen;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/misc/settings/SettingsPatchKt {
|
||||
public static final fun getSettingsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static final fun newIntent (Ljava/lang/String;)Lapp/revanced/patches/shared/misc/settings/preference/IntentPreference$Intent;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/misc/spoof/SpoofVideoStreamsPatchKt {
|
||||
public static final fun getSpoofVideoStreamsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/misc/spoof/UserAgentClientSpoofPatchKt {
|
||||
public static final fun getUserAgentClientSpoofPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/music/playservice/VersionCheckPatchKt {
|
||||
public static final fun getVersionCheckPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
public static final fun is_7_33_or_greater ()Z
|
||||
public static final fun is_8_11_or_greater ()Z
|
||||
public static final fun is_8_15_or_greater ()Z
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/myexpenses/misc/pro/UnlockProPatchKt {
|
||||
public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -983,10 +1009,6 @@ public final class app/revanced/patches/spotify/lite/ondemand/OnDemandPatchKt {
|
||||
public static final fun getOnDemandPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/spotify/misc/UnlockPremiumPatchKt {
|
||||
public static final fun getUnlockPremiumPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/spotify/misc/extension/ExtensionPatchKt {
|
||||
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1239,6 +1261,10 @@ public final class app/revanced/patches/twitter/misc/links/SanitizeSharingLinksP
|
||||
public static final fun getSanitizeSharingLinksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/viber/ads/HideAdsPatchKt {
|
||||
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/vsco/misc/pro/UnlockProPatchKt {
|
||||
public static final fun getUnlockProPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1641,7 +1667,6 @@ public final class app/revanced/patches/youtube/misc/settings/PreferenceScreen :
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/settings/SettingsPatchKt {
|
||||
public static final fun addSettingPreference (Lapp/revanced/patches/shared/misc/settings/preference/BasePreference;)V
|
||||
public static final fun getSettingsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static final fun newIntent (Ljava/lang/String;)Lapp/revanced/patches/shared/misc/settings/preference/IntentPreference$Intent;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
package app.revanced.patches.instagram.hide.explore
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal val exploreResponseJsonParserFingerprint = fingerprint {
|
||||
strings("sectional_items", "ExploreTopicalFeedResponse")
|
||||
custom { method, _ -> method.name == "parseFromJson" }
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package app.revanced.patches.instagram.hide.explore
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
val hideExportFeedPatch = bytecodePatch(
|
||||
name = "Hide explore feed",
|
||||
description = "Hides posts and reels from the explore/search page.",
|
||||
use = false
|
||||
) {
|
||||
compatibleWith("com.instagram.android")
|
||||
|
||||
execute {
|
||||
exploreResponseJsonParserFingerprint.method.apply {
|
||||
val sectionalItemStringIndex = exploreResponseJsonParserFingerprint.stringMatches!!.first().index
|
||||
val sectionalItemStringRegister = getInstruction<OneRegisterInstruction>(sectionalItemStringIndex).registerA
|
||||
|
||||
/**
|
||||
* Replacing the JSON key we want to skip with a random string that is not a valid JSON key.
|
||||
* This way the feeds array will never be populated.
|
||||
* Received JSON keys that are not handled are simply ignored, so there are no side effects.
|
||||
*/
|
||||
replaceInstruction(
|
||||
sectionalItemStringIndex,
|
||||
"const-string v$sectionalItemStringRegister, \"BOGUS\""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ internal val tabCreateButtonsLoopEndFingerprint = fingerprint {
|
||||
Opcode.IPUT_OBJECT,
|
||||
// Injection Jump
|
||||
Opcode.ADD_INT_LIT8, //Increase Index
|
||||
Opcode.GOTO_16 // Jump to loopStart
|
||||
Opcode.GOTO // Jump to loopStart
|
||||
// LoopEnd
|
||||
)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ val hideNavigationButtonsPatch = bytecodePatch(
|
||||
description = "Hides navigation bar buttons, such as the Reels and Create button.",
|
||||
use = false
|
||||
) {
|
||||
compatibleWith("com.instagram.android")
|
||||
compatibleWith("com.instagram.android"("397.1.0.52.81"))
|
||||
|
||||
val hideReels by booleanOption(
|
||||
key = "hideReels",
|
||||
|
||||
@@ -1,19 +1,49 @@
|
||||
package app.revanced.patches.music.ad.video
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.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.settings.preference.SwitchPreference
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/music/patches/HideVideoAdsPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val hideVideoAdsPatch = bytecodePatch(
|
||||
name = "Hide music video ads",
|
||||
description = "Hides ads that appear while listening to or streaming music videos, podcasts, or songs.",
|
||||
description = "Adds an option to hide ads that appear while listening to or streaming music videos, podcasts, or songs.",
|
||||
) {
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.29.52"
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("music", "ad.video.hideVideoAdsPatch")
|
||||
|
||||
PreferenceScreen.ADS.addPreferences(
|
||||
SwitchPreference("revanced_music_hide_video_ads"),
|
||||
)
|
||||
|
||||
navigate(showVideoAdsParentFingerprint.originalMethod)
|
||||
.to(showVideoAdsParentFingerprint.patternMatch!!.startIndex + 1)
|
||||
.stop()
|
||||
.addInstruction(0, "const/4 p1, 0x0")
|
||||
.addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->showVideoAds(Z)Z
|
||||
move-result p1
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package app.revanced.patches.music.audio.exclusiveaudio
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.music.misc.settings.settingsPatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Suppress("unused")
|
||||
@@ -8,7 +10,16 @@ val enableExclusiveAudioPlaybackPatch = bytecodePatch(
|
||||
name = "Enable exclusive audio playback",
|
||||
description = "Enables the option to play audio without video.",
|
||||
) {
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.29.52"
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
allowExclusiveAudioPlaybackFingerprint.method.returnEarly(true)
|
||||
|
||||
@@ -4,23 +4,55 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.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.settings.preference.SwitchPreference
|
||||
import app.revanced.util.findFreeRegister
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/music/patches/PermanentRepeatPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val permanentRepeatPatch = bytecodePatch(
|
||||
name = "Permanent repeat",
|
||||
description = "Permanently remember your repeating preference even if the playlist ends or another track is played.",
|
||||
use = false,
|
||||
description = "Adds an option to always repeat even if the playlist ends or another track is played."
|
||||
) {
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.29.52"
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("music", "interaction.permanentrepeat.permanentRepeatPatch")
|
||||
|
||||
PreferenceScreen.PLAYER.addPreferences(
|
||||
SwitchPreference("revanced_music_play_permanent_repeat"),
|
||||
)
|
||||
|
||||
val startIndex = repeatTrackFingerprint.patternMatch!!.endIndex
|
||||
val repeatIndex = startIndex + 1
|
||||
|
||||
repeatTrackFingerprint.method.apply {
|
||||
// Start index is at a branch, but the same
|
||||
// register is clobbered in both branch paths.
|
||||
val freeRegister = findFreeRegister(startIndex + 1)
|
||||
|
||||
addInstructionsWithLabels(
|
||||
startIndex,
|
||||
"goto :repeat",
|
||||
"""
|
||||
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->permanentRepeat()Z
|
||||
move-result v$freeRegister
|
||||
if-nez v$freeRegister, :repeat
|
||||
""",
|
||||
ExternalLabel("repeat", instructions[repeatIndex]),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,11 @@ val permanentShufflePatch = bytecodePatch(
|
||||
description = "Permanently remember your shuffle preference " +
|
||||
"even if the playlist ends or another track is played."
|
||||
) {
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.29.52"
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
disableShuffleFingerprint.method.addInstruction(0, "return-void")
|
||||
|
||||
@@ -1,30 +1,60 @@
|
||||
package app.revanced.patches.music.layout.compactheader
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.music.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.music.misc.settings.settingsPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.util.addInstructionsAtControlFlowLabel
|
||||
import app.revanced.util.findFreeRegister
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/music/patches/HideCategoryBarPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val hideCategoryBar = bytecodePatch(
|
||||
name = "Hide category bar",
|
||||
description = "Hides the category bar at the top of the homepage.",
|
||||
use = false,
|
||||
description = "Adds an option to hide the category bar at the top of the homepage."
|
||||
) {
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.29.52"
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
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)
|
||||
|
||||
addInstructions(
|
||||
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
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,19 +1,44 @@
|
||||
package app.revanced.patches.music.layout.premium
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.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.settings.preference.SwitchPreference
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/music/patches/HideGetPremiumPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val hideGetPremiumPatch = bytecodePatch(
|
||||
name = "Hide 'Get Music Premium' label",
|
||||
description = "Hides the \"Get Music Premium\" label from the account menu and settings.",
|
||||
name = "Hide 'Get Music Premium'",
|
||||
description = "Adds an option to hide the \"Get Music Premium\" label in the settings and account menu.",
|
||||
) {
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.29.52"
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("music", "layout.premium.hideGetPremiumPatch")
|
||||
|
||||
PreferenceScreen.ADS.addPreferences(
|
||||
SwitchPreference("revanced_music_hide_get_premium_label"),
|
||||
)
|
||||
|
||||
hideGetPremiumFingerprint.method.apply {
|
||||
val insertIndex = hideGetPremiumFingerprint.patternMatch!!.endIndex
|
||||
|
||||
@@ -33,12 +58,17 @@ val hideGetPremiumPatch = bytecodePatch(
|
||||
)
|
||||
}
|
||||
|
||||
membershipSettingsFingerprint.method.addInstructions(
|
||||
membershipSettingsFingerprint.method.addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x0
|
||||
return-object v0
|
||||
""",
|
||||
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->hideGetPremiumLabel()Z
|
||||
move-result v0
|
||||
if-eqz v0, :show
|
||||
const/4 v0, 0x0
|
||||
return-object v0
|
||||
:show
|
||||
nop
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,20 +7,47 @@ import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.extensions.newLabel
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.smali.toInstructions
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.music.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.music.misc.settings.settingsPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.util.getReference
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction22t
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/music/patches/HideUpgradeButtonPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val removeUpgradeButtonPatch = bytecodePatch(
|
||||
name = "Remove upgrade button",
|
||||
description = "Removes the upgrade tab from the pivot bar.",
|
||||
val hideUpgradeButton = bytecodePatch(
|
||||
name = "Hide upgrade button",
|
||||
description = "Hides the upgrade tab from the pivot bar.",
|
||||
) {
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.29.52"
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("music", "layout.upgradebutton.hideUpgradeButtonPatch")
|
||||
|
||||
// TODO: Add an extension patch to allow this to be enabled/disabled in app.
|
||||
if (false) {
|
||||
PreferenceScreen.ADS.addPreferences(
|
||||
SwitchPreference("revanced_music_hide_upgrade_button")
|
||||
)
|
||||
}
|
||||
|
||||
pivotBarConstructorFingerprint.method.apply {
|
||||
val pivotBarElementFieldReference =
|
||||
getInstruction(pivotBarConstructorFingerprint.patternMatch!!.endIndex - 1)
|
||||
@@ -73,3 +100,9 @@ val removeUpgradeButtonPatch = bytecodePatch(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Patch was renamed", ReplaceWith("hideUpgradeButton"))
|
||||
@Suppress("unused")
|
||||
val removeUpgradeButton = bytecodePatch{
|
||||
dependsOn(hideUpgradeButton)
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package app.revanced.patches.music.misc.androidauto
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.music.misc.settings.settingsPatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Suppress("unused")
|
||||
@@ -8,7 +10,16 @@ val bypassCertificateChecksPatch = bytecodePatch(
|
||||
name = "Bypass certificate checks",
|
||||
description = "Bypasses certificate checks which prevent YouTube Music from working on Android Auto.",
|
||||
) {
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.29.52"
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
checkCertificateFingerprint.method.returnEarly(true)
|
||||
|
||||
@@ -1,14 +1,25 @@
|
||||
package app.revanced.patches.music.misc.backgroundplayback
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.music.misc.settings.settingsPatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
val backgroundPlaybackPatch = bytecodePatch(
|
||||
name = "Remove background playback restrictions",
|
||||
description = "Removes restrictions on background playback, including playing kids videos in the background.",
|
||||
) {
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.29.52"
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
kidsBackgroundPlaybackPolicyControllerFingerprint.method.addInstruction(
|
||||
@@ -16,12 +27,6 @@ val backgroundPlaybackPatch = bytecodePatch(
|
||||
"return-void",
|
||||
)
|
||||
|
||||
backgroundPlaybackDisableFingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
""",
|
||||
)
|
||||
backgroundPlaybackDisableFingerprint.method.returnEarly(true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
package app.revanced.patches.music.misc.gms
|
||||
|
||||
import app.revanced.patcher.patch.Option
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.music.misc.gms.Constants.MUSIC_PACKAGE_NAME
|
||||
import app.revanced.patches.music.misc.gms.Constants.REVANCED_MUSIC_PACKAGE_NAME
|
||||
import app.revanced.patches.music.misc.spoof.spoofClientPatch
|
||||
import app.revanced.patches.music.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.music.misc.settings.settingsPatch
|
||||
import app.revanced.patches.music.misc.spoof.spoofVideoStreamsPatch
|
||||
import app.revanced.patches.shared.castContextFetchFingerprint
|
||||
import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.IntentPreference
|
||||
import app.revanced.patches.shared.primeMethodFingerprint
|
||||
|
||||
@Suppress("unused")
|
||||
@@ -21,7 +26,7 @@ val gmsCoreSupportPatch = gmsCoreSupportPatch(
|
||||
extensionPatch = sharedExtensionPatch,
|
||||
gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch,
|
||||
) {
|
||||
dependsOn(spoofClientPatch)
|
||||
dependsOn(spoofVideoStreamsPatch)
|
||||
|
||||
compatibleWith(MUSIC_PACKAGE_NAME)
|
||||
}
|
||||
@@ -33,4 +38,23 @@ private fun gmsCoreSupportResourcePatch(
|
||||
toPackageName = REVANCED_MUSIC_PACKAGE_NAME,
|
||||
gmsCoreVendorGroupIdOption = gmsCoreVendorGroupIdOption,
|
||||
spoofedPackageSignature = "afb0fed5eeaebdd86f56a97742f4b6b33ef59875",
|
||||
)
|
||||
executeBlock = {
|
||||
addResources("shared", "misc.gms.gmsCoreSupportResourcePatch")
|
||||
|
||||
val gmsCoreVendorGroupId by gmsCoreVendorGroupIdOption
|
||||
|
||||
PreferenceScreen.MISC.addPreferences(
|
||||
IntentPreference(
|
||||
"microg_settings",
|
||||
intent = IntentPreference.Intent("", "org.microg.gms.ui.SettingsActivity") {
|
||||
"$gmsCoreVendorGroupId.android.gms"
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
) {
|
||||
dependsOn(
|
||||
addResourcesPatch,
|
||||
settingsPatch
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package app.revanced.patches.music.misc.settings
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal val googleApiActivityFingerprint = fingerprint {
|
||||
returns("V")
|
||||
parameters("Landroid/os/Bundle;")
|
||||
custom { method, classDef ->
|
||||
classDef.endsWith("GoogleApiActivity;") && method.name == "onCreate"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package app.revanced.patches.music.misc.settings
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patches.all.misc.packagename.setOrGetFallbackPackageName
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.*
|
||||
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.patches.shared.misc.settings.settingsPatch
|
||||
import app.revanced.util.*
|
||||
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||
|
||||
private const val BASE_ACTIVITY_HOOK_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/shared/settings/BaseActivityHook;"
|
||||
private const val GOOGLE_API_ACTIVITY_HOOK_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/music/settings/GoogleApiActivityHook;"
|
||||
|
||||
private val preferences = mutableSetOf<BasePreference>()
|
||||
|
||||
|
||||
private val settingsResourcePatch = resourcePatch {
|
||||
dependsOn(
|
||||
resourceMappingPatch,
|
||||
settingsPatch(
|
||||
IntentPreference(
|
||||
titleKey = "revanced_settings_title",
|
||||
summaryKey = null,
|
||||
intent = newIntent("revanced_settings_intent"),
|
||||
) to "settings_headers",
|
||||
preferences
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
// TODO: Remove this when search will be abstract.
|
||||
copyResources(
|
||||
"settings",
|
||||
ResourceGroup(
|
||||
"layout",
|
||||
"revanced_music_settings_with_toolbar.xml"
|
||||
)
|
||||
)
|
||||
|
||||
val targetResource = "values/styles.xml"
|
||||
inputStreamFromBundledResource(
|
||||
"settings/music",
|
||||
targetResource,
|
||||
)!!.let { inputStream ->
|
||||
"resources".copyXmlNode(
|
||||
document(inputStream),
|
||||
document("res/$targetResource"),
|
||||
).close()
|
||||
}
|
||||
|
||||
// Remove horizontal divider from the settings Preferences.
|
||||
val styleFile = get("res/values/styles.xml")
|
||||
styleFile.writeText(
|
||||
styleFile.readText()
|
||||
.replace(
|
||||
"allowDividerAbove\">true",
|
||||
"allowDividerAbove\">false"
|
||||
).replace(
|
||||
"allowDividerBelow\">true",
|
||||
"allowDividerBelow\">false"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val settingsPatch = bytecodePatch(
|
||||
description = "Adds settings for ReVanced to YouTube Music.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsResourcePatch,
|
||||
addResourcesPatch,
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("music", "misc.settings.settingsPatch")
|
||||
addResources("shared", "misc.debugging.enableDebuggingPatch")
|
||||
|
||||
// Should make a separate debugging patch, but for now include it with all installations.
|
||||
PreferenceScreen.MISC.addPreferences(
|
||||
PreferenceScreenPreference(
|
||||
key = "revanced_debug_screen",
|
||||
sorting = Sorting.UNSORTED,
|
||||
preferences = setOf(
|
||||
SwitchPreference("revanced_debug"),
|
||||
NonInteractivePreference(
|
||||
"revanced_debug_export_logs_to_clipboard",
|
||||
tag = "app.revanced.extension.shared.settings.preference.ExportLogToClipboardPreference",
|
||||
selectable = true
|
||||
),
|
||||
NonInteractivePreference(
|
||||
"revanced_debug_logs_clear_buffer",
|
||||
tag = "app.revanced.extension.shared.settings.preference.ClearLogBufferPreference",
|
||||
selectable = true
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
// Add an "About" preference to the top.
|
||||
preferences += NonInteractivePreference(
|
||||
key = "revanced_settings_music_screen_0_about",
|
||||
summaryKey = null,
|
||||
tag = "app.revanced.extension.shared.settings.preference.ReVancedAboutPreference",
|
||||
selectable = true,
|
||||
)
|
||||
|
||||
// Modify GoogleApiActivity and remove all existing layout code.
|
||||
// Must modify an existing activity and cannot add a new activity to the manifest,
|
||||
// as that fails for root installations.
|
||||
|
||||
googleApiActivityFingerprint.method.addInstructions(
|
||||
1,
|
||||
"""
|
||||
invoke-static { }, $GOOGLE_API_ACTIVITY_HOOK_CLASS_DESCRIPTOR->createInstance()Lapp/revanced/extension/music/settings/GoogleApiActivityHook;
|
||||
move-result-object v0
|
||||
invoke-static { v0, p0 }, $BASE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->initialize(Lapp/revanced/extension/shared/settings/BaseActivityHook;Landroid/app/Activity;)V
|
||||
return-void
|
||||
"""
|
||||
)
|
||||
|
||||
// Remove other methods as they will break as the onCreate method is modified above.
|
||||
googleApiActivityFingerprint.classDef.apply {
|
||||
methods.removeIf { it.name != "onCreate" && !MethodUtil.isConstructor(it) }
|
||||
}
|
||||
}
|
||||
|
||||
finalize {
|
||||
PreferenceScreen.close()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an intent to open ReVanced settings.
|
||||
*/
|
||||
fun newIntent(settingsName: String) = IntentPreference.Intent(
|
||||
data = settingsName,
|
||||
targetClass = "com.google.android.gms.common.api.GoogleApiActivity"
|
||||
) {
|
||||
// The package name change has to be reflected in the intent.
|
||||
setOrGetFallbackPackageName("com.google.android.apps.youtube.music")
|
||||
}
|
||||
|
||||
object PreferenceScreen : BasePreferenceScreen() {
|
||||
val ADS = Screen(
|
||||
"revanced_settings_music_screen_1_ads",
|
||||
summaryKey = null
|
||||
)
|
||||
val GENERAL = Screen(
|
||||
"revanced_settings_music_screen_2_general",
|
||||
summaryKey = null
|
||||
)
|
||||
val PLAYER = Screen(
|
||||
"revanced_settings_music_screen_3_player",
|
||||
summaryKey = null
|
||||
)
|
||||
val MISC = Screen(
|
||||
"revanced_settings_music_screen_4_misc",
|
||||
summaryKey = null
|
||||
)
|
||||
|
||||
override fun commit(screen: PreferenceScreenPreference) {
|
||||
preferences += screen
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package app.revanced.patches.music.misc.spoof
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val playerRequestConstructorFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
strings("player")
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches using the class found in [playerRequestConstructorFingerprint].
|
||||
*/
|
||||
internal val createPlayerRequestBodyFingerprint = fingerprint {
|
||||
parameters("L")
|
||||
returns("V")
|
||||
opcodes(
|
||||
Opcode.CHECK_CAST,
|
||||
Opcode.IGET,
|
||||
Opcode.AND_INT_LIT16,
|
||||
)
|
||||
strings("ms")
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get a reference to other clientInfo fields.
|
||||
*/
|
||||
internal val setClientInfoFieldsFingerprint = fingerprint {
|
||||
returns("L")
|
||||
strings("Google Inc.")
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get a reference to the clientInfo and clientInfo.clientVersion field.
|
||||
*/
|
||||
internal val setClientInfoClientVersionFingerprint = fingerprint {
|
||||
strings("10.29")
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
package app.revanced.patches.music.misc.spoof
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.util.getReference
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/music/spoof/SpoofClientPatch;"
|
||||
|
||||
// TODO: Replace this patch with spoofVideoStreamsPatch once possible.
|
||||
val spoofClientPatch = bytecodePatch(
|
||||
name = "Spoof client",
|
||||
description = "Spoofs the client to fix playback.",
|
||||
) {
|
||||
compatibleWith("com.google.android.apps.youtube.music")
|
||||
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
// TODO: Add settingsPatch
|
||||
userAgentClientSpoofPatch,
|
||||
)
|
||||
|
||||
execute {
|
||||
val playerRequestClass = playerRequestConstructorFingerprint.classDef
|
||||
|
||||
val createPlayerRequestBodyMatch = createPlayerRequestBodyFingerprint.match(playerRequestClass)
|
||||
|
||||
val clientInfoContainerClass = createPlayerRequestBodyMatch.method
|
||||
.getInstruction(createPlayerRequestBodyMatch.patternMatch!!.startIndex)
|
||||
.getReference<TypeReference>()!!.type
|
||||
|
||||
val clientInfoField = setClientInfoClientVersionFingerprint.method.instructions.first {
|
||||
it.opcode == Opcode.IPUT_OBJECT && it.getReference<FieldReference>()!!.definingClass == clientInfoContainerClass
|
||||
}.getReference<FieldReference>()!!
|
||||
|
||||
val setClientInfoFieldInstructions = setClientInfoFieldsFingerprint.method.instructions.filter {
|
||||
(it.opcode == Opcode.IPUT_OBJECT || it.opcode == Opcode.IPUT) &&
|
||||
it.getReference<FieldReference>()!!.definingClass == clientInfoField.type
|
||||
}.map { it.getReference<FieldReference>()!! }
|
||||
|
||||
// Offsets are known for the fields in the clientInfo object.
|
||||
val clientIdField = setClientInfoFieldInstructions[0]
|
||||
val clientModelField = setClientInfoFieldInstructions[5]
|
||||
val osVersionField = setClientInfoFieldInstructions[7]
|
||||
val clientVersionField = setClientInfoClientVersionFingerprint.method
|
||||
.getInstruction(setClientInfoClientVersionFingerprint.stringMatches!!.first().index + 1)
|
||||
.getReference<FieldReference>()
|
||||
|
||||
// Helper method to spoof the client info.
|
||||
val spoofClientInfoMethod = ImmutableMethod(
|
||||
playerRequestClass.type,
|
||||
"spoofClientInfo",
|
||||
listOf(ImmutableMethodParameter(clientInfoContainerClass, null, null)),
|
||||
"V",
|
||||
AccessFlags.PRIVATE.value or AccessFlags.STATIC.value,
|
||||
null,
|
||||
null,
|
||||
MutableMethodImplementation(3),
|
||||
).toMutable().also(playerRequestClass.methods::add).apply {
|
||||
addInstructions(
|
||||
"""
|
||||
iget-object v0, p0, $clientInfoField
|
||||
|
||||
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->getClientId()I
|
||||
move-result v1
|
||||
iput v1, v0, $clientIdField
|
||||
|
||||
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->getClientModel()Ljava/lang/String;
|
||||
move-result-object v1
|
||||
iput-object v1, v0, $clientModelField
|
||||
|
||||
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->getClientVersion()Ljava/lang/String;
|
||||
move-result-object v1
|
||||
iput-object v1, v0, $clientVersionField
|
||||
|
||||
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->getOsVersion()Ljava/lang/String;
|
||||
move-result-object v1
|
||||
iput-object v1, v0, $osVersionField
|
||||
|
||||
return-void
|
||||
""",
|
||||
)
|
||||
}
|
||||
|
||||
createPlayerRequestBodyMatch.method.apply {
|
||||
val checkCastIndex = createPlayerRequestBodyMatch.patternMatch!!.startIndex
|
||||
val clientInfoContainerRegister = getInstruction<OneRegisterInstruction>(checkCastIndex).registerA
|
||||
|
||||
addInstruction(checkCastIndex + 1, "invoke-static {v$clientInfoContainerRegister}, $spoofClientInfoMethod")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package app.revanced.patches.music.misc.spoof
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.music.misc.gms.musicActivityOnCreateFingerprint
|
||||
import app.revanced.patches.music.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.music.misc.settings.settingsPatch
|
||||
import app.revanced.patches.music.playservice.is_7_33_or_greater
|
||||
import app.revanced.patches.music.playservice.is_8_11_or_greater
|
||||
import app.revanced.patches.music.playservice.is_8_15_or_greater
|
||||
import app.revanced.patches.music.playservice.versionCheckPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.ListPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.shared.misc.spoof.spoofVideoStreamsPatch
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/music/patches/spoof/SpoofVideoStreamsPatch;"
|
||||
|
||||
val spoofVideoStreamsPatch = spoofVideoStreamsPatch(
|
||||
fixMediaFetchHotConfigChanges = { true },
|
||||
fixMediaFetchHotConfigAlternativeChanges = { is_8_11_or_greater && !is_8_15_or_greater },
|
||||
fixParsePlaybackResponseFeatureFlag = { is_7_33_or_greater },
|
||||
block = {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
versionCheckPatch,
|
||||
userAgentClientSpoofPatch
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
"com.google.android.apps.youtube.music"(
|
||||
"7.29.52"
|
||||
)
|
||||
)
|
||||
},
|
||||
executeBlock = {
|
||||
addResources("shared", "misc.spoof.spoofVideoStreamsPatch")
|
||||
|
||||
PreferenceScreen.MISC.addPreferences(
|
||||
PreferenceScreenPreference(
|
||||
key = "revanced_spoof_video_streams_screen",
|
||||
sorting = PreferenceScreenPreference.Sorting.UNSORTED,
|
||||
preferences = setOf(
|
||||
SwitchPreference("revanced_spoof_video_streams"),
|
||||
ListPreference("revanced_spoof_video_streams_client_type"),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
musicActivityOnCreateFingerprint.method.addInstruction(
|
||||
0,
|
||||
"invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->setClientOrderToUse()V"
|
||||
)
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,28 @@
|
||||
@file:Suppress("ktlint:standard:property-naming")
|
||||
|
||||
package app.revanced.patches.music.playservice
|
||||
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.util.findPlayStoreServicesVersion
|
||||
|
||||
var is_7_33_or_greater = false
|
||||
private set
|
||||
var is_8_11_or_greater = false
|
||||
private set
|
||||
var is_8_15_or_greater = false
|
||||
private set
|
||||
|
||||
val versionCheckPatch = resourcePatch(
|
||||
description = "Uses the Play Store service version to find the major/minor version of the YouTube Music target app.",
|
||||
) {
|
||||
execute {
|
||||
// The app version is missing from the decompiled manifest,
|
||||
// so instead use the Google Play services version and compare against specific releases.
|
||||
val playStoreServicesVersion = findPlayStoreServicesVersion()
|
||||
|
||||
// All bug fix releases always seem to use the same play store version as the minor version.
|
||||
is_7_33_or_greater = 245199000 <= playStoreServicesVersion
|
||||
is_8_11_or_greater = 251199000 <= playStoreServicesVersion
|
||||
is_8_15_or_greater = 251530000 <= playStoreServicesVersion
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
package app.revanced.patches.shared.misc.spoof
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
internal val buildInitPlaybackRequestFingerprint = fingerprint {
|
||||
returns("Lorg/chromium/net/UrlRequest\$Builder;")
|
||||
@@ -35,8 +38,15 @@ internal val buildPlayerRequestURIFingerprint = fingerprint {
|
||||
|
||||
internal val buildRequestFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returns("Lorg/chromium/net/UrlRequest;")
|
||||
returns("Lorg/chromium/net/UrlRequest") // UrlRequest; or UrlRequest$Builder;
|
||||
custom { methodDef, _ ->
|
||||
if (methodDef.indexOfFirstInstruction {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.name == "newUrlRequestBuilder"
|
||||
} < 0) {
|
||||
return@custom false
|
||||
}
|
||||
|
||||
// Different targets have slightly different parameters
|
||||
|
||||
// Earlier targets have parameters:
|
||||
@@ -58,12 +68,22 @@ internal val buildRequestFingerprint = fingerprint {
|
||||
// Lorg/chromium/net/UrlRequest\$Callback;
|
||||
// L
|
||||
|
||||
// 20.16+ uses a refactored and extracted method:
|
||||
// L
|
||||
// Ljava/util/Map;
|
||||
// [B
|
||||
// L
|
||||
// Lorg/chromium/net/UrlRequest$Callback;
|
||||
// L
|
||||
|
||||
val parameterTypes = methodDef.parameterTypes
|
||||
(parameterTypes.size == 7 || parameterTypes.size == 8) &&
|
||||
parameterTypes[1] == "Ljava/util/Map;" // URL headers.
|
||||
val parameterTypesSize = parameterTypes.size
|
||||
(parameterTypesSize == 6 || parameterTypesSize == 7 || parameterTypesSize == 8) &&
|
||||
parameterTypes[1] == "Ljava/util/Map;" // URL headers.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal val protobufClassParseByteBufferFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PROTECTED, AccessFlags.STATIC)
|
||||
returns("L")
|
||||
@@ -148,7 +168,8 @@ internal val mediaFetchHotConfigFingerprint = fingerprint {
|
||||
literal { MEDIA_FETCH_HOT_CONFIG_FEATURE_FLAG }
|
||||
}
|
||||
|
||||
// 20.10+
|
||||
// YT 20.10+, YT Music 8.11 - 8.14.
|
||||
// Flag is missing in YT Music 8.15+, and it is not known if a replacement flag/feature exists.
|
||||
internal const val MEDIA_FETCH_HOT_CONFIG_ALTERNATIVE_FEATURE_FLAG = 45683169L
|
||||
|
||||
internal val mediaFetchHotConfigAlternativeFingerprint = fingerprint {
|
||||
@@ -162,7 +183,6 @@ internal val mediaFetchHotConfigAlternativeFingerprint = fingerprint {
|
||||
internal const val PLAYBACK_START_CHECK_ENDPOINT_USED_FEATURE_FLAG = 45665455L
|
||||
|
||||
internal val playbackStartDescriptorFeatureFlagFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
parameters()
|
||||
returns("Z")
|
||||
literal { PLAYBACK_START_CHECK_ENDPOINT_USED_FEATURE_FLAG }
|
||||
|
||||
@@ -9,6 +9,7 @@ import app.revanced.patcher.patch.BytecodePatchBuilder
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.util.findFreeRegister
|
||||
import app.revanced.util.findInstructionIndicesReversedOrThrow
|
||||
@@ -45,6 +46,8 @@ fun spoofVideoStreamsPatch(
|
||||
dependsOn(addResourcesPatch)
|
||||
|
||||
execute {
|
||||
addResources("shared", "misc.fix.playback.spoofVideoStreamsPatch")
|
||||
|
||||
// region Enable extension helper method used by other patches
|
||||
|
||||
patchIncludedExtensionMethodFingerprint.method.returnEarly(true)
|
||||
@@ -53,9 +56,8 @@ fun spoofVideoStreamsPatch(
|
||||
|
||||
// region Block /initplayback requests to fall back to /get_watch requests.
|
||||
|
||||
val moveUriStringIndex = buildInitPlaybackRequestFingerprint.patternMatch!!.startIndex
|
||||
|
||||
buildInitPlaybackRequestFingerprint.method.apply {
|
||||
val moveUriStringIndex = buildInitPlaybackRequestFingerprint.patternMatch!!.startIndex
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(moveUriStringIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
@@ -63,7 +65,7 @@ fun spoofVideoStreamsPatch(
|
||||
"""
|
||||
invoke-static { v$targetRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v$targetRegister
|
||||
""",
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
@@ -71,9 +73,8 @@ fun spoofVideoStreamsPatch(
|
||||
|
||||
// region Block /get_watch requests to fall back to /player requests.
|
||||
|
||||
val invokeToStringIndex = buildPlayerRequestURIFingerprint.patternMatch!!.startIndex
|
||||
|
||||
buildPlayerRequestURIFingerprint.method.apply {
|
||||
val invokeToStringIndex = buildPlayerRequestURIFingerprint.patternMatch!!.startIndex
|
||||
val uriRegister = getInstruction<FiveRegisterInstruction>(invokeToStringIndex).registerC
|
||||
|
||||
addInstructions(
|
||||
@@ -81,7 +82,7 @@ fun spoofVideoStreamsPatch(
|
||||
"""
|
||||
invoke-static { v$uriRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockGetWatchRequest(Landroid/net/Uri;)Landroid/net/Uri;
|
||||
move-result-object v$uriRegister
|
||||
""",
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
@@ -178,9 +179,9 @@ fun spoofVideoStreamsPatch(
|
||||
|
||||
:disabled
|
||||
return-void
|
||||
""",
|
||||
"""
|
||||
)
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -199,17 +200,17 @@ fun spoofVideoStreamsPatch(
|
||||
addInstructions(
|
||||
targetIndex,
|
||||
"""
|
||||
# Field a: Stream uri.
|
||||
# Field c: Http method.
|
||||
# Field d: Post data.
|
||||
move-object v0, p0 # method has over 15 registers and must copy p0 to a lower register.
|
||||
iget-object v1, v0, $definingClass->a:Landroid/net/Uri;
|
||||
iget v2, v0, $definingClass->c:I
|
||||
iget-object v3, v0, $definingClass->d:[B
|
||||
invoke-static { v1, v2, v3 }, $EXTENSION_CLASS_DESCRIPTOR->removeVideoPlaybackPostBody(Landroid/net/Uri;I[B)[B
|
||||
move-result-object v1
|
||||
iput-object v1, v0, $definingClass->d:[B
|
||||
""",
|
||||
# Field a: Stream uri.
|
||||
# Field c: Http method.
|
||||
# Field d: Post data.
|
||||
move-object v0, p0 # method has over 15 registers and must copy p0 to a lower register.
|
||||
iget-object v1, v0, $definingClass->a:Landroid/net/Uri;
|
||||
iget v2, v0, $definingClass->c:I
|
||||
iget-object v3, v0, $definingClass->d:[B
|
||||
invoke-static { v1, v2, v3 }, $EXTENSION_CLASS_DESCRIPTOR->removeVideoPlaybackPostBody(Landroid/net/Uri;I[B)[B
|
||||
move-result-object v1
|
||||
iput-object v1, v0, $definingClass->d:[B
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -187,11 +187,16 @@ val customThemePatch = resourcePatch(
|
||||
}
|
||||
|
||||
// Login screen gradient.
|
||||
document("res/drawable/start_screen_gradient.xml").use { document ->
|
||||
val gradientNode = document.getElementsByTagName("gradient").item(0) as Element
|
||||
try {
|
||||
document("res/drawable/start_screen_gradient.xml").use { document ->
|
||||
val gradientNode = document.getElementsByTagName("gradient").item(0) as Element
|
||||
|
||||
gradientNode.setAttribute("android:startColor", "@color/gray_7")
|
||||
gradientNode.setAttribute("android:endColor", "@color/gray_7")
|
||||
gradientNode.setAttribute("android:startColor", "@color/gray_7")
|
||||
gradientNode.setAttribute("android:endColor", "@color/gray_7")
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
// Fails for 9.0.66+
|
||||
// printWarn("Failed to locate start_screen_gradient.xml, skipping modification.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
package app.revanced.patches.spotify.misc
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
|
||||
|
||||
context(BytecodePatchContext)
|
||||
internal val accountAttributeFingerprint get() = fingerprint {
|
||||
custom { _, classDef -> classDef.type == "Lcom/spotify/remoteconfig/internal/AccountAttribute;" }
|
||||
}
|
||||
|
||||
context(BytecodePatchContext)
|
||||
internal val productStateProtoGetMapFingerprint get() = fingerprint {
|
||||
returns("Ljava/util/Map;")
|
||||
custom { _, classDef -> classDef.type == "Lcom/spotify/remoteconfig/internal/ProductStateProto;" }
|
||||
}
|
||||
|
||||
internal val buildQueryParametersFingerprint = fingerprint {
|
||||
strings("trackRows", "device_type:tablet")
|
||||
}
|
||||
|
||||
internal val contextMenuViewModelClassFingerprint = fingerprint {
|
||||
strings("ContextMenuViewModel(header=")
|
||||
}
|
||||
|
||||
/**
|
||||
* Used in versions older than "9.0.60.128".
|
||||
*/
|
||||
internal val oldContextMenuViewModelAddItemFingerprint = fingerprint {
|
||||
parameters("L")
|
||||
returns("V")
|
||||
custom { method, _ ->
|
||||
method.indexOfFirstInstruction {
|
||||
getReference<MethodReference>()?.name == "add"
|
||||
} >= 0
|
||||
}
|
||||
}
|
||||
|
||||
internal val contextMenuViewModelConstructorFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to find the interface name of a context menu item.
|
||||
*/
|
||||
internal val removeItemFromPlaylistContextMenuItemClassFingerprint = fingerprint {
|
||||
strings("spotify:playlist:", "REMOVE_TRACK")
|
||||
}
|
||||
|
||||
internal const val CONTEXT_MENU_ITEM_CLASS_DESCRIPTOR_PLACEHOLDER = "Lapp/revanced/ContextMenuItemPlaceholder;"
|
||||
internal val extensionFilterContextMenuItemsFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returns("Ljava/util/List;")
|
||||
parameters("Ljava/util/List;")
|
||||
custom { method, classDef ->
|
||||
method.name == "filterContextMenuItems" && classDef.type == EXTENSION_CLASS_DESCRIPTOR
|
||||
}
|
||||
}
|
||||
|
||||
internal val getViewModelFingerprint = fingerprint {
|
||||
custom { method, _ -> method.name == "getViewModel" }
|
||||
}
|
||||
|
||||
internal val contextFromJsonFingerprint = fingerprint {
|
||||
opcodes(
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_STATIC
|
||||
)
|
||||
custom { method, classDef ->
|
||||
method.name == "fromJson" &&
|
||||
classDef.type.endsWith("voiceassistants/playermodels/ContextJsonAdapter;")
|
||||
}
|
||||
}
|
||||
|
||||
internal val readPlayerOptionOverridesFingerprint = fingerprint {
|
||||
custom { method, classDef ->
|
||||
method.name == "readPlayerOptionOverrides" &&
|
||||
classDef.type.endsWith("voiceassistants/playermodels/PreparePlayOptionsJsonAdapter;")
|
||||
}
|
||||
}
|
||||
|
||||
internal val protobufListsFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
custom { method, _ -> method.name == "emptyProtobufList" }
|
||||
}
|
||||
|
||||
internal val abstractProtobufListEnsureIsMutableFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
parameters()
|
||||
returns("V")
|
||||
custom { method, _ ->
|
||||
method.indexOfFirstInstruction {
|
||||
getReference<TypeReference>()?.type == "Ljava/lang/UnsupportedOperationException;"
|
||||
} >= 0
|
||||
}
|
||||
}
|
||||
|
||||
internal fun structureGetSectionsFingerprint(className: String) = fingerprint {
|
||||
custom { method, classDef ->
|
||||
classDef.type.endsWith(className) && method.indexOfFirstInstruction {
|
||||
opcode == Opcode.IGET_OBJECT && getReference<FieldReference>()?.name == "sections_"
|
||||
} >= 0
|
||||
}
|
||||
}
|
||||
|
||||
internal val homeSectionFingerprint = fingerprint {
|
||||
custom { _, classDef -> classDef.type.endsWith("homeapi/proto/Section;") }
|
||||
}
|
||||
|
||||
internal val homeStructureGetSectionsFingerprint =
|
||||
structureGetSectionsFingerprint("homeapi/proto/HomeStructure;")
|
||||
|
||||
internal val browseSectionFingerprint = fingerprint {
|
||||
custom { _, classDef-> classDef.type.endsWith("browsita/v1/resolved/Section;") }
|
||||
}
|
||||
|
||||
internal val browseStructureGetSectionsFingerprint =
|
||||
structureGetSectionsFingerprint("browsita/v1/resolved/BrowseStructure;")
|
||||
|
||||
internal fun reactivexFunctionApplyWithClassInitFingerprint(className: String) = fingerprint {
|
||||
returns("Ljava/lang/Object;")
|
||||
parameters("Ljava/lang/Object;")
|
||||
custom { method, _ ->
|
||||
method.name == "apply" && method.indexOfFirstInstruction {
|
||||
opcode == Opcode.NEW_INSTANCE && getReference<TypeReference>()?.type?.endsWith(className) == true
|
||||
} >= 0
|
||||
}
|
||||
}
|
||||
|
||||
internal const val PENDRAGON_JSON_FETCH_MESSAGE_REQUEST_CLASS_NAME = "FetchMessageRequest;"
|
||||
internal val pendragonJsonFetchMessageRequestFingerprint =
|
||||
reactivexFunctionApplyWithClassInitFingerprint(PENDRAGON_JSON_FETCH_MESSAGE_REQUEST_CLASS_NAME)
|
||||
|
||||
internal const val PENDRAGON_PROTO_FETCH_MESSAGE_LIST_REQUEST_CLASS_NAME = "FetchMessageListRequest;"
|
||||
internal val pendragonProtoFetchMessageListRequestFingerprint =
|
||||
reactivexFunctionApplyWithClassInitFingerprint(PENDRAGON_PROTO_FETCH_MESSAGE_LIST_REQUEST_CLASS_NAME)
|
||||
@@ -12,9 +12,9 @@ import app.revanced.util.returnEarly
|
||||
|
||||
internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/spotify/misc/fix/SpoofClientPatch;"
|
||||
|
||||
@Deprecated("Patch no longer functions")
|
||||
@Suppress("unused")
|
||||
val spoofClientPatch = bytecodePatch(
|
||||
name = "Spoof client",
|
||||
description = "Spoofs the client to fix various functions of the app.",
|
||||
) {
|
||||
val requestListenerPort by intOption(
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
package app.revanced.patches.spotify.navbar
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.spotify.misc.unlockPremiumPatch
|
||||
|
||||
@Deprecated("Superseded by unlockPremiumPatch", ReplaceWith("unlockPremiumPatch"))
|
||||
@Deprecated("Obsolete and will be deleted soon")
|
||||
@Suppress("unused")
|
||||
val premiumNavbarTabPatch = bytecodePatch(
|
||||
description = "Hides the premium tab from the navigation bar.",
|
||||
) {
|
||||
dependsOn(unlockPremiumPatch)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.viber.ads
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal val adsFreeFingerprint = fingerprint {
|
||||
returns("I")
|
||||
parameters()
|
||||
custom { method, classDef ->
|
||||
classDef.type.contains("com/viber/voip/feature/viberplus") &&
|
||||
classDef.superclass?.contains("com/viber/voip/core/feature") == true && // Must extend com.viber.voip.core.feature.?
|
||||
classDef.methods.count() == 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package app.revanced.patches.viber.ads
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Suppress("unused")
|
||||
val hideAdsPatch = bytecodePatch(
|
||||
name = "Hide Ads",
|
||||
description = "Hides ad banners between chats.",
|
||||
) {
|
||||
compatibleWith("com.viber.voip"("25.9.2.0"))
|
||||
|
||||
execute {
|
||||
// Return 1 (true) indicating ads should be disabled.
|
||||
adsFreeFingerprint.method.returnEarly(1)
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,7 @@ val downloadsPatch = bytecodePatch(
|
||||
|
||||
// Main activity is used to launch downloader intent.
|
||||
mainActivityOnCreateFingerprint.method.addInstruction(
|
||||
1,
|
||||
0,
|
||||
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->activityCreated(Landroid/app/Activity;)V"
|
||||
)
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.revanced.patches.youtube.layout.seekbar
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patches.youtube.shared.YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
|
||||
import app.revanced.util.containsLiteralInstruction
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
@@ -103,7 +104,7 @@ internal val launchScreenLayoutTypeFingerprint = fingerprint {
|
||||
custom { method, _ ->
|
||||
val firstParameter = method.parameterTypes.firstOrNull()
|
||||
// 19.25 - 19.45
|
||||
(firstParameter == "Lcom/google/android/apps/youtube/app/watchwhile/MainActivity;"
|
||||
(firstParameter == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
|
||||
|| firstParameter == "Landroid/app/Activity;") // 19.46+
|
||||
&& method.containsLiteralInstruction(launchScreenLayoutTypeLotteFeatureFlag)
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ val shortsAutoplayPatch = bytecodePatch(
|
||||
|
||||
// Main activity is used to check if app is in pip mode.
|
||||
mainActivityOnCreateFingerprint.method.addInstruction(
|
||||
1,
|
||||
0,
|
||||
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->setMainActivity(Landroid/app/Activity;)V",
|
||||
)
|
||||
|
||||
|
||||
@@ -90,8 +90,8 @@ val openShortsInRegularPlayerPatch = bytecodePatch(
|
||||
|
||||
// Activity is used as the context to launch an Intent.
|
||||
mainActivityOnCreateFingerprint.method.addInstruction(
|
||||
1,
|
||||
"invoke-static/range { p0 .. p0 }, ${EXTENSION_CLASS_DESCRIPTOR}->" +
|
||||
0,
|
||||
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->" +
|
||||
"setMainActivity(Landroid/app/Activity;)V",
|
||||
)
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package app.revanced.patches.youtube.layout.sponsorblock
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionReversed
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
@@ -56,3 +59,20 @@ internal val rectangleFieldInvalidatorFingerprint = fingerprint {
|
||||
reference?.parameterTypes?.size == 1 && reference.name == "invalidate" // the reference is the invalidate(..) method
|
||||
}
|
||||
}
|
||||
|
||||
internal val adProgressTextViewVisibilityFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
parameters("Z")
|
||||
custom { method, _ ->
|
||||
indexOfAdProgressTextViewVisibilityInstruction(method) >= 0
|
||||
}
|
||||
}
|
||||
|
||||
internal fun indexOfAdProgressTextViewVisibilityInstruction(method: Method) =
|
||||
method.indexOfFirstInstructionReversed {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.definingClass ==
|
||||
"Lcom/google/android/libraries/youtube/ads/player/ui/AdProgressTextView;"
|
||||
&& reference.name =="setVisibility"
|
||||
}
|
||||
|
||||
@@ -252,5 +252,16 @@ val sponsorBlockPatch = bytecodePatch(
|
||||
}
|
||||
} ?: throw PatchException("Could not find the method which contains the replaceMeWith* strings")
|
||||
}
|
||||
|
||||
adProgressTextViewVisibilityFingerprint.method.apply {
|
||||
val index = indexOfAdProgressTextViewVisibilityInstruction(this)
|
||||
val register = getInstruction<FiveRegisterInstruction>(index).registerD
|
||||
|
||||
addInstructionsAtControlFlowLabel(
|
||||
index,
|
||||
"invoke-static { v$register }, $EXTENSION_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setAdProgressTextVisibility(I)V"
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.revanced.patches.youtube.layout.theme
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patches.youtube.shared.YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
|
||||
import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
@@ -37,6 +38,6 @@ internal val splashScreenStyleFingerprint = fingerprint {
|
||||
parameters("Landroid/os/Bundle;")
|
||||
literal { SPLASH_SCREEN_STYLE_FEATURE_FLAG }
|
||||
custom { method, classDef ->
|
||||
method.name == "onCreate" && classDef.endsWith("/MainActivity;")
|
||||
method.name == "onCreate" && classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,9 +40,7 @@ val announcementsPatch = bytecodePatch(
|
||||
)
|
||||
|
||||
mainActivityOnCreateFingerprint.method.addInstruction(
|
||||
// Insert index must be greater than the insert index used by GmsCoreSupport,
|
||||
// as both patch the same method and GmsCore check should be first.
|
||||
1,
|
||||
0,
|
||||
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->showAnnouncement(Landroid/app/Activity;)V",
|
||||
)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/EnableDebuggingPatch;"
|
||||
|
||||
// TODO: Refactor this into a shared patch that can be used by both YT and YT Music.
|
||||
// Almost all of the feature flag hooks are the same between both apps.
|
||||
val enableDebuggingPatch = bytecodePatch(
|
||||
name = "Enable debugging",
|
||||
description = "Adds options for debugging and exporting ReVanced logs to the clipboard.",
|
||||
@@ -45,6 +47,7 @@ val enableDebuggingPatch = bytecodePatch(
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("shared", "misc.debugging.enableDebuggingPatch")
|
||||
addResources("youtube", "misc.debugging.enableDebuggingPatch")
|
||||
|
||||
PreferenceScreen.MISC.addPreferences(
|
||||
@@ -58,13 +61,13 @@ val enableDebuggingPatch = bytecodePatch(
|
||||
SwitchPreference("revanced_debug_toast_on_error"),
|
||||
NonInteractivePreference(
|
||||
"revanced_debug_export_logs_to_clipboard",
|
||||
tag = "app.revanced.extension.youtube.settings.preference.ExportLogToClipboardPreference",
|
||||
selectable = true,
|
||||
tag = "app.revanced.extension.shared.settings.preference.ExportLogToClipboardPreference",
|
||||
selectable = true
|
||||
),
|
||||
NonInteractivePreference(
|
||||
"revanced_debug_logs_clear_buffer",
|
||||
tag = "app.revanced.extension.youtube.settings.preference.ClearLogBufferPreference",
|
||||
selectable = true,
|
||||
tag = "app.revanced.extension.shared.settings.preference.ClearLogBufferPreference",
|
||||
selectable = true
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -34,12 +34,7 @@ val checkWatchHistoryDomainNameResolutionPatch = bytecodePatch(
|
||||
addResources("youtube", "misc.dns.checkWatchHistoryDomainNameResolutionPatch")
|
||||
|
||||
mainActivityOnCreateFingerprint.method.addInstruction(
|
||||
// FIXME: Insert index must be greater than the insert index used by GmsCoreSupport,
|
||||
// as both patch the same method and GmsCoreSupport check should be first,
|
||||
// but the patch does not depend on GmsCoreSupport, so it should not be possible to enforce this
|
||||
// unless a third patch is added that this patch and GmsCoreSupport depend on to manage
|
||||
// the order of the patches.
|
||||
1,
|
||||
0,
|
||||
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->checkDnsResolver(Landroid/app/Activity;)V",
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,4 +3,5 @@ package app.revanced.patches.youtube.misc.extension
|
||||
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.extension.hooks.*
|
||||
|
||||
val sharedExtensionPatch = sharedExtensionPatch("youtube", applicationInitHook)
|
||||
val sharedExtensionPatch = sharedExtensionPatch("youtube",
|
||||
applicationInitHook, applicationInitOnCrateHook)
|
||||
|
||||
@@ -1,11 +1,23 @@
|
||||
package app.revanced.patches.youtube.misc.extension.hooks
|
||||
|
||||
import app.revanced.patches.shared.misc.extension.extensionHook
|
||||
import app.revanced.patches.youtube.shared.YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
|
||||
|
||||
/**
|
||||
* Hooks the context when the app is launched as a regular application (and is not an embedded video playback).
|
||||
*/
|
||||
// Extension context is the Activity itself.
|
||||
internal val applicationInitHook = extensionHook {
|
||||
// Does _not_ resolve to the YouTube main activity.
|
||||
// Required as some hooked code runs before the main activity is launched.
|
||||
strings("Application creation", "Application.onCreate")
|
||||
}
|
||||
|
||||
internal val applicationInitOnCrateHook = extensionHook {
|
||||
returns("V")
|
||||
parameters("Landroid/os/Bundle;")
|
||||
custom { method, classDef ->
|
||||
method.name == "onCreate" && classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ private fun gmsCoreSupportResourcePatch(
|
||||
gmsCoreVendorGroupIdOption = gmsCoreVendorGroupIdOption,
|
||||
spoofedPackageSignature = "24bb24c05e47e0aefa68a58a766179d9b613a600",
|
||||
executeBlock = {
|
||||
addResources("youtube", "misc.gms.gmsCoreSupportResourcePatch")
|
||||
addResources("shared", "misc.gms.gmsCoreSupportResourcePatch")
|
||||
|
||||
val gmsCoreVendorGroupId by gmsCoreVendorGroupIdOption
|
||||
|
||||
@@ -62,10 +62,14 @@ private fun gmsCoreSupportResourcePatch(
|
||||
"microg_settings",
|
||||
intent = IntentPreference.Intent("", "org.microg.gms.ui.SettingsActivity") {
|
||||
"$gmsCoreVendorGroupId.android.gms"
|
||||
},
|
||||
),
|
||||
}
|
||||
)
|
||||
)
|
||||
},
|
||||
}
|
||||
) {
|
||||
dependsOn(settingsPatch, addResourcesPatch, accountCredentialsInvalidTextPatch)
|
||||
dependsOn(
|
||||
addResourcesPatch,
|
||||
settingsPatch,
|
||||
accountCredentialsInvalidTextPatch
|
||||
)
|
||||
}
|
||||
|
||||
@@ -127,8 +127,7 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig
|
||||
// Litho filtering based on navigation tab before the tab is updated.
|
||||
mainActivityOnBackPressedFingerprint.method.addInstruction(
|
||||
0,
|
||||
"invoke-static { p0 }, " +
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->onBackPressed(Landroid/app/Activity;)V",
|
||||
"invoke-static { p0 }, $EXTENSION_CLASS_DESCRIPTOR->onBackPressed(Landroid/app/Activity;)V",
|
||||
)
|
||||
|
||||
// Hook the search bar.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
package app.revanced.patches.youtube.misc.playservice
|
||||
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.util.findElementByAttributeValueOrThrow
|
||||
import app.revanced.util.findPlayStoreServicesVersion
|
||||
|
||||
@Deprecated("19.34.42 is the lowest supported version")
|
||||
var is_19_03_or_greater = false
|
||||
@@ -77,12 +77,7 @@ val versionCheckPatch = resourcePatch(
|
||||
execute {
|
||||
// The app version is missing from the decompiled manifest,
|
||||
// so instead use the Google Play services version and compare against specific releases.
|
||||
val playStoreServicesVersion = document("res/values/integers.xml").use { document ->
|
||||
document.documentElement.childNodes.findElementByAttributeValueOrThrow(
|
||||
"name",
|
||||
"google_play_services_version",
|
||||
).textContent.toInt()
|
||||
}
|
||||
val playStoreServicesVersion = findPlayStoreServicesVersion()
|
||||
|
||||
// All bug fix releases always seem to use the same play store version as the minor version.
|
||||
is_19_03_or_greater = 240402000 <= playStoreServicesVersion
|
||||
|
||||
@@ -29,7 +29,9 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
private const val BASE_ACTIVITY_HOOK_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/shared/settings/BaseActivityHook;"
|
||||
private const val LICENSE_ACTIVITY_HOOK_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/settings/LicenseActivityHook;"
|
||||
|
||||
internal var appearanceStringId = -1L
|
||||
@@ -37,10 +39,6 @@ internal var appearanceStringId = -1L
|
||||
|
||||
private val preferences = mutableSetOf<BasePreference>()
|
||||
|
||||
fun addSettingPreference(screen: BasePreference) {
|
||||
preferences += screen
|
||||
}
|
||||
|
||||
private val settingsResourcePatch = resourcePatch {
|
||||
dependsOn(
|
||||
resourceMappingPatch,
|
||||
@@ -225,7 +223,9 @@ val settingsPatch = bytecodePatch(
|
||||
licenseActivityOnCreateFingerprint.method.addInstructions(
|
||||
1,
|
||||
"""
|
||||
invoke-static { p0 }, $EXTENSION_CLASS_DESCRIPTOR->initialize(Landroid/app/Activity;)V
|
||||
invoke-static {}, $LICENSE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->createInstance()Lapp/revanced/extension/youtube/settings/LicenseActivityHook;
|
||||
move-result-object v0
|
||||
invoke-static { v0, p0 }, $BASE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->initialize(Lapp/revanced/extension/shared/settings/BaseActivityHook;Landroid/app/Activity;)V
|
||||
return-void
|
||||
"""
|
||||
)
|
||||
@@ -249,7 +249,7 @@ val settingsPatch = bytecodePatch(
|
||||
).toMutable().apply {
|
||||
addInstructions(
|
||||
"""
|
||||
invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->getAttachBaseContext(Landroid/content/Context;)Landroid/content/Context;
|
||||
invoke-static { p1 }, $LICENSE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->getAttachBaseContext(Landroid/content/Context;)Landroid/content/Context;
|
||||
move-result-object p1
|
||||
invoke-super { p0, p1 }, $superclass->attachBaseContext(Landroid/content/Context;)V
|
||||
return-void
|
||||
@@ -294,7 +294,7 @@ val settingsPatch = bytecodePatch(
|
||||
addInstructions(
|
||||
"""
|
||||
invoke-super { p0, p1 }, Landroid/app/Activity;->onConfigurationChanged(Landroid/content/res/Configuration;)V
|
||||
invoke-static { p0, p1 }, $EXTENSION_CLASS_DESCRIPTOR->handleConfigurationChanged(Landroid/app/Activity;Landroid/content/res/Configuration;)V
|
||||
invoke-static { p0, p1 }, $LICENSE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->handleConfigurationChanged(Landroid/app/Activity;Landroid/content/res/Configuration;)V
|
||||
return-void
|
||||
"""
|
||||
)
|
||||
@@ -309,15 +309,15 @@ val settingsPatch = bytecodePatch(
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
addInstructionsAtControlFlowLabel(
|
||||
index,
|
||||
"invoke-static { v$register }, ${EXTENSION_CLASS_DESCRIPTOR}->updateLightDarkModeStatus(Ljava/lang/Enum;)V",
|
||||
"invoke-static { v$register }, ${LICENSE_ACTIVITY_HOOK_CLASS_DESCRIPTOR}->updateLightDarkModeStatus(Ljava/lang/Enum;)V",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Add setting to force cairo settings fragment on/off.
|
||||
// Add setting to force Cairo settings fragment on/off.
|
||||
cairoFragmentConfigFingerprint.method.insertLiteralOverride(
|
||||
CAIRO_CONFIG_LITERAL_VALUE,
|
||||
"$EXTENSION_CLASS_DESCRIPTOR->useCairoSettingsFragment(Z)Z"
|
||||
"$LICENSE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->useCairoSettingsFragment(Z)Z"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package app.revanced.patches.youtube.misc.spoof
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.shared.misc.settings.preference.ListPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference
|
||||
@@ -13,56 +14,69 @@ import app.revanced.patches.youtube.misc.playservice.is_20_14_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
|
||||
|
||||
val spoofVideoStreamsPatch = spoofVideoStreamsPatch({
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
"20.12.46",
|
||||
"20.13.41",
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/spoof/SpoofVideoStreamsPatch;"
|
||||
|
||||
val spoofVideoStreamsPatch = spoofVideoStreamsPatch(
|
||||
block = {
|
||||
compatibleWith(
|
||||
"com.google.android.youtube"(
|
||||
"19.34.42",
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
"20.12.46",
|
||||
"20.13.41",
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
dependsOn(
|
||||
userAgentClientSpoofPatch,
|
||||
settingsPatch,
|
||||
versionCheckPatch
|
||||
)
|
||||
}, {
|
||||
is_19_34_or_greater
|
||||
}, {
|
||||
// In 20.14 the flag was merged with 20.03 start playback flag.
|
||||
is_20_10_or_greater && !is_20_14_or_greater
|
||||
}, {
|
||||
is_20_03_or_greater
|
||||
}, {
|
||||
addResources("youtube", "misc.fix.playback.spoofVideoStreamsPatch")
|
||||
dependsOn(
|
||||
userAgentClientSpoofPatch,
|
||||
settingsPatch,
|
||||
versionCheckPatch
|
||||
)
|
||||
},
|
||||
fixMediaFetchHotConfigChanges = {
|
||||
is_19_34_or_greater
|
||||
},
|
||||
fixMediaFetchHotConfigAlternativeChanges = {
|
||||
// In 20.14 the flag was merged with 20.03 start playback flag.
|
||||
is_20_10_or_greater && !is_20_14_or_greater
|
||||
},
|
||||
fixParsePlaybackResponseFeatureFlag = {
|
||||
is_20_03_or_greater
|
||||
},
|
||||
executeBlock = {
|
||||
addResources("youtube", "misc.fix.playback.spoofVideoStreamsPatch")
|
||||
|
||||
PreferenceScreen.MISC.addPreferences(
|
||||
PreferenceScreenPreference(
|
||||
key = "revanced_spoof_video_streams_screen",
|
||||
sorting = PreferenceScreenPreference.Sorting.UNSORTED,
|
||||
preferences = setOf(
|
||||
SwitchPreference("revanced_spoof_video_streams"),
|
||||
ListPreference("revanced_spoof_video_streams_client_type"),
|
||||
NonInteractivePreference(
|
||||
// Requires a key and title but the actual text is chosen at runtime.
|
||||
key = "revanced_spoof_video_streams_about_android",
|
||||
tag = "app.revanced.extension.youtube.settings.preference.SpoofStreamingDataSideEffectsPreference"
|
||||
),
|
||||
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.shared.settings.preference.SortedListPreference"
|
||||
),
|
||||
SwitchPreference("revanced_spoof_video_streams_ios_force_avc"),
|
||||
SwitchPreference("revanced_spoof_streaming_data_stats_for_nerds"),
|
||||
),
|
||||
),
|
||||
)
|
||||
})
|
||||
PreferenceScreen.MISC.addPreferences(
|
||||
PreferenceScreenPreference(
|
||||
key = "revanced_spoof_video_streams_screen",
|
||||
sorting = PreferenceScreenPreference.Sorting.UNSORTED,
|
||||
preferences = setOf(
|
||||
SwitchPreference("revanced_spoof_video_streams"),
|
||||
ListPreference("revanced_spoof_video_streams_client_type"),
|
||||
NonInteractivePreference(
|
||||
// Requires a key and title but the actual text is chosen at runtime.
|
||||
key = "revanced_spoof_video_streams_about_android",
|
||||
tag = "app.revanced.extension.youtube.settings.preference.SpoofStreamingDataSideEffectsPreference"
|
||||
),
|
||||
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"),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
mainActivityOnCreateFingerprint.method.addInstruction(
|
||||
0,
|
||||
"invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->setClientOrderToUse()V"
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -4,6 +4,8 @@ import app.revanced.patcher.fingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal const val YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE = "Lcom/google/android/apps/youtube/app/watchwhile/MainActivity;"
|
||||
|
||||
internal val conversionContextFingerprintToString = fingerprint {
|
||||
parameters()
|
||||
strings(
|
||||
@@ -48,7 +50,7 @@ internal val mainActivityConstructorFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
parameters()
|
||||
custom { _, classDef ->
|
||||
classDef.endsWith("/MainActivity;")
|
||||
classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +59,7 @@ internal val mainActivityOnBackPressedFingerprint = fingerprint {
|
||||
returns("V")
|
||||
parameters()
|
||||
custom { method, classDef ->
|
||||
method.name == "onBackPressed" && classDef.endsWith("/MainActivity;")
|
||||
method.name == "onBackPressed" && classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +67,7 @@ internal val mainActivityOnCreateFingerprint = fingerprint {
|
||||
returns("V")
|
||||
parameters("Landroid/os/Bundle;")
|
||||
custom { method, classDef ->
|
||||
method.name == "onCreate" && classDef.endsWith("/MainActivity;")
|
||||
method.name == "onCreate" && classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package app.revanced.patches.youtube.video.audio
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
@@ -14,6 +15,7 @@ import app.revanced.patches.youtube.misc.playservice.is_20_07_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
|
||||
import app.revanced.util.findMethodFromToString
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.insertLiteralOverride
|
||||
@@ -55,10 +57,12 @@ val forceOriginalAudioPatch = bytecodePatch(
|
||||
addResources("youtube", "video.audio.forceOriginalAudioPatch")
|
||||
|
||||
PreferenceScreen.VIDEO.addPreferences(
|
||||
SwitchPreference(
|
||||
key = "revanced_force_original_audio",
|
||||
tag = "app.revanced.extension.youtube.settings.preference.ForceOriginalAudioSwitchPreference"
|
||||
)
|
||||
SwitchPreference("revanced_force_original_audio")
|
||||
)
|
||||
|
||||
mainActivityOnCreateFingerprint.method.addInstruction(
|
||||
0,
|
||||
"invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->setPreferredLanguage()V"
|
||||
)
|
||||
|
||||
// Disable feature flag that ignores the default track flag
|
||||
|
||||
@@ -178,3 +178,15 @@ internal fun Element.copyAttributesFrom(oldContainer: Element) {
|
||||
setAttribute(attr.name, attr.value)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The play store services version.
|
||||
*/
|
||||
internal fun ResourcePatchContext.findPlayStoreServicesVersion(): Int =
|
||||
document("res/values/integers.xml").use { document ->
|
||||
document.documentElement.childNodes.findElementByAttributeValueOrThrow(
|
||||
"name",
|
||||
"google_play_services_version",
|
||||
).textContent.toInt()
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,10 @@ Second \"item\" text"</string>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
</patch>
|
||||
</app>
|
||||
<app id="youtube">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
@@ -207,8 +211,6 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="misc.dimensions.spoof.spoofDeviceDimensionsPatch">
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
</patch>
|
||||
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
|
||||
</patch>
|
||||
<patch id="misc.gms.accountCredentialsInvalidTextPatch">
|
||||
@@ -242,6 +244,20 @@ Second \"item\" text"</string>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
</patch>
|
||||
</app>
|
||||
<app id="music">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
</patch>
|
||||
<patch id="ad.video.hideVideoAdsPatch">
|
||||
</patch>
|
||||
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
|
||||
</patch>
|
||||
<patch id="layout.compactheader.hideCategoryBar">
|
||||
</patch>
|
||||
<patch id="layout.premium.hideGetPremiumPatch">
|
||||
</patch>
|
||||
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
<patch id="ad.audio.audioAdsPatch">
|
||||
</patch>
|
||||
|
||||
@@ -30,6 +30,10 @@ Second \"item\" text"</string>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
</patch>
|
||||
</app>
|
||||
<app id="youtube">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
@@ -207,8 +211,6 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="misc.dimensions.spoof.spoofDeviceDimensionsPatch">
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
</patch>
|
||||
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
|
||||
</patch>
|
||||
<patch id="misc.gms.accountCredentialsInvalidTextPatch">
|
||||
@@ -242,6 +244,20 @@ Second \"item\" text"</string>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
</patch>
|
||||
</app>
|
||||
<app id="music">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
</patch>
|
||||
<patch id="ad.video.hideVideoAdsPatch">
|
||||
</patch>
|
||||
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
|
||||
</patch>
|
||||
<patch id="layout.compactheader.hideCategoryBar">
|
||||
</patch>
|
||||
<patch id="layout.premium.hideGetPremiumPatch">
|
||||
</patch>
|
||||
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
<patch id="ad.audio.audioAdsPatch">
|
||||
</patch>
|
||||
|
||||
@@ -68,6 +68,8 @@ Second \"item\" text"</string>
|
||||
and changes made here must also be made there. -->
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<string name="microg_settings_title">إعدادات GmsCore</string>
|
||||
<string name="microg_settings_summary">إعدادات لـ GmsCore</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="gms_core_toast_not_installed_message">لم يتم تثبيت MicroG GmsCore. قم بتثبيته.</string>
|
||||
<string name="gms_core_dialog_title">الإجراء مطلوب</string>
|
||||
@@ -84,6 +86,37 @@ Second \"item\" text"</string>
|
||||
انقر فوق زر الاستمرار واسمح بتغييرات التحسين."</string>
|
||||
<string name="gms_core_dialog_continue_text">متابعة</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<string name="revanced_spoof_video_streams_screen_title">Spoof Video Streams</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">تزييف تدفقات الفيديو الخاصة بالعميل لمنع حدوث مشكلات أثناء التشغيل</string>
|
||||
<string name="revanced_spoof_video_streams_screen_title">انتحال بثوث الفيديو</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">انتحال بثوث الفيديو الخاصة بالعميل لمنع مشكلات التشغيل</string>
|
||||
<string name="revanced_spoof_video_streams_title">Spoof Video Streams</string>
|
||||
<string name="revanced_spoof_video_streams_summary_on">"تدفقات الفيديو مزورة
|
||||
|
||||
إذا كنت مستخدمًا لـ YouTube Premium، فقد لا يكون هذا الإعداد مطلوبًا"</string>
|
||||
<string name="revanced_spoof_video_streams_summary_off">"لم يتم انتحال بثوث الفيديو
|
||||
|
||||
قد لا يعمل التشغيل"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">قد يؤدي إيقاف تشغيل هذا الإعداد إلى مشكلات في التشغيل.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">العميل الافتراضي</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">تصحيح الأخطاء</string>
|
||||
<string name="revanced_debug_screen_summary">تمكين أو تعطيل خيارات تصحيح الأخطاء</string>
|
||||
<string name="revanced_debug_title">تسجيل تصحيح الأخطاء</string>
|
||||
<string name="revanced_debug_summary_on">تم تمكين تسجيلات تصحيح الأخطاء</string>
|
||||
<string name="revanced_debug_summary_off">تم تعطيل تسجيلات تصحيح الأخطاء</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_title">تصدير سجلات تصحيح الأخطاء</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_summary">نسخ سجلات تصحيح أخطاء ReVanced إلى الحافظة</string>
|
||||
<string name="revanced_debug_logs_disabled">تم تعطيل تسجيلات تصحيح الأخطاء</string>
|
||||
<string name="revanced_debug_logs_none_found">لم يتم العثور على سجلات</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">تم نسخ السجلات</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">فشل تصدير السجلات: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">مسح سجلات تصحيح الأخطاء</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">يمسح جميع سجلات تصحيح أخطاء ReVanced المخزنة</string>
|
||||
<string name="revanced_debug_logs_clear_toast">تم مسح السجلات</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="youtube">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
@@ -110,11 +143,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_shorts_disable_background_playback_summary_off">تم تمكين تشغيل Shorts بالخلفية</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">تصحيح الأخطاء</string>
|
||||
<string name="revanced_debug_screen_summary">تمكين أو تعطيل خيارات تصحيح الأخطاء</string>
|
||||
<string name="revanced_debug_title">تسجيل تصحيح الأخطاء</string>
|
||||
<string name="revanced_debug_summary_on">تم تمكين تسجيلات تصحيح الأخطاء</string>
|
||||
<string name="revanced_debug_summary_off">تم تعطيل تسجيلات تصحيح الأخطاء</string>
|
||||
<string name="revanced_debug_protobuffer_title">سجل بروتوكول التخزين المؤقت</string>
|
||||
<string name="revanced_debug_protobuffer_summary_on">تتضمن سجلات التصحيح التخزين المؤقت</string>
|
||||
<string name="revanced_debug_protobuffer_summary_off">لا تتضمن سجلات التصحيح التخزين المؤقت</string>
|
||||
@@ -132,15 +160,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_debug_toast_on_error_user_dialog_message">"يؤدي إيقاف تشغيل ملاحظات الأخطاء إلى إخفاء كافة إشعارات أخطاء ReVanced.
|
||||
|
||||
لن يتم إعلامك بأي أخطاء غير متوقعة."</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_title">تصدير سجلات تصحيح الأخطاء</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_summary">نسخ سجلات تصحيح أخطاء ReVanced إلى الحافظة</string>
|
||||
<string name="revanced_debug_logs_disabled">تم تعطيل تسجيلات تصحيح الأخطاء</string>
|
||||
<string name="revanced_debug_logs_none_found">لم يتم العثور على سجلات</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">تم نسخ السجلات</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">فشل تصدير السجلات: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">مسح سجلات تصحيح الأخطاء</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">يمسح جميع سجلات تصحيح أخطاء ReVanced المخزنة</string>
|
||||
<string name="revanced_debug_logs_clear_toast">تم مسح السجلات</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.general.hideLayoutComponentsPatch">
|
||||
<string name="revanced_hide_album_cards_title">إخفاء بطاقات الألبوم</string>
|
||||
@@ -700,9 +719,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_player_flyout_audio_track_summary_on">تم إخفاء قائمة المقطع الصوتي</string>
|
||||
<string name="revanced_hide_player_flyout_audio_track_summary_off">يتم عرض قائمة المقطع الصوتي</string>
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
<string name="revanced_hide_player_flyout_audio_track_not_available">"تم إخفاء قائمة المقطع الصوتي
|
||||
<string name="revanced_hide_player_flyout_audio_track_not_available">"قائمة المسارات الصوتية مخفية
|
||||
|
||||
لعرض قائمة المقطع الصوتي، غيّر 'Spoof Video Streams' إلى iOS TV"</string>
|
||||
قائمة المسارات الصوتية غير متاحة عندما يكون \"تزوير تدفقات الفيديو\" مُمكَّنًا"</string>
|
||||
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
|
||||
<string name="revanced_hide_player_flyout_watch_in_vr_title">إخفاء المشاهدة في VR</string>
|
||||
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">تم إخفاء قائمة المشاهدة في الوضع الافتراضي</string>
|
||||
@@ -1075,10 +1094,12 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_sb_segments_intro_sum">فاصل زمني بدون محتوى فعلي. قد يكون توقفًا مؤقتًا، أو إطارًا ثابتًا، أو رسومًا متحركة متكررة. لا يتضمن انتقالات تحتوي على معلومات</string>
|
||||
<string name="revanced_sb_segments_outro">الخاتمة / تترات النهاية</string>
|
||||
<string name="revanced_sb_segments_outro_sum">تتر النهاية أو عندما تظهر بطاقات نهاية YouTube، نهايات غير منطوقة. ليس للاستنتاجات مع المعلومات</string>
|
||||
<string name="revanced_sb_segments_preview">معاينة/موجز/ربط</string>
|
||||
<string name="revanced_sb_segments_hook">مقدمة / تحيات</string>
|
||||
<string name="revanced_sb_segments_hook_sum">مقاطع دعائية مروية للفيديو القادم، تحيات ووداعات. لا تشمل الأقسام التي تضيف محتوى إضافيًا</string>
|
||||
<string name="revanced_sb_segments_preview">معاينة / ملخص</string>
|
||||
<string name="revanced_sb_segments_preview_sum">مجموعة من المقاطع التي توضح ما هو قادم أو ما حدث في الفيديو أو في مقاطع فيديو أخرى من السلسلة، حيث تتكرر جميع المعلومات في مكان آخر</string>
|
||||
<string name="revanced_sb_segments_filler">خارج الموضوع/النكات</string>
|
||||
<string name="revanced_sb_segments_filler_sum">تم إضافة مشاهد ملتقطة خارج الموضوع أو الفكاهة التي ليست مطلوبة لفهم المحتوى الرئيسي للفيديو. لا تتضمن مقاطع توفر تَعبِير أو تفاصيل الخلفية</string>
|
||||
<string name="revanced_sb_segments_filler">استطراد / نكات</string>
|
||||
<string name="revanced_sb_segments_filler_sum">مشاهد أو نكات جانبية غير ضرورية لفهم المحتوى الرئيسي للفيديو. لا تشمل الأقسام التي توفر سياقًا أو تفاصيل خلفية</string>
|
||||
<string name="revanced_sb_segments_nomusic">الموسيقى: مقطع غير موسيقي</string>
|
||||
<string name="revanced_sb_segments_nomusic_sum">فقط للاستخدام في المقاطع الموسيقية. أقسام المقاطع الموسيقية بدون موسيقى، والتي لم يتم تغطيتها بالفعل من قبل فئة أخرى</string>
|
||||
<string name="revanced_sb_skip_button_compact">تخطي</string>
|
||||
@@ -1091,10 +1112,11 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_sb_skip_button_intro_middle">تخطي الفاصل</string>
|
||||
<string name="revanced_sb_skip_button_intro_end">تخطي الفاصل</string>
|
||||
<string name="revanced_sb_skip_button_outro">تخطي الخاتمة</string>
|
||||
<string name="revanced_sb_skip_button_hook">تخطي المقدمة</string>
|
||||
<string name="revanced_sb_skip_button_preview_beginning">تخطي النظرة العامة</string>
|
||||
<string name="revanced_sb_skip_button_preview_middle">تخطي النظرة العامة</string>
|
||||
<string name="revanced_sb_skip_button_preview_end">تخطي الملخص</string>
|
||||
<string name="revanced_sb_skip_button_filler">تخطي مقطع غير ذي صلة</string>
|
||||
<string name="revanced_sb_skip_button_filler">تخطي الجزء الجانبي</string>
|
||||
<string name="revanced_sb_skip_button_nomusic">تخطي غير الموسيقى</string>
|
||||
<string name="revanced_sb_skip_button_unsubmitted">تخطي المقطع</string>
|
||||
<string name="revanced_sb_skipped_sponsor">تم تخطي الراعي</string>
|
||||
@@ -1105,10 +1127,11 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_sb_skipped_intro_middle">تم تخطي الفاصل</string>
|
||||
<string name="revanced_sb_skipped_intro_end">تم تخطي الفاصل</string>
|
||||
<string name="revanced_sb_skipped_outro">تم تخطي الخاتمة</string>
|
||||
<string name="revanced_sb_skipped_hook">تم تخطي المقدمة</string>
|
||||
<string name="revanced_sb_skipped_preview_beginning">تم تخطي النظرة العامة</string>
|
||||
<string name="revanced_sb_skipped_preview_middle">تم تخطي النظرة العامة</string>
|
||||
<string name="revanced_sb_skipped_preview_end">تم تخطي الملخص</string>
|
||||
<string name="revanced_sb_skipped_filler">تم تخطي مقطع غير ذي صلة</string>
|
||||
<string name="revanced_sb_skipped_filler">تم تخطي الجزء الجانبي</string>
|
||||
<string name="revanced_sb_skipped_nomusic">تم تخطي جزء غير موسيقي</string>
|
||||
<string name="revanced_sb_skipped_unsubmitted">تم تخطي المقطع الغير المرسل</string>
|
||||
<string name="revanced_sb_skipped_multiple_segments">تم تخطي عدة مقاطع</string>
|
||||
@@ -1411,10 +1434,6 @@ Second \"item\" text"</string>
|
||||
يمكن أن يؤدي تفعيل هذا إلى فتح جودة أعلى للفيديو"</string>
|
||||
<string name="revanced_spoof_device_dimensions_user_dialog_message">قد يؤدي تمكين هذا إلى تباطؤ تشغيل الفيديو وتدهور عمر البطارية وآثار جانبية غير معروفة.</string>
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<string name="microg_settings_title">إعدادات GmsCore</string>
|
||||
<string name="microg_settings_summary">إعدادات لـ GmsCore</string>
|
||||
</patch>
|
||||
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
|
||||
<string name="revanced_disable_haptic_feedback_title">الاهتزاز عند الضغط</string>
|
||||
<string name="revanced_disable_haptic_feedback_summary">تغيير الاهتزاز عند الضغط</string>
|
||||
@@ -1528,35 +1547,51 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_slide_to_seek_summary_off">تم تعطيل التمرير للتقديم أو الترجيع</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<string name="revanced_spoof_video_streams_screen_title">Spoof Video Streams</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">تزييف تدفقات الفيديو الخاصة بالعميل لمنع حدوث مشكلات أثناء التشغيل</string>
|
||||
<string name="revanced_spoof_video_streams_title">Spoof Video Streams</string>
|
||||
<string name="revanced_spoof_video_streams_summary_on">يتم تزييف تدفقات الفيديو</string>
|
||||
<string name="revanced_spoof_video_streams_summary_off">"لا يتم تزييف تدفقات الفيديو
|
||||
|
||||
قد لا يعمل تشغيل الفيديو"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">إيقاف تشغيل هذا الإعداد قد يسبب مشاكل في تشغيل الفيديو.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">العميل الافتراضي</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">فرض iOS AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">يتم فرض ترميز فيديو على AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">يتم تحديد ترميز الفيديو تلقائيًا</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"قد يؤدي تمكين هذا إلى تحسين عمر البطارية وإصلاح تقطيع التشغيل.
|
||||
|
||||
AVC لديه حد أقصى للدقة 1080p، لا يتوفر ترميز الصوت Opus، وسوف يستخدم تشغيل الفيديو بيانات إنترنت أكثر من VP9 أو AV1."</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_title">الآثار الجانبية لمحاكاة هوية iOS</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• قد لا يتم تشغيل الأفلام أو الفيديوهات المدفوعة
|
||||
• مستوى الصوت الثابت غير متوفر
|
||||
• تنتهي الفيديوهات قبل ب 1 ثانية"</string>
|
||||
<string name="revanced_spoof_video_streams_about_title">الآثار الجانبية للتزوير</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_title">الآثار الجانبية لمحاكاة هوية Android</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"• قائمة المقطع الصوتي مفقودة
|
||||
• مستوى الصوت الثابت غير متاح
|
||||
• فرض الصوت الأصلي غير متوفر"</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"• قائمة المسارات الصوتية مفقودة
|
||||
• مستوى الصوت المستقر غير متاح"</string>
|
||||
<string name="revanced_spoof_video_streams_about_experimental">• عميل تجريبي وقد يتوقف عن العمل في أي وقت</string>
|
||||
<string name="revanced_spoof_video_streams_about_no_av1">• لا يوجد ترميز الفيديو AV1</string>
|
||||
<string name="revanced_spoof_video_streams_about_kids_videos">• قد لا يتم تشغيل الفيديوهات المخصصة للأطفال عند تسجيل الخروج أو عند استخدام وضع التصفح المتخفي</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">لغة البث الصوتي الافتراضية للواقع الافتراضي VR</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">لغة بث الصوت</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="music">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
<string name="revanced_settings_music_screen_0_about_title">حول</string>
|
||||
<string name="revanced_settings_music_screen_1_ads_title">إعلانات</string>
|
||||
<string name="revanced_settings_music_screen_2_general_title">عام</string>
|
||||
<string name="revanced_settings_music_screen_3_player_title">المشغل</string>
|
||||
<string name="revanced_settings_music_screen_4_misc_title">متنوعة</string>
|
||||
</patch>
|
||||
<patch id="ad.video.hideVideoAdsPatch">
|
||||
<string name="revanced_music_hide_video_ads_title">إخفاء إعلانات الفيديو</string>
|
||||
<string name="revanced_music_hide_video_ads_summary_on">تم إخفاء إعلانات الفيديو</string>
|
||||
<string name="revanced_music_hide_video_ads_summary_off">تم عرض إعلانات الفيديو</string>
|
||||
</patch>
|
||||
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
|
||||
<string name="revanced_music_play_permanent_repeat_title">تمكين التكرار الدائم</string>
|
||||
<string name="revanced_music_play_permanent_repeat_summary_on">تم تمكين التكرار الدائم</string>
|
||||
<string name="revanced_music_play_permanent_repeat_summary_off">تم تعطيل التكرار الدائم</string>
|
||||
</patch>
|
||||
<patch id="layout.compactheader.hideCategoryBar">
|
||||
<string name="revanced_music_hide_category_bar_title">إخفاء شريط الفئات</string>
|
||||
<string name="revanced_music_hide_category_bar_summary_on">شريط الفئات مخفي</string>
|
||||
<string name="revanced_music_hide_category_bar_summary_off">شريط الفئات معروض</string>
|
||||
</patch>
|
||||
<patch id="layout.premium.hideGetPremiumPatch">
|
||||
<string name="revanced_music_hide_get_premium_label_title">إخفاء تسمية \'الحصول على Music Premium\'</string>
|
||||
<string name="revanced_music_hide_get_premium_label_summary_on">التسمية مخفية</string>
|
||||
<string name="revanced_music_hide_get_premium_label_summary_off">التسمية معروضة</string>
|
||||
</patch>
|
||||
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
|
||||
<string name="revanced_music_hide_upgrade_button_title">إخفاء زر الترقية</string>
|
||||
<string name="revanced_music_hide_upgrade_button_summary_on">الزر مخفي</string>
|
||||
<string name="revanced_music_hide_upgrade_button_summary_off">الزر معروض</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
|
||||
@@ -30,6 +30,10 @@ Second \"item\" text"</string>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
</patch>
|
||||
</app>
|
||||
<app id="youtube">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
@@ -209,8 +213,6 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="misc.dimensions.spoof.spoofDeviceDimensionsPatch">
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
</patch>
|
||||
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
|
||||
</patch>
|
||||
<patch id="misc.gms.accountCredentialsInvalidTextPatch">
|
||||
@@ -244,6 +246,20 @@ Second \"item\" text"</string>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
</patch>
|
||||
</app>
|
||||
<app id="music">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
</patch>
|
||||
<patch id="ad.video.hideVideoAdsPatch">
|
||||
</patch>
|
||||
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
|
||||
</patch>
|
||||
<patch id="layout.compactheader.hideCategoryBar">
|
||||
</patch>
|
||||
<patch id="layout.premium.hideGetPremiumPatch">
|
||||
</patch>
|
||||
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
<patch id="ad.audio.audioAdsPatch">
|
||||
</patch>
|
||||
|
||||
@@ -68,6 +68,8 @@ Yeni dilləri tərcümə etmək üçün translate.revanced.app 'ə daxil olun"</
|
||||
and changes made here must also be made there. -->
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<string name="microg_settings_title">GmsCore Tənzimləmələri</string>
|
||||
<string name="microg_settings_summary">GmsCore üçün Tənzimləmələr</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="gms_core_toast_not_installed_message">MicroG GmsCore quraşdırılmayıb. Bunu quraşdır.</string>
|
||||
<string name="gms_core_dialog_title">Fəaliyyət lazımdır</string>
|
||||
@@ -84,6 +86,31 @@ MicroG üçün batareya optimallaşmasın qapatma batareya istifadəsinə mənfi
|
||||
Davam et düyməsinə toxun və optimallaşdırma dəyişikliklərin qəbul et."</string>
|
||||
<string name="gms_core_dialog_continue_text">Davam et</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<string name="revanced_spoof_video_streams_screen_title">Video yayımları saxtalaşdır</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Oynatma problemlərin önləmək üçün qəbuledici video yayımların saxtalaşdır</string>
|
||||
<string name="revanced_spoof_video_streams_title">Video yayımları saxtalaşdır</string>
|
||||
<string name="revanced_spoof_video_streams_summary_on">"Video yayımları saxtalaşdırılıb
|
||||
|
||||
Əgər YouTube Premium istifadəçisisinizsə, bu tənzimlənmə tələb olunmaya bilər"</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">İlkin qəbuledici</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">Sazlama</string>
|
||||
<string name="revanced_debug_screen_summary">Sazlama seçimlərini aktiv/qeyri-aktiv et</string>
|
||||
<string name="revanced_debug_title">Sazlama jurnalı</string>
|
||||
<string name="revanced_debug_summary_on">Sazlama jurnalı işləkdir</string>
|
||||
<string name="revanced_debug_summary_off">Sazlama jurnalı qeyri-aktivdir</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_title">Sazlama qeydlərini ixrac edin</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_summary">ReVanced sazlama qeydlərini buferə köçürür</string>
|
||||
<string name="revanced_debug_logs_disabled">Sazlama qeydi qapalıdır</string>
|
||||
<string name="revanced_debug_logs_none_found">Qeydlər tapılmadı</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Qeydlər köçürüldü</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Qeydləri ixrac etmək alınmadı: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Sazlama qeydlərini təmizlə</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Saxlanılan bütün ReVanced sazlama qeydlərini təmizləyir</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Qeydlər silindi</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="youtube">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
@@ -110,11 +137,6 @@ Davam et düyməsinə toxun və optimallaşdırma dəyişikliklərin qəbul et."
|
||||
<string name="revanced_shorts_disable_background_playback_summary_off">Shorts arxa plan oynatma aktivdir</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">Sazlama</string>
|
||||
<string name="revanced_debug_screen_summary">Sazlama seçimlərini aktiv/qeyri-aktiv et</string>
|
||||
<string name="revanced_debug_title">Sazlama jurnalı</string>
|
||||
<string name="revanced_debug_summary_on">Sazlama jurnalı işləkdir</string>
|
||||
<string name="revanced_debug_summary_off">Sazlama jurnalı qeyri-aktivdir</string>
|
||||
<string name="revanced_debug_protobuffer_title">Bufer protokol jurnalı</string>
|
||||
<string name="revanced_debug_protobuffer_summary_on">Sazlama jurnallarına protokol buferi daxildir</string>
|
||||
<string name="revanced_debug_protobuffer_summary_off">Sazlama jurnallarına protokol buferi daxil deyil</string>
|
||||
@@ -132,15 +154,6 @@ Hər halda, bunu aktivləşdirmə IP ünvanınız kimi bəzi istifadəçi məlum
|
||||
<string name="revanced_debug_toast_on_error_user_dialog_message">"Xəta ani bildirişlərin qapatmaq, bütün ReVanced xəta bildirişlərin gizlədir.
|
||||
|
||||
Gözlənilməz hallardan xəbərdar olmayacaqsınız."</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_title">Sazlama qeydlərini ixrac edin</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_summary">ReVanced sazlama qeydlərini buferə köçürür</string>
|
||||
<string name="revanced_debug_logs_disabled">Sazlama qeydi qapalıdır</string>
|
||||
<string name="revanced_debug_logs_none_found">Qeydlər tapılmadı</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Qeydlər köçürüldü</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Qeydləri ixrac etmək alınmadı: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Sazlama qeydlərini təmizlə</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Saxlanılan bütün ReVanced sazlama qeydlərini təmizləyir</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Qeydlər silindi</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.general.hideLayoutComponentsPatch">
|
||||
<string name="revanced_hide_album_cards_title">Albom kartlarını gizlət</string>
|
||||
@@ -700,9 +713,9 @@ Bu seçimi dəyişdirmə işə düşmürsə, Gizli rejimə keçməyə çalışı
|
||||
<string name="revanced_hide_player_flyout_audio_track_summary_on">Səs axını menyusu gizlidir</string>
|
||||
<string name="revanced_hide_player_flyout_audio_track_summary_off">Səs axını menyusu göstərilir</string>
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
<string name="revanced_hide_player_flyout_audio_track_not_available">"Audio trek seçimi gizlədilib
|
||||
<string name="revanced_hide_player_flyout_audio_track_not_available">"Səs treki menyusu gizlidir
|
||||
|
||||
Audio trek seçimin göstərmək üçün \"Video axınları saxtalaşdır\"ı iOS TV-yə dəyiş"</string>
|
||||
\"Video yayımları saxtalaşdır\" aktivləşdikdə səs trek menyusu mövcud deyil "</string>
|
||||
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
|
||||
<string name="revanced_hide_player_flyout_watch_in_vr_title">\"VR-da İzləni\" gizlət</string>
|
||||
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">VR menyusunda izləmə gizlidir</string>
|
||||
@@ -1074,10 +1087,12 @@ Sizin istifadəçi Id-niz parol kimidir və heç vaxt paylaşmaq olmaz.
|
||||
<string name="revanced_sb_segments_intro_sum">Həqiqi məzmunu olmayan aralıq. Fasilə, statik kadr və ya təkrarlanan animasiya ola bilər. Məlumat ehtiva edən keçidlər daxil deyil</string>
|
||||
<string name="revanced_sb_segments_outro">Son kartlar / Zaminlər</string>
|
||||
<string name="revanced_sb_segments_outro_sum">Zaminlər və ya YouTube bitiş kartları görünəndə. Məlumat daxil olan nəticələr üçün deyil</string>
|
||||
<string name="revanced_sb_segments_preview">Önizləmə/Anons/Qısa</string>
|
||||
<string name="revanced_sb_segments_hook">Giriş / Salamlar</string>
|
||||
<string name="revanced_sb_segments_hook_sum">Yaxınlaşan video üçün danışılan kadrlar, salamlama və sağollaşma. Əlavə məzmun əlavə edən bölmələr daxil deyil</string>
|
||||
<string name="revanced_sb_segments_preview">Önizləmə / Anons</string>
|
||||
<string name="revanced_sb_segments_preview_sum">Videoda və ya seriyanın digər videolarında nə gözlənildiyini və ya baş verdiyini göstərən, bütün məlumatların başqa yerdə təkrarlandığı bölüm toplusu</string>
|
||||
<string name="revanced_sb_segments_filler">Əlaqəsiz/Zarafatlar</string>
|
||||
<string name="revanced_sb_segments_filler_sum">Videonun əsas məzmununu başa düşmək tələb olunmayan yalnız əlaqəsiz və ya yumor üçün əlavə edilmiş təsiredici səhnələr. Məzmun və ya arxa plan detallarını təqdim edən bölümlər daxil deyil</string>
|
||||
<string name="revanced_sb_segments_filler">Əlaqəsiz / Zarafatlar</string>
|
||||
<string name="revanced_sb_segments_filler_sum">Videonun əsas məzmunun başa düşmək tələb olunmayan əlaqəsiz səhnələr və ya zarafatlar. Məzmun və ya arxa plan təfərrüatlarını təmin edən bölmələr daxil deyil</string>
|
||||
<string name="revanced_sb_segments_nomusic">Musiqi: Musiqi olmayan bölmə</string>
|
||||
<string name="revanced_sb_segments_nomusic_sum">Yalnız musiqi videolarında istifadə üçün. Artıq başqa kateqoriyaya aid edilməyən musiqisiz musiqi videoları bölmələri</string>
|
||||
<string name="revanced_sb_skip_button_compact">Ötür</string>
|
||||
@@ -1090,10 +1105,11 @@ Sizin istifadəçi Id-niz parol kimidir və heç vaxt paylaşmaq olmaz.
|
||||
<string name="revanced_sb_skip_button_intro_middle">Fasiləni ötür</string>
|
||||
<string name="revanced_sb_skip_button_intro_end">Fasiləni ötür</string>
|
||||
<string name="revanced_sb_skip_button_outro">Bitişi ötür</string>
|
||||
<string name="revanced_sb_skip_button_hook">Girişi ötür</string>
|
||||
<string name="revanced_sb_skip_button_preview_beginning">Önizləməni ötür</string>
|
||||
<string name="revanced_sb_skip_button_preview_middle">Önizləməni ötür</string>
|
||||
<string name="revanced_sb_skip_button_preview_end">Anonsu ötür</string>
|
||||
<string name="revanced_sb_skip_button_filler">Əlaqəsiz hissəni ötür</string>
|
||||
<string name="revanced_sb_skip_button_filler">Əlaqəsiz olanı ötür</string>
|
||||
<string name="revanced_sb_skip_button_nomusic">Musiqisiz hissəni ötür</string>
|
||||
<string name="revanced_sb_skip_button_unsubmitted">Bölümü ötür</string>
|
||||
<string name="revanced_sb_skipped_sponsor">Sponsorlu hissə ötürüldü</string>
|
||||
@@ -1104,10 +1120,11 @@ Sizin istifadəçi Id-niz parol kimidir və heç vaxt paylaşmaq olmaz.
|
||||
<string name="revanced_sb_skipped_intro_middle">Fasilə ötürüldü</string>
|
||||
<string name="revanced_sb_skipped_intro_end">Fasilə ötürüldü</string>
|
||||
<string name="revanced_sb_skipped_outro">Bitiş ötürüldü</string>
|
||||
<string name="revanced_sb_skipped_hook">Giriş ötürüldü</string>
|
||||
<string name="revanced_sb_skipped_preview_beginning">Önbaxış ötürüldü</string>
|
||||
<string name="revanced_sb_skipped_preview_middle">Önbaxış ötürüldü</string>
|
||||
<string name="revanced_sb_skipped_preview_end">Anons ötürüldü</string>
|
||||
<string name="revanced_sb_skipped_filler">Əlaqəsiz hissə ötürüldü</string>
|
||||
<string name="revanced_sb_skipped_filler">Əlaqəsiz ötürüldü</string>
|
||||
<string name="revanced_sb_skipped_nomusic">Musiqi olmayan bölmə ötürüldü</string>
|
||||
<string name="revanced_sb_skipped_unsubmitted">Göndərilməmiş bölüm ötürüldü</string>
|
||||
<string name="revanced_sb_skipped_multiple_segments">Çoxlu bölümlər ötürüldü</string>
|
||||
@@ -1410,10 +1427,6 @@ Yüksək video keyfiyyətlər görünə bilər, ancaq video oynadılmasında qı
|
||||
Bunu aktivləşdirmə daha yüksək video keyfiyyətləri əngəlin silə bilər"</string>
|
||||
<string name="revanced_spoof_device_dimensions_user_dialog_message">Bunu aktivləşdirmə, video oynatma donmalarına, daha pis batareya istismarına və bilinməyən yan təsirlərə səbəb ola bilər.</string>
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<string name="microg_settings_title">GmsCore Tənzimləmələri</string>
|
||||
<string name="microg_settings_summary">GmsCore üçün Tənzimləmələr</string>
|
||||
</patch>
|
||||
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
|
||||
<string name="revanced_disable_haptic_feedback_title">Əks-əlaqə reaksiyası</string>
|
||||
<string name="revanced_disable_haptic_feedback_summary">Əks-əlaqə reaksiyasını dəyişdir</string>
|
||||
@@ -1527,35 +1540,32 @@ Bunu aktivləşdirmə daha yüksək video keyfiyyətləri əngəlin silə bilər
|
||||
<string name="revanced_slide_to_seek_summary_off">Axtarmaq üçün sürüşdürmə aktiv deyil</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<string name="revanced_spoof_video_streams_screen_title">Video yayımları saxtalaşdır</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Oynatma problemlərin önləmək üçün qəbuledici video yayımların saxtalaşdır</string>
|
||||
<string name="revanced_spoof_video_streams_title">Video yayımları saxtalaşdır</string>
|
||||
<string name="revanced_spoof_video_streams_summary_on">Video yayımları saxtalaşdırılır</string>
|
||||
<string name="revanced_spoof_video_streams_summary_off">"Video yayımlar saxtalaşdırılmır
|
||||
|
||||
Video oynatma işləməyə bilər"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">Bu seçimi bağlamaq, video oynatma problemlərinə səbəb olar.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">İlkin qəbuledici</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">IOS-da AVC (H.264)-ni məcbur et</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">Video kodlama AVC (H.264)-yə məcbur edilir</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">Video kodlayıcı avtomatik müəyyən edilir</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"Bunu aktivləşdirmə, batareya ömrün yaxşılaşdıra və oynatma qırılmasın düzəldə bilər.
|
||||
|
||||
AVC maksimum 1080p görüntü imkanına malikdir, Opus audio kodlama olmur və video oynatma VP9 və ya AV1-dən daha çox internet məlumatı sərf edəcək."</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_title">iOS saxtalaşdırma yan təsirləri</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• Filmlər və ya ödənişli videolar oynadıla bilməz
|
||||
• Stabil səs səviyyəsi mövcud deyil
|
||||
• Videolar 1 saniyə tez bitir"</string>
|
||||
<string name="revanced_spoof_video_streams_about_title">Saxtakarlıq yan təsirləri</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_title">Android saxtalaşdırma yan təsirləri</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"• Səs treki menyusu yoxdur
|
||||
• Sabit səs səviyyəsi yoxdur
|
||||
• İlkin səsi məcbur etmə mümkün deyil"</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"• Səs treki menyusu əlçatmazdır
|
||||
• Sabit səs səviyyəsi yoxdur"</string>
|
||||
<string name="revanced_spoof_video_streams_about_experimental">• Təcrübi qəbuledici və hər vaxt işləməyi dayandıra bilər</string>
|
||||
<string name="revanced_spoof_video_streams_about_no_av1">• AV1 video kodlayıcı yoxdur</string>
|
||||
<string name="revanced_spoof_video_streams_about_kids_videos">• Giriş edilməyəndə və ya gizli rejimdə uşaq videoları oynadıla bilməz</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">VR-da ilkin səs yayımı dili</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">Səs yayım dili</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="music">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
<string name="revanced_settings_music_screen_4_misc_title">Çoxvariantlı</string>
|
||||
</patch>
|
||||
<patch id="ad.video.hideVideoAdsPatch">
|
||||
</patch>
|
||||
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
|
||||
</patch>
|
||||
<patch id="layout.compactheader.hideCategoryBar">
|
||||
</patch>
|
||||
<patch id="layout.premium.hideGetPremiumPatch">
|
||||
</patch>
|
||||
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
|
||||
@@ -68,6 +68,8 @@ Second \"item\" text"</string>
|
||||
and changes made here must also be made there. -->
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<string name="microg_settings_title">Налады GmsCore</string>
|
||||
<string name="microg_settings_summary">Налады для GmsCore</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="gms_core_toast_not_installed_message">MicroG GmsCore не ўсталяваны. Усталюйце яго.</string>
|
||||
<string name="gms_core_dialog_title">Патрабуецца дзеянне</string>
|
||||
@@ -84,6 +86,37 @@ Second \"item\" text"</string>
|
||||
Націсніце кнопку \"Працягнуць\" і дазвольце змяніць аптымізацыю."</string>
|
||||
<string name="gms_core_dialog_continue_text">Працягнуць</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<string name="revanced_spoof_video_streams_screen_title">Подделывать потоки видео</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Имитируйте потоки видео клиентов, чтобы предотвратить проблемы с воспроизведением</string>
|
||||
<string name="revanced_spoof_video_streams_screen_title">Падмена відэапатокаў</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Падмена відэапатокаў кліента для прадухілення праблем з прайграваннем</string>
|
||||
<string name="revanced_spoof_video_streams_title">Подделывать потоки видео</string>
|
||||
<string name="revanced_spoof_video_streams_summary_on">"Відэаструмені падроблены
|
||||
|
||||
Калі вы карыстаецеся YouTube Premium, гэтая налада можа не спатрэбіцца"</string>
|
||||
<string name="revanced_spoof_video_streams_summary_off">"Відэапатокі не падменены
|
||||
|
||||
Прайграванне можа не працаваць"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">Адключэнне гэтай налады можа выклікаць праблемы з прайграваннем.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">Клиент по умолчанию</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">Адладка</string>
|
||||
<string name="revanced_debug_screen_summary">Уключыць або выключыць параметры адладкі</string>
|
||||
<string name="revanced_debug_title">Запіс адладкі</string>
|
||||
<string name="revanced_debug_summary_on">Журналы адладкі ўключаны</string>
|
||||
<string name="revanced_debug_summary_off">Журналы адладкі адключаны</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_title">Экспартаваць адладачныя лагі</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_summary">Капіруе адладачныя лагі ReVanced у буфер абмену</string>
|
||||
<string name="revanced_debug_logs_disabled">Адладачнае лагаванне адключана</string>
|
||||
<string name="revanced_debug_logs_none_found">Лагі не знойдзены</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Лагі скапіяваны</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Не ўдалося экспартаваць журналы: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Ачысціць адладачныя лагі</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Ачышчае ўсе захаваныя адладачныя лагі ReVanced</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Лагі ачышчаны</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="youtube">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
@@ -110,11 +143,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_shorts_disable_background_playback_summary_off">Фоновый плейлист Shorts включен</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">Адладка</string>
|
||||
<string name="revanced_debug_screen_summary">Уключыць або выключыць параметры адладкі</string>
|
||||
<string name="revanced_debug_title">Запіс адладкі</string>
|
||||
<string name="revanced_debug_summary_on">Журналы адладкі ўключаны</string>
|
||||
<string name="revanced_debug_summary_off">Журналы адладкі адключаны</string>
|
||||
<string name="revanced_debug_protobuffer_title">Буфер пратаколу часопіса</string>
|
||||
<string name="revanced_debug_protobuffer_summary_on">Журналы адладкі ўключаюць пратабуфер</string>
|
||||
<string name="revanced_debug_protobuffer_summary_off">Журналы адладкі не ўключаюць пратабуфер</string>
|
||||
@@ -132,15 +160,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_debug_toast_on_error_user_dialog_message">"Адключэнне паведамленняў пра памылкі схавае ўсе апавяшчэнні ReVanced пра памылкі.
|
||||
|
||||
Вы не будзеце атрымліваць апавяшчэнні пра нечаканыя падзеі."</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_title">Экспартаваць адладачныя лагі</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_summary">Капіруе адладачныя лагі ReVanced у буфер абмену</string>
|
||||
<string name="revanced_debug_logs_disabled">Адладачнае лагаванне адключана</string>
|
||||
<string name="revanced_debug_logs_none_found">Лагі не знойдзены</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Лагі скапіяваны</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Не ўдалося экспартаваць журналы: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Ачысціць адладачныя лагі</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Ачышчае ўсе захаваныя адладачныя лагі ReVanced</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Лагі ачышчаны</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.general.hideLayoutComponentsPatch">
|
||||
<string name="revanced_hide_album_cards_title">Схаваць карты альбома</string>
|
||||
@@ -700,9 +719,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_player_flyout_audio_track_summary_on">Меню гукавой дарожкі схавана</string>
|
||||
<string name="revanced_hide_player_flyout_audio_track_summary_off">Адлюструецца меню гукавой дарожкі</string>
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
<string name="revanced_hide_player_flyout_audio_track_not_available">"Меню аўдыядарожкі схавана
|
||||
<string name="revanced_hide_player_flyout_audio_track_not_available">"Меню гукавой дарожкі схавана
|
||||
|
||||
Каб паказаць меню аўдыядарожкі, змяніце \"Падробка відэаструменяў\" на iOS TV"</string>
|
||||
Меню гукавой дарожкі недаступна, калі ўключана \"Падробка відэаструменяў\""</string>
|
||||
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
|
||||
<string name="revanced_hide_player_flyout_watch_in_vr_title">Схаваць гадзіннік у VR</string>
|
||||
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Меню прагляду ў VR схавана</string>
|
||||
@@ -1076,10 +1095,12 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_sb_segments_intro_sum">Інтэрвал без фактычнага зместу. Гэта можа быць паўза, статычны кадр або паўтаральная анімацыя. Не ўключае пераходы, якія змяшчаюць інфармацыю</string>
|
||||
<string name="revanced_sb_segments_outro">Канцоўкі / Цітры</string>
|
||||
<string name="revanced_sb_segments_outro_sum">Крэдыты або калі з\"яўляюцца канцавыя карткі YouTube. Не для высноў з інфармацыяй</string>
|
||||
<string name="revanced_sb_segments_preview">Папярэдні прагляд/Паўзвядзенне/Хук</string>
|
||||
<string name="revanced_sb_segments_hook">Уступ / Прывітанні</string>
|
||||
<string name="revanced_sb_segments_hook_sum">Агучаныя трэйлеры для будучага відэа, прывітанні і развітанні. Не ўключае раздзелы, якія дадаюць дадатковы змест</string>
|
||||
<string name="revanced_sb_segments_preview">Прадпрагляд / Паўтарэнне</string>
|
||||
<string name="revanced_sb_segments_preview_sum">Калекцыя кліпаў, якія паказваюць, што адбываецца або што адбылося ў відэа ці ў іншых відэа серыі, дзе ўся інфармацыя паўтараецца ў іншым месцы</string>
|
||||
<string name="revanced_sb_segments_filler">Філер Тангенс / Жарты</string>
|
||||
<string name="revanced_sb_segments_filler_sum">Датычныя сцэны дададзены толькі для напаўнення або гумару, якія не патрэбныя для разумення асноўнага зместу відэа. Не ўключае сегменты, якія прадстаўляюць кантэкст або даведку</string>
|
||||
<string name="revanced_sb_segments_filler">Лірычнае адступленне / Жарты</string>
|
||||
<string name="revanced_sb_segments_filler_sum">Тангенцыяльныя сцэны або жарты, якія не патрабуюцца для разумення асноўнага зместу відэа. Не ўключае раздзелы, якія прадастаўляюць кантэкст або фонавыя дэталі</string>
|
||||
<string name="revanced_sb_segments_nomusic">Музыка: немузычны раздзел</string>
|
||||
<string name="revanced_sb_segments_nomusic_sum">Толькі для выкарыстання ў музычных відэа. Раздзелы музычных відэа без музыкі, якія яшчэ не ахоплены іншай катэгорыяй</string>
|
||||
<string name="revanced_sb_skip_button_compact">Прапусціць</string>
|
||||
@@ -1092,10 +1113,11 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_sb_skip_button_intro_middle">Прапусціць антракт</string>
|
||||
<string name="revanced_sb_skip_button_intro_end">Прапусціць антракт</string>
|
||||
<string name="revanced_sb_skip_button_outro">Прапусціць іншы</string>
|
||||
<string name="revanced_sb_skip_button_hook">Прапусціць уступ</string>
|
||||
<string name="revanced_sb_skip_button_preview_beginning">Прапусціць папярэдні прагляд</string>
|
||||
<string name="revanced_sb_skip_button_preview_middle">Прапусціць папярэдні прагляд</string>
|
||||
<string name="revanced_sb_skip_button_preview_end">Прапусціць рэзюмэ</string>
|
||||
<string name="revanced_sb_skip_button_filler">Скіп напаўняльнік</string>
|
||||
<string name="revanced_sb_skip_button_filler">Прапусціць тангенс</string>
|
||||
<string name="revanced_sb_skip_button_nomusic">Прапусціць не музыку</string>
|
||||
<string name="revanced_sb_skip_button_unsubmitted">Прапусціць сегмент</string>
|
||||
<string name="revanced_sb_skipped_sponsor">Прапусціў спонсара</string>
|
||||
@@ -1106,10 +1128,11 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_sb_skipped_intro_middle">Прапушчаны антракт</string>
|
||||
<string name="revanced_sb_skipped_intro_end">Прапушчаны антракт</string>
|
||||
<string name="revanced_sb_skipped_outro">Прапушчаны выхад</string>
|
||||
<string name="revanced_sb_skipped_hook">Уступ прапушчаны</string>
|
||||
<string name="revanced_sb_skipped_preview_beginning">Прапушчаны папярэдні прагляд</string>
|
||||
<string name="revanced_sb_skipped_preview_middle">Прапушчаны папярэдні прагляд</string>
|
||||
<string name="revanced_sb_skipped_preview_end">Прапушчаны рэзюмэ</string>
|
||||
<string name="revanced_sb_skipped_filler">Прапушчаны напаўняльнік</string>
|
||||
<string name="revanced_sb_skipped_filler">Тангенс прапушчаны</string>
|
||||
<string name="revanced_sb_skipped_nomusic">Прапусціў немузычны раздзел</string>
|
||||
<string name="revanced_sb_skipped_unsubmitted">Прапушчаны неадпраўлены сегмент</string>
|
||||
<string name="revanced_sb_skipped_multiple_segments">Прапушчаны некалькі сегментаў</string>
|
||||
@@ -1412,10 +1435,6 @@ Second \"item\" text"</string>
|
||||
Уключэнне гэтага можа разблакаваць больш высокія якасці відэа"</string>
|
||||
<string name="revanced_spoof_device_dimensions_user_dialog_message">Уключэнне гэтага можа прывесці да прыпынкаў прайгравання відэа, пагаршэння тэрміну службы батарэі і невядомых пабочных эфектаў.</string>
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<string name="microg_settings_title">Налады GmsCore</string>
|
||||
<string name="microg_settings_summary">Налады для GmsCore</string>
|
||||
</patch>
|
||||
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
|
||||
<string name="revanced_disable_haptic_feedback_title">Тактыльная зваротная сувязь</string>
|
||||
<string name="revanced_disable_haptic_feedback_summary">Змяніць тактыльную зваротную сувязь</string>
|
||||
@@ -1529,35 +1548,51 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_slide_to_seek_summary_off">Слайд для пошуку не ўключаны</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<string name="revanced_spoof_video_streams_screen_title">Подделывать потоки видео</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Имитируйте потоки видео клиентов, чтобы предотвратить проблемы с воспроизведением</string>
|
||||
<string name="revanced_spoof_video_streams_title">Подделывать потоки видео</string>
|
||||
<string name="revanced_spoof_video_streams_summary_on">Потоки видео подделаны</string>
|
||||
<string name="revanced_spoof_video_streams_summary_off">"Відэаструм не падроблены
|
||||
|
||||
Прайграванне відэа можа не працаваць"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">Адключэнне гэтай налады можа выклікаць праблемы з прайграваннем відэа.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">Клиент по умолчанию</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">Вымусіць iOS AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">Відэакaдэк зафіксаваны ў AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">Відэакaдэк вызначаецца аўтаматычна</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"Уключэнне гэтага можа палепшыць час аўтаномнай працы і выправіць заіканне прайгравання.
|
||||
|
||||
AVC мае максімальнае дазвол 1080p, аўдыёкадэк Opus недаступны, а прайграванне відэа будзе выкарыстоўваць больш інтэрнэт-даных, чым VP9 або AV1."</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_title">Пабочныя эфекты падробкі iOS</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• Фільмы або платныя відэа могуць не прайгравацца
|
||||
• Стабільная гучнасць недаступная
|
||||
• Відэа заканчваюцца на 1 секунду раней"</string>
|
||||
<string name="revanced_spoof_video_streams_about_title">Пабочныя эфекты падробкі</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_title">Побічныя эфекты падробкі Android</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"• Меню гукавой дарожкі адсутнічае
|
||||
• Стабільны гук недаступны
|
||||
• Прымусовае арыгінальнае аўдыё недаступна"</string>
|
||||
• Стабільная гучнасць недаступна"</string>
|
||||
<string name="revanced_spoof_video_streams_about_experimental">• Эксперыментальны кліент і можа спыніць працу ў любы час</string>
|
||||
<string name="revanced_spoof_video_streams_about_no_av1">• Няма відэакідавання AV1</string>
|
||||
<string name="revanced_spoof_video_streams_about_kids_videos">• Дзіцячыя відэа могуць не прайгравацца ў стане выхаду з акаўнта або ў рэжыме інкогніта</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">Мова гукавой дарожкі па змаўчанні для VR</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">Мова аўдыяпатоку</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="music">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
<string name="revanced_settings_music_screen_0_about_title">Пра</string>
|
||||
<string name="revanced_settings_music_screen_1_ads_title">Рэклама</string>
|
||||
<string name="revanced_settings_music_screen_2_general_title">Агульныя</string>
|
||||
<string name="revanced_settings_music_screen_3_player_title">Плэер</string>
|
||||
<string name="revanced_settings_music_screen_4_misc_title">Рознае</string>
|
||||
</patch>
|
||||
<patch id="ad.video.hideVideoAdsPatch">
|
||||
<string name="revanced_music_hide_video_ads_title">Схаваць відэарэкламу</string>
|
||||
<string name="revanced_music_hide_video_ads_summary_on">Відэарэклама схаваная</string>
|
||||
<string name="revanced_music_hide_video_ads_summary_off">Відэарэклама паказаная</string>
|
||||
</patch>
|
||||
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
|
||||
<string name="revanced_music_play_permanent_repeat_title">Уключыць пастаянны паўтор</string>
|
||||
<string name="revanced_music_play_permanent_repeat_summary_on">Пастаянны паўтор уключаны</string>
|
||||
<string name="revanced_music_play_permanent_repeat_summary_off">Пастаянны паўтор адключаны</string>
|
||||
</patch>
|
||||
<patch id="layout.compactheader.hideCategoryBar">
|
||||
<string name="revanced_music_hide_category_bar_title">Схаваць панэль катэгорый</string>
|
||||
<string name="revanced_music_hide_category_bar_summary_on">Панэль катэгорый схаваная</string>
|
||||
<string name="revanced_music_hide_category_bar_summary_off">Панэль катэгорый паказаная</string>
|
||||
</patch>
|
||||
<patch id="layout.premium.hideGetPremiumPatch">
|
||||
<string name="revanced_music_hide_get_premium_label_title">Схаваць надпіс \"Атрымаць Music Premium\"</string>
|
||||
<string name="revanced_music_hide_get_premium_label_summary_on">Надпіс схаваны</string>
|
||||
<string name="revanced_music_hide_get_premium_label_summary_off">Надпіс паказаны</string>
|
||||
</patch>
|
||||
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
|
||||
<string name="revanced_music_hide_upgrade_button_title">Схаваць кнопку абнаўлення</string>
|
||||
<string name="revanced_music_hide_upgrade_button_summary_on">Кнопка схаваная</string>
|
||||
<string name="revanced_music_hide_upgrade_button_summary_off">Кнопка паказаная</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
|
||||
@@ -68,6 +68,8 @@ Second \"item\" text"</string>
|
||||
and changes made here must also be made there. -->
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<string name="microg_settings_title">GmsCore Настройки</string>
|
||||
<string name="microg_settings_summary">Настройки на GmsCore</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="gms_core_toast_not_installed_message">GmsCore не е инсталиран. Инсталирайте го.</string>
|
||||
<string name="gms_core_dialog_title">Нужно е действие</string>
|
||||
@@ -84,6 +86,37 @@ Second \"item\" text"</string>
|
||||
Докоснете бутона за продължаване и разрешете промени в оптимизацията."</string>
|
||||
<string name="gms_core_dialog_continue_text">Продължи</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<string name="revanced_spoof_video_streams_screen_title">Подправяне на видео потоци</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Подправете клиентските видео потоци, за да предотвратите проблеми с възпроизвеждането</string>
|
||||
<string name="revanced_spoof_video_streams_screen_title">Имитиране на видео потоци</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Имитирайте видео потоците на клиента, за да предотвратите проблеми с възпроизвеждането</string>
|
||||
<string name="revanced_spoof_video_streams_title">Подправяне на видео потоци</string>
|
||||
<string name="revanced_spoof_video_streams_summary_on">"Видео потоците са подменени
|
||||
|
||||
Ако сте потребител на YouTube Premium, тази настройка може да не е необходима"</string>
|
||||
<string name="revanced_spoof_video_streams_summary_off">"Видеопотоците не са подправени
|
||||
|
||||
Възпроизвеждането може да не работи"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">Изключването на тази настройка може да причини проблеми с възпроизвеждането.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">Клиент по подразбиране</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">Отстраняване на грешки</string>
|
||||
<string name="revanced_debug_screen_summary">Активиране или деактивиране на отстраняването на грешки</string>
|
||||
<string name="revanced_debug_title">Дневник на отстраняването на грешки</string>
|
||||
<string name="revanced_debug_summary_on">Дневникът за остраняване на грешки е активиран</string>
|
||||
<string name="revanced_debug_summary_off">Дневникът за остраняване на грешки е деактивиран</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_title">Експортиране на логове за отстраняване на грешки</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_summary">Копира логовете за отстраняване на грешки на ReVanced в клипборда</string>
|
||||
<string name="revanced_debug_logs_disabled">Отстраняването на грешки е деактивирано</string>
|
||||
<string name="revanced_debug_logs_none_found">Не са намерени логове</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Логовете са копирани</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Неуспешно експортиране на логове: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Изчистване на логовете за отстраняване на грешки</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Изчиства всички съхранени логове за отстраняване на грешки на ReVanced</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Логовете са изчистени</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="youtube">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
@@ -110,11 +143,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_shorts_disable_background_playback_summary_off">Фоновото възпроизвеждане на Shorts е активирано</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">Отстраняване на грешки</string>
|
||||
<string name="revanced_debug_screen_summary">Активиране или деактивиране на отстраняването на грешки</string>
|
||||
<string name="revanced_debug_title">Дневник на отстраняването на грешки</string>
|
||||
<string name="revanced_debug_summary_on">Дневникът за остраняване на грешки е активиран</string>
|
||||
<string name="revanced_debug_summary_off">Дневникът за остраняване на грешки е деактивиран</string>
|
||||
<string name="revanced_debug_protobuffer_title">Буфер на протокола за дневника</string>
|
||||
<string name="revanced_debug_protobuffer_summary_on">Файлове с дневници за грешки включват буфера</string>
|
||||
<string name="revanced_debug_protobuffer_summary_off">Файлове с дневници за грешки не включват буфера</string>
|
||||
@@ -132,15 +160,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_debug_toast_on_error_user_dialog_message">"Изключването на изскачащи съобщения за грешки крие всички известия за грешки на ReVanced.
|
||||
|
||||
Няма да бъдете уведомени за неочаквани събития."</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_title">Експортиране на логове за отстраняване на грешки</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_summary">Копира логовете за отстраняване на грешки на ReVanced в клипборда</string>
|
||||
<string name="revanced_debug_logs_disabled">Отстраняването на грешки е деактивирано</string>
|
||||
<string name="revanced_debug_logs_none_found">Не са намерени логове</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Логовете са копирани</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Неуспешно експортиране на логове: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Изчистване на логовете за отстраняване на грешки</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Изчиства всички съхранени логове за отстраняване на грешки на ReVanced</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Логовете са изчистени</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.general.hideLayoutComponentsPatch">
|
||||
<string name="revanced_hide_album_cards_title">\"Карти на албумите\"</string>
|
||||
@@ -700,9 +719,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_player_flyout_audio_track_summary_on">Менюто за избор на Аудио е скрито</string>
|
||||
<string name="revanced_hide_player_flyout_audio_track_summary_off">Менюто за избор на Аудио се показва</string>
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
<string name="revanced_hide_player_flyout_audio_track_not_available">"Менюто за аудио тракове е скрито
|
||||
<string name="revanced_hide_player_flyout_audio_track_not_available">"Менюто за аудиозаписи е скрито
|
||||
|
||||
За да покажете менюто за аудио тракове, променете \"Подмяна на видео потоци\" на iOS TV"</string>
|
||||
Менюто за аудиозаписи не е налично, когато „Подменяне на видео потоци“ е активирано"</string>
|
||||
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
|
||||
<string name="revanced_hide_player_flyout_watch_in_vr_title">Гледайте във VR</string>
|
||||
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Менюто за гледане в VR е скрито</string>
|
||||
@@ -1075,10 +1094,12 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_sb_segments_intro_sum">Интервал без реално съдържание. Може да бъде пауза, статичен кадър, повтаряща се анимация. Това не трябва да се използва за преходи, съдържащи информация</string>
|
||||
<string name="revanced_sb_segments_outro">Край на клипа / Надписи</string>
|
||||
<string name="revanced_sb_segments_outro_sum">Информация или когато се показват крайните карти на YouTube. Не за заключения с информация</string>
|
||||
<string name="revanced_sb_segments_preview">Кратък преглед/Обобщение</string>
|
||||
<string name="revanced_sb_segments_hook">Начало / Поздрави</string>
|
||||
<string name="revanced_sb_segments_hook_sum">Озвучени трейлъри за предстоящото видео, поздрави и сбогувания. Не включва секции, които добавят допълнително съдържание</string>
|
||||
<string name="revanced_sb_segments_preview">Предварителен преглед / Резюме</string>
|
||||
<string name="revanced_sb_segments_preview_sum">Колекция от клипове, които показват какво предстои в този видеоклип или в други видеоклипове от поредицата, където цялата информация се повтаря по-късно във видеоклипа</string>
|
||||
<string name="revanced_sb_segments_filler">Пълнеж/Шеги</string>
|
||||
<string name="revanced_sb_segments_filler_sum">Сцени извън темата, добавени само за пълнеж или хумор, които не са необходими за разбирането на основното съдържание на видеоклипа. Това не трябва да включва сегменти, предоставящи контекст или справочни данни</string>
|
||||
<string name="revanced_sb_segments_filler">Отклонение / Шеги</string>
|
||||
<string name="revanced_sb_segments_filler_sum">Странични сцени или шеги, които не са необходими за разбиране на основното съдържание на видеоклипа. Не включва секции, предоставящи контекст или фонови детайли</string>
|
||||
<string name="revanced_sb_segments_nomusic">Музика: Част без музика</string>
|
||||
<string name="revanced_sb_segments_nomusic_sum">За използване само в музикални видеоклипове. Това трябва да се използва само за части от музикални видеоклипове, които вече не са обхванати от друга категория</string>
|
||||
<string name="revanced_sb_skip_button_compact">Пропусни</string>
|
||||
@@ -1091,10 +1112,11 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_sb_skip_button_intro_middle">Пропусни пауза</string>
|
||||
<string name="revanced_sb_skip_button_intro_end">Пропусни пауза</string>
|
||||
<string name="revanced_sb_skip_button_outro">Пропусни заключение</string>
|
||||
<string name="revanced_sb_skip_button_hook">Пропускане на увод</string>
|
||||
<string name="revanced_sb_skip_button_preview_beginning">Пропусни преглед</string>
|
||||
<string name="revanced_sb_skip_button_preview_middle">Пропусни преглед</string>
|
||||
<string name="revanced_sb_skip_button_preview_end">Пропуснете обобщението</string>
|
||||
<string name="revanced_sb_skip_button_filler">Пропусни пълнеж</string>
|
||||
<string name="revanced_sb_skip_button_filler">Пропускане на отклонение</string>
|
||||
<string name="revanced_sb_skip_button_nomusic">Пропусни част без музика</string>
|
||||
<string name="revanced_sb_skip_button_unsubmitted">Пропускане на сегмент</string>
|
||||
<string name="revanced_sb_skipped_sponsor">Пропуснат спонсор</string>
|
||||
@@ -1105,10 +1127,11 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_sb_skipped_intro_middle">Пропусни паузи</string>
|
||||
<string name="revanced_sb_skipped_intro_end">Пропусни паузи</string>
|
||||
<string name="revanced_sb_skipped_outro">Пропуснато заключение</string>
|
||||
<string name="revanced_sb_skipped_hook">Пропуснато увод</string>
|
||||
<string name="revanced_sb_skipped_preview_beginning">Пропуснат преглед</string>
|
||||
<string name="revanced_sb_skipped_preview_middle">Пропуснат преглед</string>
|
||||
<string name="revanced_sb_skipped_preview_end">Пропуснато повторение</string>
|
||||
<string name="revanced_sb_skipped_filler">Пропуснат пълнеж</string>
|
||||
<string name="revanced_sb_skipped_filler">Пропуснато отклонение</string>
|
||||
<string name="revanced_sb_skipped_nomusic">Пропусната част без музика</string>
|
||||
<string name="revanced_sb_skipped_unsubmitted">Пропуснат неизпратен сегмент</string>
|
||||
<string name="revanced_sb_skipped_multiple_segments">Пропуснати множество части</string>
|
||||
@@ -1411,10 +1434,6 @@ Second \"item\" text"</string>
|
||||
Активирането на това може да отключи по-високи видео качества"</string>
|
||||
<string name="revanced_spoof_device_dimensions_user_dialog_message">Разрешаването на това може да причини прекъсване на възпроизвеждането на видео, влошен живот на батерията и неизвестни странични ефекти.</string>
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<string name="microg_settings_title">GmsCore Настройки</string>
|
||||
<string name="microg_settings_summary">Настройки на GmsCore</string>
|
||||
</patch>
|
||||
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
|
||||
<string name="revanced_disable_haptic_feedback_title">Вибрационна обратна връзка</string>
|
||||
<string name="revanced_disable_haptic_feedback_summary">Промяна на вибрационната обратна връзка</string>
|
||||
@@ -1528,35 +1547,51 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_slide_to_seek_summary_off">Слайд за превъртане е деактивиран</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<string name="revanced_spoof_video_streams_screen_title">Подправяне на видео потоци</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Подправете клиентските видео потоци, за да предотвратите проблеми с възпроизвеждането</string>
|
||||
<string name="revanced_spoof_video_streams_title">Подправяне на видео потоци</string>
|
||||
<string name="revanced_spoof_video_streams_summary_on">Видео потоците са подправени</string>
|
||||
<string name="revanced_spoof_video_streams_summary_off">"Потоците на видеоклипове не са фалшифицирани
|
||||
|
||||
Възпроизвеждането на видеоклипове може да не работи"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">Деактивирането на тази настройка ще доведе до проблеми с възпроизвеждането на видео.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">Клиент по подразбиране</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">Принудително използване на AVC (H.264) на iOS</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">Видео кодекът е принудително зададен на AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">Видео кодекът се определя автоматично</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"Включването на това може да подобри живота на батерията и да поправи заекването при възпроизвеждане.
|
||||
|
||||
AVC има максимална резолюция от 1080p, Opus аудио кодек не е наличен и възпроизвеждането на видео ще използва повече интернет данни от VP9 или AV1."</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_title">Ефекти на измамата в iOS</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• Филми или платени видеоклипове може да не се възпроизвеждат
|
||||
• Стабилен звук не е наличен
|
||||
• Видеоклиповете завършват 1 секунда по-рано"</string>
|
||||
<string name="revanced_spoof_video_streams_about_title">Странични ефекти от подменянето</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_title">Strani4ni efekti na fal6ivoto predstavqne na Android</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"• Lipsva menju za audio pisti
|
||||
• Ne e nali4na stabilna glasnost
|
||||
• Ne e nali4na forsirana originalna audio pista"</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"• Липсва менюто за аудиозаписи
|
||||
• Стабилен звук не е наличен"</string>
|
||||
<string name="revanced_spoof_video_streams_about_experimental">• Експериментален клиент и може да спре да работи по всяко време</string>
|
||||
<string name="revanced_spoof_video_streams_about_no_av1">• Без AV1 видео кодек</string>
|
||||
<string name="revanced_spoof_video_streams_about_kids_videos">• Детските видеоклипове може да не се възпроизвеждат, когато сте излезли от профила си или в режим \"инкогнито\"</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">Ezik po подразбиране za audio potok v VR</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">Език на аудио потока</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="music">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
<string name="revanced_settings_music_screen_0_about_title">Относно</string>
|
||||
<string name="revanced_settings_music_screen_1_ads_title">Реклами</string>
|
||||
<string name="revanced_settings_music_screen_2_general_title">Общи</string>
|
||||
<string name="revanced_settings_music_screen_3_player_title">Плейър</string>
|
||||
<string name="revanced_settings_music_screen_4_misc_title">Разни</string>
|
||||
</patch>
|
||||
<patch id="ad.video.hideVideoAdsPatch">
|
||||
<string name="revanced_music_hide_video_ads_title">Скриване на видеореклами</string>
|
||||
<string name="revanced_music_hide_video_ads_summary_on">Видеорекламите са скрити</string>
|
||||
<string name="revanced_music_hide_video_ads_summary_off">Видеорекламите са показани</string>
|
||||
</patch>
|
||||
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
|
||||
<string name="revanced_music_play_permanent_repeat_title">Активиране на постоянно повтаряне</string>
|
||||
<string name="revanced_music_play_permanent_repeat_summary_on">Постоянното повтаряне е активирано</string>
|
||||
<string name="revanced_music_play_permanent_repeat_summary_off">Постоянното повтаряне е деактивирано</string>
|
||||
</patch>
|
||||
<patch id="layout.compactheader.hideCategoryBar">
|
||||
<string name="revanced_music_hide_category_bar_title">Скриване на лентата с категории</string>
|
||||
<string name="revanced_music_hide_category_bar_summary_on">Лентата с категории е скрита</string>
|
||||
<string name="revanced_music_hide_category_bar_summary_off">Лентата с категории е показана</string>
|
||||
</patch>
|
||||
<patch id="layout.premium.hideGetPremiumPatch">
|
||||
<string name="revanced_music_hide_get_premium_label_title">Скриване на етикета „Вземете Music Premium“</string>
|
||||
<string name="revanced_music_hide_get_premium_label_summary_on">Етикетът е скрит</string>
|
||||
<string name="revanced_music_hide_get_premium_label_summary_off">Етикетът е показан</string>
|
||||
</patch>
|
||||
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
|
||||
<string name="revanced_music_hide_upgrade_button_title">Скриване на бутона за надстройка</string>
|
||||
<string name="revanced_music_hide_upgrade_button_summary_on">Бутонът е скрит</string>
|
||||
<string name="revanced_music_hide_upgrade_button_summary_off">Бутонът е показан</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
|
||||
@@ -68,6 +68,8 @@ Second \"item\" text"</string>
|
||||
and changes made here must also be made there. -->
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<string name="microg_settings_title">GmsCore সেটিং</string>
|
||||
<string name="microg_settings_summary">GmsCore এর জন্য সেটিং</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="gms_core_toast_not_installed_message">MicroG GmsCore ইনস্টল করা হয়নি। ইনস্টল করুন।</string>
|
||||
<string name="gms_core_dialog_title">পদক্ষেপ প্রয়োজন</string>
|
||||
@@ -84,6 +86,37 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
|
||||
চালিয়ে যান বোতামটি ট্যাপ করুন এবং অপ্টিমাইজেশন পরিবর্তনগুলি অনুমোদন করুন।"</string>
|
||||
<string name="gms_core_dialog_continue_text">এগিয়ে যান</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<string name="revanced_spoof_video_streams_screen_title">ভিডিও স্ট্রিমিং স্পুফ করুন</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">প্লেব্যাক সমস্যা প্রতিরোধ করতে ক্লায়েন্ট ভিডিও স্ট্রিম স্পুফ করুন</string>
|
||||
<string name="revanced_spoof_video_streams_screen_title">ভিডিও স্ট্রিম স্পুফ করুন</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">প্লেব্যাক সংক্রান্ত সমস্যা রোধ করতে ক্লায়েন্টের ভিডিও স্ট্রিমগুলি স্পুফ করুন</string>
|
||||
<string name="revanced_spoof_video_streams_title">ভিডিও স্ট্রিমিং স্পুফ করুন</string>
|
||||
<string name="revanced_spoof_video_streams_summary_on">"ভিডিও স্ট্রিম স্পুফ করা হয়েছে
|
||||
|
||||
আপনি যদি YouTube Premium ব্যবহারকারী হন, তাহলে এই সেটিংটির প্রয়োজন নাও হতে পারে"</string>
|
||||
<string name="revanced_spoof_video_streams_summary_off">"ভিডিও স্ট্রিম স্পুফ করা হয়নি
|
||||
|
||||
প্লেব্যাক কাজ নাও করতে পারে"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">এই সেটিং বন্ধ করলে প্লেব্যাক সমস্যা হতে পারে।</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">ডিফল্ট ক্লায়েন্ট</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">ডিবাগিং</string>
|
||||
<string name="revanced_debug_screen_summary">ডিবাগিং অপশন সক্রিয় বা নিষ্ক্রিয় করুন</string>
|
||||
<string name="revanced_debug_title">ডিবাগ লগিং</string>
|
||||
<string name="revanced_debug_summary_on">ডিবাগ লগ সক্রিয় হয়েছে</string>
|
||||
<string name="revanced_debug_summary_off">ডিবাগ লগ নিষ্ক্রিয় হয়েছে</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_title">ডিবাগ লগগুলি রফতানি করুন</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_summary">ক্লিপবোর্ডে ReVanced ডিবাগ লগগুলি অনুলিপি করে</string>
|
||||
<string name="revanced_debug_logs_disabled">ডিবাগ লগিং নিষ্ক্রিয় করা হয়েছে</string>
|
||||
<string name="revanced_debug_logs_none_found">কোনো লগ পাওয়া যায়নি</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">লগ অনুলিপি করা হয়েছে</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">লগ এক্সপোর্ট করা যায়নি: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">ডিবাগ লগগুলি সাফ করুন</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">সমস্ত সঞ্চিত ReVanced ডিবাগ লগ সাফ করে</string>
|
||||
<string name="revanced_debug_logs_clear_toast">লগ সাফ করা হয়েছে</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="youtube">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
@@ -110,11 +143,6 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
|
||||
<string name="revanced_shorts_disable_background_playback_summary_off">Shorts ব্যাকগ্রাউন্ড প্লে সক্ষম করা হয়েছে</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">ডিবাগিং</string>
|
||||
<string name="revanced_debug_screen_summary">ডিবাগিং অপশন সক্রিয় বা নিষ্ক্রিয় করুন</string>
|
||||
<string name="revanced_debug_title">ডিবাগ লগিং</string>
|
||||
<string name="revanced_debug_summary_on">ডিবাগ লগ সক্রিয় হয়েছে</string>
|
||||
<string name="revanced_debug_summary_off">ডিবাগ লগ নিষ্ক্রিয় হয়েছে</string>
|
||||
<string name="revanced_debug_protobuffer_title">প্রটোকল বাফার লগ</string>
|
||||
<string name="revanced_debug_protobuffer_summary_on">ডিবাগ লগ প্রটোকল বাফার সংযুক্ত করবে</string>
|
||||
<string name="revanced_debug_protobuffer_summary_off">ডিবাগ লগ প্রটোকল বাফার সংযুক্ত করবে না</string>
|
||||
@@ -128,15 +156,6 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
|
||||
<string name="revanced_debug_toast_on_error_user_dialog_message">"ত্রুটি \"toast\" বন্ধ করে ReVanced ত্রুটি বিজ্ঞপ্তিগুলি লুকানো হয়।
|
||||
|
||||
আপনি কোনও অপ্রত্যাশিত ঘটনার বিষয়ে অবহিত হবেন না।"</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_title">ডিবাগ লগগুলি রফতানি করুন</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_summary">ক্লিপবোর্ডে ReVanced ডিবাগ লগগুলি অনুলিপি করে</string>
|
||||
<string name="revanced_debug_logs_disabled">ডিবাগ লগিং নিষ্ক্রিয় করা হয়েছে</string>
|
||||
<string name="revanced_debug_logs_none_found">কোনো লগ পাওয়া যায়নি</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">লগ অনুলিপি করা হয়েছে</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">লগ এক্সপোর্ট করা যায়নি: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">ডিবাগ লগগুলি সাফ করুন</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">সমস্ত সঞ্চিত ReVanced ডিবাগ লগ সাফ করে</string>
|
||||
<string name="revanced_debug_logs_clear_toast">লগ সাফ করা হয়েছে</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.general.hideLayoutComponentsPatch">
|
||||
<string name="revanced_hide_album_cards_title">অ্যালবাম কার্ড লুকান</string>
|
||||
@@ -698,7 +717,7 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
<string name="revanced_hide_player_flyout_audio_track_not_available">"অডিও ট্র্যাক মেনু লুকানো আছে
|
||||
|
||||
অডিও ট্র্যাক মেনু দেখাতে, 'স্পুফ ভিডিও স্ট্রিম' পরিবর্তন করে iOS TV করুন"</string>
|
||||
\"ভিডিও স্ট্রিম স্পুফ করুন\" সক্ষম করা হলে অডিও ট্র্যাক মেনু উপলব্ধ থাকে না"</string>
|
||||
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
|
||||
<string name="revanced_hide_player_flyout_watch_in_vr_title">ভিআর-এ ঘড়ি লুকান</string>
|
||||
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">ভিআর মেনুতে দেখুন লুকানো আছে</string>
|
||||
@@ -1070,10 +1089,12 @@ YouTube সেটিংসে অটো প্লে পরিবর্তন
|
||||
<string name="revanced_sb_segments_intro_sum">প্রকৃত বিষয়বস্তু ছাড়াই একটি বিরতি। বিরতি, স্থির ফ্রেম, অ্যানিমেশন পুনরাবৃত্তি হতে পারে। এটি তথ্যযুক্ত ট্রানজিশনের জন্য ব্যবহার করা উচিত নয়</string>
|
||||
<string name="revanced_sb_segments_outro">এন্ডকার্ডস / কৃতজ্ঞতা স্বীকার</string>
|
||||
<string name="revanced_sb_segments_outro_sum">ক্রেডিট বা যখন ইউটিউব এন্ডকার্ডগুলি উপস্থিত হয়। তথ্য সহ সিদ্ধান্তের জন্য নয়</string>
|
||||
<string name="revanced_sb_segments_preview">পূর্বরূপ/সংক্ষিপ্তবৃত্তি/হুক</string>
|
||||
<string name="revanced_sb_segments_hook">হুক / শুভেচ্ছা</string>
|
||||
<string name="revanced_sb_segments_hook_sum">আসন্ন ভিডিওর জন্য বর্ণিত ট্রেলার, শুভেচ্ছা এবং বিদায়। এমন অংশগুলি অন্তর্ভুক্ত নয় যা অতিরিক্ত সামগ্রী যোগ করে।</string>
|
||||
<string name="revanced_sb_segments_preview">পূর্বরূপ / সারসংক্ষেপ</string>
|
||||
<string name="revanced_sb_segments_preview_sum">একটি সমষ্টি ক্লিপ সমূহ যা ভিডিওতে এসে যা হচ্ছে বা অন্য ভিডিও সিরিজে ঘটেছে সেগুলি দেখায় যেখানে সমস্ত তথ্য অন্যত্র পুনরাবৃত্তি করা হয়</string>
|
||||
<string name="revanced_sb_segments_filler">স্পর্শক/কৌতুক ফিল্টার করুন</string>
|
||||
<string name="revanced_sb_segments_filler_sum">স্পর্শকাতর দৃশ্যগুলি শুধুমাত্র ফিলার বা হাস্যরসের জন্য যোগ করা হয়েছে যা ভিডিওর মূল বিষয়বস্তু বোঝার প্রয়োজন নেই। প্রসঙ্গ বা পটভূমির বিশদ প্রদানকারী বিভাগগুলি এতে অন্তর্ভুক্ত করা উচিত নয়</string>
|
||||
<string name="revanced_sb_segments_filler">অপ্রাসঙ্গিক / কৌতুক</string>
|
||||
<string name="revanced_sb_segments_filler_sum">পার্শ্বীয় দৃশ্য বা কৌতুক যা ভিডিওর মূল বিষয়বস্তু বোঝার জন্য অপরিহার্য নয়। প্রসঙ্গ বা পটভূমি বিশদ প্রদানকারী অংশগুলি অন্তর্ভুক্ত নয়।</string>
|
||||
<string name="revanced_sb_segments_nomusic">সঙ্গীত: সঙ্গীতবিহীন অংশ</string>
|
||||
<string name="revanced_sb_segments_nomusic_sum">শুধুমাত্র সঙ্গীত ভিডিওতে ব্যবহারের জন্য। এটি কেবলমাত্র সংগীত ভিডিওর সেসব বিভাগের জন্য ব্যবহার করা উচিত যা ইতিমধ্যে অন্য কোনও বিভাগ দ্বারা আচ্ছাদিত নয়।</string>
|
||||
<string name="revanced_sb_skip_button_compact">এড়িয়ে যান</string>
|
||||
@@ -1086,10 +1107,11 @@ YouTube সেটিংসে অটো প্লে পরিবর্তন
|
||||
<string name="revanced_sb_skip_button_intro_middle">উপসংহার এড়িয়ে যান</string>
|
||||
<string name="revanced_sb_skip_button_intro_end">উপসংহার এড়িয়ে যান</string>
|
||||
<string name="revanced_sb_skip_button_outro">শেষ অংশ এড়িয়ে যান</string>
|
||||
<string name="revanced_sb_skip_button_hook">হুক এড়িয়ে যান</string>
|
||||
<string name="revanced_sb_skip_button_preview_beginning">প্রিভিউ এড়িয়ে যান</string>
|
||||
<string name="revanced_sb_skip_button_preview_middle">প্রিভিউ এড়িয়ে যান</string>
|
||||
<string name="revanced_sb_skip_button_preview_end">সংক্ষিপ্তবৃত্তি এড়িয়ে যান</string>
|
||||
<string name="revanced_sb_skip_button_filler">ফিল্টার এড়িয়ে যান</string>
|
||||
<string name="revanced_sb_skip_button_filler">প্রাসঙ্গিকতা এড়িয়ে যান</string>
|
||||
<string name="revanced_sb_skip_button_nomusic">সঙ্গীত-বিহীন অংশ এড়িয়ে যান</string>
|
||||
<string name="revanced_sb_skip_button_unsubmitted">সেগমেন্ট এড়িয়ে যান</string>
|
||||
<string name="revanced_sb_skipped_sponsor">স্পন্সর এড়িয়ে গেছে</string>
|
||||
@@ -1100,10 +1122,11 @@ YouTube সেটিংসে অটো প্লে পরিবর্তন
|
||||
<string name="revanced_sb_skipped_intro_middle">উপসংহার এড়িয়ে গেছে</string>
|
||||
<string name="revanced_sb_skipped_intro_end">উপসংহার এড়িয়ে গেছে</string>
|
||||
<string name="revanced_sb_skipped_outro">শেষ অংশ এড়িয়ে গেছে</string>
|
||||
<string name="revanced_sb_skipped_hook">হুক এড়িয়ে যাওয়া হয়েছে</string>
|
||||
<string name="revanced_sb_skipped_preview_beginning">প্রাকদর্শন এড়িয়ে গেছে</string>
|
||||
<string name="revanced_sb_skipped_preview_middle">প্রাকদর্শন এড়িয়ে গেছে</string>
|
||||
<string name="revanced_sb_skipped_preview_end">সংক্ষিপ্তবৃত্তি এড়িয়ে গেছে</string>
|
||||
<string name="revanced_sb_skipped_filler">ফিল্টার এড়িয়ে গেছে</string>
|
||||
<string name="revanced_sb_skipped_filler">প্রাসঙ্গিকতা এড়িয়ে যাওয়া হয়েছে</string>
|
||||
<string name="revanced_sb_skipped_nomusic">একটি সঙ্গীতবিহীন অংশ এড়িয়ে গেছে</string>
|
||||
<string name="revanced_sb_skipped_unsubmitted">জমা না হওয়া সেগমেন্ট এড়িয়ে গেছে</string>
|
||||
<string name="revanced_sb_skipped_multiple_segments">একটানা একাধিক সেগমেন্ট এড়িয়ে গেছে</string>
|
||||
@@ -1407,10 +1430,6 @@ DeArrow সম্পর্কে আরও জানতে এখানে ট
|
||||
এটি সক্রিয় করা উচ্চ ভিডিও গুণমানগুলি আনলক করতে পারে"</string>
|
||||
<string name="revanced_spoof_device_dimensions_user_dialog_message">এটি সক্রিয় করার ফলে আপনি ভিডিও চলার ক্ষেত্রে আটকে চলা, খারাপ ব্যাটারি লাইফ এবং অজানা পার্শ্ব-প্রতিক্রিয়ার সম্মুখিন হতে পারেন।</string>
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<string name="microg_settings_title">GmsCore সেটিং</string>
|
||||
<string name="microg_settings_summary">GmsCore এর জন্য সেটিং</string>
|
||||
</patch>
|
||||
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
|
||||
<string name="revanced_disable_haptic_feedback_title">কম্পন প্রতিক্রিয়া</string>
|
||||
<string name="revanced_disable_haptic_feedback_summary">কম্পন প্রতিক্রিয়া পরিবর্তন করুন</string>
|
||||
@@ -1524,35 +1543,51 @@ DeArrow সম্পর্কে আরও জানতে এখানে ট
|
||||
<string name="revanced_slide_to_seek_summary_off">ভিডিওর নির্দিষ্ট অংশে যেতে টানুন সক্রিয় করা হয়নি</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<string name="revanced_spoof_video_streams_screen_title">ভিডিও স্ট্রিমিং স্পুফ করুন</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">প্লেব্যাক সমস্যা প্রতিরোধ করতে ক্লায়েন্ট ভিডিও স্ট্রিম স্পুফ করুন</string>
|
||||
<string name="revanced_spoof_video_streams_title">ভিডিও স্ট্রিমিং স্পুফ করুন</string>
|
||||
<string name="revanced_spoof_video_streams_summary_on">ভিডিও স্ট্রিম স্পুফ করা হয়েছে</string>
|
||||
<string name="revanced_spoof_video_streams_summary_off">"ভিডিও স্ট্রিম ভুয়া নয়
|
||||
|
||||
ভিডিও প্লেব্যাক কাজ নাও করতে পারে"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">এই সেটিংটি বন্ধ করার ফলে ভিডিও প্লেব্যাক ত্রুটি হতে পারে।</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">ডিফল্ট ক্লায়েন্ট</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">iOS AVC (H.264) বাধ্যতামূলক করুন</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">ভিডিও কোডেক AVC (H.264) এ বাধ্যতামূলক করা হয়েছে</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">ভিডিও কোডেক স্বয়ংক্রিয়ভাবে নির্ধারিত হয়</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"এটি সক্ষম করলে ব্যাটারি লাইফ উন্নত হতে পারে এবং প্লেব্যাক স্টাটারিং সমস্যা সমাধান হতে পারে।
|
||||
|
||||
AVC-এর সর্বোচ্চ রেজোলিউশন হল 1080p, Opus অডিও কোডেক পাওয়া যায় না এবং VP9 বা AV1-এর তুলনায় ভিডিও প্লেব্যাকে বেশি ইন্টারনেট ডেটা ব্যবহার করা হবে。"</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_title">আইওএস স্পুফিংয়ের পার্শ্ব প্রতিক্রিয়া</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• মুভি বা অর্থ প্রদানের ভিডিও চালু নাও হতে পারে
|
||||
• স্থির ভলিউম পাওয়া যায় না
|
||||
• ভিডিওগুলি 1 সেকেন্ড আগে শেষ হয়ে যায়"</string>
|
||||
<string name="revanced_spoof_video_streams_about_title">স্পুফিংয়ের পার্শ্বপ্রতিক্রিয়া</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_title">Android স্পুফিংয়ের পার্শ্বপ্রতিক্রিয়া</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"• অডিও ট্র্যাক মেনু নেই
|
||||
• স্থির ভলিউম পাওয়া যায় না
|
||||
• মূল অডিও জোর করে চালু করা যায় না"</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"• অডিও ট্র্যাক মেনু অনুপস্থিত
|
||||
• স্থিতিশীল ভলিউম উপলব্ধ নেই"</string>
|
||||
<string name="revanced_spoof_video_streams_about_experimental">• পরীক্ষামূলক ক্লায়েন্ট এবং যেকোনো সময় কাজ করা বন্ধ করতে পারে</string>
|
||||
<string name="revanced_spoof_video_streams_about_no_av1">• কোনো AV1 ভিডিও কোডেক নেই</string>
|
||||
<string name="revanced_spoof_video_streams_about_kids_videos">• লগআউট করা হলে বা ছদ্মবেশী মোডে বাচ্চাদের ভিডিও চলতে নাও পারে</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">VR ডিফল্ট অডিও স্ট্রিম ভাষা</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">অডিও স্ট্রিম ভাষা</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="music">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
<string name="revanced_settings_music_screen_0_about_title">সম্পর্কে</string>
|
||||
<string name="revanced_settings_music_screen_1_ads_title">বিজ্ঞাপন</string>
|
||||
<string name="revanced_settings_music_screen_2_general_title">সাধারণ</string>
|
||||
<string name="revanced_settings_music_screen_3_player_title">প্লেয়ার</string>
|
||||
<string name="revanced_settings_music_screen_4_misc_title">বিবিধ</string>
|
||||
</patch>
|
||||
<patch id="ad.video.hideVideoAdsPatch">
|
||||
<string name="revanced_music_hide_video_ads_title">ভিডিও বিজ্ঞাপন লুকান</string>
|
||||
<string name="revanced_music_hide_video_ads_summary_on">ভিডিও বিজ্ঞাপন লুকানো আছে</string>
|
||||
<string name="revanced_music_hide_video_ads_summary_off">ভিডিও বিজ্ঞাপন দেখানো আছে</string>
|
||||
</patch>
|
||||
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
|
||||
<string name="revanced_music_play_permanent_repeat_title">স্থায়ী পুনরাবৃত্তি সক্ষম করুন</string>
|
||||
<string name="revanced_music_play_permanent_repeat_summary_on">স্থায়ী পুনরাবৃত্তি সক্ষম করা হয়েছে</string>
|
||||
<string name="revanced_music_play_permanent_repeat_summary_off">স্থায়ী পুনরাবৃত্তি অক্ষম করা হয়েছে</string>
|
||||
</patch>
|
||||
<patch id="layout.compactheader.hideCategoryBar">
|
||||
<string name="revanced_music_hide_category_bar_title">ক্যাটাগরি বার লুকান</string>
|
||||
<string name="revanced_music_hide_category_bar_summary_on">ক্যাটাগরি বার লুকানো আছে</string>
|
||||
<string name="revanced_music_hide_category_bar_summary_off">ক্যাটাগরি বার দেখানো আছে</string>
|
||||
</patch>
|
||||
<patch id="layout.premium.hideGetPremiumPatch">
|
||||
<string name="revanced_music_hide_get_premium_label_title">\'গেট মিউজিক প্রিমিয়াম\' লেবেল লুকান</string>
|
||||
<string name="revanced_music_hide_get_premium_label_summary_on">লেবেল লুকানো আছে</string>
|
||||
<string name="revanced_music_hide_get_premium_label_summary_off">লেবেল দেখানো আছে</string>
|
||||
</patch>
|
||||
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
|
||||
<string name="revanced_music_hide_upgrade_button_title">আপগ্রেড বাটন লুকান</string>
|
||||
<string name="revanced_music_hide_upgrade_button_summary_on">বাটন লুকানো আছে</string>
|
||||
<string name="revanced_music_hide_upgrade_button_summary_off">বাটন দেখানো আছে</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
|
||||
@@ -30,6 +30,10 @@ Second \"item\" text"</string>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
</patch>
|
||||
</app>
|
||||
<app id="youtube">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
@@ -207,8 +211,6 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="misc.dimensions.spoof.spoofDeviceDimensionsPatch">
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
</patch>
|
||||
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
|
||||
</patch>
|
||||
<patch id="misc.gms.accountCredentialsInvalidTextPatch">
|
||||
@@ -242,6 +244,20 @@ Second \"item\" text"</string>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
</patch>
|
||||
</app>
|
||||
<app id="music">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
</patch>
|
||||
<patch id="ad.video.hideVideoAdsPatch">
|
||||
</patch>
|
||||
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
|
||||
</patch>
|
||||
<patch id="layout.compactheader.hideCategoryBar">
|
||||
</patch>
|
||||
<patch id="layout.premium.hideGetPremiumPatch">
|
||||
</patch>
|
||||
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
<patch id="ad.audio.audioAdsPatch">
|
||||
</patch>
|
||||
|
||||
@@ -30,6 +30,10 @@ Second \"item\" text"</string>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
</patch>
|
||||
</app>
|
||||
<app id="youtube">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
@@ -207,8 +211,6 @@ Second \"item\" text"</string>
|
||||
</patch>
|
||||
<patch id="misc.dimensions.spoof.spoofDeviceDimensionsPatch">
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
</patch>
|
||||
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
|
||||
</patch>
|
||||
<patch id="misc.gms.accountCredentialsInvalidTextPatch">
|
||||
@@ -242,6 +244,20 @@ Second \"item\" text"</string>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
</patch>
|
||||
</app>
|
||||
<app id="music">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
</patch>
|
||||
<patch id="ad.video.hideVideoAdsPatch">
|
||||
</patch>
|
||||
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
|
||||
</patch>
|
||||
<patch id="layout.compactheader.hideCategoryBar">
|
||||
</patch>
|
||||
<patch id="layout.premium.hideGetPremiumPatch">
|
||||
</patch>
|
||||
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
<patch id="ad.audio.audioAdsPatch">
|
||||
</patch>
|
||||
|
||||
@@ -68,6 +68,8 @@ Nové jazyky přeložíte na translate.revanced.app"</string>
|
||||
and changes made here must also be made there. -->
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<string name="microg_settings_title">Nastavení GmsCore</string>
|
||||
<string name="microg_settings_summary">Nastavení pro GmsCore</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="gms_core_toast_not_installed_message">MicroG GmsCore není nainstalován. Nainstalujte jej.</string>
|
||||
<string name="gms_core_dialog_title">Požadovaná akce</string>
|
||||
@@ -84,6 +86,37 @@ Zakázání optimalizace baterie pro MicroG nebude mít negativní vliv na spot
|
||||
Klepněte na tlačítko Pokračovat a povolte změny optimalizace."</string>
|
||||
<string name="gms_core_dialog_continue_text">Pokračovat</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<string name="revanced_spoof_video_streams_screen_title">Napodobovat video streamy</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Napodobovat klientské video streamy, aby se zabránilo problémům s přehráváním</string>
|
||||
<string name="revanced_spoof_video_streams_screen_title">Falšovat video streamy</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Falšovat video streamy klienta, aby se předešlo problémům s přehráváním.</string>
|
||||
<string name="revanced_spoof_video_streams_title">Napodobovat video streamy</string>
|
||||
<string name="revanced_spoof_video_streams_summary_on">"Video streamy jsou maskovány
|
||||
|
||||
Pokud jste uživatelem YouTube Premium, toto nastavení nemusí být vyžadováno."</string>
|
||||
<string name="revanced_spoof_video_streams_summary_off">"Video streamy nejsou falšované
|
||||
|
||||
Přehrávání nemusí fungovat"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">Vypnutí tohoto nastavení může způsobit problémy s přehráváním.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">Výchozí klient</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">Debugování</string>
|
||||
<string name="revanced_debug_screen_summary">Povolit nebo zakázat debugovací možnosti</string>
|
||||
<string name="revanced_debug_title">Debugovací záznamy</string>
|
||||
<string name="revanced_debug_summary_on">Debugovací záznamy jsou zapnuty</string>
|
||||
<string name="revanced_debug_summary_off">Debugovací záznamy jsou vypnuty</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_title">Exportovat ladicí protokoly</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_summary">Zkopíruje ladicí protokoly ReVanced do schránky</string>
|
||||
<string name="revanced_debug_logs_disabled">Ladění je vypnuto</string>
|
||||
<string name="revanced_debug_logs_none_found">Nebyly nalezeny žádné protokoly</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Protokoly zkopírovány</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Nepodařilo se exportovat protokoly: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Vymazat ladicí protokoly</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Vymaže všechny uložené ladicí protokoly ReVanced</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Protokoly vymazány</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="youtube">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
@@ -110,11 +143,6 @@ Klepněte na tlačítko Pokračovat a povolte změny optimalizace."</string>
|
||||
<string name="revanced_shorts_disable_background_playback_summary_off">Přehrávání Shorts v pozadí je povoleno</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">Debugování</string>
|
||||
<string name="revanced_debug_screen_summary">Povolit nebo zakázat debugovací možnosti</string>
|
||||
<string name="revanced_debug_title">Debugovací záznamy</string>
|
||||
<string name="revanced_debug_summary_on">Debugovací záznamy jsou zapnuty</string>
|
||||
<string name="revanced_debug_summary_off">Debugovací záznamy jsou vypnuty</string>
|
||||
<string name="revanced_debug_protobuffer_title">Záznam bufferu protokolu</string>
|
||||
<string name="revanced_debug_protobuffer_summary_on">Debugovací záznamy obsahují proto buffer</string>
|
||||
<string name="revanced_debug_protobuffer_summary_off">Debugovací záznamy neobsahují proto buffer</string>
|
||||
@@ -132,15 +160,6 @@ Povolením této možnosti se však budou zaznamenávat i některá uživatelsk
|
||||
<string name="revanced_debug_toast_on_error_user_dialog_message">"Vypnutí chybových toastů skryje všechna chybová oznámení ReVanced.
|
||||
|
||||
Nebudete informováni o žádné neočekávané události."</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_title">Exportovat ladicí protokoly</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_summary">Zkopíruje ladicí protokoly ReVanced do schránky</string>
|
||||
<string name="revanced_debug_logs_disabled">Ladění je vypnuto</string>
|
||||
<string name="revanced_debug_logs_none_found">Nebyly nalezeny žádné protokoly</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Protokoly zkopírovány</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Nepodařilo se exportovat protokoly: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Vymazat ladicí protokoly</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Vymaže všechny uložené ladicí protokoly ReVanced</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Protokoly vymazány</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.general.hideLayoutComponentsPatch">
|
||||
<string name="revanced_hide_album_cards_title">Skrýt karty alb</string>
|
||||
@@ -700,9 +719,9 @@ Pokud změna tohoto nastavení nemá žádný účinek, zkuste přepnout do rež
|
||||
<string name="revanced_hide_player_flyout_audio_track_summary_on">Menu Zvuková stopa je skryto</string>
|
||||
<string name="revanced_hide_player_flyout_audio_track_summary_off">Menu Zvuková stopa je zobrazeno</string>
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
<string name="revanced_hide_player_flyout_audio_track_not_available">"Nabídka zvukové stopy je skrytá.
|
||||
<string name="revanced_hide_player_flyout_audio_track_not_available">"Nabídka zvukové stopy je skrytá
|
||||
|
||||
Chcete-li zobrazit nabídku zvukové stopy, změňte možnost „Zfalšovat streamy videa“ na iOS TV"</string>
|
||||
Nabídka zvukové stopy není dostupná, když je povoleno 'Maskování video streamů'."</string>
|
||||
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
|
||||
<string name="revanced_hide_player_flyout_watch_in_vr_title">Skrýt Sledovat ve VR</string>
|
||||
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Menu Sledovat ve VR je skryto</string>
|
||||
@@ -1075,10 +1094,12 @@ Vaše ID uživatele je jako heslo a nikdy by nemělo být sdíleno."</string>
|
||||
<string name="revanced_sb_segments_intro_sum">Interval bez skutečného obsahu. Může to být pauza, statický snímek nebo opakující se animace. Neobsahuje přechody s informacemi</string>
|
||||
<string name="revanced_sb_segments_outro">Outro / Závěrečné titulky</string>
|
||||
<string name="revanced_sb_segments_outro_sum">Titulky nebo když se objeví závěrečné karty YouTube. Ne pro závěry s informacemi</string>
|
||||
<string name="revanced_sb_segments_preview">Náhled/Shrnutí/Háček</string>
|
||||
<string name="revanced_sb_segments_hook">Úvod / Pozdravy</string>
|
||||
<string name="revanced_sb_segments_hook_sum">Komentované upoutávky na nadcházející video, pozdravy a rozloučení. Neobsahuje sekce, které přidávají další obsah</string>
|
||||
<string name="revanced_sb_segments_preview">Náhled / Shrnutí</string>
|
||||
<string name="revanced_sb_segments_preview_sum">Sbírka klipů, které ukazují, co se chystá nebo co se stalo ve videu nebo v jiných videích série, kde jsou všechny informace opakované jinde</string>
|
||||
<string name="revanced_sb_segments_filler">Výplň / vtipy</string>
|
||||
<string name="revanced_sb_segments_filler_sum">Vedlejší scény přidány pouze pro výplň nebo humor, které nejsou nutné pro pochopení hlavního obsahu videa. Neobsahuje segmenty poskytující kontext nebo podrobnosti o pozadí</string>
|
||||
<string name="revanced_sb_segments_filler">Odbočka / Vtipy</string>
|
||||
<string name="revanced_sb_segments_filler_sum">Vedlejší scény nebo vtipy, které nejsou nutné k pochopení hlavního obsahu videa. Neobsahuje sekce poskytující kontext nebo podrobnosti na pozadí</string>
|
||||
<string name="revanced_sb_segments_nomusic">Hudba: nehudební sekce</string>
|
||||
<string name="revanced_sb_segments_nomusic_sum">Pouze pro použití v hudebních videích. Sekce hudebních videí bez hudby, které nejsou již pokryty jinou kategorií</string>
|
||||
<string name="revanced_sb_skip_button_compact">Přeskočit</string>
|
||||
@@ -1091,10 +1112,11 @@ Vaše ID uživatele je jako heslo a nikdy by nemělo být sdíleno."</string>
|
||||
<string name="revanced_sb_skip_button_intro_middle">Přeskočit přestávku</string>
|
||||
<string name="revanced_sb_skip_button_intro_end">Přeskočit přestávku</string>
|
||||
<string name="revanced_sb_skip_button_outro">Přeskočit závěr</string>
|
||||
<string name="revanced_sb_skip_button_hook">Přeskočit úvod</string>
|
||||
<string name="revanced_sb_skip_button_preview_beginning">Přeskočit náhled</string>
|
||||
<string name="revanced_sb_skip_button_preview_middle">Přeskočit náhled</string>
|
||||
<string name="revanced_sb_skip_button_preview_end">Přeskočit shrnutí</string>
|
||||
<string name="revanced_sb_skip_button_filler">Přeskočit výplň</string>
|
||||
<string name="revanced_sb_skip_button_filler">Přeskočit vedlejší část</string>
|
||||
<string name="revanced_sb_skip_button_nomusic">Přeskočit bez hudby</string>
|
||||
<string name="revanced_sb_skip_button_unsubmitted">Přeskočit segment</string>
|
||||
<string name="revanced_sb_skipped_sponsor">Sponzor přeskočen</string>
|
||||
@@ -1105,10 +1127,11 @@ Vaše ID uživatele je jako heslo a nikdy by nemělo být sdíleno."</string>
|
||||
<string name="revanced_sb_skipped_intro_middle">Přeskočena přestávka</string>
|
||||
<string name="revanced_sb_skipped_intro_end">Přeskočena přestávka</string>
|
||||
<string name="revanced_sb_skipped_outro">Outro přeskočeno</string>
|
||||
<string name="revanced_sb_skipped_hook">Úvod přeskočen</string>
|
||||
<string name="revanced_sb_skipped_preview_beginning">Přeskočena ukázka/rekapitulace</string>
|
||||
<string name="revanced_sb_skipped_preview_middle">Přeskočena ukázka/rekapitulace</string>
|
||||
<string name="revanced_sb_skipped_preview_end">Přeskočeno shrnutí</string>
|
||||
<string name="revanced_sb_skipped_filler">Přeskočená nepodstatná výplň videa</string>
|
||||
<string name="revanced_sb_skipped_filler">Vedlejší část přeskočena</string>
|
||||
<string name="revanced_sb_skipped_nomusic">Přeskočena nehudební sekce</string>
|
||||
<string name="revanced_sb_skipped_unsubmitted">Přeskočen neodeslaný segment</string>
|
||||
<string name="revanced_sb_skipped_multiple_segments">Přeskočeno více segmentů</string>
|
||||
@@ -1411,10 +1434,6 @@ Mohou být odemčeny vyšší kvality videa, ale může dojít k zadrhávání p
|
||||
Povolením této funkce lze odemknout vyšší kvality videa"</string>
|
||||
<string name="revanced_spoof_device_dimensions_user_dialog_message">Povolení může způsobit zasekávání přehrávání, zhoršenou výdrž baterie a neznámé vedlejší účinky.</string>
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<string name="microg_settings_title">Nastavení GmsCore</string>
|
||||
<string name="microg_settings_summary">Nastavení pro GmsCore</string>
|
||||
</patch>
|
||||
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
|
||||
<string name="revanced_disable_haptic_feedback_title">Haptická odezva</string>
|
||||
<string name="revanced_disable_haptic_feedback_summary">Změnit haptickou odezvu</string>
|
||||
@@ -1528,35 +1547,51 @@ Povolením této funkce lze odemknout vyšší kvality videa"</string>
|
||||
<string name="revanced_slide_to_seek_summary_off">Posun pro hledání není povolen</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<string name="revanced_spoof_video_streams_screen_title">Napodobovat video streamy</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Napodobovat klientské video streamy, aby se zabránilo problémům s přehráváním</string>
|
||||
<string name="revanced_spoof_video_streams_title">Napodobovat video streamy</string>
|
||||
<string name="revanced_spoof_video_streams_summary_on">Video streamy jsou napodobeny</string>
|
||||
<string name="revanced_spoof_video_streams_summary_off">"Video streamy nejsou zfalšovány
|
||||
|
||||
Přehrávání videa nemusí fungovat"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">Vypnutí tohoto nastavení může způsobit problémy s přehráváním videa.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">Výchozí klient</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">Vynucení kodeku iOS AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">Kodek videa je vynucen na AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">Kodek videa je určen automaticky</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"Povolení této funkce může zlepšit výdrž baterie a opravit sekání videa.
|
||||
|
||||
AVC má maximální rozlišení 1080p, zvukový kodek Opus není dostupný a přehrávání videa bude používat více dat než VP9 nebo AV1."</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_title">iOS spoofing vedlejší účinky</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• Filmy nebo placená videa se nemusí přehrávat
|
||||
• Stabilní hlasitost není k dispozici
|
||||
• Videa končí o 1 sekundu dříve"</string>
|
||||
<string name="revanced_spoof_video_streams_about_title">Vedlejší účinky maskování</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_title">Vedlejší účinky spoofingu Androidu</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"• Chybí nabídka zvukových stop
|
||||
• Není k dispozici stabilní hlasitost
|
||||
• Není k dispozici možnost vynucení originálního zvuku"</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"• Chybí nabídka zvukové stopy
|
||||
• Stabilní hlasitost není k dispozici"</string>
|
||||
<string name="revanced_spoof_video_streams_about_experimental">• Experimentální klient a může kdykoli přestat fungovat</string>
|
||||
<string name="revanced_spoof_video_streams_about_no_av1">• Žádný video kodek AV1</string>
|
||||
<string name="revanced_spoof_video_streams_about_kids_videos">• Dětská videa se nemusí přehrávat, když jste odhlášení nebo v anonymním režimu</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">Výchozí jazyk zvukového streamu ve VR</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">Jazyk zvukového streamu</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="music">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
<string name="revanced_settings_music_screen_0_about_title">O aplikaci</string>
|
||||
<string name="revanced_settings_music_screen_1_ads_title">Reklamy</string>
|
||||
<string name="revanced_settings_music_screen_2_general_title">Obecné</string>
|
||||
<string name="revanced_settings_music_screen_3_player_title">Přehrávač</string>
|
||||
<string name="revanced_settings_music_screen_4_misc_title">Různé</string>
|
||||
</patch>
|
||||
<patch id="ad.video.hideVideoAdsPatch">
|
||||
<string name="revanced_music_hide_video_ads_title">Skrýt videoreklamy</string>
|
||||
<string name="revanced_music_hide_video_ads_summary_on">Videoreklamy jsou skryty</string>
|
||||
<string name="revanced_music_hide_video_ads_summary_off">Videoreklamy jsou zobrazeny</string>
|
||||
</patch>
|
||||
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
|
||||
<string name="revanced_music_play_permanent_repeat_title">Povolit trvalé opakování</string>
|
||||
<string name="revanced_music_play_permanent_repeat_summary_on">Trvalé opakování je povoleno</string>
|
||||
<string name="revanced_music_play_permanent_repeat_summary_off">Trvalé opakování je zakázáno</string>
|
||||
</patch>
|
||||
<patch id="layout.compactheader.hideCategoryBar">
|
||||
<string name="revanced_music_hide_category_bar_title">Skrýt panel kategorií</string>
|
||||
<string name="revanced_music_hide_category_bar_summary_on">Panel kategorií je skryt</string>
|
||||
<string name="revanced_music_hide_category_bar_summary_off">Panel kategorií je zobrazen</string>
|
||||
</patch>
|
||||
<patch id="layout.premium.hideGetPremiumPatch">
|
||||
<string name="revanced_music_hide_get_premium_label_title">Skrýt štítek \"Získat Music Premium\"</string>
|
||||
<string name="revanced_music_hide_get_premium_label_summary_on">Štítek je skryt</string>
|
||||
<string name="revanced_music_hide_get_premium_label_summary_off">Štítek je zobrazen</string>
|
||||
</patch>
|
||||
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
|
||||
<string name="revanced_music_hide_upgrade_button_title">Skrýt tlačítko pro upgrade</string>
|
||||
<string name="revanced_music_hide_upgrade_button_summary_on">Tlačítko je skryto</string>
|
||||
<string name="revanced_music_hide_upgrade_button_summary_off">Tlačítko je zobrazeno</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
|
||||
@@ -68,6 +68,8 @@ For at oversætte til nye sprog skal du besøge translate.revanced.app"</string>
|
||||
and changes made here must also be made there. -->
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<string name="microg_settings_title">GmsCore Indstillinger</string>
|
||||
<string name="microg_settings_summary">Indstillinger for GmsCore</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="gms_core_toast_not_installed_message">MicroG GmsCore er ikke installeret. Installer det.</string>
|
||||
<string name="gms_core_dialog_title">Handling påkrævet</string>
|
||||
@@ -84,6 +86,37 @@ Deaktivering af batterioptimeringer for MicroG vil ikke påvirke batteriforbruge
|
||||
Tap på knappen Fortsæt, og tillad optimeringsændringer."</string>
|
||||
<string name="gms_core_dialog_continue_text">Fortsæt</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<string name="revanced_spoof_video_streams_screen_title">Spoof videostreams</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Spoof klienten video streams for at forhindre afspilning problemer</string>
|
||||
<string name="revanced_spoof_video_streams_screen_title">Simuler videostreams</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Simuler klientens videostreams for at forhindre afspilningsproblemer</string>
|
||||
<string name="revanced_spoof_video_streams_title">Spoof videostreams</string>
|
||||
<string name="revanced_spoof_video_streams_summary_on">"Videostreams er spoofede
|
||||
|
||||
Hvis du er en YouTube Premium-bruger, er denne indstilling muligvis ikke påkrævet"</string>
|
||||
<string name="revanced_spoof_video_streams_summary_off">"Videostreams simuleres ikke
|
||||
|
||||
Afspilning fungerer muligvis ikke"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">Deaktivering af denne indstilling kan forårsage afspilningsproblemer.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">Standard klient</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">Fejlfinding</string>
|
||||
<string name="revanced_debug_screen_summary">Aktivér eller deaktiver fejlfindingsindstillinger</string>
|
||||
<string name="revanced_debug_title">Fejlfindingslogning</string>
|
||||
<string name="revanced_debug_summary_on">Fejlfindingslogge er aktiveret</string>
|
||||
<string name="revanced_debug_summary_off">Fejlfindingslogge er deaktiveret</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_title">Eksportér fejlsøgningslogfiler</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_summary">Kopierer ReVanced-fejlsøgningslogfiler til udklipsholderen</string>
|
||||
<string name="revanced_debug_logs_disabled">Fejlsøgningslogning er deaktiveret</string>
|
||||
<string name="revanced_debug_logs_none_found">Ingen logfiler fundet</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Logfiler kopieret</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Kunne ikke eksportere logfiler: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Ryd fejlsøgningslogfiler</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Rydder alle gemte ReVanced-fejlsøgningslogfiler</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Logfiler ryddet</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="youtube">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
@@ -110,11 +143,6 @@ Tap på knappen Fortsæt, og tillad optimeringsændringer."</string>
|
||||
<string name="revanced_shorts_disable_background_playback_summary_off">Baggrundsafspilning af Shorts er aktiveret</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">Fejlfinding</string>
|
||||
<string name="revanced_debug_screen_summary">Aktivér eller deaktiver fejlfindingsindstillinger</string>
|
||||
<string name="revanced_debug_title">Fejlfindingslogning</string>
|
||||
<string name="revanced_debug_summary_on">Fejlfindingslogge er aktiveret</string>
|
||||
<string name="revanced_debug_summary_off">Fejlfindingslogge er deaktiveret</string>
|
||||
<string name="revanced_debug_protobuffer_title">Logprotokolbuffer</string>
|
||||
<string name="revanced_debug_protobuffer_summary_on">Fejlfindingslogge inkluderer protobuffer</string>
|
||||
<string name="revanced_debug_protobuffer_summary_off">Fejlfindingslogge inkluderer ikke protobuffer</string>
|
||||
@@ -132,15 +160,6 @@ Aktivering af dette vil dog også logge nogle brugerdata, såsom din IP-adresse.
|
||||
<string name="revanced_debug_toast_on_error_user_dialog_message">"Hvis du deaktiverer fejl-toasts, skjules alle ReVanced-fejlmeddelelser.
|
||||
|
||||
Du modtager ikke notifikationer om uventede hændelser."</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_title">Eksportér fejlsøgningslogfiler</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_summary">Kopierer ReVanced-fejlsøgningslogfiler til udklipsholderen</string>
|
||||
<string name="revanced_debug_logs_disabled">Fejlsøgningslogning er deaktiveret</string>
|
||||
<string name="revanced_debug_logs_none_found">Ingen logfiler fundet</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Logfiler kopieret</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Kunne ikke eksportere logfiler: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Ryd fejlsøgningslogfiler</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Rydder alle gemte ReVanced-fejlsøgningslogfiler</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Logfiler ryddet</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.general.hideLayoutComponentsPatch">
|
||||
<string name="revanced_hide_album_cards_title">Skjul albumkort</string>
|
||||
@@ -700,9 +719,9 @@ Hvis ændring af denne indstilling ikke træder i kraft, kan du prøve at skifte
|
||||
<string name="revanced_hide_player_flyout_audio_track_summary_on">Menuen for lydspor er skjult</string>
|
||||
<string name="revanced_hide_player_flyout_audio_track_summary_off">Menuen Lydspor vises</string>
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
<string name="revanced_hide_player_flyout_audio_track_not_available">"Lydspormenuen er skjult
|
||||
<string name="revanced_hide_player_flyout_audio_track_not_available">"Lydsporsmenuen er skjult
|
||||
|
||||
For at vise lydspormenuen skal du ændre \"Spoof videostream\" til iOS TV"</string>
|
||||
Lydsporsmenuen er ikke tilgængelig, når 'Spoof videostreams' er aktiveret"</string>
|
||||
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
|
||||
<string name="revanced_hide_player_flyout_watch_in_vr_title">Skjul vagt i VR</string>
|
||||
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Se i VR-menuen er skjult</string>
|
||||
@@ -1077,10 +1096,12 @@ Dit bruger-id er som en adgangskode, og det må aldrig deles.
|
||||
<string name="revanced_sb_segments_intro_sum">Et interval uden reelt indhold. Kunne være en pause, statisk ramme eller gentagelse af animation. Omfatter ikke overgange indeholdende information</string>
|
||||
<string name="revanced_sb_segments_outro">Slutkort / Kredit</string>
|
||||
<string name="revanced_sb_segments_outro_sum">Medvirkende eller når YouTube-endcards vises. Ikke for konklusioner med information</string>
|
||||
<string name="revanced_sb_segments_preview">Forhåndsvisning/Genoptag/Krog</string>
|
||||
<string name="revanced_sb_segments_hook">Intro / Hilsener</string>
|
||||
<string name="revanced_sb_segments_hook_sum">Fortalte trailere for den kommende video, hilsener og farvel. Indeholder ikke afsnit, der tilføjer yderligere indhold</string>
|
||||
<string name="revanced_sb_segments_preview">Forhåndsvisning / Resumé</string>
|
||||
<string name="revanced_sb_segments_preview_sum">Indsamling af klip, der viser, hvad der kommer op, eller hvad der skete i videoen eller i andre videoer af en serie, hvor alle oplysninger gentages andetsteds</string>
|
||||
<string name="revanced_sb_segments_filler">Fyldstof-tangent/jokes</string>
|
||||
<string name="revanced_sb_segments_filler_sum">Tangential scener tilføjet kun for fyldstof eller humor, der ikke er forpligtet til at forstå hovedindholdet af videoen. Omfatter ikke segmenter, der giver kontekst- eller baggrundsoplysninger</string>
|
||||
<string name="revanced_sb_segments_filler">Sidespor / Vittigheder</string>
|
||||
<string name="revanced_sb_segments_filler_sum">Tangentielle scener eller vittigheder, der ikke er nødvendige for at forstå videoens hovedindhold. Indeholder ikke afsnit, der giver kontekst eller baggrundsoplysninger</string>
|
||||
<string name="revanced_sb_segments_nomusic">Musik: Ikke-Musik Sektion</string>
|
||||
<string name="revanced_sb_segments_nomusic_sum">Kun til brug i musikvideoer. Sektioner af musikvideoer uden musik, der ikke allerede er dækket af en anden kategori</string>
|
||||
<string name="revanced_sb_skip_button_compact">Overspring</string>
|
||||
@@ -1093,10 +1114,11 @@ Dit bruger-id er som en adgangskode, og det må aldrig deles.
|
||||
<string name="revanced_sb_skip_button_intro_middle">Spring intermission over</string>
|
||||
<string name="revanced_sb_skip_button_intro_end">Spring intermission over</string>
|
||||
<string name="revanced_sb_skip_button_outro">Spring outro over</string>
|
||||
<string name="revanced_sb_skip_button_hook">Spring hook over</string>
|
||||
<string name="revanced_sb_skip_button_preview_beginning">Spring forhåndsvisning over</string>
|
||||
<string name="revanced_sb_skip_button_preview_middle">Spring forhåndsvisning over</string>
|
||||
<string name="revanced_sb_skip_button_preview_end">Spring resumé over</string>
|
||||
<string name="revanced_sb_skip_button_filler">Spring filler over</string>
|
||||
<string name="revanced_sb_skip_button_filler">Spring tangent over</string>
|
||||
<string name="revanced_sb_skip_button_nomusic">Spring over ikke-musik</string>
|
||||
<string name="revanced_sb_skip_button_unsubmitted">Overspring segment</string>
|
||||
<string name="revanced_sb_skipped_sponsor">Sponsor sprunget over</string>
|
||||
@@ -1107,10 +1129,11 @@ Dit bruger-id er som en adgangskode, og det må aldrig deles.
|
||||
<string name="revanced_sb_skipped_intro_middle">Intermission sprunget over</string>
|
||||
<string name="revanced_sb_skipped_intro_end">Intermission sprunget over</string>
|
||||
<string name="revanced_sb_skipped_outro">Sprunget over outro</string>
|
||||
<string name="revanced_sb_skipped_hook">Hook sprunget over</string>
|
||||
<string name="revanced_sb_skipped_preview_beginning">Forklaring sprunget over</string>
|
||||
<string name="revanced_sb_skipped_preview_middle">Forklaring sprunget over</string>
|
||||
<string name="revanced_sb_skipped_preview_end">Oversprunget resumé</string>
|
||||
<string name="revanced_sb_skipped_filler">Fyldstof sprunget over</string>
|
||||
<string name="revanced_sb_skipped_filler">Tangent sprunget over</string>
|
||||
<string name="revanced_sb_skipped_nomusic">Oversprunget en ikke-musiksektion over</string>
|
||||
<string name="revanced_sb_skipped_unsubmitted">Uindsendt segment sprunget over</string>
|
||||
<string name="revanced_sb_skipped_multiple_segments">Oversprunget over flere segmenter</string>
|
||||
@@ -1413,10 +1436,6 @@ Højere videokvalitet kan låses op, men du kan opleve videoafspilningshakkethed
|
||||
Aktivering af dette kan låse op for højere videokvalitet"</string>
|
||||
<string name="revanced_spoof_device_dimensions_user_dialog_message">Aktivering af dette kan forårsage videoafspilning stuttering, værre batterilevetid og ukendte bivirkninger.</string>
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<string name="microg_settings_title">GmsCore Indstillinger</string>
|
||||
<string name="microg_settings_summary">Indstillinger for GmsCore</string>
|
||||
</patch>
|
||||
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
|
||||
<string name="revanced_disable_haptic_feedback_title">Haptisk feedback</string>
|
||||
<string name="revanced_disable_haptic_feedback_summary">Skift haptisk feedback</string>
|
||||
@@ -1530,33 +1549,51 @@ Aktivering af dette kan låse op for højere videokvalitet"</string>
|
||||
<string name="revanced_slide_to_seek_summary_off">Dias til søgning er ikke aktiveret</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<string name="revanced_spoof_video_streams_screen_title">Spoof videostreams</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Spoof klienten video streams for at forhindre afspilning problemer</string>
|
||||
<string name="revanced_spoof_video_streams_title">Spoof videostreams</string>
|
||||
<string name="revanced_spoof_video_streams_summary_on">Video streams er spoofed</string>
|
||||
<string name="revanced_spoof_video_streams_summary_off">"Videostreams forfalskes ikke
|
||||
|
||||
Videoafspilning virker muligvis ikke"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">At slå denne indstilling fra kan forårsage problemer med videoafspilning.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">Standard klient</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">Forceer iOS AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">Videokodec er tvunget til AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">Videokodec bestemmes automatisk</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"Aktivering af dette kan forbedre batterilevetiden og rette afspilningshakken.\n\nAVC har en maksimal opløsning på 1080p, Opus-lydkodec er ikke tilgængelig, og videoafspilning vil bruge mere internetdata end VP9 eller AV1."</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_title">iOS-spoofing kan have følgende bivirkninger</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• Film eller betalte videoer afspilles muligvis ikke
|
||||
• Stabil lydstyrke er ikke tilgængelig
|
||||
• Videoer slutter 1 sekund for tidligt"</string>
|
||||
<string name="revanced_spoof_video_streams_about_title">Bivirkninger ved spoofing</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_title">Bivirkninger ved Android-spoofing</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"• Lydspormenu mangler
|
||||
• Stabil lydstyrke er ikke tilgængelig
|
||||
• Gennemtving original lyd er ikke tilgængelig"</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"• Lydsporsmenuen mangler
|
||||
• Stabil lydstyrke er ikke tilgængelig"</string>
|
||||
<string name="revanced_spoof_video_streams_about_experimental">• Eksperimentel klient og kan stoppe med at fungere når som helst</string>
|
||||
<string name="revanced_spoof_video_streams_about_no_av1">• Intet AV1-videokodek</string>
|
||||
<string name="revanced_spoof_video_streams_about_kids_videos">• Videoer til børn afspilles muligvis ikke, når du er logget ud eller i inkognitotilstand</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">VR-standardsprog for lydstrømme</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">Lydstreamsprog</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="music">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
<string name="revanced_settings_music_screen_0_about_title">Om</string>
|
||||
<string name="revanced_settings_music_screen_1_ads_title">Annoncer</string>
|
||||
<string name="revanced_settings_music_screen_2_general_title">Generelt</string>
|
||||
<string name="revanced_settings_music_screen_3_player_title">Afspiller</string>
|
||||
<string name="revanced_settings_music_screen_4_misc_title">Diverse</string>
|
||||
</patch>
|
||||
<patch id="ad.video.hideVideoAdsPatch">
|
||||
<string name="revanced_music_hide_video_ads_title">Skjul videoannoncer</string>
|
||||
<string name="revanced_music_hide_video_ads_summary_on">Videoannoncer er skjult</string>
|
||||
<string name="revanced_music_hide_video_ads_summary_off">Videoannoncer vises</string>
|
||||
</patch>
|
||||
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
|
||||
<string name="revanced_music_play_permanent_repeat_title">Aktiver permanent gentagelse</string>
|
||||
<string name="revanced_music_play_permanent_repeat_summary_on">Permanent gentagelse er aktiveret</string>
|
||||
<string name="revanced_music_play_permanent_repeat_summary_off">Permanent gentagelse er deaktiveret</string>
|
||||
</patch>
|
||||
<patch id="layout.compactheader.hideCategoryBar">
|
||||
<string name="revanced_music_hide_category_bar_title">Skjul kategorilinje</string>
|
||||
<string name="revanced_music_hide_category_bar_summary_on">Kategorilinjen er skjult</string>
|
||||
<string name="revanced_music_hide_category_bar_summary_off">Kategorilinjen vises</string>
|
||||
</patch>
|
||||
<patch id="layout.premium.hideGetPremiumPatch">
|
||||
<string name="revanced_music_hide_get_premium_label_title">Skjul \'Få Music Premium\'-etiket</string>
|
||||
<string name="revanced_music_hide_get_premium_label_summary_on">Etiketten er skjult</string>
|
||||
<string name="revanced_music_hide_get_premium_label_summary_off">Etiketten vises</string>
|
||||
</patch>
|
||||
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
|
||||
<string name="revanced_music_hide_upgrade_button_title">Skjul opgraderingsknap</string>
|
||||
<string name="revanced_music_hide_upgrade_button_summary_on">Knappen er skjult</string>
|
||||
<string name="revanced_music_hide_upgrade_button_summary_off">Knappen vises</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
|
||||
@@ -68,6 +68,8 @@ Um neue Sprachen zu übersetzen, besuchen Sie translate.revanced.app"</string>
|
||||
and changes made here must also be made there. -->
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<string name="microg_settings_title">GmsCore Einstellungen</string>
|
||||
<string name="microg_settings_summary">Einstellungen für GmsCore</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="gms_core_toast_not_installed_message">MicroG GmsCore ist nicht installiert. Installieren Sie es.</string>
|
||||
<string name="gms_core_dialog_title">Aktion notwendig</string>
|
||||
@@ -82,6 +84,37 @@ Die Deaktivierung der Batterieoptimierung für MicroG hat keinen negativen Einfl
|
||||
Tippen Sie auf die Schaltfläche \"Fortfahren\" und erlauben Sie die Optimierungsänderungen."</string>
|
||||
<string name="gms_core_dialog_continue_text">Weiter</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<string name="revanced_spoof_video_streams_screen_title">Spoof-Video-Streams</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Spoof der Client-Videostreams um Wiedergabeprobleme zu verhindern</string>
|
||||
<string name="revanced_spoof_video_streams_screen_title">Video-Streams vortäuschen</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Die Client-Video-Streams vortäuschen, um Wiedergabeprobleme zu verhindern</string>
|
||||
<string name="revanced_spoof_video_streams_title">Spoof-Video-Streams</string>
|
||||
<string name="revanced_spoof_video_streams_summary_on">"Videostreams werden gespooft
|
||||
|
||||
Wenn Sie ein YouTube Premium-Nutzer sind, ist diese Einstellung möglicherweise nicht erforderlich"</string>
|
||||
<string name="revanced_spoof_video_streams_summary_off">"Video-Streams werden nicht vorgetäuscht
|
||||
|
||||
Die Wiedergabe funktioniert möglicherweise nicht"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">Das Deaktivieren dieser Einstellung kann Wiedergabeprobleme verursachen.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">Standard-Client</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">Fehlerbehebung</string>
|
||||
<string name="revanced_debug_screen_summary">Aktiviert oder deaktiviert Debugging-Optionen</string>
|
||||
<string name="revanced_debug_title">Debug-Protokollierung</string>
|
||||
<string name="revanced_debug_summary_on">Debug-Protokolle sind aktiviert</string>
|
||||
<string name="revanced_debug_summary_off">Debug-Protokolle sind deaktiviert</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_title">Debug-Protokolle exportieren</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_summary">Kopiert ReVanced-Debug-Protokolle in die Zwischenablage</string>
|
||||
<string name="revanced_debug_logs_disabled">Debug-Protokollierung ist deaktiviert</string>
|
||||
<string name="revanced_debug_logs_none_found">Keine Protokolle gefunden</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Protokolle kopiert</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Fehler beim Exportieren der Protokolle: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Debug-Protokolle löschen</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Löscht alle gespeicherten ReVanced-Debug-Protokolle</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Protokolle gelöscht</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="youtube">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
@@ -108,11 +141,6 @@ Tippen Sie auf die Schaltfläche \"Fortfahren\" und erlauben Sie die Optimierung
|
||||
<string name="revanced_shorts_disable_background_playback_summary_off">Shorts-Hintergrundwiedergabe ist aktiviert</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">Fehlerbehebung</string>
|
||||
<string name="revanced_debug_screen_summary">Aktiviert oder deaktiviert Debugging-Optionen</string>
|
||||
<string name="revanced_debug_title">Debug-Protokollierung</string>
|
||||
<string name="revanced_debug_summary_on">Debug-Protokolle sind aktiviert</string>
|
||||
<string name="revanced_debug_summary_off">Debug-Protokolle sind deaktiviert</string>
|
||||
<string name="revanced_debug_protobuffer_title">Protokollpuffer protokollieren</string>
|
||||
<string name="revanced_debug_protobuffer_summary_on">Debug-Protokolle enthalten Protokollpuffer</string>
|
||||
<string name="revanced_debug_protobuffer_summary_off">Debug-Protokolle enthalten kein Protokollpuffer</string>
|
||||
@@ -130,15 +158,6 @@ Wenn Sie dies aktivieren, werden jedoch auch einige Benutzerdaten wie Ihre IP-Ad
|
||||
<string name="revanced_debug_toast_on_error_user_dialog_message">"Das Ausschalten von Fehler-Toasts blendet alle Benachrichtigungen über Fehler in ReVanced aus.
|
||||
|
||||
Sie werden nicht über unerwartete Ereignisse informiert."</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_title">Debug-Protokolle exportieren</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_summary">Kopiert ReVanced-Debug-Protokolle in die Zwischenablage</string>
|
||||
<string name="revanced_debug_logs_disabled">Debug-Protokollierung ist deaktiviert</string>
|
||||
<string name="revanced_debug_logs_none_found">Keine Protokolle gefunden</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Protokolle kopiert</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Fehler beim Exportieren der Protokolle: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Debug-Protokolle löschen</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Löscht alle gespeicherten ReVanced-Debug-Protokolle</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Protokolle gelöscht</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.general.hideLayoutComponentsPatch">
|
||||
<string name="revanced_hide_album_cards_title">Albumkarten ausblenden</string>
|
||||
@@ -695,9 +714,9 @@ Wenn diese Änderung nicht wirksam wird, versuchen Sie, in den Inkognito-Modus z
|
||||
<string name="revanced_hide_player_flyout_audio_track_summary_on">Audiospur-Menü ist ausgeblendet</string>
|
||||
<string name="revanced_hide_player_flyout_audio_track_summary_off">Audiospurmenü wird angezeigt</string>
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
<string name="revanced_hide_player_flyout_audio_track_not_available">"Das Audiotrack-Menü ist ausgeblendet.
|
||||
<string name="revanced_hide_player_flyout_audio_track_not_available">"Audiotrack-Menü ist ausgeblendet
|
||||
|
||||
Um das Audiotrack-Menü anzuzeigen, ändere \"Video-Streams fälschen\" zu iOS TV"</string>
|
||||
Audiotrack-Menü ist nicht verfügbar, wenn 'Videostreams spoofen' aktiviert ist"</string>
|
||||
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
|
||||
<string name="revanced_hide_player_flyout_watch_in_vr_title">Überwachung in VR ausblenden</string>
|
||||
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Im VR-Menü beobachten ist ausgeblendet</string>
|
||||
@@ -1070,10 +1089,12 @@ Ihre Benutzer-ID ist wie ein Passwort und sollte niemals weitergegeben werden.
|
||||
<string name="revanced_sb_segments_intro_sum">Ein Intervall ohne aktuellen Inhalt. Kann eine Pause, ein statischer Rahmen oder eine Wiederholung der Animation sein. Enthält keine Übergänge mit Informationen</string>
|
||||
<string name="revanced_sb_segments_outro">Endkarten / Credits</string>
|
||||
<string name="revanced_sb_segments_outro_sum">Credits oder wenn die YouTube-Endkarten erscheinen. Nicht für Schlussfolgerungen mit Informationen</string>
|
||||
<string name="revanced_sb_segments_preview">Vorschau/Recap/Hook</string>
|
||||
<string name="revanced_sb_segments_hook">Hook / Begrüßungen</string>
|
||||
<string name="revanced_sb_segments_hook_sum">Erzählte Trailer für das kommende Video, Begrüßungen und Verabschiedungen. Enthält keine Abschnitte, die zusätzlichen Inhalt hinzufügen</string>
|
||||
<string name="revanced_sb_segments_preview">Vorschau / Rückblick</string>
|
||||
<string name="revanced_sb_segments_preview_sum">Sammlung von Clips, die zeigen, was im Video oder in anderen Videos einer Serie vor sich geht, wo alle Informationen andernorts wiederholt werden</string>
|
||||
<string name="revanced_sb_segments_filler">Füller/Witze</string>
|
||||
<string name="revanced_sb_segments_filler_sum">Tangentielle Szenen, die nur für Füller oder Humor hinzugefügt werden, die nicht erforderlich sind, um den Hauptinhalt des Videos zu verstehen. Enthält keine Segmente mit Kontext oder Hintergrunddetails</string>
|
||||
<string name="revanced_sb_segments_filler">Abschweifung / Witze</string>
|
||||
<string name="revanced_sb_segments_filler_sum">Tangentiale Szenen oder Witze, die nicht erforderlich sind, um den Hauptinhalt des Videos zu verstehen. Dies sollte keine Segmente enthalten, die Kontext oder Hintergrunddetails liefern</string>
|
||||
<string name="revanced_sb_segments_nomusic">Musik: Nicht-Musik-Sektion</string>
|
||||
<string name="revanced_sb_segments_nomusic_sum">Nur für die Verwendung in Musikvideos. Abschnitte von Musikvideos ohne Musik, die noch nicht von einer anderen Kategorie abgedeckt sind</string>
|
||||
<string name="revanced_sb_skip_button_compact">Überspringen</string>
|
||||
@@ -1086,10 +1107,11 @@ Ihre Benutzer-ID ist wie ein Passwort und sollte niemals weitergegeben werden.
|
||||
<string name="revanced_sb_skip_button_intro_middle">Unterbrechung überspringen</string>
|
||||
<string name="revanced_sb_skip_button_intro_end">Unterbrechung überspringen</string>
|
||||
<string name="revanced_sb_skip_button_outro">Überspringen</string>
|
||||
<string name="revanced_sb_skip_button_hook">Hook überspringen</string>
|
||||
<string name="revanced_sb_skip_button_preview_beginning">Vorschau überspringen</string>
|
||||
<string name="revanced_sb_skip_button_preview_middle">Vorschau überspringen</string>
|
||||
<string name="revanced_sb_skip_button_preview_end">Rückfall überspringen</string>
|
||||
<string name="revanced_sb_skip_button_filler">Füller überspringen</string>
|
||||
<string name="revanced_sb_skip_button_filler">Abschweifung überspringen</string>
|
||||
<string name="revanced_sb_skip_button_nomusic">Nicht-Musik überspringen</string>
|
||||
<string name="revanced_sb_skip_button_unsubmitted">Segment überspringen</string>
|
||||
<string name="revanced_sb_skipped_sponsor">Sponsor übersprungen</string>
|
||||
@@ -1100,10 +1122,11 @@ Ihre Benutzer-ID ist wie ein Passwort und sollte niemals weitergegeben werden.
|
||||
<string name="revanced_sb_skipped_intro_middle">Übersprungene Unterbrechung</string>
|
||||
<string name="revanced_sb_skipped_intro_end">Übersprungene Unterbrechung</string>
|
||||
<string name="revanced_sb_skipped_outro">Outro übersprungen</string>
|
||||
<string name="revanced_sb_skipped_hook">Hook übersprungen</string>
|
||||
<string name="revanced_sb_skipped_preview_beginning">Vorschau übersprungen</string>
|
||||
<string name="revanced_sb_skipped_preview_middle">Vorschau übersprungen</string>
|
||||
<string name="revanced_sb_skipped_preview_end">Übersprungene Rücklage</string>
|
||||
<string name="revanced_sb_skipped_filler">Füller übersprungen</string>
|
||||
<string name="revanced_sb_skipped_filler">Abschweifung übersprungen</string>
|
||||
<string name="revanced_sb_skipped_nomusic">Nicht-Musik-Sektion übersprungen</string>
|
||||
<string name="revanced_sb_skipped_unsubmitted">Nicht übermitteltes Segment übersprungen</string>
|
||||
<string name="revanced_sb_skipped_multiple_segments">Mehrere Segmente übersprungen</string>
|
||||
@@ -1406,10 +1429,6 @@ Höhere Videoqualitäten können freigeschaltet werden, aber es kann zu Stottern
|
||||
Durch Aktivieren dieser Option können höhere Videoqualitäten freigeschaltet werden"</string>
|
||||
<string name="revanced_spoof_device_dimensions_user_dialog_message">Aktivieren kann dazu führen, dass Videowiedergabe blockiert, die Batterielebensdauer verschlechtert und unbekannte Nebeneffekte entstehen.</string>
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<string name="microg_settings_title">GmsCore Einstellungen</string>
|
||||
<string name="microg_settings_summary">Einstellungen für GmsCore</string>
|
||||
</patch>
|
||||
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
|
||||
<string name="revanced_disable_haptic_feedback_title">Haptisches Feedback</string>
|
||||
<string name="revanced_disable_haptic_feedback_summary">Haptisches Feedback ändern</string>
|
||||
@@ -1523,35 +1542,51 @@ Durch Aktivieren dieser Option können höhere Videoqualitäten freigeschaltet w
|
||||
<string name="revanced_slide_to_seek_summary_off">Slide zum Suchen ist nicht aktiviert</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<string name="revanced_spoof_video_streams_screen_title">Spoof-Video-Streams</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Spoof der Client-Videostreams um Wiedergabeprobleme zu verhindern</string>
|
||||
<string name="revanced_spoof_video_streams_title">Spoof-Video-Streams</string>
|
||||
<string name="revanced_spoof_video_streams_summary_on">Video-Streams sind gefälscht</string>
|
||||
<string name="revanced_spoof_video_streams_summary_off">"Videoströme werden nicht gefälscht
|
||||
|
||||
Die Videowiedergabe funktioniert möglicherweise nicht"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">Das Deaktivieren dieser Einstellung kann zu Videowiedergabeproblemen führen.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">Standard-Client</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">iOS AVC (H.264) erzwingen</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">Der Videocodec ist auf AVC (H.264) erzwungen.</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">Der Videocodec wird automatisch bestimmt.</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"Aktivieren Sie dies, um die Akkulaufzeit zu verbessern und Ruckeln bei der Wiedergabe zu beheben.
|
||||
|
||||
AVC hat eine maximale Auflösung von 1080p, Opus-Audiocodec ist nicht verfügbar und die Videowiedergabe verbraucht mehr Internetdaten als VP9 oder AV1."</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_title">iOS-Spoofing-Nebenwirkungen</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• Filme oder kostenpflichtige Videos können möglicherweise nicht abgespielt werden
|
||||
• Eine stabile Lautstärke ist nicht verfügbar
|
||||
• Videos enden 1 Sekunde zu früh"</string>
|
||||
<string name="revanced_spoof_video_streams_about_title">Nebenwirkungen des Spoofings</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_title">Android-Spoofing-Nebenwirkungen</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"• Audiospur-Menü fehlt
|
||||
• Stabile Lautstärke ist nicht verfügbar
|
||||
• Original-Audio erzwingen ist nicht verfügbar"</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"• Audiotrack-Menü fehlt
|
||||
• Stabile Lautstärke ist nicht verfügbar"</string>
|
||||
<string name="revanced_spoof_video_streams_about_experimental">• Experimenteller Client und kann jederzeit aufhören zu funktionieren</string>
|
||||
<string name="revanced_spoof_video_streams_about_no_av1">• Kein AV1-Videocodec</string>
|
||||
<string name="revanced_spoof_video_streams_about_kids_videos">• Kinder-Videos werden möglicherweise nicht abgespielt, wenn du abgemeldet bist oder den Inkognito-Modus verwendest.</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">Standard-Audiostreamsprache für VR</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">Audiodatenstromsprache</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="music">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
<string name="revanced_settings_music_screen_0_about_title">Über</string>
|
||||
<string name="revanced_settings_music_screen_1_ads_title">Werbung</string>
|
||||
<string name="revanced_settings_music_screen_2_general_title">Allgemein</string>
|
||||
<string name="revanced_settings_music_screen_3_player_title">Spieler</string>
|
||||
<string name="revanced_settings_music_screen_4_misc_title">Sonstiges</string>
|
||||
</patch>
|
||||
<patch id="ad.video.hideVideoAdsPatch">
|
||||
<string name="revanced_music_hide_video_ads_title">Videoanzeigen ausblenden</string>
|
||||
<string name="revanced_music_hide_video_ads_summary_on">Videoanzeigen sind ausgeblendet</string>
|
||||
<string name="revanced_music_hide_video_ads_summary_off">Videoanzeigen werden angezeigt</string>
|
||||
</patch>
|
||||
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
|
||||
<string name="revanced_music_play_permanent_repeat_title">Dauerwiederholung aktivieren</string>
|
||||
<string name="revanced_music_play_permanent_repeat_summary_on">Dauerwiederholung ist aktiviert</string>
|
||||
<string name="revanced_music_play_permanent_repeat_summary_off">Dauerwiederholung ist deaktiviert</string>
|
||||
</patch>
|
||||
<patch id="layout.compactheader.hideCategoryBar">
|
||||
<string name="revanced_music_hide_category_bar_title">Kategorieleiste ausblenden</string>
|
||||
<string name="revanced_music_hide_category_bar_summary_on">Kategorieleiste ist ausgeblendet</string>
|
||||
<string name="revanced_music_hide_category_bar_summary_off">Kategorieleiste wird angezeigt</string>
|
||||
</patch>
|
||||
<patch id="layout.premium.hideGetPremiumPatch">
|
||||
<string name="revanced_music_hide_get_premium_label_title">\"Music Premium holen\"-Label ausblenden</string>
|
||||
<string name="revanced_music_hide_get_premium_label_summary_on">Label ist ausgeblendet</string>
|
||||
<string name="revanced_music_hide_get_premium_label_summary_off">Label wird angezeigt</string>
|
||||
</patch>
|
||||
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
|
||||
<string name="revanced_music_hide_upgrade_button_title">Upgrade-Button ausblenden</string>
|
||||
<string name="revanced_music_hide_upgrade_button_summary_on">Button ist ausgeblendet</string>
|
||||
<string name="revanced_music_hide_upgrade_button_summary_off">Button wird angezeigt</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
|
||||
@@ -68,6 +68,8 @@ Second \"item\" text"</string>
|
||||
and changes made here must also be made there. -->
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<string name="microg_settings_title">Ρυθμίσεις GmsCore</string>
|
||||
<string name="microg_settings_summary">Ρυθμίσεις για το MicroG GmsCore</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="gms_core_toast_not_installed_message">Το MicroG GmsCore δεν έχει εγκατασταθεί. Εγκαταστήστε το.</string>
|
||||
<string name="gms_core_dialog_title">Απαιτείται ενέργεια</string>
|
||||
@@ -84,6 +86,37 @@ Second \"item\" text"</string>
|
||||
Πατήστε το κουμπί «Συνέχεια» και επιτρέψτε τις αλλαγές βελτιστοποίησης."</string>
|
||||
<string name="gms_core_dialog_continue_text">Συνέχεια</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<string name="revanced_spoof_video_streams_screen_title">Παραποίηση ροών βίντεο</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Παραποίηση ροών βίντεο του προγράμματος πελάτη για την αποφυγή προβλημάτων αναπαραγωγής</string>
|
||||
<string name="revanced_spoof_video_streams_screen_title">Παραποίηση ροών βίντεο</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Παραποίηση ροών βίντεο του προγράμματος πελάτη για την αποφυγή προβλημάτων αναπαραγωγής</string>
|
||||
<string name="revanced_spoof_video_streams_title">Παραποίηση ροών βίντεο</string>
|
||||
<string name="revanced_spoof_video_streams_summary_on">"Οι ροές βίντεο παραποιούνται
|
||||
|
||||
Αν είστε χρήστης YouTube Premium, αυτή η ρύθμιση μπορεί να μην απαιτείται"</string>
|
||||
<string name="revanced_spoof_video_streams_summary_off">"Οι ροές βίντεο δεν παραποιούνται
|
||||
|
||||
Η αναπαραγωγή ενδέχεται να μην λειτουργεί"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">Η απενεργοποίηση αυτής της ρύθμισης ενδέχεται να προκαλέσει προβλήματα αναπαραγωγής.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">Προεπιλεγμένο πρόγραμμα πελάτη</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">Εντοπισμός σφαλμάτων</string>
|
||||
<string name="revanced_debug_screen_summary">Ενεργοποίηση ή απενεργοποίηση επιλογών εντοπισμού σφαλμάτων</string>
|
||||
<string name="revanced_debug_title">Καταγραφή εντοπισμού σφαλμάτων</string>
|
||||
<string name="revanced_debug_summary_on">Η καταγραφή εντοπισμού σφαλμάτων είναι ενεργοποιημένη</string>
|
||||
<string name="revanced_debug_summary_off">Η καταγραφή εντοπισμού σφαλμάτων είναι απενεργοποιημένη</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_title">Εξαγωγή αρχείων καταγραφής εντοπισμού σφαλμάτων</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_summary">Αντιγραφή των αρχείων καταγραφής εντοπισμού σφαλμάτων ReVanced στο πρόχειρο</string>
|
||||
<string name="revanced_debug_logs_disabled">Η καταγραφή εντοπισμού σφαλμάτων είναι απενεργοποιημένη</string>
|
||||
<string name="revanced_debug_logs_none_found">Δεν βρέθηκαν αρχεία καταγραφής</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Τα αρχεία καταγραφής αντιγράφηκαν</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Αποτυχία εξαγωγής αρχείων καταγραφής: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Εκκαθάριση αρχείων καταγραφής εντοπισμού σφαλμάτων</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Εκκαθάριση όλων των αποθηκευμένων αρχειών καταγραφής εντοπισμού σφαλμάτων ReVanced</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Τα αρχεία καταγραφής εκκαθαρίστηκαν</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="youtube">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
@@ -110,11 +143,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_shorts_disable_background_playback_summary_off">Η αναπαραγωγή παρασκηνίου είναι ενεργοποιημένη για τα Shorts</string>
|
||||
</patch>
|
||||
<patch id="misc.debugging.enableDebuggingPatch">
|
||||
<string name="revanced_debug_screen_title">Εντοπισμός σφαλμάτων</string>
|
||||
<string name="revanced_debug_screen_summary">Ενεργοποίηση ή απενεργοποίηση επιλογών εντοπισμού σφαλμάτων</string>
|
||||
<string name="revanced_debug_title">Καταγραφή εντοπισμού σφαλμάτων</string>
|
||||
<string name="revanced_debug_summary_on">Η καταγραφή εντοπισμού σφαλμάτων είναι ενεργοποιημένη</string>
|
||||
<string name="revanced_debug_summary_off">Η καταγραφή εντοπισμού σφαλμάτων είναι απενεργοποιημένη</string>
|
||||
<string name="revanced_debug_protobuffer_title">Καταγραφή του buffer πρωτοκόλλου</string>
|
||||
<string name="revanced_debug_protobuffer_summary_on">Τα αρχεία καταγραφής σφαλμάτων περιλαμβάνουν το buffer του πρωτοκόλλου</string>
|
||||
<string name="revanced_debug_protobuffer_summary_off">Τα αρχεία καταγραφής σφαλμάτων δεν περιλαμβάνουν τον buffer πρωτοκόλλου</string>
|
||||
@@ -132,15 +160,6 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_debug_toast_on_error_user_dialog_message">"Η απενεργοποίηση των μηνυμάτων σφαλμάτων κρύβει όλες τις ειδοποιήσεις σφαλμάτων που αφορούν το ReVanced.
|
||||
|
||||
Δεν θα ειδοποιηθείτε για τυχόν απρόβλεπτα γεγονότα."</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_title">Εξαγωγή αρχείων καταγραφής εντοπισμού σφαλμάτων</string>
|
||||
<string name="revanced_debug_export_logs_to_clipboard_summary">Αντιγραφή των αρχείων καταγραφής εντοπισμού σφαλμάτων ReVanced στο πρόχειρο</string>
|
||||
<string name="revanced_debug_logs_disabled">Η καταγραφή εντοπισμού σφαλμάτων είναι απενεργοποιημένη</string>
|
||||
<string name="revanced_debug_logs_none_found">Δεν βρέθηκαν αρχεία καταγραφής</string>
|
||||
<string name="revanced_debug_logs_copied_to_clipboard">Τα αρχεία καταγραφής αντιγράφηκαν</string>
|
||||
<string name="revanced_debug_logs_failed_to_export">Αποτυχία εξαγωγής αρχείων καταγραφής: %s</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_title">Εκκαθάριση αρχείων καταγραφής εντοπισμού σφαλμάτων</string>
|
||||
<string name="revanced_debug_logs_clear_buffer_summary">Εκκαθάριση όλων των αποθηκευμένων αρχειών καταγραφής εντοπισμού σφαλμάτων ReVanced</string>
|
||||
<string name="revanced_debug_logs_clear_toast">Τα αρχεία καταγραφής εκκαθαρίστηκαν</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.general.hideLayoutComponentsPatch">
|
||||
<string name="revanced_hide_album_cards_title">Κάρτες άλμπουμ</string>
|
||||
@@ -704,7 +723,7 @@ Second \"item\" text"</string>
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
<string name="revanced_hide_player_flyout_audio_track_not_available">"Το μενού «Κομμάτι ήχου» είναι κρυμμένο
|
||||
|
||||
Για να εμφανίζεται το μενού κομματιού ήχου, αλλάξτε την «Παραποίηση ροών βίντεο» σε iOS TV"</string>
|
||||
Το μενού «Κομμάτι ήχου» δεν είναι διαθέσιμο όταν είναι ενεργοποιημένη η ρύθμιση «Παραποίηση ροών βίντεο»"</string>
|
||||
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
|
||||
<string name="revanced_hide_player_flyout_watch_in_vr_title">Μενού «Προβολή σε VR»</string>
|
||||
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Κρυμμένο</string>
|
||||
@@ -1076,10 +1095,12 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_sb_segments_intro_sum">Χρονικό διάστημα χωρίς πραγματικό περιεχόμενο. Θα μπορούσε να είναι μια παύση, ένα στατικό καρέ ή μια επαναλαμβανόμενη κίνηση. Δεν περιλαμβάνει μεταβάσεις που περιέχουν πληροφορίες</string>
|
||||
<string name="revanced_sb_segments_outro">Τελική Οθόνη / Συντελεστές</string>
|
||||
<string name="revanced_sb_segments_outro_sum">Όταν εμφανίζονται οι συντελεστές ή τα προτεινόμενα βίντεο των καναλιών. Όχι για επίλογους που περιέχουν πληροφορίες</string>
|
||||
<string name="revanced_sb_segments_preview">Προεπισκόπηση/Περίληψη</string>
|
||||
<string name="revanced_sb_segments_hook">Έναρξη / Χαιρετισμοί</string>
|
||||
<string name="revanced_sb_segments_hook_sum">Αφηγηματικά τρέιλερ για το επερχόμενο βίντεο, χαιρετισμοί και αποχαιρετισμοί. Δεν περιλαμβάνει τμήματα που προσθέτουν επιπλέον περιεχόμενο</string>
|
||||
<string name="revanced_sb_segments_preview">Προεπισκόπηση / Περίληψη</string>
|
||||
<string name="revanced_sb_segments_preview_sum">Συλλογή από κλιπ που δείχνουν τι έρχεται ή τι συνέβη στο βίντεο ή σε άλλα βίντεο μιας σειράς, όπου όλες οι πληροφορίες επαναλαμβάνονται αλλού</string>
|
||||
<string name="revanced_sb_segments_filler">Σπατάλη Χρόνου/Αστεία</string>
|
||||
<string name="revanced_sb_segments_filler_sum">Παρεμβατικές σκηνές που προστίθενται μόνο για γέμισμα του βίντεο ή χιούμορ οι οποίες δεν είναι απαραίτητες για την κατανόηση του κύριου περιεχομένου του βίντεο. Δεν περιλαμβάνει τμήματα που παρέχουν συνάφεια ή λεπτομέρειες ως υπόβαθρο</string>
|
||||
<string name="revanced_sb_segments_filler">Εφαπτομενικές Σκηνές / Αστεία</string>
|
||||
<string name="revanced_sb_segments_filler_sum">Παρεμβατικές σκηνές ή αστεία που δεν είναι απαραίτητα για την κατανόηση του κύριου περιεχομένου του βίντεο. Δεν περιλαμβάνει τμήματα που παρέχουν πλαίσιο ή λεπτομέρειες υποβάθρου</string>
|
||||
<string name="revanced_sb_segments_nomusic">Μουσική: Τμήμα χωρίς μουσική</string>
|
||||
<string name="revanced_sb_segments_nomusic_sum">Μόνο για χρήση σε βίντεο μουσικής. Τμήματα χωρίς μουσική σε βίντεο μουσικής, που δεν καλύπτονται ήδη από άλλη κατηγορία</string>
|
||||
<string name="revanced_sb_skip_button_compact">Παράλειψη</string>
|
||||
@@ -1092,6 +1113,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_sb_skip_button_intro_middle">Παράλειψη διακοπής</string>
|
||||
<string name="revanced_sb_skip_button_intro_end">Παράλειψη διακοπής</string>
|
||||
<string name="revanced_sb_skip_button_outro">Παράλειψη επιλόγου</string>
|
||||
<string name="revanced_sb_skip_button_hook">Παράλειψη έναρξης</string>
|
||||
<string name="revanced_sb_skip_button_preview_beginning">Παράλειψη προεπισκόπησης</string>
|
||||
<string name="revanced_sb_skip_button_preview_middle">Παράλειψη προεπισκόπησης</string>
|
||||
<string name="revanced_sb_skip_button_preview_end">Παράλειψη περίληψης</string>
|
||||
@@ -1106,6 +1128,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_sb_skipped_intro_middle">Παραλείφθηκε η διακοπή</string>
|
||||
<string name="revanced_sb_skipped_intro_end">Παραλείφθηκε η διακοπή</string>
|
||||
<string name="revanced_sb_skipped_outro">Παραλείφθηκε ο επίλογος</string>
|
||||
<string name="revanced_sb_skipped_hook">Παραλείφθηκε η έναρξη</string>
|
||||
<string name="revanced_sb_skipped_preview_beginning">Παραλείφθηκε η προεπισκόπηση</string>
|
||||
<string name="revanced_sb_skipped_preview_middle">Παραλείφθηκε η προεπισκόπηση</string>
|
||||
<string name="revanced_sb_skipped_preview_end">Παραλείφθηκε η περίληψη</string>
|
||||
@@ -1410,10 +1433,6 @@ Second \"item\" text"</string>
|
||||
Η ενεργοποίηση αυτής της λειτουργίας μπορεί να ξεκλειδώσει υψηλότερες ποιότητες βίντεο"</string>
|
||||
<string name="revanced_spoof_device_dimensions_user_dialog_message">Η ενεργοποίηση αυτής της λειτουργίας μπορεί να προκαλέσει μικρο-κολλήματα κατά την αναπαραγωγή, χειρότερη διάρκεια ζωής μπαταρίας, και άλλες άγνωστες παρενέργειες.</string>
|
||||
</patch>
|
||||
<patch id="misc.gms.gmsCoreSupportResourcePatch">
|
||||
<string name="microg_settings_title">Ρυθμίσεις GmsCore</string>
|
||||
<string name="microg_settings_summary">Ρυθμίσεις για το MicroG GmsCore</string>
|
||||
</patch>
|
||||
<patch id="misc.hapticfeedback.disableHapticFeedbackPatch">
|
||||
<string name="revanced_disable_haptic_feedback_title">Απόκριση δόνησης</string>
|
||||
<string name="revanced_disable_haptic_feedback_summary">Αλλαγή απόκρισης δόνησης</string>
|
||||
@@ -1527,35 +1546,51 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_slide_to_seek_summary_off">Η χειρονομία συρσίματος για αναζήτηση στη γραμμή προόδου είναι απενεργοποιημένη</string>
|
||||
</patch>
|
||||
<patch id="misc.fix.playback.spoofVideoStreamsPatch">
|
||||
<string name="revanced_spoof_video_streams_screen_title">Παραποίηση ροών βίντεο</string>
|
||||
<string name="revanced_spoof_video_streams_screen_summary">Παραποίηση ροών βίντεο του προγράμματος πελάτη για την αποφυγή προβλημάτων αναπαραγωγής</string>
|
||||
<string name="revanced_spoof_video_streams_title">Παραποίηση ροών βίντεο</string>
|
||||
<string name="revanced_spoof_video_streams_summary_on">Οι ροές βίντεο παραποιούνται</string>
|
||||
<string name="revanced_spoof_video_streams_summary_off">"Οι ροές βίντεο δεν παραποιούνται
|
||||
|
||||
Η αναπαραγωγή βίντεο ενδέχεται να μην λειτουργεί"</string>
|
||||
<string name="revanced_spoof_video_streams_user_dialog_message">Η απενεργοποίηση αυτής της ρύθμισης ενδέχεται να προκαλέσει προβλήματα αναπαραγωγής βίντεο.</string>
|
||||
<string name="revanced_spoof_video_streams_client_type_title">Προεπιλεγμένο πρόγραμμα πελάτη</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_title">Εξαναγκασμός iOS AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_on">Ο κωδικοποιητής βίντεο έχει οριστεί υποχρεωτικά σε AVC (H.264)</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_summary_off">Ο κωδικοποιητής βίντεο ορίζεται αυτόματα</string>
|
||||
<string name="revanced_spoof_video_streams_ios_force_avc_user_dialog_message">"Η ενεργοποίηση αυτής της λειτουργίας ενδέχεται να βελτιώσει τη διάρκεια ζωής της μπαταρίας και να διορθώσει κολλήματα αναπαραγωγής.
|
||||
|
||||
Ο AVC έχει μέγιστη ανάλυση 1080p, ο κωδικοποιητής ήχου Opus δεν είναι διαθέσιμος και η αναπαραγωγή βίντεο θα χρησιμοποιεί περισσότερα δεδομένα ίντερνετ από τον VP9 ή τον AV1."</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_title">Παρενέργειες παραποίησης σε iOS</string>
|
||||
<string name="revanced_spoof_video_streams_about_ios_tv_summary">"• Οι ταινίες ή τα επί πληρωμή βίντεο ενδέχεται να μην αναπαράγονται
|
||||
• Η λειτουργία «Σταθερή ένταση» δεν είναι διαθέσιμη
|
||||
• Τα βίντεο τελειώνουν 1 δευτερόλεπτο νωρίτερα"</string>
|
||||
<string name="revanced_spoof_video_streams_about_title">Παρενέργειες παραποίησης</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_title">Παρενέργειες παραποίησης σε Android</string>
|
||||
<string name="revanced_spoof_video_streams_about_android_summary">"• Το μενού «Κομμάτι ήχου» λείπει
|
||||
• Η λειτουργία «Σταθερή ένταση» δεν είναι διαθέσιμη
|
||||
• Η λειτουργία «Εξαναγκασμός αρχικού ήχου» δεν είναι διαθέσιμη"</string>
|
||||
• Η λειτουργία «Σταθερή ένταση» δεν είναι διαθέσιμη"</string>
|
||||
<string name="revanced_spoof_video_streams_about_experimental">• Πειραματικός πελάτης και μπορεί να σταματήσει να λειτουργεί ανά πάσα στιγμή</string>
|
||||
<string name="revanced_spoof_video_streams_about_no_av1">• Δεν υπάρχει ο κωδικοποιητής βίντεο AV1</string>
|
||||
<string name="revanced_spoof_video_streams_about_kids_videos">• Τα βίντεο για παιδιά ενδέχεται να μην αναπαράγονται αν είστε αποσυνδεδεμένοι ή σε λειτουργία ανώνυμης περιήγησης</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">Προεπιλεγμένη γλώσσα ροής ήχου VR</string>
|
||||
<string name="revanced_spoof_video_streams_language_title">Γλώσσα ροής ήχου</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="music">
|
||||
<patch id="misc.settings.settingsPatch">
|
||||
<string name="revanced_settings_music_screen_0_about_title">Ομάδα προγραμματιστών</string>
|
||||
<string name="revanced_settings_music_screen_1_ads_title">Διαφημίσεις</string>
|
||||
<string name="revanced_settings_music_screen_2_general_title">Γενικά</string>
|
||||
<string name="revanced_settings_music_screen_3_player_title">Οθόνη αναπαραγωγής</string>
|
||||
<string name="revanced_settings_music_screen_4_misc_title">Διάφορα</string>
|
||||
</patch>
|
||||
<patch id="ad.video.hideVideoAdsPatch">
|
||||
<string name="revanced_music_hide_video_ads_title">Διαφημίσεις βίντεο</string>
|
||||
<string name="revanced_music_hide_video_ads_summary_on">Κρυμμένες</string>
|
||||
<string name="revanced_music_hide_video_ads_summary_off">Εμφανίζονται</string>
|
||||
</patch>
|
||||
<patch id="interaction.permanentrepeat.permanentRepeatPatch">
|
||||
<string name="revanced_music_play_permanent_repeat_title">Ενεργοποίηση μόνιμης επανάληψης</string>
|
||||
<string name="revanced_music_play_permanent_repeat_summary_on">Η μόνιμη επανάληψη είναι ενεργοποιημένη</string>
|
||||
<string name="revanced_music_play_permanent_repeat_summary_off">Η μόνιμη επανάληψη είναι απενεργοποιημένη</string>
|
||||
</patch>
|
||||
<patch id="layout.compactheader.hideCategoryBar">
|
||||
<string name="revanced_music_hide_category_bar_title">Απόκρυψη γραμμής κατηγοριών</string>
|
||||
<string name="revanced_music_hide_category_bar_summary_on">Η γραμμή κατηγοριών είναι κρυμμένη</string>
|
||||
<string name="revanced_music_hide_category_bar_summary_off">Η γραμμή κατηγοριών εμφανίζεται</string>
|
||||
</patch>
|
||||
<patch id="layout.premium.hideGetPremiumPatch">
|
||||
<string name="revanced_music_hide_get_premium_label_title">Απόκρυψη ετικέτας «Απόκτηση Music Premium»</string>
|
||||
<string name="revanced_music_hide_get_premium_label_summary_on">Η ετικέτα είναι κρυμμένη</string>
|
||||
<string name="revanced_music_hide_get_premium_label_summary_off">Η ετικέτα εμφανίζεται</string>
|
||||
</patch>
|
||||
<patch id="layout.upgradebutton.hideUpgradeButtonPatch">
|
||||
<string name="revanced_music_hide_upgrade_button_title">Απόκρυψη κουμπιού αναβάθμισης</string>
|
||||
<string name="revanced_music_hide_upgrade_button_summary_on">Κρυμμένο</string>
|
||||
<string name="revanced_music_hide_upgrade_button_summary_off">Εμφανίζεται</string>
|
||||
</patch>
|
||||
</app>
|
||||
<app id="twitch">
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user