mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-05-23 18:37:14 +02:00
Merge branch 'dev' into revanced-extended
This commit is contained in:
commit
03c0826fab
28
.github/workflows/discord_ping_on_release.yml
vendored
28
.github/workflows/discord_ping_on_release.yml
vendored
@ -10,13 +10,33 @@ jobs:
|
||||
steps:
|
||||
- uses: sarisia/actions-status-discord@v1
|
||||
if: always()
|
||||
id: webhook # set id to reference output payload later
|
||||
with:
|
||||
webhook: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
||||
username: ReVanced Extended
|
||||
color: 0xff5252
|
||||
ack_no_webhook: true # suppress warning
|
||||
nodetail: true
|
||||
notimestamp: true
|
||||
|
||||
username: ReVanced Extended
|
||||
content: "<@&1271197877724643461>"
|
||||
title: "Patches `${{ github.event.release.tag_name }}` has been released!"
|
||||
description: |
|
||||
Click [here](${{ github.event.release.html_url }}) to read the changelog and release notes.
|
||||
Click [here](${{ github.event.release.html_url }}) to read the changelog and release notes.
|
||||
|
||||
- run: npm install axios
|
||||
- uses: actions/github-script@v7
|
||||
env:
|
||||
WEBHOOK_PAYLOAD: ${{ steps.webhook.outputs.payload }}
|
||||
WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
||||
with:
|
||||
script: |
|
||||
const axios = require("axios")
|
||||
|
||||
const { WEBHOOK_PAYLOAD, WEBHOOK_URL } = process.env
|
||||
|
||||
const payload = JSON.parse(WEBHOOK_PAYLOAD)
|
||||
|
||||
// remove the color field to make it transparent
|
||||
delete payload.embeds[0].color
|
||||
|
||||
// send to Discord
|
||||
axios.post(WEBHOOK_URL, payload)
|
||||
|
80
README.md
80
README.md
@ -80,46 +80,46 @@ See the [documentation](https://github.com/inotia00/revanced-documentation#readm
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `Amoled` | Applies a pure black theme to some components. | 6.20.51 ~ 7.25.52 |
|
||||
| `Bitrate default value` | Sets the audio quality to 'Always High' when you first install the app. | 6.20.51 ~ 7.25.52 |
|
||||
| `Bypass image region restrictions` | Adds an option to use a different host for static images, so that images blocked in some countries can be received. | 6.20.51 ~ 7.25.52 |
|
||||
| `Certificate spoof` | Enables YouTube Music to work with Android Auto by spoofing the YouTube Music certificate. | 6.20.51 ~ 7.25.52 |
|
||||
| `Change share sheet` | Add option to change from in-app share sheet to system share sheet. | 6.20.51 ~ 7.25.52 |
|
||||
| `Change start page` | Adds an option to set which page the app opens in instead of the homepage. | 6.20.51 ~ 7.25.52 |
|
||||
| `Custom branding icon for YouTube Music` | Changes the YouTube Music app icon to the icon specified in patch options. | 6.20.51 ~ 7.25.52 |
|
||||
| `Custom branding name for YouTube Music` | Renames the YouTube Music app to the name specified in patch options. | 6.20.51 ~ 7.25.52 |
|
||||
| `Custom header for YouTube Music` | Applies a custom header in the top left corner within the app. | 6.20.51 ~ 7.25.52 |
|
||||
| `Disable Cairo splash animation` | Adds an option to disable Cairo splash animation. | 7.06.54 ~ 7.25.52 |
|
||||
| `Disable DRC audio` | Adds an option to disable DRC (Dynamic Range Compression) audio. | 6.20.51 ~ 7.25.52 |
|
||||
| `Disable auto captions` | Adds an option to disable captions from being automatically enabled. | 6.20.51 ~ 7.25.52 |
|
||||
| `Disable dislike redirection` | Adds an option to disable redirection to the next track when clicking the Dislike button. | 6.20.51 ~ 7.25.52 |
|
||||
| `Enable OPUS codec` | Adds an options to enable the OPUS audio codec if the player response includes. | 6.20.51 ~ 7.25.52 |
|
||||
| `Enable debug logging` | Adds an option to enable debug logging. | 6.20.51 ~ 7.25.52 |
|
||||
| `Enable landscape mode` | Adds an option to enable landscape mode when rotating the screen on phones. | 6.20.51 ~ 7.25.52 |
|
||||
| `Flyout menu components` | Adds options to hide or change flyout menu components. | 6.20.51 ~ 7.25.52 |
|
||||
| `GmsCore support` | Allows patched Google apps to run without root and under a different package name by using GmsCore instead of Google Play Services. | 6.20.51 ~ 7.25.52 |
|
||||
| `Hide account components` | Adds options to hide components related to the account menu. | 6.20.51 ~ 7.25.52 |
|
||||
| `Hide action bar components` | Adds options to hide action bar components and replace the offline download button with an external download button. | 6.20.51 ~ 7.25.52 |
|
||||
| `Hide ads` | Adds options to hide ads. | 6.20.51 ~ 7.25.52 |
|
||||
| `Hide layout components` | Adds options to hide general layout components. | 6.20.51 ~ 7.25.52 |
|
||||
| `Hide overlay filter` | Removes, at compile time, the dark overlay that appears when player flyout menus are open. | 6.20.51 ~ 7.25.52 |
|
||||
| `Hide player overlay filter` | Removes, at compile time, the dark overlay that appears when single-tapping in the player. | 6.20.51 ~ 7.25.52 |
|
||||
| `Navigation bar components` | Adds options to hide or change components related to the navigation bar. | 6.20.51 ~ 7.25.52 |
|
||||
| `Player components` | Adds options to hide or change components related to the player. | 6.20.51 ~ 7.25.52 |
|
||||
| `Remove background playback restrictions` | Removes restrictions on background playback, including for kids videos. | 6.20.51 ~ 7.25.52 |
|
||||
| `Remove viewer discretion dialog` | Adds an option to remove the dialog that appears when opening a video that has been age-restricted by accepting it automatically. This does not bypass the age restriction. | 6.20.51 ~ 7.25.52 |
|
||||
| `Restore old style library shelf` | Adds an option to return the Library tab to the old style. | 6.20.51 ~ 7.25.52 |
|
||||
| `Return YouTube Dislike` | Adds an option to show the dislike count of songs using the Return YouTube Dislike API. | 6.20.51 ~ 7.25.52 |
|
||||
| `Return YouTube Username` | Adds an option to replace YouTube handles with usernames in comments using YouTube Data API v3. | 6.20.51 ~ 7.25.52 |
|
||||
| `Sanitize sharing links` | Adds an option to remove tracking query parameters from URLs when sharing links. | 6.20.51 ~ 7.25.52 |
|
||||
| `Settings for YouTube Music` | Applies mandatory patches to implement ReVanced Extended settings into the application. | 6.20.51 ~ 7.25.52 |
|
||||
| `SponsorBlock` | Adds options to enable and configure SponsorBlock, which can skip undesired video segments, such as non-music sections. | 6.20.51 ~ 7.25.52 |
|
||||
| `Amoled` | Applies a pure black theme to some components. | 6.20.51 ~ 7.25.53 |
|
||||
| `Bitrate default value` | Sets the audio quality to 'Always High' when you first install the app. | 6.20.51 ~ 7.25.53 |
|
||||
| `Bypass image region restrictions` | Adds an option to use a different host for static images, so that images blocked in some countries can be received. | 6.20.51 ~ 7.25.53 |
|
||||
| `Certificate spoof` | Enables YouTube Music to work with Android Auto by spoofing the YouTube Music certificate. | 6.20.51 ~ 7.25.53 |
|
||||
| `Change share sheet` | Add option to change from in-app share sheet to system share sheet. | 6.20.51 ~ 7.25.53 |
|
||||
| `Change start page` | Adds an option to set which page the app opens in instead of the homepage. | 6.20.51 ~ 7.25.53 |
|
||||
| `Custom branding icon for YouTube Music` | Changes the YouTube Music app icon to the icon specified in patch options. | 6.20.51 ~ 7.25.53 |
|
||||
| `Custom branding name for YouTube Music` | Renames the YouTube Music app to the name specified in patch options. | 6.20.51 ~ 7.25.53 |
|
||||
| `Custom header for YouTube Music` | Applies a custom header in the top left corner within the app. | 6.20.51 ~ 7.25.53 |
|
||||
| `Disable Cairo splash animation` | Adds an option to disable Cairo splash animation. | 7.06.54 ~ 7.25.53 |
|
||||
| `Disable DRC audio` | Adds an option to disable DRC (Dynamic Range Compression) audio. | 6.20.51 ~ 7.25.53 |
|
||||
| `Disable auto captions` | Adds an option to disable captions from being automatically enabled. | 6.20.51 ~ 7.25.53 |
|
||||
| `Disable dislike redirection` | Adds an option to disable redirection to the next track when clicking the Dislike button. | 6.20.51 ~ 7.25.53 |
|
||||
| `Enable OPUS codec` | Adds an options to enable the OPUS audio codec if the player response includes. | 6.20.51 ~ 7.25.53 |
|
||||
| `Enable debug logging` | Adds an option to enable debug logging. | 6.20.51 ~ 7.25.53 |
|
||||
| `Enable landscape mode` | Adds an option to enable landscape mode when rotating the screen on phones. | 6.20.51 ~ 7.25.53 |
|
||||
| `Flyout menu components` | Adds options to hide or change flyout menu components. | 6.20.51 ~ 7.25.53 |
|
||||
| `GmsCore support` | Allows patched Google apps to run without root and under a different package name by using GmsCore instead of Google Play Services. | 6.20.51 ~ 7.25.53 |
|
||||
| `Hide account components` | Adds options to hide components related to the account menu. | 6.20.51 ~ 7.25.53 |
|
||||
| `Hide action bar components` | Adds options to hide action bar components and replace the offline download button with an external download button. | 6.20.51 ~ 7.25.53 |
|
||||
| `Hide ads` | Adds options to hide ads. | 6.20.51 ~ 7.25.53 |
|
||||
| `Hide layout components` | Adds options to hide general layout components. | 6.20.51 ~ 7.25.53 |
|
||||
| `Hide overlay filter` | Removes, at compile time, the dark overlay that appears when player flyout menus are open. | 6.20.51 ~ 7.25.53 |
|
||||
| `Hide player overlay filter` | Removes, at compile time, the dark overlay that appears when single-tapping in the player. | 6.20.51 ~ 7.25.53 |
|
||||
| `Navigation bar components` | Adds options to hide or change components related to the navigation bar. | 6.20.51 ~ 7.25.53 |
|
||||
| `Player components` | Adds options to hide or change components related to the player. | 6.20.51 ~ 7.25.53 |
|
||||
| `Remove background playback restrictions` | Removes restrictions on background playback, including for kids videos. | 6.20.51 ~ 7.25.53 |
|
||||
| `Remove viewer discretion dialog` | Adds an option to remove the dialog that appears when opening a video that has been age-restricted by accepting it automatically. This does not bypass the age restriction. | 6.20.51 ~ 7.25.53 |
|
||||
| `Restore old style library shelf` | Adds an option to return the Library tab to the old style. | 6.20.51 ~ 7.25.53 |
|
||||
| `Return YouTube Dislike` | Adds an option to show the dislike count of songs using the Return YouTube Dislike API. | 6.20.51 ~ 7.25.53 |
|
||||
| `Return YouTube Username` | Adds an option to replace YouTube handles with usernames in comments using YouTube Data API v3. | 6.20.51 ~ 7.25.53 |
|
||||
| `Sanitize sharing links` | Adds an option to remove tracking query parameters from URLs when sharing links. | 6.20.51 ~ 7.25.53 |
|
||||
| `Settings for YouTube Music` | Applies mandatory patches to implement ReVanced Extended settings into the application. | 6.20.51 ~ 7.25.53 |
|
||||
| `SponsorBlock` | Adds options to enable and configure SponsorBlock, which can skip undesired video segments, such as non-music sections. | 6.20.51 ~ 7.25.53 |
|
||||
| `Spoof app version` | Adds options to spoof the YouTube Music client version. This can remove the radio mode restriction in Canadian regions or disable real-time lyrics. | 6.20.51 ~ 7.16.53 |
|
||||
| `Spoof client` | Adds options to spoof the client to allow playback. | 6.20.51 ~ 7.25.52 |
|
||||
| `Spoof streaming data` | Adds options to spoof the streaming data to allow playback. | 6.20.51 ~ 7.25.52 |
|
||||
| `Translations for YouTube Music` | Add translations or remove string resources. | 6.20.51 ~ 7.25.52 |
|
||||
| `Video playback` | Adds options to customize settings related to video playback, such as default video quality and playback speed. | 6.20.51 ~ 7.25.52 |
|
||||
| `Visual preferences icons for YouTube Music` | Adds icons to specific preferences in the settings. | 6.20.51 ~ 7.25.52 |
|
||||
| `Spoof client` | Adds options to spoof the client to allow playback. | 6.20.51 ~ 7.16.53 |
|
||||
| `Spoof streaming data` | Adds options to spoof the streaming data to allow playback. | 6.20.51 ~ 7.25.53 |
|
||||
| `Translations for YouTube Music` | Add translations or remove string resources. | 6.20.51 ~ 7.25.53 |
|
||||
| `Video playback` | Adds options to customize settings related to video playback, such as default video quality and playback speed. | 6.20.51 ~ 7.25.53 |
|
||||
| `Visual preferences icons for YouTube Music` | Adds icons to specific preferences in the settings. | 6.20.51 ~ 7.25.53 |
|
||||
</details>
|
||||
|
||||
### [📦 `com.reddit.frontpage`](https://play.google.com/store/apps/details?id=com.reddit.frontpage)
|
||||
@ -180,7 +180,7 @@ Example:
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
|
@ -8,6 +8,7 @@ import android.view.View;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import app.revanced.extension.music.settings.Settings;
|
||||
import app.revanced.extension.music.utils.VideoUtils;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ActionBarPatch {
|
||||
@ -39,6 +40,15 @@ public class ActionBarPatch {
|
||||
);
|
||||
}
|
||||
|
||||
public static void inAppDownloadButtonOnClick(View view) {
|
||||
if (!Settings.EXTERNAL_DOWNLOADER_ACTION_BUTTON.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (buttonType.equals(ActionButton.DOWNLOAD.name))
|
||||
view.setOnClickListener(imageView -> VideoUtils.launchExternalDownloader());
|
||||
}
|
||||
|
||||
public static void setButtonType(@NonNull Object obj) {
|
||||
final String buttonType = obj.toString();
|
||||
|
||||
|
@ -2,11 +2,11 @@ package app.revanced.extension.music.patches.misc;
|
||||
|
||||
import app.revanced.extension.music.patches.misc.client.AppClient.ClientType;
|
||||
import app.revanced.extension.music.settings.Settings;
|
||||
import app.revanced.extension.shared.patches.BlockRequestPatch;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class SpoofClientPatch extends BlockRequestPatch {
|
||||
public class SpoofClientPatch {
|
||||
private static final ClientType CLIENT_TYPE = Settings.SPOOF_CLIENT_TYPE.get();
|
||||
public static final boolean SPOOF_CLIENT = Settings.SPOOF_CLIENT.get();
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
|
@ -2,49 +2,78 @@ package app.revanced.extension.music.patches.misc.client;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import app.revanced.extension.music.settings.Settings;
|
||||
|
||||
public class AppClient {
|
||||
private static final String CLIENT_VERSION_ANDROID_MUSIC = Settings.SPOOF_CLIENT_LEGACY.get()
|
||||
? "4.27.53" // Audio codec is MP4A.
|
||||
: "5.29.53"; // Audio codec is OPUS.
|
||||
private static final String OS_VERSION_ANDROID_MUSIC = Build.VERSION.RELEASE;
|
||||
private static final String USER_AGENT_ANDROID_MUSIC = "com.google.android.apps.youtube.music/" +
|
||||
CLIENT_VERSION_ANDROID_MUSIC +
|
||||
" (Linux; U; Android " +
|
||||
OS_VERSION_ANDROID_MUSIC +
|
||||
"; GB) gzip";
|
||||
|
||||
private static final String CLIENT_VERSION_IOS_MUSIC = Settings.SPOOF_CLIENT_LEGACY.get()
|
||||
? "4.27" // Audio codec is MP4A.
|
||||
: "7.31.2"; // Audio codec is OPUS.
|
||||
// Audio codec is MP4A.
|
||||
private static final String CLIENT_VERSION_ANDROID_MUSIC_4_27 = "4.27.53";
|
||||
|
||||
// Audio codec is OPUS.
|
||||
private static final String CLIENT_VERSION_ANDROID_MUSIC_5_29 = "5.29.53";
|
||||
|
||||
private static final String PACKAGE_NAME_ANDROID_MUSIC = "com.google.android.apps.youtube.music";
|
||||
private static final String DEVICE_MODEL_ANDROID_MUSIC = Build.MODEL;
|
||||
private static final String OS_VERSION_ANDROID_MUSIC = Build.VERSION.RELEASE;
|
||||
|
||||
// Audio codec is MP4A.
|
||||
private static final String CLIENT_VERSION_IOS_MUSIC_6_21 = "6.21";
|
||||
|
||||
// Audio codec is OPUS.
|
||||
private static final String CLIENT_VERSION_IOS_MUSIC_7_04 = "7.04";
|
||||
|
||||
private static final String PACKAGE_NAME_IOS_MUSIC = "com.google.ios.youtubemusic";
|
||||
private static final String DEVICE_MODEL_IOS_MUSIC = "iPhone14,3";
|
||||
private static final String OS_VERSION_IOS_MUSIC = "15.7.1.19H117";
|
||||
private static final String USER_AGENT_VERSION_IOS_MUSIC = "15_7_1";
|
||||
private static final String USER_AGENT_IOS_MUSIC = "com.google.ios.youtubemusic/" +
|
||||
CLIENT_VERSION_IOS_MUSIC +
|
||||
"(" +
|
||||
DEVICE_MODEL_IOS_MUSIC +
|
||||
"; U; CPU iOS " +
|
||||
USER_AGENT_VERSION_IOS_MUSIC +
|
||||
" like Mac OS X)";
|
||||
|
||||
private AppClient() {
|
||||
}
|
||||
|
||||
private static String androidUserAgent(String clientVersion) {
|
||||
return PACKAGE_NAME_ANDROID_MUSIC +
|
||||
"/" +
|
||||
clientVersion +
|
||||
" (Linux; U; Android " +
|
||||
OS_VERSION_ANDROID_MUSIC +
|
||||
"; GB) gzip";
|
||||
}
|
||||
|
||||
private static String iOSUserAgent(String clientVersion) {
|
||||
return PACKAGE_NAME_IOS_MUSIC +
|
||||
"/" +
|
||||
clientVersion +
|
||||
"(" +
|
||||
DEVICE_MODEL_IOS_MUSIC +
|
||||
"; U; CPU iOS " +
|
||||
USER_AGENT_VERSION_IOS_MUSIC +
|
||||
" like Mac OS X)";
|
||||
}
|
||||
|
||||
public enum ClientType {
|
||||
ANDROID_MUSIC(21,
|
||||
Build.MODEL,
|
||||
ANDROID_MUSIC_4_27(21,
|
||||
DEVICE_MODEL_ANDROID_MUSIC,
|
||||
OS_VERSION_ANDROID_MUSIC,
|
||||
USER_AGENT_ANDROID_MUSIC,
|
||||
CLIENT_VERSION_ANDROID_MUSIC
|
||||
androidUserAgent(CLIENT_VERSION_ANDROID_MUSIC_4_27),
|
||||
CLIENT_VERSION_ANDROID_MUSIC_4_27
|
||||
),
|
||||
IOS_MUSIC(
|
||||
ANDROID_MUSIC_5_29(21,
|
||||
DEVICE_MODEL_ANDROID_MUSIC,
|
||||
OS_VERSION_ANDROID_MUSIC,
|
||||
androidUserAgent(CLIENT_VERSION_ANDROID_MUSIC_5_29),
|
||||
CLIENT_VERSION_ANDROID_MUSIC_5_29
|
||||
),
|
||||
IOS_MUSIC_6_21(
|
||||
26,
|
||||
DEVICE_MODEL_IOS_MUSIC,
|
||||
OS_VERSION_IOS_MUSIC,
|
||||
USER_AGENT_IOS_MUSIC,
|
||||
CLIENT_VERSION_IOS_MUSIC
|
||||
iOSUserAgent(CLIENT_VERSION_IOS_MUSIC_6_21),
|
||||
CLIENT_VERSION_IOS_MUSIC_6_21
|
||||
),
|
||||
IOS_MUSIC_7_04(
|
||||
26,
|
||||
DEVICE_MODEL_IOS_MUSIC,
|
||||
OS_VERSION_IOS_MUSIC,
|
||||
iOSUserAgent(CLIENT_VERSION_IOS_MUSIC_7_04),
|
||||
CLIENT_VERSION_IOS_MUSIC_7_04
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -180,8 +180,8 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting DISABLE_DRC_AUDIO = new BooleanSetting("revanced_disable_drc_audio", FALSE, true);
|
||||
public static final BooleanSetting ENABLE_OPUS_CODEC = new BooleanSetting("revanced_enable_opus_codec", FALSE, true);
|
||||
public static final BooleanSetting SETTINGS_IMPORT_EXPORT = new BooleanSetting("revanced_extended_settings_import_export", FALSE, false);
|
||||
public static final BooleanSetting SPOOF_CLIENT_LEGACY = new BooleanSetting("revanced_spoof_client_legacy", FALSE, true);
|
||||
public static final EnumSetting<ClientType> SPOOF_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_client_type", ClientType.ANDROID_MUSIC, true);
|
||||
public static final BooleanSetting SPOOF_CLIENT = new BooleanSetting("revanced_spoof_client", FALSE, true);
|
||||
public static final EnumSetting<ClientType> SPOOF_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_client_type", ClientType.IOS_MUSIC_6_21, true);
|
||||
|
||||
|
||||
// PreferenceScreen: Return YouTube Dislike
|
||||
|
@ -1,80 +0,0 @@
|
||||
package app.revanced.extension.shared.patches;
|
||||
|
||||
import static app.revanced.extension.shared.patches.PatchStatus.SpoofClient;
|
||||
import static app.revanced.extension.shared.patches.PatchStatus.SpoofStreamingData;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.shared.utils.Logger;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class BlockRequestPatch {
|
||||
/**
|
||||
* Used in YouTube and YouTube Music.
|
||||
*/
|
||||
public static final boolean SPOOF_STREAMING_DATA = BaseSettings.SPOOF_STREAMING_DATA.get();
|
||||
|
||||
/**
|
||||
* Used in YouTube Music.
|
||||
* Disabled by default.
|
||||
*/
|
||||
public static final boolean SPOOF_CLIENT = BaseSettings.SPOOF_CLIENT.get();
|
||||
|
||||
private static final boolean BLOCK_REQUEST = (SpoofStreamingData() && SPOOF_STREAMING_DATA) || (SpoofClient() && SPOOF_CLIENT);
|
||||
|
||||
/**
|
||||
* Any unreachable ip address. Used to intentionally fail requests.
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* Blocks /get_watch requests by returning an unreachable URI.
|
||||
*
|
||||
* @param playerRequestUri The URI of the player request.
|
||||
* @return An unreachable URI if the request is a /get_watch request, otherwise the original URI.
|
||||
*/
|
||||
public static Uri blockGetWatchRequest(Uri playerRequestUri) {
|
||||
if (BLOCK_REQUEST) {
|
||||
try {
|
||||
String path = playerRequestUri.getPath();
|
||||
|
||||
if (path != null && path.contains("get_watch")) {
|
||||
Logger.printDebug(() -> "Blocking 'get_watch' by returning unreachable uri");
|
||||
|
||||
return UNREACHABLE_HOST_URI;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "blockGetWatchRequest failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
return playerRequestUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* <p>
|
||||
* Blocks /initplayback requests.
|
||||
*/
|
||||
public static String blockInitPlaybackRequest(String originalUrlString) {
|
||||
if (BLOCK_REQUEST) {
|
||||
try {
|
||||
var originalUri = Uri.parse(originalUrlString);
|
||||
String path = originalUri.getPath();
|
||||
|
||||
if (path != null && path.contains("initplayback")) {
|
||||
Logger.printDebug(() -> "Blocking 'initplayback' by clearing query");
|
||||
|
||||
return originalUri.buildUpon().clearQuery().build().toString();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "blockInitPlaybackRequest failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
return originalUrlString;
|
||||
}
|
||||
}
|
@ -1,24 +1,18 @@
|
||||
package app.revanced.extension.shared.patches;
|
||||
|
||||
import app.revanced.extension.shared.patches.client.AppClient.ClientType;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class PatchStatus {
|
||||
public static boolean HideFullscreenAdsDefaultBoolean() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static ClientType SpoofStreamingDataDefaultClient() {
|
||||
return ClientType.IOS;
|
||||
}
|
||||
|
||||
public static boolean SpoofClient() {
|
||||
// Replace this with true If the Spoof client patch succeeds
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean SpoofStreamingData() {
|
||||
// Replace this with true If the Spoof streaming data patch succeeds
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean SpoofStreamingDataAndroidOnlyDefaultBoolean() {
|
||||
// Replace this with true If the Spoof streaming data patch succeeds in YouTube
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,15 @@ import android.os.Build;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
|
||||
public class AppClient {
|
||||
// IOS
|
||||
/**
|
||||
* Video not playable: Paid / Movie / Private / Age-restricted
|
||||
* Note: Audio track available
|
||||
*/
|
||||
private static final String PACKAGE_NAME_IOS = "com.google.ios.youtube";
|
||||
/**
|
||||
* The hardcoded client version of the iOS app used for InnerTube requests with this client.
|
||||
*
|
||||
@ -29,15 +36,35 @@ public class AppClient {
|
||||
private static final String DEVICE_MODEL_IOS = "iPhone16,2";
|
||||
private static final String OS_VERSION_IOS = "17.7.2.21H221";
|
||||
private static final String USER_AGENT_VERSION_IOS = "17_7_2";
|
||||
private static final String USER_AGENT_IOS = "com.google.ios.youtube/" +
|
||||
CLIENT_VERSION_IOS +
|
||||
"(" +
|
||||
DEVICE_MODEL_IOS +
|
||||
"; U; CPU iOS " +
|
||||
USER_AGENT_VERSION_IOS +
|
||||
" like Mac OS X)";
|
||||
private static final String USER_AGENT_IOS =
|
||||
iOSUserAgent(PACKAGE_NAME_IOS, CLIENT_VERSION_IOS);
|
||||
|
||||
|
||||
// IOS UNPLUGGED
|
||||
/**
|
||||
* Video not playable: Paid / Movie
|
||||
* Note: Audio track available
|
||||
*/
|
||||
private static final String PACKAGE_NAME_IOS_UNPLUGGED = "com.google.ios.youtubeunplugged";
|
||||
/**
|
||||
* The hardcoded client version of the iOS app used for InnerTube requests with this client.
|
||||
*
|
||||
* <p>
|
||||
* It can be extracted by getting the latest release version of the app on
|
||||
* <a href="https://apps.apple.com/us/app/youtube-tv/id1193350206/">the App
|
||||
* Store page of the YouTube TV app</a>, in the {@code What’s New} section.
|
||||
* </p>
|
||||
*/
|
||||
private static final String CLIENT_VERSION_IOS_UNPLUGGED = "8.33";
|
||||
private static final String USER_AGENT_IOS_UNPLUGGED =
|
||||
iOSUserAgent(PACKAGE_NAME_IOS_UNPLUGGED, CLIENT_VERSION_IOS_UNPLUGGED);
|
||||
|
||||
|
||||
// IOS MUSIC
|
||||
/**
|
||||
* Video not playable: All videos that can't be played on YouTube Music
|
||||
*/
|
||||
private static final String PACKAGE_NAME_IOS_MUSIC = "com.google.ios.youtubemusic";
|
||||
/**
|
||||
* The hardcoded client version of the iOS app used for InnerTube requests with this client.
|
||||
*
|
||||
@ -47,16 +74,21 @@ public class AppClient {
|
||||
* Store page of the YouTube Music app</a>, in the {@code What’s New} section.
|
||||
* </p>
|
||||
*/
|
||||
private static final String CLIENT_VERSION_IOS_MUSIC = "7.31.2";
|
||||
private static final String USER_AGENT_IOS_MUSIC = "com.google.ios.youtubemusic/" +
|
||||
CLIENT_VERSION_IOS_MUSIC +
|
||||
"(" +
|
||||
DEVICE_MODEL_IOS +
|
||||
"; U; CPU iOS " +
|
||||
USER_AGENT_VERSION_IOS +
|
||||
" like Mac OS X)";
|
||||
private static final String CLIENT_VERSION_IOS_MUSIC = "7.04";
|
||||
private static final String USER_AGENT_IOS_MUSIC =
|
||||
iOSUserAgent(PACKAGE_NAME_IOS_MUSIC, CLIENT_VERSION_IOS_MUSIC);
|
||||
|
||||
|
||||
// ANDROID VR
|
||||
/**
|
||||
* Video not playable: Kids
|
||||
* Note: Audio track is not available
|
||||
* <p>
|
||||
* Package name for YouTube VR (Google DayDream): com.google.android.apps.youtube.vr (Deprecated)
|
||||
* Package name for YouTube VR (Meta Quests): com.google.android.apps.youtube.vr.oculus
|
||||
* Package name for YouTube VR (ByteDance Pico 4): com.google.android.apps.youtube.vr.pico
|
||||
*/
|
||||
private static final String PACKAGE_NAME_ANDROID_VR = "com.google.android.apps.youtube.vr.oculus";
|
||||
/**
|
||||
* The hardcoded client version of the Android VR app used for InnerTube requests with this client.
|
||||
*
|
||||
@ -66,7 +98,7 @@ public class AppClient {
|
||||
* Store page of the YouTube app</a>, in the {@code Additional details} section.
|
||||
* </p>
|
||||
*/
|
||||
private static final String CLIENT_VERSION_ANDROID_VR = "1.61.47";
|
||||
private static final String CLIENT_VERSION_ANDROID_VR = "1.61.48";
|
||||
/**
|
||||
* The device machine id for the Meta Quest 3, used to get opus codec with the Android VR client.
|
||||
*
|
||||
@ -82,19 +114,17 @@ public class AppClient {
|
||||
* but for some reason the build.props for the {@code Quest 3} state that the SDK version is 32.
|
||||
*/
|
||||
private static final String ANDROID_SDK_VERSION_ANDROID_VR = "32";
|
||||
/**
|
||||
* Package name for YouTube VR (Google DayDream): com.google.android.apps.youtube.vr (Deprecated)
|
||||
* Package name for YouTube VR (Meta Quests): com.google.android.apps.youtube.vr.oculus
|
||||
* Package name for YouTube VR (ByteDance Pico 4): com.google.android.apps.youtube.vr.pico
|
||||
*/
|
||||
private static final String USER_AGENT_ANDROID_VR = "com.google.android.apps.youtube.vr.oculus/" +
|
||||
CLIENT_VERSION_ANDROID_VR +
|
||||
" (Linux; U; Android " +
|
||||
OS_VERSION_ANDROID_VR +
|
||||
"; GB) gzip";
|
||||
private static final String USER_AGENT_ANDROID_VR =
|
||||
androidUserAgent(PACKAGE_NAME_ANDROID_VR, CLIENT_VERSION_ANDROID_VR, OS_VERSION_ANDROID_VR);
|
||||
|
||||
|
||||
// ANDROID UNPLUGGED
|
||||
private static final String CLIENT_VERSION_ANDROID_UNPLUGGED = "8.49.0";
|
||||
/**
|
||||
* Video not playable: Playlists / Music
|
||||
* Note: Audio track is not available
|
||||
*/
|
||||
private static final String PACKAGE_NAME_ANDROID_UNPLUGGED = "com.google.android.apps.youtube.unplugged";
|
||||
private static final String CLIENT_VERSION_ANDROID_UNPLUGGED = "8.16.0";
|
||||
/**
|
||||
* The device machine id for the Chromecast with Google TV 4K.
|
||||
*
|
||||
@ -106,15 +136,47 @@ public class AppClient {
|
||||
private static final String DEVICE_MODEL_ANDROID_UNPLUGGED = "Google TV Streamer";
|
||||
private static final String OS_VERSION_ANDROID_UNPLUGGED = "14";
|
||||
private static final String ANDROID_SDK_VERSION_ANDROID_UNPLUGGED = "34";
|
||||
private static final String USER_AGENT_ANDROID_UNPLUGGED = "com.google.android.apps.youtube.unplugged/" +
|
||||
CLIENT_VERSION_ANDROID_UNPLUGGED +
|
||||
" (Linux; U; Android " +
|
||||
OS_VERSION_ANDROID_UNPLUGGED +
|
||||
"; GB) gzip";
|
||||
private static final String USER_AGENT_ANDROID_UNPLUGGED =
|
||||
androidUserAgent(PACKAGE_NAME_ANDROID_UNPLUGGED, CLIENT_VERSION_ANDROID_UNPLUGGED, OS_VERSION_ANDROID_UNPLUGGED);
|
||||
|
||||
|
||||
// ANDROID CREATOR
|
||||
/**
|
||||
* Video not playable: Livestream
|
||||
* Note: Audio track is not available
|
||||
*/
|
||||
private static final String PACKAGE_NAME_ANDROID_CREATOR = "com.google.android.apps.youtube.creator";
|
||||
private static final String CLIENT_VERSION_ANDROID_CREATOR = "24.14.101";
|
||||
private static final String DEVICE_MODEL_ANDROID_CREATOR = Build.MODEL;
|
||||
private static final String OS_VERSION_ANDROID_CREATOR = Build.VERSION.RELEASE;
|
||||
private static final String ANDROID_SDK_VERSION_ANDROID_CREATOR = String.valueOf(Build.VERSION.SDK_INT);
|
||||
private static final String USER_AGENT_ANDROID_CREATOR =
|
||||
androidUserAgent(PACKAGE_NAME_ANDROID_CREATOR, CLIENT_VERSION_ANDROID_CREATOR, OS_VERSION_ANDROID_CREATOR);
|
||||
|
||||
|
||||
private AppClient() {
|
||||
}
|
||||
|
||||
private static String androidUserAgent(String packageName, String clientVersion, String osVersion) {
|
||||
return packageName +
|
||||
"/" +
|
||||
clientVersion +
|
||||
" (Linux; U; Android " +
|
||||
osVersion +
|
||||
"; GB) gzip";
|
||||
}
|
||||
|
||||
private static String iOSUserAgent(String packageName, String clientVersion) {
|
||||
return packageName +
|
||||
"/" +
|
||||
clientVersion +
|
||||
"(" +
|
||||
DEVICE_MODEL_IOS +
|
||||
"; U; CPU iOS " +
|
||||
USER_AGENT_VERSION_IOS +
|
||||
" like Mac OS X)";
|
||||
}
|
||||
|
||||
public enum ClientType {
|
||||
IOS(5,
|
||||
DEVICE_MODEL_IOS,
|
||||
@ -140,6 +202,22 @@ public class AppClient {
|
||||
CLIENT_VERSION_ANDROID_UNPLUGGED,
|
||||
true
|
||||
),
|
||||
ANDROID_CREATOR(14,
|
||||
DEVICE_MODEL_ANDROID_CREATOR,
|
||||
OS_VERSION_ANDROID_CREATOR,
|
||||
USER_AGENT_ANDROID_CREATOR,
|
||||
ANDROID_SDK_VERSION_ANDROID_CREATOR,
|
||||
CLIENT_VERSION_ANDROID_CREATOR,
|
||||
true
|
||||
),
|
||||
IOS_UNPLUGGED(33,
|
||||
DEVICE_MODEL_IOS,
|
||||
OS_VERSION_IOS,
|
||||
USER_AGENT_IOS_UNPLUGGED,
|
||||
null,
|
||||
CLIENT_VERSION_IOS_UNPLUGGED,
|
||||
true
|
||||
),
|
||||
IOS_MUSIC(
|
||||
26,
|
||||
DEVICE_MODEL_IOS,
|
||||
@ -208,8 +286,28 @@ public class AppClient {
|
||||
this.canLogin = canLogin;
|
||||
}
|
||||
|
||||
private static final ClientType[] CLIENT_ORDER_TO_USE_ANDROID = {
|
||||
ANDROID_VR,
|
||||
ANDROID_UNPLUGGED,
|
||||
ANDROID_CREATOR,
|
||||
};
|
||||
|
||||
private static final ClientType[] CLIENT_ORDER_TO_USE_DEFAULT = {
|
||||
IOS,
|
||||
ANDROID_VR,
|
||||
ANDROID_UNPLUGGED,
|
||||
IOS_UNPLUGGED,
|
||||
IOS_MUSIC,
|
||||
};
|
||||
|
||||
public final String getFriendlyName() {
|
||||
return getString("revanced_spoof_streaming_data_type_entry_" + name().toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
public static ClientType[] getAvailableClientTypes() {
|
||||
return BaseSettings.SPOOF_STREAMING_DATA_ANDROID_ONLY.get()
|
||||
? ClientType.CLIENT_ORDER_TO_USE_ANDROID
|
||||
: ClientType.CLIENT_ORDER_TO_USE_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
@ -1,33 +1,31 @@
|
||||
package app.revanced.extension.shared.patches.spoof;
|
||||
|
||||
import static app.revanced.extension.shared.patches.PatchStatus.SpoofStreamingData;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.protos.youtube.api.innertube.StreamingDataOuterClass$StreamingData;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import app.revanced.extension.shared.patches.BlockRequestPatch;
|
||||
import app.revanced.extension.shared.patches.spoof.requests.StreamingDataRequest;
|
||||
import app.revanced.extension.shared.settings.BaseSettings;
|
||||
import app.revanced.extension.shared.utils.Logger;
|
||||
import app.revanced.extension.shared.utils.Utils;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class SpoofStreamingDataPatch extends BlockRequestPatch {
|
||||
public class SpoofStreamingDataPatch {
|
||||
public static final boolean SPOOF_STREAMING_DATA = SpoofStreamingData() && BaseSettings.SPOOF_STREAMING_DATA.get();
|
||||
|
||||
/**
|
||||
* Even if the default client is not iOS, videos that cannot be played on Android VR or Android TV will fall back to iOS.
|
||||
* Do not add a dependency that checks whether the default client is iOS or not.
|
||||
* Any unreachable ip address. Used to intentionally fail requests.
|
||||
*/
|
||||
private static final boolean SPOOF_STREAMING_DATA_SYNC_VIDEO_LENGTH =
|
||||
SPOOF_STREAMING_DATA && BaseSettings.SPOOF_STREAMING_DATA_SYNC_VIDEO_LENGTH.get();
|
||||
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);
|
||||
|
||||
/**
|
||||
* Key: video id
|
||||
@ -43,6 +41,55 @@ public class SpoofStreamingDataPatch extends BlockRequestPatch {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* Blocks /get_watch requests by returning an unreachable URI.
|
||||
*
|
||||
* @param playerRequestUri The URI of the player request.
|
||||
* @return An unreachable URI if the request is a /get_watch request, otherwise the original URI.
|
||||
*/
|
||||
public static Uri blockGetWatchRequest(Uri playerRequestUri) {
|
||||
if (SPOOF_STREAMING_DATA) {
|
||||
try {
|
||||
String path = playerRequestUri.getPath();
|
||||
|
||||
if (path != null && path.contains("get_watch")) {
|
||||
Logger.printDebug(() -> "Blocking 'get_watch' by returning unreachable uri");
|
||||
|
||||
return UNREACHABLE_HOST_URI;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "blockGetWatchRequest failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
return playerRequestUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* <p>
|
||||
* Blocks /initplayback requests.
|
||||
*/
|
||||
public static String blockInitPlaybackRequest(String originalUrlString) {
|
||||
if (SPOOF_STREAMING_DATA) {
|
||||
try {
|
||||
var originalUri = Uri.parse(originalUrlString);
|
||||
String path = originalUri.getPath();
|
||||
|
||||
if (path != null && path.contains("initplayback")) {
|
||||
Logger.printDebug(() -> "Blocking 'initplayback' by clearing query");
|
||||
|
||||
return originalUri.buildUpon().clearQuery().build().toString();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "blockInitPlaybackRequest failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
return originalUrlString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
@ -133,29 +180,13 @@ public class SpoofStreamingDataPatch extends BlockRequestPatch {
|
||||
* <p>
|
||||
* Called after {@link #getStreamingData(String)}.
|
||||
*/
|
||||
public static void setApproxDurationMs(String videoId, String approxDurationMsFieldName,
|
||||
StreamingDataOuterClass$StreamingData originalStreamingData, StreamingDataOuterClass$StreamingData spoofedStreamingData) {
|
||||
if (SPOOF_STREAMING_DATA_SYNC_VIDEO_LENGTH) {
|
||||
if (formatsIsEmpty(spoofedStreamingData)) {
|
||||
List<?> originalFormats = getFormatsFromStreamingData(originalStreamingData);
|
||||
Long approxDurationMs = getApproxDurationMs(originalFormats, approxDurationMsFieldName);
|
||||
if (approxDurationMs != null) {
|
||||
approxDurationMsMap.put(videoId, approxDurationMs);
|
||||
Logger.printDebug(() -> "New approxDurationMs loaded, video id: " + videoId + ", video length: " + approxDurationMs);
|
||||
} else {
|
||||
Logger.printDebug(() -> "Ignoring as original approxDurationMs is not found, video id: " + videoId);
|
||||
}
|
||||
} else {
|
||||
Logger.printDebug(() -> "Ignoring as spoofed formats is not empty, video id: " + videoId);
|
||||
}
|
||||
public static void setApproxDurationMs(String videoId, long approxDurationMs) {
|
||||
if (approxDurationMs != Long.MAX_VALUE) {
|
||||
approxDurationMsMap.put(videoId, approxDurationMs);
|
||||
Logger.printDebug(() -> "New approxDurationMs loaded, video id: " + videoId + ", video length: " + approxDurationMs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks like the initial value for the videoId field.
|
||||
*/
|
||||
private static final String MASKED_VIDEO_ID = "zzzzzzzzzzz";
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* <p>
|
||||
@ -171,22 +202,16 @@ public class SpoofStreamingDataPatch extends BlockRequestPatch {
|
||||
* <p>
|
||||
* Called after {@link #getStreamingData(String)}.
|
||||
*/
|
||||
public static long getApproxDurationMsFromOriginalResponse(String videoId, long lengthMilliseconds) {
|
||||
if (SPOOF_STREAMING_DATA_SYNC_VIDEO_LENGTH) {
|
||||
try {
|
||||
if (videoId != null && !videoId.equals(MASKED_VIDEO_ID)) {
|
||||
Long approxDurationMs = approxDurationMsMap.get(videoId);
|
||||
if (approxDurationMs != null) {
|
||||
Logger.printDebug(() -> "Replacing video length from " + lengthMilliseconds + " to " + approxDurationMs + " , videoId: " + videoId);
|
||||
approxDurationMsMap.remove(videoId);
|
||||
return approxDurationMs;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "getOriginalFormats failure", ex);
|
||||
public static long getApproxDurationMs(String videoId) {
|
||||
if (SPOOF_STREAMING_DATA && videoId != null) {
|
||||
final Long approxDurationMs = approxDurationMsMap.get(videoId);
|
||||
if (approxDurationMs != null) {
|
||||
Logger.printDebug(() -> "Replacing video length: " + approxDurationMs + " for videoId: " + videoId);
|
||||
approxDurationMsMap.remove(videoId);
|
||||
return approxDurationMs;
|
||||
}
|
||||
}
|
||||
return lengthMilliseconds;
|
||||
return Long.MAX_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -228,47 +253,4 @@ public class SpoofStreamingDataPatch extends BlockRequestPatch {
|
||||
|
||||
return videoFormat;
|
||||
}
|
||||
|
||||
// Utils
|
||||
|
||||
private static boolean formatsIsEmpty(StreamingDataOuterClass$StreamingData streamingData) {
|
||||
List<?> formats = getFormatsFromStreamingData(streamingData);
|
||||
return formats == null || formats.size() == 0;
|
||||
}
|
||||
|
||||
private static List<?> getFormatsFromStreamingData(StreamingDataOuterClass$StreamingData streamingData) {
|
||||
try {
|
||||
// Field e: 'formats'.
|
||||
// Field name is always 'e', regardless of the client version.
|
||||
Field field = streamingData.getClass().getDeclaredField("e");
|
||||
field.setAccessible(true);
|
||||
if (field.get(streamingData) instanceof List<?> list) {
|
||||
return list;
|
||||
}
|
||||
} catch (NoSuchFieldException | IllegalAccessException ex) {
|
||||
Logger.printException(() -> "Reflection error accessing formats", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Long getApproxDurationMs(List<?> list, String approxDurationMsFieldName) {
|
||||
try {
|
||||
if (list != null) {
|
||||
var iterator = list.listIterator();
|
||||
if (iterator.hasNext()) {
|
||||
var formats = iterator.next();
|
||||
Field field = formats.getClass().getDeclaredField(approxDurationMsFieldName);
|
||||
field.setAccessible(true);
|
||||
if (field.get(formats) instanceof Long approxDurationMs) {
|
||||
return approxDurationMs;
|
||||
} else {
|
||||
Logger.printDebug(() -> "Field type is null: " + approxDurationMsFieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (NoSuchFieldException | IllegalAccessException ex) {
|
||||
Logger.printException(() -> "Reflection error accessing field: " + approxDurationMsFieldName, ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,10 @@ public final class PlayerRoutes {
|
||||
client.put("osVersion", clientType.osVersion);
|
||||
if (clientType.androidSdkVersion != null) {
|
||||
client.put("androidSdkVersion", clientType.androidSdkVersion);
|
||||
client.put("osName", "Android");
|
||||
} else {
|
||||
client.put("deviceMake", "Apple");
|
||||
client.put("osName", "iOS");
|
||||
}
|
||||
client.put("hl", LOCALE_LANGUAGE);
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package app.revanced.extension.shared.patches.spoof.requests;
|
||||
|
||||
import static app.revanced.extension.shared.patches.client.AppClient.getAvailableClientTypes;
|
||||
import static app.revanced.extension.shared.patches.spoof.requests.PlayerRoutes.GET_STREAMING_DATA;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@ -13,6 +14,7 @@ import java.net.HttpURLConnection;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
@ -80,16 +82,20 @@ public class StreamingDataRequest {
|
||||
}
|
||||
|
||||
static {
|
||||
ClientType[] allClientTypes = ClientType.values();
|
||||
ClientType[] allClientTypes = getAvailableClientTypes();
|
||||
ClientType preferredClient = BaseSettings.SPOOF_STREAMING_DATA_TYPE.get();
|
||||
|
||||
CLIENT_ORDER_TO_USE = new ClientType[allClientTypes.length];
|
||||
CLIENT_ORDER_TO_USE[0] = preferredClient;
|
||||
if (Arrays.stream(allClientTypes).noneMatch(preferredClient::equals)) {
|
||||
CLIENT_ORDER_TO_USE = allClientTypes;
|
||||
} else {
|
||||
CLIENT_ORDER_TO_USE = new ClientType[allClientTypes.length];
|
||||
CLIENT_ORDER_TO_USE[0] = preferredClient;
|
||||
|
||||
int i = 1;
|
||||
for (ClientType c : allClientTypes) {
|
||||
if (c != preferredClient) {
|
||||
CLIENT_ORDER_TO_USE[i++] = c;
|
||||
int i = 1;
|
||||
for (ClientType c : allClientTypes) {
|
||||
if (c != preferredClient) {
|
||||
CLIENT_ORDER_TO_USE[i++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package app.revanced.extension.shared.settings;
|
||||
import static java.lang.Boolean.FALSE;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static app.revanced.extension.shared.patches.PatchStatus.HideFullscreenAdsDefaultBoolean;
|
||||
import static app.revanced.extension.shared.patches.PatchStatus.SpoofStreamingDataDefaultClient;
|
||||
import static app.revanced.extension.shared.patches.PatchStatus.SpoofStreamingDataAndroidOnlyDefaultBoolean;
|
||||
|
||||
import app.revanced.extension.shared.patches.ReturnYouTubeUsernamePatch.DisplayFormat;
|
||||
import app.revanced.extension.shared.patches.client.AppClient.ClientType;
|
||||
@ -36,13 +36,9 @@ public class BaseSettings {
|
||||
public static final EnumSetting<DisplayFormat> RETURN_YOUTUBE_USERNAME_DISPLAY_FORMAT = new EnumSetting<>("revanced_return_youtube_username_display_format", DisplayFormat.USERNAME_ONLY, true);
|
||||
public static final StringSetting RETURN_YOUTUBE_USERNAME_YOUTUBE_DATA_API_V3_DEVELOPER_KEY = new StringSetting("revanced_return_youtube_username_youtube_data_api_v3_developer_key", "", true, false);
|
||||
|
||||
// Used only in YouTube Music.
|
||||
// Moved to a shared class to prevent YouTube from accessing YouTube Music's extension classes.
|
||||
public static final BooleanSetting SPOOF_CLIENT = new BooleanSetting("revanced_spoof_client", FALSE, true);
|
||||
|
||||
public static final BooleanSetting SPOOF_STREAMING_DATA = new BooleanSetting("revanced_spoof_streaming_data", TRUE, true, "revanced_spoof_streaming_data_user_dialog_message");
|
||||
public static final EnumSetting<ClientType> SPOOF_STREAMING_DATA_TYPE = new EnumSetting<>("revanced_spoof_streaming_data_type", SpoofStreamingDataDefaultClient(), true);
|
||||
public static final BooleanSetting SPOOF_STREAMING_DATA_SYNC_VIDEO_LENGTH = new BooleanSetting("revanced_spoof_streaming_data_sync_video_length", TRUE, true);
|
||||
public static final EnumSetting<ClientType> SPOOF_STREAMING_DATA_TYPE = new EnumSetting<>("revanced_spoof_streaming_data_type", ClientType.ANDROID_VR, true);
|
||||
public static final BooleanSetting SPOOF_STREAMING_DATA_ANDROID_ONLY = new BooleanSetting("revanced_spoof_streaming_data_android_only", SpoofStreamingDataAndroidOnlyDefaultBoolean(), true, "revanced_spoof_streaming_data_android_only_user_dialog_message");
|
||||
public static final BooleanSetting SPOOF_STREAMING_DATA_STATS_FOR_NERDS = new BooleanSetting("revanced_spoof_streaming_data_stats_for_nerds", TRUE);
|
||||
|
||||
/**
|
||||
|
@ -246,8 +246,12 @@ public class GeneralPatch {
|
||||
}
|
||||
|
||||
public static boolean useTranslucentNavigationStatusBar(boolean original) {
|
||||
if (Settings.DISABLE_TRANSLUCENT_STATUS_BAR.get()) {
|
||||
return false;
|
||||
try {
|
||||
if (Settings.DISABLE_TRANSLUCENT_STATUS_BAR.get()) {
|
||||
return false;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "Failed to load useTranslucentNavigationStatusBar", ex);
|
||||
}
|
||||
|
||||
return original;
|
||||
@ -260,22 +264,27 @@ public class GeneralPatch {
|
||||
= Settings.DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK.get();
|
||||
|
||||
public static boolean useTranslucentNavigationButtons(boolean original) {
|
||||
// Feature requires Android 13+
|
||||
if (!isSDKAbove(33)) {
|
||||
return original;
|
||||
}
|
||||
try {
|
||||
// Feature requires Android 13+
|
||||
if (!isSDKAbove(33)) {
|
||||
return original;
|
||||
}
|
||||
|
||||
if (!DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK && !DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT) {
|
||||
return original;
|
||||
}
|
||||
if (!DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK && !DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT) {
|
||||
return original;
|
||||
}
|
||||
|
||||
if (DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK && DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT) {
|
||||
return false;
|
||||
}
|
||||
if (DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK && DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Utils.isDarkModeEnabled()
|
||||
? !DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK
|
||||
: !DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT;
|
||||
return Utils.isDarkModeEnabled()
|
||||
? !DISABLE_TRANSLUCENT_NAVIGATION_BAR_DARK
|
||||
: !DISABLE_TRANSLUCENT_NAVIGATION_BAR_LIGHT;
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "Failed to load useTranslucentNavigationButtons", ex);
|
||||
}
|
||||
return original;
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
@ -480,9 +480,9 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting SHORTS_CUSTOM_ACTIONS_REPEAT_STATE = new BooleanSetting("revanced_shorts_custom_actions_repeat_state", FALSE, true);
|
||||
|
||||
public static final BooleanSetting ENABLE_SHORTS_CUSTOM_ACTIONS_FLYOUT_MENU = new BooleanSetting("revanced_enable_shorts_custom_actions_flyout_menu", FALSE, true,
|
||||
parentsAny(SHORTS_CUSTOM_ACTIONS_COPY_VIDEO_URL, SHORTS_CUSTOM_ACTIONS_COPY_VIDEO_URL_TIMESTAMP, SHORTS_CUSTOM_ACTIONS_OPEN_VIDEO, SHORTS_CUSTOM_ACTIONS_REPEAT_STATE));
|
||||
parentsAny(SHORTS_CUSTOM_ACTIONS_COPY_VIDEO_URL, SHORTS_CUSTOM_ACTIONS_COPY_VIDEO_URL_TIMESTAMP, SHORTS_CUSTOM_ACTIONS_EXTERNAL_DOWNLOADER, SHORTS_CUSTOM_ACTIONS_OPEN_VIDEO, SHORTS_CUSTOM_ACTIONS_REPEAT_STATE));
|
||||
public static final BooleanSetting ENABLE_SHORTS_CUSTOM_ACTIONS_TOOLBAR = new BooleanSetting("revanced_enable_shorts_custom_actions_toolbar", FALSE, true,
|
||||
parentsAny(SHORTS_CUSTOM_ACTIONS_COPY_VIDEO_URL, SHORTS_CUSTOM_ACTIONS_COPY_VIDEO_URL_TIMESTAMP, SHORTS_CUSTOM_ACTIONS_OPEN_VIDEO, SHORTS_CUSTOM_ACTIONS_REPEAT_STATE));
|
||||
parentsAny(SHORTS_CUSTOM_ACTIONS_COPY_VIDEO_URL, SHORTS_CUSTOM_ACTIONS_COPY_VIDEO_URL_TIMESTAMP, SHORTS_CUSTOM_ACTIONS_EXTERNAL_DOWNLOADER, SHORTS_CUSTOM_ACTIONS_OPEN_VIDEO, SHORTS_CUSTOM_ACTIONS_REPEAT_STATE));
|
||||
|
||||
// Experimental Flags
|
||||
public static final BooleanSetting ENABLE_TIME_STAMP = new BooleanSetting("revanced_enable_shorts_time_stamp", FALSE, true);
|
||||
|
@ -0,0 +1,87 @@
|
||||
package app.revanced.extension.youtube.settings.preference;
|
||||
|
||||
import static app.revanced.extension.shared.utils.ResourceUtils.getStringArray;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import app.revanced.extension.shared.patches.client.AppClient.ClientType;
|
||||
import app.revanced.extension.shared.settings.EnumSetting;
|
||||
import app.revanced.extension.shared.settings.Setting;
|
||||
import app.revanced.extension.shared.utils.Utils;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
|
||||
@SuppressWarnings({"unused", "deprecation"})
|
||||
public class SpoofStreamingDataDefaultClientListPreference extends ListPreference {
|
||||
|
||||
private final SharedPreferences.OnSharedPreferenceChangeListener listener = (sharedPreferences, str) -> {
|
||||
// Because this listener may run before the ReVanced settings fragment updates Settings,
|
||||
// this could show the prior config and not the current.
|
||||
//
|
||||
// Push this call to the end of the main run queue,
|
||||
// so all other listeners are done and Settings is up to date.
|
||||
Utils.runOnMainThread(this::updateUI);
|
||||
};
|
||||
|
||||
public SpoofStreamingDataDefaultClientListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
public SpoofStreamingDataDefaultClientListPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public SpoofStreamingDataDefaultClientListPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public SpoofStreamingDataDefaultClientListPreference(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
private void addChangeListener() {
|
||||
Setting.preferences.preferences.registerOnSharedPreferenceChangeListener(listener);
|
||||
}
|
||||
|
||||
private void removeChangeListener() {
|
||||
Setting.preferences.preferences.unregisterOnSharedPreferenceChangeListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToHierarchy(PreferenceManager preferenceManager) {
|
||||
super.onAttachedToHierarchy(preferenceManager);
|
||||
updateUI();
|
||||
addChangeListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareForRemoval() {
|
||||
super.onPrepareForRemoval();
|
||||
removeChangeListener();
|
||||
}
|
||||
|
||||
private void updateUI() {
|
||||
final boolean spoofStreamingDataAndroidOnly = Settings.SPOOF_STREAMING_DATA_ANDROID_ONLY.get();
|
||||
final String entryKey = spoofStreamingDataAndroidOnly
|
||||
? "revanced_spoof_streaming_data_type_android_entries"
|
||||
: "revanced_spoof_streaming_data_type_android_ios_entries";
|
||||
final String entryValueKey = spoofStreamingDataAndroidOnly
|
||||
? "revanced_spoof_streaming_data_type_android_entry_values"
|
||||
: "revanced_spoof_streaming_data_type_android_ios_entry_values";
|
||||
final String[] mEntries = getStringArray(entryKey);
|
||||
final String[] mEntryValues = getStringArray(entryValueKey);
|
||||
setEntries(mEntries);
|
||||
setEntryValues(mEntryValues);
|
||||
|
||||
final EnumSetting<ClientType> clientType = Settings.SPOOF_STREAMING_DATA_TYPE;
|
||||
final boolean isAndroid = clientType.get().name().startsWith("ANDROID");
|
||||
if (spoofStreamingDataAndroidOnly && !isAndroid) {
|
||||
clientType.resetToDefault();
|
||||
}
|
||||
|
||||
setEnabled(Settings.SPOOF_STREAMING_DATA.get());
|
||||
}
|
||||
}
|
@ -8,7 +8,6 @@ import android.preference.Preference;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import app.revanced.extension.shared.patches.client.AppClient.ClientType;
|
||||
import app.revanced.extension.shared.settings.Setting;
|
||||
import app.revanced.extension.shared.utils.Utils;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
@ -63,11 +62,14 @@ public class SpoofStreamingDataSideEffectsPreference extends Preference {
|
||||
}
|
||||
|
||||
private void updateUI() {
|
||||
final ClientType clientType = Settings.SPOOF_STREAMING_DATA_TYPE.get();
|
||||
final String summaryTextKey = clientType == ClientType.IOS &&
|
||||
!Settings.SPOOF_STREAMING_DATA_SYNC_VIDEO_LENGTH.get()
|
||||
? "revanced_spoof_streaming_data_side_effects_ios_skip_sync_video_length"
|
||||
: "revanced_spoof_streaming_data_side_effects_" + clientType.name().toLowerCase();
|
||||
final String clientName = Settings.SPOOF_STREAMING_DATA_TYPE.get().name().toLowerCase();
|
||||
String summaryTextKey = "revanced_spoof_streaming_data_side_effects_";
|
||||
|
||||
if (Settings.SPOOF_STREAMING_DATA_ANDROID_ONLY.get()) {
|
||||
summaryTextKey += "android";
|
||||
} else {
|
||||
summaryTextKey += clientName;
|
||||
}
|
||||
|
||||
setSummary(str(summaryTextKey));
|
||||
setEnabled(Settings.SPOOF_STREAMING_DATA.get());
|
||||
|
@ -4,5 +4,5 @@ org.gradle.parallel = true
|
||||
android.useAndroidX = true
|
||||
kotlin.code.style = official
|
||||
kotlin.jvm.target.validation.mode = IGNORE
|
||||
version = 5.1.1
|
||||
version = 5.1.2
|
||||
|
||||
|
157
patches.json
157
patches.json
@ -44,7 +44,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -60,7 +60,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -76,7 +76,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -109,7 +109,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -118,7 +118,9 @@
|
||||
"name": "Change package name",
|
||||
"description": "Changes the package name for Reddit to the name specified in patch options.",
|
||||
"use": false,
|
||||
"compatiblePackages": {},
|
||||
"compatiblePackages": {
|
||||
"com.reddit.frontpage": null
|
||||
},
|
||||
"options": [
|
||||
{
|
||||
"key": "packageNameReddit",
|
||||
@ -162,7 +164,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -195,7 +197,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -221,6 +223,7 @@
|
||||
"name": "Change version code",
|
||||
"description": "Changes the version code of the app to the value specified in patch options. Except when mounting, this can prevent app stores from updating the app and allow the app to be installed over an existing installation that has a higher version code. By default, the highest version code is set.",
|
||||
"use": false,
|
||||
"compatiblePackages": null,
|
||||
"options": [
|
||||
{
|
||||
"key": "versionCode",
|
||||
@ -302,6 +305,7 @@
|
||||
{
|
||||
"key": "changeSplashIcon",
|
||||
"default": true,
|
||||
"values": null,
|
||||
"title": "Change splash icons",
|
||||
"description": "Apply the custom branding icon to the splash screen.",
|
||||
"required": true
|
||||
@ -309,6 +313,7 @@
|
||||
{
|
||||
"key": "restoreOldSplashAnimation",
|
||||
"default": true,
|
||||
"values": null,
|
||||
"title": "Restore old splash animation",
|
||||
"description": "Restore the old style splash animation.",
|
||||
"required": true
|
||||
@ -326,7 +331,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": [
|
||||
@ -348,6 +353,7 @@
|
||||
{
|
||||
"key": "changeSplashIcon",
|
||||
"default": true,
|
||||
"values": null,
|
||||
"title": "Change splash icons",
|
||||
"description": "Apply the custom branding icon to the splash screen.",
|
||||
"required": true
|
||||
@ -355,6 +361,7 @@
|
||||
{
|
||||
"key": "restoreOldSplashIcon",
|
||||
"default": false,
|
||||
"values": null,
|
||||
"title": "Restore old splash icon",
|
||||
"description": "Restore the old style splash icon.\n\nIf you enable both the old style splash icon and the Cairo splash animation,\n\nOld style splash icon will appear first and then the Cairo splash animation will start.",
|
||||
"required": true
|
||||
@ -365,7 +372,9 @@
|
||||
"name": "Custom branding name for Reddit",
|
||||
"description": "Renames the Reddit app to the name specified in patch options.",
|
||||
"use": false,
|
||||
"compatiblePackages": {},
|
||||
"compatiblePackages": {
|
||||
"com.reddit.frontpage": null
|
||||
},
|
||||
"options": [
|
||||
{
|
||||
"key": "appName",
|
||||
@ -422,7 +431,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": [
|
||||
@ -473,6 +482,7 @@
|
||||
{
|
||||
"key": "doubleTapLengthArrays",
|
||||
"default": "3, 5, 10, 15, 20, 30, 60, 120, 180",
|
||||
"values": null,
|
||||
"title": "Double-tap to seek values",
|
||||
"description": "A list of custom Double-tap to seek lengths to be added, separated by commas.",
|
||||
"required": true
|
||||
@ -518,7 +528,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": [
|
||||
@ -559,7 +569,7 @@
|
||||
"com.google.android.apps.youtube.music": [
|
||||
"7.06.54",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -575,7 +585,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -625,7 +635,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -658,7 +668,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -701,7 +711,9 @@
|
||||
"name": "Disable screenshot popup",
|
||||
"description": "Adds an option to disable the popup that appears when taking a screenshot.",
|
||||
"use": true,
|
||||
"compatiblePackages": {},
|
||||
"compatiblePackages": {
|
||||
"com.reddit.frontpage": null
|
||||
},
|
||||
"options": []
|
||||
},
|
||||
{
|
||||
@ -732,7 +744,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -765,7 +777,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -832,7 +844,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -865,7 +877,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -915,7 +927,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": [
|
||||
@ -932,6 +944,7 @@
|
||||
{
|
||||
"key": "checkGmsCore",
|
||||
"default": true,
|
||||
"values": null,
|
||||
"title": "Check GmsCore",
|
||||
"description": "Check if GmsCore is installed on the device and has battery optimizations disabled when the app starts. \n\nIf GmsCore is not installed the app will not work, so disabling this is not recommended.",
|
||||
"required": true
|
||||
@ -989,6 +1002,7 @@
|
||||
{
|
||||
"key": "checkGmsCore",
|
||||
"default": true,
|
||||
"values": null,
|
||||
"title": "Check GmsCore",
|
||||
"description": "Check if GmsCore is installed on the device and has battery optimizations disabled when the app starts. \n\nIf GmsCore is not installed the app will not work, so disabling this is not recommended.",
|
||||
"required": true
|
||||
@ -1021,7 +1035,9 @@
|
||||
"name": "Hide Recently Visited shelf",
|
||||
"description": "Adds an option to hide the Recently Visited shelf in the sidebar.",
|
||||
"use": true,
|
||||
"compatiblePackages": {},
|
||||
"compatiblePackages": {
|
||||
"com.reddit.frontpage": null
|
||||
},
|
||||
"options": []
|
||||
},
|
||||
{
|
||||
@ -1052,7 +1068,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -1068,7 +1084,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -1101,7 +1117,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -1110,7 +1126,9 @@
|
||||
"name": "Hide ads",
|
||||
"description": "Adds options to hide ads.",
|
||||
"use": true,
|
||||
"compatiblePackages": {},
|
||||
"compatiblePackages": {
|
||||
"com.reddit.frontpage": null
|
||||
},
|
||||
"options": []
|
||||
},
|
||||
{
|
||||
@ -1192,7 +1210,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -1218,7 +1236,9 @@
|
||||
"name": "Hide navigation buttons",
|
||||
"description": "Adds options to hide buttons in the navigation bar.",
|
||||
"use": false,
|
||||
"compatiblePackages": {},
|
||||
"compatiblePackages": {
|
||||
"com.reddit.frontpage": null
|
||||
},
|
||||
"options": []
|
||||
},
|
||||
{
|
||||
@ -1232,7 +1252,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -1282,7 +1302,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -1291,7 +1311,9 @@
|
||||
"name": "Hide recommended communities shelf",
|
||||
"description": "Adds an option to hide the recommended communities shelves in subreddits.",
|
||||
"use": true,
|
||||
"compatiblePackages": {},
|
||||
"compatiblePackages": {
|
||||
"com.reddit.frontpage": null
|
||||
},
|
||||
"options": []
|
||||
},
|
||||
{
|
||||
@ -1313,6 +1335,7 @@
|
||||
{
|
||||
"key": "explore",
|
||||
"default": false,
|
||||
"values": null,
|
||||
"title": "Hide Explore",
|
||||
"description": "Hide Explore from shortcuts.",
|
||||
"required": true
|
||||
@ -1320,6 +1343,7 @@
|
||||
{
|
||||
"key": "subscriptions",
|
||||
"default": false,
|
||||
"values": null,
|
||||
"title": "Hide Subscriptions",
|
||||
"description": "Hide Subscriptions from shortcuts.",
|
||||
"required": true
|
||||
@ -1327,6 +1351,7 @@
|
||||
{
|
||||
"key": "search",
|
||||
"default": false,
|
||||
"values": null,
|
||||
"title": "Hide Search",
|
||||
"description": "Hide Search from shortcuts.",
|
||||
"required": true
|
||||
@ -1334,6 +1359,7 @@
|
||||
{
|
||||
"key": "shorts",
|
||||
"default": true,
|
||||
"values": null,
|
||||
"title": "Hide Shorts",
|
||||
"description": "Hide Shorts from shortcuts.",
|
||||
"required": true
|
||||
@ -1436,7 +1462,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -1462,14 +1488,18 @@
|
||||
"name": "Open links directly",
|
||||
"description": "Adds an option to skip over redirection URLs in external links.",
|
||||
"use": true,
|
||||
"compatiblePackages": {},
|
||||
"compatiblePackages": {
|
||||
"com.reddit.frontpage": null
|
||||
},
|
||||
"options": []
|
||||
},
|
||||
{
|
||||
"name": "Open links externally",
|
||||
"description": "Adds an option to always open links in your browser instead of in the in-app-browser.",
|
||||
"use": true,
|
||||
"compatiblePackages": {},
|
||||
"compatiblePackages": {
|
||||
"com.reddit.frontpage": null
|
||||
},
|
||||
"options": []
|
||||
},
|
||||
{
|
||||
@ -1515,6 +1545,7 @@
|
||||
{
|
||||
"key": "widerButtonsSpace",
|
||||
"default": false,
|
||||
"values": null,
|
||||
"title": "Wider between-buttons space",
|
||||
"description": "Prevent adjacent button presses by increasing the horizontal spacing between buttons.",
|
||||
"required": true
|
||||
@ -1522,6 +1553,7 @@
|
||||
{
|
||||
"key": "changeTopButtons",
|
||||
"default": false,
|
||||
"values": null,
|
||||
"title": "Change top buttons",
|
||||
"description": "Change the icons at the top of the player.",
|
||||
"required": true
|
||||
@ -1539,7 +1571,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -1565,7 +1597,9 @@
|
||||
"name": "Premium icon",
|
||||
"description": "Unlocks premium app icons.",
|
||||
"use": true,
|
||||
"compatiblePackages": {},
|
||||
"compatiblePackages": {
|
||||
"com.reddit.frontpage": null
|
||||
},
|
||||
"options": []
|
||||
},
|
||||
{
|
||||
@ -1579,7 +1613,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -1605,7 +1639,9 @@
|
||||
"name": "Remove subreddit dialog",
|
||||
"description": "Adds options to remove the NSFW community warning and notifications suggestion dialogs by dismissing them automatically.",
|
||||
"use": true,
|
||||
"compatiblePackages": {},
|
||||
"compatiblePackages": {
|
||||
"com.reddit.frontpage": null
|
||||
},
|
||||
"options": []
|
||||
},
|
||||
{
|
||||
@ -1619,7 +1655,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -1652,7 +1688,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -1668,7 +1704,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -1701,7 +1737,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -1734,7 +1770,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -1743,7 +1779,9 @@
|
||||
"name": "Sanitize sharing links",
|
||||
"description": "Adds an option to remove tracking query parameters from URLs when sharing links.",
|
||||
"use": true,
|
||||
"compatiblePackages": {},
|
||||
"compatiblePackages": {
|
||||
"com.reddit.frontpage": null
|
||||
},
|
||||
"options": []
|
||||
},
|
||||
{
|
||||
@ -1784,11 +1822,14 @@
|
||||
"name": "Settings for Reddit",
|
||||
"description": "Applies mandatory patches to implement ReVanced Extended settings into the application.",
|
||||
"use": true,
|
||||
"compatiblePackages": {},
|
||||
"compatiblePackages": {
|
||||
"com.reddit.frontpage": null
|
||||
},
|
||||
"options": [
|
||||
{
|
||||
"key": "settingsLabel",
|
||||
"default": "ReVanced Extended",
|
||||
"values": null,
|
||||
"title": "RVX settings menu name",
|
||||
"description": "The name of the RVX settings menu.",
|
||||
"required": true
|
||||
@ -1845,6 +1886,7 @@
|
||||
{
|
||||
"key": "settingsLabel",
|
||||
"default": "ReVanced Extended",
|
||||
"values": null,
|
||||
"title": "RVX settings label",
|
||||
"description": "The name of the RVX settings menu.",
|
||||
"required": true
|
||||
@ -1862,13 +1904,14 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": [
|
||||
{
|
||||
"key": "settingsLabel",
|
||||
"default": "ReVanced Extended",
|
||||
"values": null,
|
||||
"title": "RVX settings label",
|
||||
"description": "The name of the RVX settings menu.",
|
||||
"required": true
|
||||
@ -1903,7 +1946,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -1927,6 +1970,7 @@
|
||||
{
|
||||
"key": "outlineIcon",
|
||||
"default": false,
|
||||
"values": null,
|
||||
"title": "Outline icons",
|
||||
"description": "Apply the outline icon.",
|
||||
"required": true
|
||||
@ -1943,7 +1987,6 @@
|
||||
"6.29.59",
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.06.54",
|
||||
"7.16.53"
|
||||
]
|
||||
},
|
||||
@ -1976,8 +2019,7 @@
|
||||
"6.29.59",
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.16.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -1993,7 +2035,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -2121,6 +2163,7 @@
|
||||
{
|
||||
"key": "customTranslations",
|
||||
"default": "",
|
||||
"values": null,
|
||||
"title": "Custom translations",
|
||||
"description": "The path to the \u0027strings.xml\u0027 file.\nPlease note that applying the \u0027strings.xml\u0027 file will overwrite all existing translations.",
|
||||
"required": true
|
||||
@ -2128,6 +2171,7 @@
|
||||
{
|
||||
"key": "selectedTranslations",
|
||||
"default": "ar, bg-rBG, de-rDE, el-rGR, es-rES, fr-rFR, hu-rHU, it-rIT, ja-rJP, ko-rKR, pl-rPL, pt-rBR, ru-rRU, tr-rTR, uk-rUA, vi-rVN, zh-rCN, zh-rTW",
|
||||
"values": null,
|
||||
"title": "Translations to add",
|
||||
"description": "A list of translations to be added for the RVX settings, separated by commas.",
|
||||
"required": true
|
||||
@ -2135,6 +2179,7 @@
|
||||
{
|
||||
"key": "selectedStringResources",
|
||||
"default": "af, am, ar, ar-rXB, as, az, b+es+419, b+sr+Latn, be, bg, bn, bs, ca, cs, da, de, el, en-rAU, en-rCA, en-rGB, en-rIN, en-rXA, en-rXC, es, es-rUS, et, eu, fa, fi, fr, fr-rCA, gl, gu, hi, hr, hu, hy, id, in, is, it, iw, ja, ka, kk, km, kn, ko, ky, lo, lt, lv, mk, ml, mn, mr, ms, my, nb, ne, nl, no, or, pa, pl, pt, pt-rBR, pt-rPT, ro, ru, si, sk, sl, sq, sr, sv, sw, ta, te, th, tl, tr, uk, ur, uz, vi, zh, zh-rCN, zh-rHK, zh-rTW, zu",
|
||||
"values": null,
|
||||
"title": "String resources to keep",
|
||||
"description": "A list of string resources to be kept, separated by commas.\nString resources not in the list will be removed from the app.\n\nDefault string resource, English, is not removed.",
|
||||
"required": true
|
||||
@ -2152,13 +2197,14 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": [
|
||||
{
|
||||
"key": "customTranslations",
|
||||
"default": "",
|
||||
"values": null,
|
||||
"title": "Custom translations",
|
||||
"description": "The path to the \u0027strings.xml\u0027 file.\nPlease note that applying the \u0027strings.xml\u0027 file will overwrite all existing translations.",
|
||||
"required": true
|
||||
@ -2166,6 +2212,7 @@
|
||||
{
|
||||
"key": "selectedTranslations",
|
||||
"default": "bg-rBG, bn, cs-rCZ, el-rGR, es-rES, fr-rFR, hu-rHU, id-rID, in, it-rIT, ja-rJP, ko-rKR, nl-rNL, pl-rPL, pt-rBR, ro-rRO, ru-rRU, tr-rTR, uk-rUA, vi-rVN, zh-rCN, zh-rTW",
|
||||
"values": null,
|
||||
"title": "Translations to add",
|
||||
"description": "A list of translations to be added for the RVX settings, separated by commas.",
|
||||
"required": true
|
||||
@ -2173,6 +2220,7 @@
|
||||
{
|
||||
"key": "selectedStringResources",
|
||||
"default": "af, am, ar, ar-rXB, as, az, b+es+419, b+sr+Latn, be, bg, bn, bs, ca, cs, da, de, el, en-rAU, en-rCA, en-rGB, en-rIN, en-rXA, en-rXC, es, es-rUS, et, eu, fa, fi, fr, fr-rCA, gl, gu, hi, hr, hu, hy, id, in, is, it, iw, ja, ka, kk, km, kn, ko, ky, lo, lt, lv, mk, ml, mn, mr, ms, my, nb, ne, nl, no, or, pa, pl, pt, pt-rBR, pt-rPT, ro, ru, si, sk, sl, sq, sr, sv, sw, ta, te, th, tl, tr, uk, ur, uz, vi, zh, zh-rCN, zh-rHK, zh-rTW, zu",
|
||||
"values": null,
|
||||
"title": "String resources to keep",
|
||||
"description": "A list of string resources to be kept, separated by commas.\nString resources not in the list will be removed from the app.\n\nDefault string resource, English, is not removed.",
|
||||
"required": true
|
||||
@ -2190,7 +2238,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": []
|
||||
@ -2246,6 +2294,7 @@
|
||||
{
|
||||
"key": "applyToAll",
|
||||
"default": false,
|
||||
"values": null,
|
||||
"title": "Apply to all settings menu",
|
||||
"description": "Whether to apply Visual preferences icons to all settings menus.\n\nIf true: icons are applied to the parent PreferenceScreen of YouTube settings, the parent PreferenceScreen of RVX settings and the RVX sub-settings (if supported).\n\nIf false: icons are applied only to the parent PreferenceScreen of YouTube settings and RVX settings.",
|
||||
"required": true
|
||||
@ -2263,7 +2312,7 @@
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
"7.25.52"
|
||||
"7.25.53"
|
||||
]
|
||||
},
|
||||
"options": [
|
||||
|
@ -375,11 +375,6 @@ public final class app/revanced/patches/shared/ads/BaseAdsPatchKt {
|
||||
public static final fun baseAdsPatch (Ljava/lang/String;Ljava/lang/String;)Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/blockrequest/BlockRequestPatchKt {
|
||||
public static final field EXTENSION_CLASS_DESCRIPTOR Ljava/lang/String;
|
||||
public static final fun getBlockRequestPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/captions/BaseAutoCaptionsPatchKt {
|
||||
public static final fun getBaseAutoCaptionsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@ -496,11 +491,14 @@ public final class app/revanced/patches/shared/spoof/appversion/BaseSpoofAppVers
|
||||
|
||||
public final class app/revanced/patches/shared/spoof/streamingdata/BaseSpoofStreamingDataPatchKt {
|
||||
public static final field EXTENSION_CLASS_DESCRIPTOR Ljava/lang/String;
|
||||
public static final field STREAMING_DATA_INTERFACE Ljava/lang/String;
|
||||
public static final fun baseSpoofStreamingDataPatch (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static synthetic fun baseSpoofStreamingDataPatch$default (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/spoof/streamingdata/FingerprintsKt {
|
||||
public static final field STREAMING_DATA_INTERFACE Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/spoof/useragent/BaseSpoofUserAgentPatchKt {
|
||||
public static final fun baseSpoofUserAgentPatch (Ljava/lang/String;)Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ internal class JsonPatchesFileGenerator : PatchesFileGenerator {
|
||||
},
|
||||
)
|
||||
}.let {
|
||||
patchesJson.writeText(GsonBuilder().setPrettyPrinting().create().toJson(it))
|
||||
patchesJson.writeText(GsonBuilder().serializeNulls().setPrettyPrinting().create().toJson(it))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@ import app.revanced.patches.music.utils.settings.addPreferenceWithIntent
|
||||
import app.revanced.patches.music.utils.settings.addSwitchPreference
|
||||
import app.revanced.patches.music.utils.settings.settingsPatch
|
||||
import app.revanced.patches.shared.spoof.appversion.baseSpoofAppVersionPatch
|
||||
import app.revanced.util.Utils.printWarn
|
||||
import app.revanced.util.appendAppVersion
|
||||
import app.revanced.util.findMethodOrThrow
|
||||
|
||||
@ -64,7 +65,6 @@ val spoofAppVersionPatch = resourcePatch(
|
||||
"6.29.59",
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.06.54",
|
||||
"7.16.53",
|
||||
),
|
||||
)
|
||||
@ -78,7 +78,7 @@ val spoofAppVersionPatch = resourcePatch(
|
||||
|
||||
execute {
|
||||
if (is_7_25_or_greater) {
|
||||
println("WARNING: \"${SPOOF_APP_VERSION.title}\" is not supported in this version. Use YouTube Music 7.24.51 or earlier.")
|
||||
printWarn("\"${SPOOF_APP_VERSION.title}\" is not supported in this version. Use YouTube Music 7.24.51 or earlier.")
|
||||
return@execute
|
||||
}
|
||||
if (is_7_17_or_greater) {
|
||||
|
@ -9,6 +9,7 @@ import app.revanced.patches.music.utils.settings.ResourceUtils.getIconType
|
||||
import app.revanced.patches.music.utils.settings.ResourceUtils.updatePatchStatus
|
||||
import app.revanced.patches.music.utils.settings.settingsPatch
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.Utils.printWarn
|
||||
import app.revanced.util.Utils.trimIndentMultiline
|
||||
import app.revanced.util.copyFile
|
||||
import app.revanced.util.copyResources
|
||||
@ -154,7 +155,7 @@ val changeHeaderPatch = resourcePatch(
|
||||
val customBrandingIconIncluded = customBrandingIconType != "default"
|
||||
customHeader = customHeaderOption.valueOrThrow()
|
||||
|
||||
val warnings = "WARNING: Invalid header path: $customHeader. Does not apply patches."
|
||||
val warnings = "Invalid header path: $customHeader. Does not apply patches."
|
||||
|
||||
if (isPath) {
|
||||
copyFile(
|
||||
@ -169,7 +170,7 @@ val changeHeaderPatch = resourcePatch(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println(warnings)
|
||||
printWarn(warnings)
|
||||
}
|
||||
|
||||
updatePatchStatus(CUSTOM_HEADER_FOR_YOUTUBE_MUSIC)
|
||||
|
@ -16,6 +16,7 @@ import app.revanced.patches.music.utils.settings.CategoryType
|
||||
import app.revanced.patches.music.utils.settings.ResourceUtils.updatePatchStatus
|
||||
import app.revanced.patches.music.utils.settings.addSwitchPreference
|
||||
import app.revanced.patches.music.utils.settings.settingsPatch
|
||||
import app.revanced.util.Utils.printWarn
|
||||
import app.revanced.util.fingerprint.injectLiteralInstructionBooleanCall
|
||||
import app.revanced.util.fingerprint.methodOrThrow
|
||||
import app.revanced.util.getReference
|
||||
@ -38,7 +39,7 @@ val cairoSplashAnimationPatch = bytecodePatch(
|
||||
YOUTUBE_MUSIC_PACKAGE_NAME(
|
||||
"7.06.54",
|
||||
"7.16.53",
|
||||
"7.25.52",
|
||||
"7.25.53",
|
||||
),
|
||||
)
|
||||
|
||||
@ -50,7 +51,7 @@ val cairoSplashAnimationPatch = bytecodePatch(
|
||||
|
||||
execute {
|
||||
if (!is_7_06_or_greater) {
|
||||
println("WARNING: \"${DISABLE_CAIRO_SPLASH_ANIMATION.title}\" is not supported in this version. Use YouTube Music 7.06.54 or later.")
|
||||
printWarn("\"${DISABLE_CAIRO_SPLASH_ANIMATION.title}\" is not supported in this version. Use YouTube Music 7.06.54 or later.")
|
||||
return@execute
|
||||
} else if (!is_7_20_or_greater) {
|
||||
cairoSplashAnimationConfigFingerprint.injectLiteralInstructionBooleanCall(
|
||||
|
@ -14,7 +14,7 @@ internal object Constants {
|
||||
"6.42.55", // This is the latest version that supports Android 7.0
|
||||
"6.51.53", // This is the latest version of YouTube Music 6.xx.xx
|
||||
"7.16.53", // This is the latest version that supports the 'Spoof app version' patch.
|
||||
"7.25.52", // This is the latest version supported by the RVX patch.
|
||||
"7.25.53", // This is the latest version supported by the RVX patch.
|
||||
)
|
||||
)
|
||||
}
|
@ -4,24 +4,23 @@ 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.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.music.utils.compatibility.Constants
|
||||
import app.revanced.patches.music.utils.extension.Constants.MISC_PATH
|
||||
import app.revanced.patches.music.utils.patch.PatchList.SPOOF_CLIENT
|
||||
import app.revanced.patches.music.utils.playbackSpeedBottomSheetFingerprint
|
||||
import app.revanced.patches.music.utils.playservice.is_7_25_or_greater
|
||||
import app.revanced.patches.music.utils.playservice.versionCheckPatch
|
||||
import app.revanced.patches.music.utils.settings.CategoryType
|
||||
import app.revanced.patches.music.utils.settings.ResourceUtils.updatePatchStatus
|
||||
import app.revanced.patches.music.utils.settings.addPreferenceWithIntent
|
||||
import app.revanced.patches.music.utils.settings.addSwitchPreference
|
||||
import app.revanced.patches.music.utils.settings.settingsPatch
|
||||
import app.revanced.patches.shared.blockrequest.blockRequestPatch
|
||||
import app.revanced.patches.shared.createPlayerRequestBodyWithModelFingerprint
|
||||
import app.revanced.patches.shared.extension.Constants.PATCHES_PATH
|
||||
import app.revanced.patches.shared.indexOfModelInstruction
|
||||
import app.revanced.util.findMethodOrThrow
|
||||
import app.revanced.util.Utils.printWarn
|
||||
import app.revanced.util.fingerprint.matchOrThrow
|
||||
import app.revanced.util.fingerprint.methodOrThrow
|
||||
import app.revanced.util.fingerprint.mutableClassOrThrow
|
||||
@ -53,14 +52,26 @@ val spoofClientPatch = bytecodePatch(
|
||||
SPOOF_CLIENT.summary,
|
||||
false,
|
||||
) {
|
||||
dependsOn(
|
||||
settingsPatch,
|
||||
blockRequestPatch
|
||||
compatibleWith(
|
||||
Constants.YOUTUBE_MUSIC_PACKAGE_NAME(
|
||||
"6.20.51",
|
||||
"6.29.59",
|
||||
"6.42.55",
|
||||
"6.51.53",
|
||||
"7.16.53",
|
||||
),
|
||||
)
|
||||
|
||||
compatibleWith(COMPATIBLE_PACKAGE)
|
||||
dependsOn(
|
||||
settingsPatch,
|
||||
versionCheckPatch,
|
||||
)
|
||||
|
||||
execute {
|
||||
if (is_7_25_or_greater) {
|
||||
printWarn("\"${SPOOF_CLIENT.title}\" is not supported in this version. Use YouTube Music 7.24.51 or earlier.")
|
||||
return@execute
|
||||
}
|
||||
|
||||
// region Get field references to be used below.
|
||||
|
||||
@ -262,24 +273,11 @@ val spoofClientPatch = bytecodePatch(
|
||||
|
||||
// endregion
|
||||
|
||||
findMethodOrThrow("$PATCHES_PATH/PatchStatus;") {
|
||||
name == "SpoofClient"
|
||||
}.replaceInstruction(
|
||||
0,
|
||||
"const/4 v0, 0x1"
|
||||
)
|
||||
|
||||
addSwitchPreference(
|
||||
CategoryType.MISC,
|
||||
"revanced_spoof_client",
|
||||
"false"
|
||||
)
|
||||
addSwitchPreference(
|
||||
CategoryType.MISC,
|
||||
"revanced_spoof_client_legacy",
|
||||
"false",
|
||||
"revanced_spoof_client"
|
||||
)
|
||||
addPreferenceWithIntent(
|
||||
CategoryType.MISC,
|
||||
"revanced_spoof_client_type",
|
||||
|
@ -1,7 +1,5 @@
|
||||
package app.revanced.patches.music.utils.fix.streamingdata
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.music.utils.compatibility.Constants.YOUTUBE_MUSIC_PACKAGE_NAME
|
||||
import app.revanced.patches.music.utils.patch.PatchList.SPOOF_STREAMING_DATA
|
||||
@ -10,15 +8,8 @@ import app.revanced.patches.music.utils.settings.ResourceUtils.updatePatchStatus
|
||||
import app.revanced.patches.music.utils.settings.addPreferenceWithIntent
|
||||
import app.revanced.patches.music.utils.settings.addSwitchPreference
|
||||
import app.revanced.patches.music.utils.settings.settingsPatch
|
||||
import app.revanced.patches.shared.extension.Constants.PATCHES_PATH
|
||||
import app.revanced.patches.shared.spoof.streamingdata.baseSpoofStreamingDataPatch
|
||||
import app.revanced.patches.shared.spoof.useragent.baseSpoofUserAgentPatch
|
||||
import app.revanced.util.findMethodOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
private const val DEFAULT_CLIENT_TYPE = "ANDROID_VR"
|
||||
|
||||
@Suppress("unused")
|
||||
val spoofStreamingDataPatch = baseSpoofStreamingDataPatch(
|
||||
@ -31,17 +22,6 @@ val spoofStreamingDataPatch = baseSpoofStreamingDataPatch(
|
||||
)
|
||||
},
|
||||
{
|
||||
findMethodOrThrow("$PATCHES_PATH/PatchStatus;") {
|
||||
name == "SpoofStreamingDataDefaultClient"
|
||||
}.apply {
|
||||
val register = getInstruction<OneRegisterInstruction>(0).registerA
|
||||
val type = (getInstruction<ReferenceInstruction>(0).reference as FieldReference).type
|
||||
replaceInstruction(
|
||||
0,
|
||||
"sget-object v$register, $type->$DEFAULT_CLIENT_TYPE:$type"
|
||||
)
|
||||
}
|
||||
|
||||
addSwitchPreference(
|
||||
CategoryType.MISC,
|
||||
"revanced_spoof_streaming_data",
|
||||
|
@ -17,12 +17,10 @@ import app.revanced.util.fingerprint.methodOrThrow
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.getWalkerMethod
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.indexOfFirstStringInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import app.revanced.util.indexOfFirstStringInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
private const val RESOURCE_FILE_PATH = "res/layout/merge_listheader_link_detail.xml"
|
||||
|
||||
@ -113,13 +111,13 @@ val adsPatch = bytecodePatch(
|
||||
// The new feeds work by inserting posts into lists.
|
||||
// AdElementConverter is conveniently responsible for inserting all feed ads.
|
||||
// By removing the appending instruction no ad posts gets appended to the feed.
|
||||
newAdPostFingerprint.methodOrThrow().apply {
|
||||
val stringIndex =
|
||||
indexOfFirstStringInstructionOrThrow("android_feed_freeform_render_variant")
|
||||
val targetIndex = indexOfFirstInstructionOrThrow(stringIndex) {
|
||||
opcode == Opcode.INVOKE_VIRTUAL
|
||||
&& getReference<MethodReference>()?.toString() == "Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z"
|
||||
}
|
||||
val newAdPostMethod = newAdPostFingerprint.second.methodOrNull
|
||||
?: newAdPostLegacyFingerprint.methodOrThrow()
|
||||
|
||||
newAdPostMethod.apply {
|
||||
val startIndex =
|
||||
0.coerceAtLeast(indexOfFirstStringInstruction("android_feed_freeform_render_variant"))
|
||||
val targetIndex = indexOfAddArrayListInstruction(this, startIndex)
|
||||
val targetInstruction = getInstruction<FiveRegisterInstruction>(targetIndex)
|
||||
|
||||
replaceInstruction(
|
||||
|
@ -6,6 +6,7 @@ import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.or
|
||||
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.reference.MethodReference
|
||||
|
||||
internal val commentAdsFingerprint = legacyFingerprint(
|
||||
@ -37,7 +38,7 @@ internal val adPostFingerprint = legacyFingerprint(
|
||||
"children",
|
||||
"uxExperiences"
|
||||
),
|
||||
customFingerprint = { method, classDef ->
|
||||
customFingerprint = { _, classDef ->
|
||||
classDef.type.endsWith("/Listing;")
|
||||
},
|
||||
)
|
||||
@ -51,9 +52,27 @@ internal val newAdPostFingerprint = legacyFingerprint(
|
||||
"android_feed_freeform_render_variant",
|
||||
),
|
||||
customFingerprint = { method, _ ->
|
||||
method.indexOfFirstInstruction {
|
||||
getReference<MethodReference>()?.toString() == "Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z"
|
||||
} >= 0
|
||||
indexOfAddArrayListInstruction(method) >= 0
|
||||
},
|
||||
)
|
||||
|
||||
internal val newAdPostLegacyFingerprint = legacyFingerprint(
|
||||
name = "newAdPostLegacyFingerprint",
|
||||
returnType = "L",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
opcodes = listOf(Opcode.INVOKE_VIRTUAL),
|
||||
strings = listOf(
|
||||
"chain",
|
||||
"feedElement"
|
||||
),
|
||||
customFingerprint = { method, classDef ->
|
||||
classDef.sourceFile == "AdElementConverter.kt" &&
|
||||
indexOfAddArrayListInstruction(method) >= 0
|
||||
},
|
||||
)
|
||||
|
||||
internal fun indexOfAddArrayListInstruction(method: Method, index: Int = 0) =
|
||||
method.indexOfFirstInstruction(index) {
|
||||
getReference<MethodReference>()?.toString() == "Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z"
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import app.revanced.patcher.patch.stringOption
|
||||
import app.revanced.patches.reddit.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.reddit.utils.patch.PatchList.CUSTOM_BRANDING_NAME_FOR_REDDIT
|
||||
import app.revanced.patches.reddit.utils.settings.updatePatchStatus
|
||||
import app.revanced.util.Utils.printInfo
|
||||
import app.revanced.util.valueOrThrow
|
||||
import java.io.FileWriter
|
||||
import java.nio.file.Files
|
||||
@ -37,7 +38,7 @@ val customBrandingNamePatch = resourcePatch(
|
||||
.valueOrThrow()
|
||||
|
||||
if (appName == ORIGINAL_APP_NAME) {
|
||||
println("INFO: App name will remain unchanged as it matches the original.")
|
||||
printInfo("App name will remain unchanged as it matches the original.")
|
||||
return@execute
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import app.revanced.patcher.patch.stringOption
|
||||
import app.revanced.patches.reddit.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.reddit.utils.patch.PatchList.CHANGE_PACKAGE_NAME
|
||||
import app.revanced.patches.reddit.utils.settings.updatePatchStatus
|
||||
import app.revanced.util.Utils.printInfo
|
||||
import app.revanced.util.valueOrThrow
|
||||
import org.w3c.dom.Element
|
||||
|
||||
@ -71,7 +72,7 @@ val changePackageNamePatch = resourcePatch(
|
||||
.valueOrThrow()
|
||||
|
||||
if (redditPackageName == PACKAGE_NAME_REDDIT) {
|
||||
println("INFO: Package name will remain unchanged as it matches the original.")
|
||||
printInfo("Package name will remain unchanged as it matches the original.")
|
||||
return@execute
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ import app.revanced.patches.reddit.utils.patch.PatchList.HIDE_NAVIGATION_BUTTONS
|
||||
import app.revanced.patches.reddit.utils.settings.is_2024_18_or_greater
|
||||
import app.revanced.patches.reddit.utils.settings.settingsPatch
|
||||
import app.revanced.patches.reddit.utils.settings.updatePatchStatus
|
||||
import app.revanced.util.Utils.printWarn
|
||||
import app.revanced.util.fingerprint.methodOrThrow
|
||||
import app.revanced.util.fingerprint.resolvable
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
@ -34,7 +35,7 @@ val navigationButtonsPatch = bytecodePatch(
|
||||
execute {
|
||||
|
||||
if (is_2024_18_or_greater) {
|
||||
println("WARNING: \"Hide navigation buttons\" patch is not supported in this version. Use Reddit 2024.17.0 or earlier.")
|
||||
printWarn("\"Hide navigation buttons\" patch is not supported in this version. Use Reddit 2024.17.0 or earlier.")
|
||||
return@execute
|
||||
}
|
||||
|
||||
|
@ -1,57 +0,0 @@
|
||||
package app.revanced.patches.shared.blockrequest
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.shared.extension.Constants.PATCHES_PATH
|
||||
import app.revanced.util.fingerprint.matchOrThrow
|
||||
import app.revanced.util.fingerprint.methodOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"$PATCHES_PATH/BlockRequestPatch;"
|
||||
|
||||
val blockRequestPatch = bytecodePatch(
|
||||
description = "blockRequestPatch"
|
||||
) {
|
||||
execute {
|
||||
// region Block /initplayback requests to fall back to /get_watch requests.
|
||||
|
||||
buildInitPlaybackRequestFingerprint.matchOrThrow().let {
|
||||
it.method.apply {
|
||||
val moveUriStringIndex = it.patternMatch!!.startIndex
|
||||
val targetRegister =
|
||||
getInstruction<OneRegisterInstruction>(moveUriStringIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
moveUriStringIndex + 1,
|
||||
"""
|
||||
invoke-static { v$targetRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v$targetRegister
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Block /get_watch requests to fall back to /player requests.
|
||||
|
||||
buildPlayerRequestURIFingerprint.methodOrThrow().apply {
|
||||
val invokeToStringIndex = indexOfToStringInstruction(this)
|
||||
val uriRegister =
|
||||
getInstruction<FiveRegisterInstruction>(invokeToStringIndex).registerC
|
||||
|
||||
addInstructions(
|
||||
invokeToStringIndex,
|
||||
"""
|
||||
invoke-static { v$uriRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockGetWatchRequest(Landroid/net/Uri;)Landroid/net/Uri;
|
||||
move-result-object v$uriRegister
|
||||
""",
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
package app.revanced.patches.shared.blockrequest
|
||||
|
||||
import app.revanced.util.fingerprint.legacyFingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
internal val buildInitPlaybackRequestFingerprint = legacyFingerprint(
|
||||
name = "buildInitPlaybackRequestFingerprint",
|
||||
returnType = "Lorg/chromium/net/UrlRequest\$Builder;",
|
||||
opcodes = listOf(
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.IGET_OBJECT, // Moves the request URI string to a register to build the request with.
|
||||
),
|
||||
strings = listOf(
|
||||
"Content-Type",
|
||||
"Range",
|
||||
),
|
||||
)
|
||||
|
||||
internal val buildPlayerRequestURIFingerprint = legacyFingerprint(
|
||||
name = "buildPlayerRequestURIFingerprint",
|
||||
returnType = "Ljava/lang/String;",
|
||||
strings = listOf(
|
||||
"key",
|
||||
"asig",
|
||||
),
|
||||
customFingerprint = { method, _ ->
|
||||
indexOfToStringInstruction(method) >= 0
|
||||
},
|
||||
)
|
||||
|
||||
internal fun indexOfToStringInstruction(method: Method) =
|
||||
method.indexOfFirstInstruction {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>().toString() == "Landroid/net/Uri;->toString()Ljava/lang/String;"
|
||||
}
|
||||
|
@ -35,16 +35,14 @@ class ExtensionHook internal constructor(
|
||||
) {
|
||||
context(BytecodePatchContext)
|
||||
operator fun invoke(extensionClassDescriptor: String) {
|
||||
if (System.getenv("GITHUB_REPOSITORY") == null) {
|
||||
val insertIndex = insertIndexResolver(fingerprint.method)
|
||||
val contextRegister = contextRegisterResolver(fingerprint.method)
|
||||
val insertIndex = insertIndexResolver(fingerprint.method)
|
||||
val contextRegister = contextRegisterResolver(fingerprint.method)
|
||||
|
||||
fingerprint.method.addInstruction(
|
||||
insertIndex,
|
||||
"invoke-static/range { $contextRegister .. $contextRegister }, " +
|
||||
"$extensionClassDescriptor->setContext(Landroid/content/Context;)V",
|
||||
)
|
||||
}
|
||||
fingerprint.method.addInstruction(
|
||||
insertIndex,
|
||||
"invoke-static/range { $contextRegister .. $contextRegister }, " +
|
||||
"$extensionClassDescriptor->setContext(Landroid/content/Context;)V",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,13 +5,13 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatchBuilder
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patches.shared.blockrequest.blockRequestPatch
|
||||
import app.revanced.patches.shared.extension.Constants.PATCHES_PATH
|
||||
import app.revanced.patches.shared.extension.Constants.SPOOF_PATH
|
||||
import app.revanced.patches.shared.formatStreamModelConstructorFingerprint
|
||||
@ -22,7 +22,7 @@ import app.revanced.util.fingerprint.injectLiteralInstructionBooleanCall
|
||||
import app.revanced.util.fingerprint.matchOrThrow
|
||||
import app.revanced.util.fingerprint.methodOrThrow
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
||||
@ -37,10 +37,6 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||
const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"$SPOOF_PATH/SpoofStreamingDataPatch;"
|
||||
|
||||
// In YouTube 17.34.36, this class is obfuscated.
|
||||
const val STREAMING_DATA_INTERFACE =
|
||||
"Lcom/google/protos/youtube/api/innertube/StreamingDataOuterClass${'$'}StreamingData;"
|
||||
|
||||
fun baseSpoofStreamingDataPatch(
|
||||
block: BytecodePatchBuilder.() -> Unit = {},
|
||||
executeBlock: BytecodePatchContext.() -> Unit = {},
|
||||
@ -48,11 +44,47 @@ fun baseSpoofStreamingDataPatch(
|
||||
name = "Spoof streaming data",
|
||||
description = "Adds options to spoof the streaming data to allow playback."
|
||||
) {
|
||||
dependsOn(blockRequestPatch)
|
||||
|
||||
block()
|
||||
|
||||
execute {
|
||||
// region Block /initplayback requests to fall back to /get_watch requests.
|
||||
|
||||
buildInitPlaybackRequestFingerprint.matchOrThrow().let {
|
||||
it.method.apply {
|
||||
val moveUriStringIndex = it.patternMatch!!.startIndex
|
||||
val targetRegister =
|
||||
getInstruction<OneRegisterInstruction>(moveUriStringIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
moveUriStringIndex + 1,
|
||||
"""
|
||||
invoke-static { v$targetRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v$targetRegister
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Block /get_watch requests to fall back to /player requests.
|
||||
|
||||
buildPlayerRequestURIFingerprint.methodOrThrow().apply {
|
||||
val invokeToStringIndex = indexOfToStringInstruction(this)
|
||||
val uriRegister =
|
||||
getInstruction<FiveRegisterInstruction>(invokeToStringIndex).registerC
|
||||
|
||||
addInstructions(
|
||||
invokeToStringIndex,
|
||||
"""
|
||||
invoke-static { v$uriRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockGetWatchRequest(Landroid/net/Uri;)Landroid/net/Uri;
|
||||
move-result-object v$uriRegister
|
||||
""",
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Get replacement streams at player requests.
|
||||
|
||||
buildRequestFingerprint.methodOrThrow().apply {
|
||||
@ -84,18 +116,51 @@ fun baseSpoofStreamingDataPatch(
|
||||
|
||||
// region Replace the streaming data.
|
||||
|
||||
val approxDurationMsFieldName = formatStreamModelConstructorFingerprint.matchOrThrow().let {
|
||||
with(it.method) {
|
||||
val approxDurationMsFieldIndex = it.patternMatch!!.startIndex
|
||||
(getInstruction<ReferenceInstruction>(approxDurationMsFieldIndex).reference as FieldReference).name
|
||||
val approxDurationMsReference = formatStreamModelConstructorFingerprint.matchOrThrow().let {
|
||||
with (it.method) {
|
||||
getInstruction<ReferenceInstruction>(it.patternMatch!!.startIndex).reference
|
||||
}
|
||||
}
|
||||
|
||||
val streamingDataFormatsReference = with(videoStreamingDataConstructorFingerprint.methodOrThrow(videoStreamingDataToStringFingerprint)) {
|
||||
val getFormatsFieldIndex = indexOfGetFormatsFieldInstruction(this)
|
||||
val longMaxValueIndex = indexOfLongMaxValueInstruction(this, getFormatsFieldIndex)
|
||||
val longMaxValueRegister = getInstruction<OneRegisterInstruction>(longMaxValueIndex).registerA
|
||||
val videoIdIndex =
|
||||
indexOfFirstInstructionOrThrow(longMaxValueIndex) {
|
||||
val reference = getReference<FieldReference>()
|
||||
opcode == Opcode.IGET_OBJECT &&
|
||||
reference?.type == "Ljava/lang/String;" &&
|
||||
reference.definingClass == definingClass
|
||||
}
|
||||
|
||||
val definingClassRegister =
|
||||
getInstruction<TwoRegisterInstruction>(videoIdIndex).registerB
|
||||
val videoIdReference =
|
||||
getInstruction<ReferenceInstruction>(videoIdIndex).reference
|
||||
|
||||
addInstructions(
|
||||
longMaxValueIndex + 1, """
|
||||
# Get video id.
|
||||
iget-object v$longMaxValueRegister, v$definingClassRegister, $videoIdReference
|
||||
|
||||
# Override approxDurationMs.
|
||||
invoke-static { v$longMaxValueRegister }, $EXTENSION_CLASS_DESCRIPTOR->getApproxDurationMs(Ljava/lang/String;)J
|
||||
move-result-wide v$longMaxValueRegister
|
||||
"""
|
||||
)
|
||||
removeInstruction(longMaxValueIndex)
|
||||
|
||||
getInstruction<ReferenceInstruction>(getFormatsFieldIndex).reference
|
||||
}
|
||||
|
||||
createStreamingDataFingerprint.matchOrThrow(createStreamingDataParentFingerprint)
|
||||
.let { result ->
|
||||
result.method.apply {
|
||||
val setStreamDataMethodName = "patch_setStreamingData"
|
||||
val resultMethodType = result.classDef.type
|
||||
val calcApproxDurationMsMethodName = "patch_calcApproxDurationMs"
|
||||
val resultClassDef = result.classDef
|
||||
val resultMethodType = resultClassDef.type
|
||||
val setStreamingDataIndex = result.patternMatch!!.startIndex
|
||||
val setStreamingDataField =
|
||||
getInstruction(setStreamingDataIndex).getReference<FieldReference>()
|
||||
@ -167,58 +232,83 @@ fun baseSpoofStreamingDataPatch(
|
||||
iget-object v6, v5, $getStreamingDataField
|
||||
if-eqz v6, :disabled
|
||||
|
||||
# Get original streaming data.
|
||||
iget-object v0, p0, $setStreamingDataField
|
||||
# Caculate approxDurationMs.
|
||||
invoke-direct { p0, v2 }, $resultMethodType->$calcApproxDurationMsMethodName(Ljava/lang/String;)V
|
||||
|
||||
# Set spoofed streaming data.
|
||||
iput-object v6, p0, $setStreamingDataField
|
||||
|
||||
# Get video length from original streaming data and save to extension.
|
||||
const-string v5, "$approxDurationMsFieldName"
|
||||
invoke-static { v2, v5, v0, v6 }, $EXTENSION_CLASS_DESCRIPTOR->setApproxDurationMs(Ljava/lang/String;Ljava/lang/String;$STREAMING_DATA_INTERFACE$STREAMING_DATA_INTERFACE)V
|
||||
|
||||
:disabled
|
||||
return-void
|
||||
""",
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
resultClassDef.methods.add(
|
||||
ImmutableMethod(
|
||||
resultMethodType,
|
||||
calcApproxDurationMsMethodName,
|
||||
listOf(
|
||||
ImmutableMethodParameter(
|
||||
"Ljava/lang/String;",
|
||||
annotations,
|
||||
"videoId"
|
||||
)
|
||||
),
|
||||
"V",
|
||||
AccessFlags.PRIVATE.value or AccessFlags.FINAL.value,
|
||||
annotations,
|
||||
null,
|
||||
MutableMethodImplementation(12),
|
||||
).toMutable().apply {
|
||||
addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
# Get video format list.
|
||||
iget-object v0, p0, $setStreamingDataField
|
||||
iget-object v0, v0, $streamingDataFormatsReference
|
||||
invoke-interface {v0}, Ljava/util/List;->iterator()Ljava/util/Iterator;
|
||||
move-result-object v0
|
||||
|
||||
# Initialize approxDurationMs field.
|
||||
const-wide v1, 0x7fffffffffffffffL
|
||||
|
||||
:loop
|
||||
# Loop over all video formats to get the approxDurationMs
|
||||
invoke-interface {v0}, Ljava/util/Iterator;->hasNext()Z
|
||||
move-result v3
|
||||
const-wide/16 v4, 0x0
|
||||
|
||||
if-eqz v3, :exit
|
||||
invoke-interface {v0}, Ljava/util/Iterator;->next()Ljava/lang/Object;
|
||||
move-result-object v3
|
||||
check-cast v3, ${(approxDurationMsReference as FieldReference).definingClass}
|
||||
|
||||
# Get approxDurationMs from format
|
||||
iget-wide v6, v3, $approxDurationMsReference
|
||||
|
||||
# Compare with zero to make sure approxDurationMs is not negative
|
||||
cmp-long v8, v6, v4
|
||||
if-lez v8, :loop
|
||||
|
||||
# Only use the min value of approxDurationMs
|
||||
invoke-static {v1, v2, v6, v7}, Ljava/lang/Math;->min(JJ)J
|
||||
move-result-wide v1
|
||||
goto :loop
|
||||
|
||||
:exit
|
||||
# Save approxDurationMs to integrations
|
||||
invoke-static { p1, v1, v2 }, $EXTENSION_CLASS_DESCRIPTOR->setApproxDurationMs(Ljava/lang/String;J)V
|
||||
|
||||
return-void
|
||||
""",
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
videoStreamingDataConstructorFingerprint.methodOrThrow(videoStreamingDataToStringFingerprint)
|
||||
.apply {
|
||||
val formatStreamModelInitIndex = indexOfFormatStreamModelInitInstruction(this)
|
||||
val videoIdIndex =
|
||||
indexOfFirstInstructionReversedOrThrow(formatStreamModelInitIndex) {
|
||||
val reference = getReference<FieldReference>()
|
||||
opcode == Opcode.IGET_OBJECT &&
|
||||
reference?.type == "Ljava/lang/String;" &&
|
||||
reference.definingClass == definingClass
|
||||
}
|
||||
val definingClassRegister =
|
||||
getInstruction<TwoRegisterInstruction>(videoIdIndex).registerB
|
||||
val videoIdReference =
|
||||
getInstruction<ReferenceInstruction>(videoIdIndex).reference
|
||||
|
||||
val toMillisIndex = indexOfToMillisInstruction(this)
|
||||
val freeRegister =
|
||||
getInstruction<FiveRegisterInstruction>(toMillisIndex).registerC
|
||||
val lengthMillisecondsRegister =
|
||||
getInstruction<OneRegisterInstruction>(toMillisIndex + 1).registerA
|
||||
|
||||
addInstructions(
|
||||
toMillisIndex + 2, """
|
||||
# Get video id.
|
||||
iget-object v$freeRegister, v$definingClassRegister, $videoIdReference
|
||||
|
||||
# Override streaming data formats.
|
||||
invoke-static { v$freeRegister, v$lengthMillisecondsRegister, v${lengthMillisecondsRegister + 1} }, $EXTENSION_CLASS_DESCRIPTOR->getApproxDurationMsFromOriginalResponse(Ljava/lang/String;J)J
|
||||
move-result-wide v$lengthMillisecondsRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Remove /videoplayback request body to fix playback.
|
||||
|
@ -7,8 +7,45 @@ import app.revanced.util.or
|
||||
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.WideLiteralInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
// In YouTube 17.34.36, this class is obfuscated.
|
||||
const val STREAMING_DATA_INTERFACE =
|
||||
"Lcom/google/protos/youtube/api/innertube/StreamingDataOuterClass${'$'}StreamingData;"
|
||||
|
||||
internal val buildInitPlaybackRequestFingerprint = legacyFingerprint(
|
||||
name = "buildInitPlaybackRequestFingerprint",
|
||||
returnType = "Lorg/chromium/net/UrlRequest\$Builder;",
|
||||
opcodes = listOf(
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.IGET_OBJECT, // Moves the request URI string to a register to build the request with.
|
||||
),
|
||||
strings = listOf(
|
||||
"Content-Type",
|
||||
"Range",
|
||||
),
|
||||
)
|
||||
|
||||
internal val buildPlayerRequestURIFingerprint = legacyFingerprint(
|
||||
name = "buildPlayerRequestURIFingerprint",
|
||||
returnType = "Ljava/lang/String;",
|
||||
strings = listOf(
|
||||
"key",
|
||||
"asig",
|
||||
),
|
||||
customFingerprint = { method, _ ->
|
||||
indexOfToStringInstruction(method) >= 0
|
||||
},
|
||||
)
|
||||
|
||||
internal fun indexOfToStringInstruction(method: Method) =
|
||||
method.indexOfFirstInstruction {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>().toString() == "Landroid/net/Uri;->toString()Ljava/lang/String;"
|
||||
}
|
||||
|
||||
internal val buildMediaDataSourceFingerprint = legacyFingerprint(
|
||||
name = "buildMediaDataSourceFingerprint",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
@ -108,11 +145,28 @@ internal val videoStreamingDataConstructorFingerprint = legacyFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
returnType = "V",
|
||||
customFingerprint = { method, _ ->
|
||||
indexOfFormatStreamModelInitInstruction(method) >= 0 &&
|
||||
indexOfToMillisInstruction(method) >= 0
|
||||
indexOfGetFormatsFieldInstruction(method) >= 0 &&
|
||||
indexOfLongMaxValueInstruction(method) >= 0 &&
|
||||
indexOfFormatStreamModelInitInstruction(method) >= 0
|
||||
},
|
||||
)
|
||||
|
||||
internal fun indexOfGetFormatsFieldInstruction(method: Method) =
|
||||
method.indexOfFirstInstruction {
|
||||
val reference = getReference<FieldReference>()
|
||||
opcode == Opcode.IGET_OBJECT &&
|
||||
reference?.definingClass == STREAMING_DATA_INTERFACE &&
|
||||
// Field e: 'formats'.
|
||||
// Field name is always 'e', regardless of the client version.
|
||||
reference.name == "e" &&
|
||||
reference.type.startsWith("L")
|
||||
}
|
||||
|
||||
internal fun indexOfLongMaxValueInstruction(method: Method, index: Int = 0) =
|
||||
method.indexOfFirstInstruction(index) {
|
||||
(this as? WideLiteralInstruction)?.wideLiteral == Long.MAX_VALUE
|
||||
}
|
||||
|
||||
internal fun indexOfFormatStreamModelInitInstruction(method: Method) =
|
||||
method.indexOfFirstInstruction {
|
||||
val reference = getReference<MethodReference>()
|
||||
@ -121,13 +175,6 @@ internal fun indexOfFormatStreamModelInitInstruction(method: Method) =
|
||||
reference.parameterTypes.size > 1
|
||||
}
|
||||
|
||||
internal fun indexOfToMillisInstruction(method: Method) =
|
||||
method.indexOfFirstInstruction {
|
||||
val reference = getReference<MethodReference>()
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
reference?.name == "toMillis"
|
||||
}
|
||||
|
||||
/**
|
||||
* On YouTube, this class is 'Lcom/google/android/libraries/youtube/innertube/model/media/VideoStreamingData;'
|
||||
* On YouTube Music, class names are obfuscated.
|
||||
|
@ -155,6 +155,27 @@ internal val searchBarParentFingerprint = legacyFingerprint(
|
||||
literals = listOf(voiceSearch),
|
||||
)
|
||||
|
||||
internal val voiceInputControllerParentFingerprint = legacyFingerprint(
|
||||
name = "voiceInputControllerParentFingerprint",
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("[B", "Z"),
|
||||
strings = listOf("VoiceInputController"),
|
||||
)
|
||||
|
||||
internal val voiceInputControllerFingerprint = legacyFingerprint(
|
||||
name = "voiceInputControllerFingerprint",
|
||||
returnType = "Z",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = emptyList(),
|
||||
customFingerprint = { method, _ ->
|
||||
method.indexOfFirstInstruction {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>()?.name == "resolveActivity"
|
||||
} >= 0
|
||||
},
|
||||
)
|
||||
|
||||
internal val searchResultFingerprint = legacyFingerprint(
|
||||
name = "searchResultFingerprint",
|
||||
returnType = "Landroid/view/View;",
|
||||
|
@ -18,7 +18,6 @@ import app.revanced.patches.youtube.utils.patch.PatchList.TOOLBAR_COMPONENTS
|
||||
import app.revanced.patches.youtube.utils.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.utils.resourceid.actionBarRingoBackground
|
||||
import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.resourceid.voiceSearch
|
||||
import app.revanced.patches.youtube.utils.resourceid.ytOutlineVideoCamera
|
||||
import app.revanced.patches.youtube.utils.resourceid.ytPremiumWordMarkHeader
|
||||
import app.revanced.patches.youtube.utils.resourceid.ytWordMarkHeader
|
||||
@ -32,6 +31,7 @@ import app.revanced.util.doRecursively
|
||||
import app.revanced.util.findInstructionIndicesReversedOrThrow
|
||||
import app.revanced.util.findMethodOrThrow
|
||||
import app.revanced.util.fingerprint.matchOrThrow
|
||||
import app.revanced.util.fingerprint.methodCall
|
||||
import app.revanced.util.fingerprint.methodOrThrow
|
||||
import app.revanced.util.fingerprint.mutableClassOrThrow
|
||||
import app.revanced.util.getReference
|
||||
@ -332,8 +332,17 @@ val toolBarComponentsPatch = bytecodePatch(
|
||||
|
||||
searchResultFingerprint.matchOrThrow().let {
|
||||
it.method.apply {
|
||||
val startIndex = indexOfFirstLiteralInstructionOrThrow(voiceSearch)
|
||||
val setOnClickListenerIndex = indexOfFirstInstructionOrThrow(startIndex) {
|
||||
val voiceInputControllerActivityMethodCall =
|
||||
voiceInputControllerFingerprint
|
||||
.methodOrThrow(voiceInputControllerParentFingerprint)
|
||||
.methodCall()
|
||||
|
||||
val voiceInputControllerActivityIndex =
|
||||
indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>()?.toString() == voiceInputControllerActivityMethodCall
|
||||
}
|
||||
val setOnClickListenerIndex = indexOfFirstInstructionOrThrow(voiceInputControllerActivityIndex) {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>()?.name == "setOnClickListener"
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import app.revanced.patches.youtube.utils.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.utils.settings.ResourceUtils.addPreference
|
||||
import app.revanced.patches.youtube.utils.settings.settingsPatch
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.Utils.printInfo
|
||||
import app.revanced.util.copyResources
|
||||
import app.revanced.util.inputStreamFromBundledResourceOrThrow
|
||||
import app.revanced.util.lowerCaseOrThrow
|
||||
@ -63,7 +64,7 @@ val shortsActionButtonsPatch = resourcePatch(
|
||||
.lowerCaseOrThrow()
|
||||
|
||||
if (iconType == YOUTUBE_ICON) {
|
||||
println("INFO: Shorts action buttons will remain unchanged as it matches the original.")
|
||||
printInfo("Shorts action buttons will remain unchanged as it matches the original.")
|
||||
addPreference(CUSTOM_SHORTS_ACTION_BUTTONS)
|
||||
return@execute
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ val customBrandingIconPatch = resourcePatch(
|
||||
val copiedFiles = copyFile(
|
||||
launcherIconResourceGroups,
|
||||
appIcon,
|
||||
"WARNING: Invalid app icon path: $appIcon. Does not apply patches."
|
||||
"Invalid app icon path: $appIcon. Does not apply patches."
|
||||
)
|
||||
if (copiedFiles)
|
||||
updatePatchStatusIcon("custom")
|
||||
|
@ -7,6 +7,7 @@ import app.revanced.patches.youtube.utils.patch.PatchList.CUSTOM_HEADER_FOR_YOUT
|
||||
import app.revanced.patches.youtube.utils.settings.ResourceUtils.getIconType
|
||||
import app.revanced.patches.youtube.utils.settings.settingsPatch
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.Utils.printWarn
|
||||
import app.revanced.util.Utils.trimIndentMultiline
|
||||
import app.revanced.util.copyFile
|
||||
import app.revanced.util.copyResources
|
||||
@ -125,7 +126,7 @@ val changeHeaderPatch = resourcePatch(
|
||||
customBrandingIconType != "default" && customBrandingIconType != "custom"
|
||||
customHeader = customHeaderOption.valueOrThrow()
|
||||
|
||||
val warnings = "WARNING: Invalid header path: $customHeader. Does not apply patches."
|
||||
val warnings = "Invalid header path: $customHeader. Does not apply patches."
|
||||
|
||||
if (isPath) {
|
||||
copyFile(
|
||||
@ -140,7 +141,7 @@ val changeHeaderPatch = resourcePatch(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println(warnings)
|
||||
printWarn(warnings)
|
||||
return@execute
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ import app.revanced.patches.youtube.utils.youtubeControlsOverlayFingerprint
|
||||
import app.revanced.patches.youtube.video.information.hookVideoInformation
|
||||
import app.revanced.patches.youtube.video.information.videoInformationPatch
|
||||
import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT
|
||||
import app.revanced.util.Utils.printWarn
|
||||
import app.revanced.util.findMethodOrThrow
|
||||
import app.revanced.util.fingerprint.injectLiteralInstructionBooleanCall
|
||||
import app.revanced.util.fingerprint.injectLiteralInstructionViewCall
|
||||
@ -382,7 +383,7 @@ val playerComponentsPatch = bytecodePatch(
|
||||
name == "onClick"
|
||||
}.hookInitVideoPanel(0)
|
||||
} else {
|
||||
println("WARNING: target Opcode not found in ${fingerprint.first}")
|
||||
printWarn("target Opcode not found in ${fingerprint.first}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.settings.ResourceUtils.addPreference
|
||||
import app.revanced.patches.youtube.utils.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.utils.youtubeControlsOverlayFingerprint
|
||||
import app.revanced.util.Utils.printWarn
|
||||
import app.revanced.util.findMethodOrThrow
|
||||
import app.revanced.util.fingerprint.methodOrThrow
|
||||
import app.revanced.util.fingerprint.mutableClassOrThrow
|
||||
@ -321,7 +322,7 @@ val fullscreenComponentsPatch = bytecodePatch(
|
||||
|
||||
settingArray += "SETTINGS: KEEP_LANDSCAPE_MODE"
|
||||
} else {
|
||||
println("WARNING: \"Keep landscape mode\" is not supported in this version. Use YouTube 19.16.39 or earlier.")
|
||||
printWarn("\"Keep landscape mode\" is not supported in this version. Use YouTube 19.16.39 or earlier.")
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
@ -35,6 +35,7 @@ import app.revanced.patches.youtube.utils.settings.ResourceUtils.getContext
|
||||
import app.revanced.patches.youtube.utils.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.utils.totalTimeFingerprint
|
||||
import app.revanced.patches.youtube.video.information.videoInformationPatch
|
||||
import app.revanced.util.Utils.printWarn
|
||||
import app.revanced.util.copyXmlNode
|
||||
import app.revanced.util.findElementByAttributeValueOrThrow
|
||||
import app.revanced.util.findMethodsOrThrow
|
||||
@ -468,7 +469,7 @@ val seekbarComponentsPatch = bytecodePatch(
|
||||
|
||||
updatePatchStatus(PATCH_STATUS_CLASS_DESCRIPTOR, "OldSeekbarThumbnailsDefaultBoolean")
|
||||
} else {
|
||||
println("WARNING: \"Restore old seekbar thumbnails\" is not supported in this version. Use YouTube 19.16.39 or earlier.")
|
||||
printWarn("\"Restore old seekbar thumbnails\" is not supported in this version. Use YouTube 19.16.39 or earlier.")
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
@ -28,6 +28,7 @@ import app.revanced.patches.youtube.utils.lottie.lottieAnimationViewHookPatch
|
||||
import app.revanced.patches.youtube.utils.mainactivity.mainActivityResolvePatch
|
||||
import app.revanced.patches.youtube.utils.navigation.addBottomBarContainerHook
|
||||
import app.revanced.patches.youtube.utils.navigation.navigationBarHookPatch
|
||||
import app.revanced.patches.youtube.utils.patch.PatchList.HIDE_FEED_FLYOUT_MENU
|
||||
import app.revanced.patches.youtube.utils.patch.PatchList.SHORTS_COMPONENTS
|
||||
import app.revanced.patches.youtube.utils.playertype.playerTypeHookPatch
|
||||
import app.revanced.patches.youtube.utils.playservice.is_18_31_or_greater
|
||||
@ -315,11 +316,8 @@ private val shortsCustomActionsPatch = bytecodePatch(
|
||||
|
||||
val insertIndex = charSequenceIndex + 2
|
||||
|
||||
if (getInstruction<ReferenceInstruction>(insertIndex).reference.toString()
|
||||
.startsWith("Lapp/revanced")
|
||||
) {
|
||||
if (HIDE_FEED_FLYOUT_MENU.included == true)
|
||||
removeInstructions(insertIndex, 2)
|
||||
}
|
||||
|
||||
addInstructions(
|
||||
insertIndex, """
|
||||
|
@ -1,5 +1,7 @@
|
||||
package app.revanced.patches.youtube.utils.fix.streamingdata
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patches.shared.extension.Constants.PATCHES_PATH
|
||||
import app.revanced.patches.shared.spoof.streamingdata.baseSpoofStreamingDataPatch
|
||||
import app.revanced.patches.shared.spoof.useragent.baseSpoofUserAgentPatch
|
||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
@ -7,6 +9,7 @@ import app.revanced.patches.youtube.utils.compatibility.Constants.YOUTUBE_PACKAG
|
||||
import app.revanced.patches.youtube.utils.patch.PatchList.SPOOF_STREAMING_DATA
|
||||
import app.revanced.patches.youtube.utils.settings.ResourceUtils.addPreference
|
||||
import app.revanced.patches.youtube.utils.settings.settingsPatch
|
||||
import app.revanced.util.findMethodOrThrow
|
||||
|
||||
val spoofStreamingDataPatch = baseSpoofStreamingDataPatch(
|
||||
{
|
||||
@ -18,6 +21,13 @@ val spoofStreamingDataPatch = baseSpoofStreamingDataPatch(
|
||||
)
|
||||
},
|
||||
{
|
||||
findMethodOrThrow("$PATCHES_PATH/PatchStatus;") {
|
||||
name == "SpoofStreamingDataAndroidOnlyDefaultBoolean"
|
||||
}.replaceInstruction(
|
||||
0,
|
||||
"const/4 v0, 0x1"
|
||||
)
|
||||
|
||||
addPreference(
|
||||
arrayOf(
|
||||
"SETTINGS: SPOOF_STREAMING_DATA"
|
||||
|
@ -20,6 +20,7 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMu
|
||||
import app.revanced.patches.shared.mapping.get
|
||||
import app.revanced.patches.shared.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.mapping.resourceMappings
|
||||
import app.revanced.util.Utils.printWarn
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
@ -135,7 +136,7 @@ internal fun MutableMethod.addInstructionsAtControlFlowLabel(
|
||||
fun Method.indexOfFirstResourceId(resourceName: String): Int {
|
||||
val resourceId = resourceMappings["id", resourceName]
|
||||
if (resourceId == -1L) {
|
||||
println("WARNING: Could not find resource type: id name: $name")
|
||||
printWarn("Could not find resource type: id name: $name")
|
||||
return -1
|
||||
}
|
||||
return indexOfFirstLiteralInstruction(resourceId)
|
||||
|
@ -5,6 +5,7 @@ import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.ResourcePatchContext
|
||||
import app.revanced.patcher.util.Document
|
||||
import app.revanced.util.Utils.printWarn
|
||||
import org.w3c.dom.Element
|
||||
import org.w3c.dom.Node
|
||||
import org.w3c.dom.NodeList
|
||||
@ -202,7 +203,7 @@ fun ResourcePatchContext.copyFile(
|
||||
|
||||
return true
|
||||
} catch (_: Exception) {
|
||||
println(warning)
|
||||
printWarn(warning)
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
@ -1,8 +1,18 @@
|
||||
package app.revanced.util
|
||||
|
||||
import java.util.logging.Logger
|
||||
|
||||
internal object Utils {
|
||||
internal fun String.trimIndentMultiline() =
|
||||
this.split("\n")
|
||||
.joinToString("\n") { it.trimIndent() } // Remove the leading whitespace from each line.
|
||||
.trimIndent() // Remove the leading newline.
|
||||
|
||||
private val logger = Logger.getLogger(this::class.java.name)
|
||||
|
||||
internal fun printInfo(msg: String) =
|
||||
logger.info(msg)
|
||||
|
||||
internal fun printWarn(msg: String) =
|
||||
logger.warning(msg)
|
||||
}
|
||||
|
@ -56,12 +56,14 @@
|
||||
<item>4.27.53</item>
|
||||
</string-array>
|
||||
<string-array name="revanced_spoof_client_type_entries">
|
||||
<item>@string/revanced_spoof_client_type_entry_android_music</item>
|
||||
<item>@string/revanced_spoof_client_type_entry_ios_music</item>
|
||||
<item>@string/revanced_spoof_client_type_entry_ios_music_6_21</item>
|
||||
<item>@string/revanced_spoof_client_type_entry_android_music_5_29</item>
|
||||
<item>@string/revanced_spoof_client_type_entry_android_music_4_27</item>
|
||||
</string-array>
|
||||
<string-array name="revanced_spoof_client_type_entry_values">
|
||||
<item>ANDROID_MUSIC</item>
|
||||
<item>IOS_MUSIC</item>
|
||||
<item>IOS_MUSIC_6_21</item>
|
||||
<item>ANDROID_MUSIC_5_29</item>
|
||||
<item>ANDROID_MUSIC_4_27</item>
|
||||
</string-array>
|
||||
<string-array name="revanced_spoof_streaming_data_type_entries">
|
||||
<item>@string/revanced_spoof_streaming_data_type_entry_android_vr</item>
|
||||
|
@ -452,14 +452,13 @@ Tap the continue button and allow optimization changes."</string>
|
||||
<string name="revanced_spoof_client_summary">"Spoof the client to prevent playback issues.
|
||||
|
||||
※ When used with 'Spoofing streaming data', playback issues may occur."</string>
|
||||
<string name="revanced_spoof_client_legacy_title">Use old client</string>
|
||||
<string name="revanced_spoof_client_legacy_summary">"Spoofing with version 4.27.53.
|
||||
|
||||
OPUS codec may not work."</string>
|
||||
<string name="revanced_spoof_client_type_title">Default client</string>
|
||||
<string name="revanced_spoof_client_type_summary">Defines a default client to spoofing.</string>
|
||||
<string name="revanced_spoof_client_type_entry_android_music">Android Music</string>
|
||||
<string name="revanced_spoof_client_type_entry_ios_music">iOS Music</string>
|
||||
<string name="revanced_spoof_client_type_summary">"Defines a default client to spoofing.
|
||||
|
||||
※ When using the Android client, it is recommended to use it with 'Spoof app version'."</string>
|
||||
<string name="revanced_spoof_client_type_entry_android_music_4_27">Android Music 4.27.53</string>
|
||||
<string name="revanced_spoof_client_type_entry_android_music_5_29">Android Music 5.29.53</string>
|
||||
<string name="revanced_spoof_client_type_entry_ios_music_6_21">iOS Music 6.21</string>
|
||||
|
||||
<string name="revanced_spoof_streaming_data_title">Spoof streaming data</string>
|
||||
<string name="revanced_spoof_streaming_data_summary">"Spoof the streaming data to prevent playback issues.
|
||||
|
@ -172,7 +172,7 @@
|
||||
<string name="revanced_spoof_app_version_title">Παραποίηση έκδοσης εφαρμογής</string>
|
||||
<string name="revanced_spoof_app_version_summary">"Παραποίηση έκδοσης εφαρμογής σε παλιότερη έκδοση.
|
||||
|
||||
• Αυτό θα αλλάξει την εμφάνιση της εφαρμογής, αλλά πιθανότατα να προκύψουν άγνωστα θέματα.
|
||||
• Αυτό θα αλλάξει την εμφάνιση της εφαρμογής, αλλά πιθανότατα να προκύψουν άγνωστες παρενέργειες.
|
||||
• Αν αργότερα γίνει απενεργοποίηση, η παλιά εμφάνιση μπορεί να παραμείνει μέχρι να διαγραφούν τα δεδομένα της εφαρμογής."</string>
|
||||
<string name="revanced_spoof_app_version_target_title">Έκδοση της εφαρμογής που θα χρησιμοποιηθεί</string>
|
||||
<string name="revanced_spoof_app_version_target_summary">Επιλέξτε την έκδοση εφαρμογής που θα χρησιμοποιηθεί.</string>
|
||||
@ -400,12 +400,16 @@
|
||||
Πατήστε το κουμπί «Συνέχεια» και επιτρέψτε τις αλλαγές βελτιστοποίησης."</string>
|
||||
<string name="gms_core_dialog_continue_text">Συνέχεια</string>
|
||||
<string name="revanced_spoof_client_title">Παραποίηση προγράμματος πελάτη</string>
|
||||
<string name="revanced_spoof_client_summary">"Παραποίηση του προγράμματος πελάτη για την αποφυγή προβλημάτων αναπαραγωγής. Περιορισμοί:
|
||||
• Ο κωδικοποιητής ήχου OPUS ενδέχεται να μην υποστηρίζεται.
|
||||
• Οι μικρογραφίες προεπισκόπησης στη γραμμή προόδου ενδέχεται να μην υπάρχουν.
|
||||
• Το ιστορικό παρακολούθησης δεν λειτουργεί σε λογαριασμούς επωνυμίας (brand).
|
||||
<string name="revanced_spoof_client_summary">"Παραποίηση του προγράμματος πελάτη για την αποφυγή προβλημάτων αναπαραγωγής.
|
||||
|
||||
※ Αν ενεργοποιηθεί παράλληλα με τη λειτουργία «Παραποίηση δεδομένων ροής», ενδέχεται να εμφανιστούν προβλήματα αναπαραγωγής."</string>
|
||||
<string name="revanced_spoof_client_type_title">Προεπιλεγμένο πρόγραμμα πελάτη</string>
|
||||
<string name="revanced_spoof_client_type_summary">"Καθορισμός ενός προεπιλεγμένου πρόγραμμα πελάτη για παραποίηση.
|
||||
|
||||
※ Όταν ορίζεται πρόγραμμα πελάτη τύπου Android, συνιστάται να το χρησιμοποιήσετε μαζί με την λειτουργία «Παραποίηση έκδοσης εφαρμογής»."</string>
|
||||
<string name="revanced_spoof_client_type_entry_android_music_4_27">Android Music 4.27.53</string>
|
||||
<string name="revanced_spoof_client_type_entry_android_music_5_29">Android Music 5.29.53</string>
|
||||
<string name="revanced_spoof_client_type_entry_ios_music_6_21">iOS Music 6.21</string>
|
||||
<string name="revanced_spoof_streaming_data_title">Παραποίηση δεδομένων ροής</string>
|
||||
<string name="revanced_spoof_streaming_data_summary">"Παραποίηση των δεδομένων ροής για την αποφυγή προβλημάτων αναπαραγωγής.
|
||||
|
||||
|
@ -89,6 +89,7 @@ Információ:
|
||||
<string name="revanced_hide_flyout_menu_go_to_episode_title">Rész menü elrejtése</string>
|
||||
<string name="revanced_hide_flyout_menu_go_to_podcast_title">Podcast menü elrejtése</string>
|
||||
<string name="revanced_hide_flyout_menu_help_title">Súgó & visszajelzés menü elrejtése</string>
|
||||
<string name="revanced_hide_flyout_menu_pin_to_speed_dial_title">Fül elrejtése a Gyors elérés menüben</string>
|
||||
<string name="revanced_hide_flyout_menu_play_next_title">Következő lejátszása menü elrejtése</string>
|
||||
<string name="revanced_hide_flyout_menu_quality_title">Minőség menü elrejtése</string>
|
||||
<string name="revanced_hide_flyout_menu_remove_from_library_title">Eltávolítás a könyvtárból menü elrejtése</string>
|
||||
@ -103,6 +104,7 @@ Információ:
|
||||
<string name="revanced_hide_flyout_menu_start_radio_title">Rádió indítás menü elrejtése</string>
|
||||
<string name="revanced_hide_flyout_menu_stats_for_nerds_title">Statisztikák kockáknak menü elrejtése</string>
|
||||
<string name="revanced_hide_flyout_menu_subscribe_title">Feliratkozás / Leiratkozás menü elrejtése</string>
|
||||
<string name="revanced_hide_flyout_menu_unpin_from_speed_dial_title">Kitűzés a Gyorshívóba menü elrejtése</string>
|
||||
<string name="revanced_hide_flyout_menu_view_song_credit_title">Dalkredit menü elrejtése</string>
|
||||
<string name="revanced_replace_flyout_menu_dismiss_queue_continue_watch_title">Megtekintés folytatása</string>
|
||||
<string name="revanced_replace_flyout_menu_dismiss_queue_continue_watch_summary">Folytatja a videót attól az időponttól, amikor átváltasz a Youtube-ra.</string>
|
||||
@ -173,6 +175,7 @@ Ez nem kerüli meg a korhatárkorlátozást. Csak automatikusan elfogadja azt."<
|
||||
<string name="revanced_spoof_app_version_target_summary">Válaszd ki, hogy melyik alkalmazásverziót akarod használni.</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_4_27_53">4.27.53 - Letiltja a rádió módot Kanada területén</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_6_11_52">6.11.52 - Letiltja a valós idejű dalszövegeket</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_7_16_53">7.16.53 - Régi menüsor visszaállítása</string>
|
||||
<!-- PreferenceScreen: Navigation Bar -->
|
||||
<string name="revanced_preference_screen_navigation_title">Navigációs sor</string>
|
||||
<string name="revanced_enable_black_navigation_bar_title">Fekete navigációs sor engedélyezése</string>
|
||||
@ -240,8 +243,12 @@ Előfordulhat, hogy egyes funkciók nem működnek megfelelően a régi lejátsz
|
||||
<string name="revanced_hide_settings_menu_general_title">Általános menü elrejtése</string>
|
||||
<string name="revanced_hide_settings_menu_playback_title">Következő lejátszása menü elrejtése</string>
|
||||
<string name="revanced_hide_settings_menu_data_saving_title">Adatmegtakarító menü elejtése</string>
|
||||
<string name="revanced_hide_settings_menu_downloads_and_storage_title">Letöltések és tárhely menü elrejtése</string>
|
||||
<string name="revanced_hide_settings_menu_notification_title">Értesítések menü elrejtése</string>
|
||||
<string name="revanced_hide_settings_menu_about_title">Névjegy menü elrejtése</string>
|
||||
<string name="revanced_hide_settings_menu_privacy_and_location_title">Adatvédelem és adatok elrejtése</string>
|
||||
<string name="revanced_hide_settings_menu_recommendations_title">Ajánlott elrejtése</string>
|
||||
<string name="revanced_hide_settings_menu_paid_memberships_title">Music Premium-tagság vásárlása menü elrejtése</string>
|
||||
<string name="revanced_hide_settings_menu_about_title">A Youtube Music névjegye menü elrejtése</string>
|
||||
<!-- PreferenceScreen: Video -->
|
||||
<string name="revanced_preference_screen_video_title">Videó</string>
|
||||
<string name="revanced_custom_playback_speeds_title">Egyéni lejátszási sebességek szerkesztése</string>
|
||||
@ -249,11 +256,13 @@ Előfordulhat, hogy egyes funkciók nem működnek megfelelően a régi lejátsz
|
||||
<string name="revanced_remember_playback_speed_last_selected_title">Lejátszási sebesség módosításainak megjegyzése</string>
|
||||
<string name="revanced_remember_playback_speed_last_selected_summary">Megjegyzi az utoljára kiválasztott lejátszási sebességet.</string>
|
||||
<string name="revanced_remember_playback_speed_last_selected_toast_title">Mutass egy felugró értesítést</string>
|
||||
<string name="revanced_remember_playback_speed_last_selected_toast_summary">Értesíts, ha változik a lejátszás sebessége.</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_title">Videó minőség megjegyzése</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_summary">Megjegyezi a legutolsó videó minőséget, amit kiválasztottál.</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_toast_title">Mutass egy felugró értesítést</string>
|
||||
<string name="revanced_custom_playback_speeds_invalid">Az egyéni sebességnek kisebbnek kell lennie, mint %sx. Alapértelmezett értékek használata.</string>
|
||||
<string name="revanced_custom_playback_speeds_parse_exception">Érvénytelen egyedi lejátszási sebesség. Használd az alap értékeket.</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_toast_summary">Értesíts ha meg változik a lejátszás minőségének beállítása.</string>
|
||||
<string name="revanced_custom_playback_speeds_invalid">Az egyéni sebességnek kisebbnek kell lennie, mint %sx.</string>
|
||||
<string name="revanced_custom_playback_speeds_parse_exception">Érvénytelen egyedi lejátszási sebesség.</string>
|
||||
<string name="revanced_remember_playback_speed_toast">Megváltoztatva az alap sebességet %s-re.</string>
|
||||
<string name="revanced_remember_video_quality_mobile">Az alapértelmezett mobiladat minőség módosítása a következőre %s.</string>
|
||||
<string name="revanced_remember_video_quality_none">Nem sikerült beállítani a minőséget.</string>
|
||||
@ -266,6 +275,8 @@ Előfordulhat, hogy egyes funkciók nem működnek megfelelően a régi lejátsz
|
||||
<string name="revanced_ryd_dislike_percentage_summary">A nem tetszések százalékos arányát jeleníti meg a nem tetszések száma helyett.</string>
|
||||
<string name="revanced_ryd_compact_layout_title">Kompakt kedvelés gomb</string>
|
||||
<string name="revanced_ryd_compact_layout_summary">Elrejti a kedvelés gomb elválasztóját.</string>
|
||||
<string name="revanced_ryd_estimated_like_title">Mutassa a becsült kedveléseket</string>
|
||||
<string name="revanced_ryd_estimated_like_summary">Megjeleníti a becsült kedvelések számát a videóknál.</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_title">Köszöntő megjelenítése, ha az API nem elérhető</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_summary">Megjelenik egy üzenet, ha a YouTube nem tetszések visszaállítása API nem érhető el.</string>
|
||||
<string name="revanced_ryd_about">Névjegy</string>
|
||||
@ -277,12 +288,24 @@ Előfordulhat, hogy egyes funkciók nem működnek megfelelően a régi lejátsz
|
||||
<string name="revanced_ryd_failure_generic">A nem tetszik funkció nem elérhető (%s).</string>
|
||||
<string name="revanced_ryd_video_likes_hidden_by_video_owner">Rejtett</string>
|
||||
<!-- PreferenceScreen: Return YouTube Username -->
|
||||
<string name="revanced_preference_screen_return_youtube_username_title">Youtube felhasználónév visszaállítása</string>
|
||||
<string name="revanced_return_youtube_username_enabled_title">Youtube felhasználónév visszaállítása</string>
|
||||
<string name="revanced_return_youtube_username_enabled_summary">A hozzászólásokban az azonosítót lecseréli a felhasználónevekre.</string>
|
||||
<string name="revanced_return_youtube_username_display_format_title">Megjelenítési formátum</string>
|
||||
<string name="revanced_return_youtube_username_display_format_summary">Válaszd ki a felhasználónév megjelenítési formátumát.</string>
|
||||
<string name="revanced_return_youtube_username_display_format_username_only">Felhasználónév</string>
|
||||
<string name="revanced_return_youtube_username_display_format_username_handle">Felhasználónév (@kezelő)</string>
|
||||
<string name="revanced_return_youtube_username_display_format_handle_username">\@kezelő (felhasználónév)</string>
|
||||
<string name="revanced_return_youtube_username_youtube_data_api_v3_developer_key_title">YouTube adat API kulcs</string>
|
||||
<string name="revanced_return_youtube_username_display_format_username_handle">Felhasználónév (@azonosító)</string>
|
||||
<string name="revanced_return_youtube_username_display_format_handle_username">\@azonosító (felhasználónév)</string>
|
||||
<string name="revanced_return_youtube_username_youtube_data_api_v3_developer_key_title">YouTube Data API kulcs</string>
|
||||
<string name="revanced_return_youtube_username_youtube_data_api_v3_developer_key_summary">A fejlesztői kulcs a YouTube Data API v3 használatához.</string>
|
||||
<string name="revanced_return_youtube_username_youtube_data_api_v3_about_title">A YouTube Data API-kulcsról</string>
|
||||
<string name="revanced_return_youtube_username_youtube_data_api_v3_about_summary">"YouTube Data API v3 fejlesztői kulcsra van szükség az azonosítók felhasználónevekre való cseréjéhez.
|
||||
|
||||
Az ingyenes csomagban az API-kulcsok napi kvótája 10 000, és 1 kvótával 1 megjegyzéshez egy azonosító felhasználónévre cserélhető.
|
||||
|
||||
Kattints ide az API-kulcs megszerzéséhez."</string>
|
||||
<string name="revanced_return_youtube_username_youtube_data_api_v3_dialog_title">YouTube Data API v3 fejlesztői kulcs megszerzése</string>
|
||||
<string name="revanced_return_youtube_username_youtube_data_api_v3_dialog_message">1. Nyisd meg az <a href=%1$s>Új projekt létrehozását</a>.<br>2. Kattints a <b>LÉTREHOZÁS</b> gombra.<br>3. Lépj a <a href=%2$s>YouTube Data API v3</a> oldalára.<br>4. Kattints az <b>Engedélyezés</b> gombra.<br>5. Kattints a <b>HITELEZÉSI ADATOK LÉTREHOZÁSA</b> gombot.<br>6. Válaszd ki a <b>Nyilvános adatok</b> lehetőség.<br>7. Kattints a <b>KÖVETKEZŐ</b> gombra.<br>8. Másold ki az API-kulcsot.<br><br>※ Az API-kulcsot soha nem szabad megosztani másokkal, így az nem szerepel az importálási/exportálási beállításokban.</string>
|
||||
<!-- PreferenceScreen: SponsorBlock -->
|
||||
<string name="revanced_preference_screen_sb_title">Szponzor Blokk</string>
|
||||
<string name="revanced_sb_enabled">SzponsorBlokk engedélyezése</string>
|
||||
@ -334,7 +357,7 @@ Előfordulhat, hogy egyes funkciók nem működnek megfelelően a régi lejátsz
|
||||
<string name="revanced_sb_color_dot_label">Szín:</string>
|
||||
<string name="revanced_sb_color_changed">Szín módosítva.</string>
|
||||
<string name="revanced_sb_color_reset">Szín visszaállítva.</string>
|
||||
<string name="revanced_sb_color_invalid">Érvénytelen színkód. Visszaállítva alapra.</string>
|
||||
<string name="revanced_sb_color_invalid">Érvénytelen színkód.</string>
|
||||
<string name="revanced_sb_reset_color">Szín visszaállítása</string>
|
||||
<string name="revanced_sb_about_api_sum">Az adatokat a SponsorBlock API biztosítja. Nyomj ide, ha többet szeretnél megtudni és megtekintenéd a letöltéseket más platformokra.</string>
|
||||
<string name="revanced_sb_about">Névjegy</string>
|
||||
@ -345,6 +368,10 @@ Előfordulhat, hogy egyes funkciók nem működnek megfelelően a régi lejátsz
|
||||
<string name="revanced_bypass_image_region_restrictions_summary">Helyettesíti az egyes régiókban blokkolt tartományt, így a lejátszási lista miniatűrjei, csatorna avatarok stb. fogadhatóak.</string>
|
||||
<string name="revanced_change_share_sheet_title">Megosztási lap megváltoztatása</string>
|
||||
<string name="revanced_change_share_sheet_summary">Váltás az alkalmazáson belüli megosztási lapról a rendszer megosztási lapjára.</string>
|
||||
<string name="revanced_disable_cairo_splash_animation_title">Betöltési animáció kikapcsolása</string>
|
||||
<string name="revanced_disable_cairo_splash_animation_summary">Letiltja a betöltési animációt amikor az app indul.</string>
|
||||
<string name="revanced_disable_drc_audio_title">DRC hang letiltása</string>
|
||||
<string name="revanced_disable_drc_audio_summary">Letiltja a hangra alkalmazott DRC-t (dinamikatartomány-kompresszió).</string>
|
||||
<string name="revanced_enable_debug_logging_title">Hibanaplók engedélyezése</string>
|
||||
<string name="revanced_enable_debug_logging_summary">Kiírja a hibanaplót.</string>
|
||||
<string name="revanced_enable_debug_buffer_logging_title">Hibakeresési puffer naplózásának engedélyezése</string>
|
||||
@ -367,10 +394,37 @@ Ez szükséges az app működéséhez."</string>
|
||||
<string name="gms_core_dialog_open_website_text">Weboldal megnyitása</string>
|
||||
<string name="gms_core_dialog_not_whitelisted_using_battery_optimizations_message">"A GmsCore akkumulátor-optimalizálásokat le kell tiltani a problémák megelőzése érdekében.
|
||||
|
||||
Nyomd meg a folytatás gombot, és tiltsd le az akkumulátor-optimalizálásokat."</string>
|
||||
A GmsCore akkumulátor-optimalizálás letiltása nem fogyasztja jobban az akkumulátort.
|
||||
|
||||
Nyomj a folytatás gombra, és engedélyezd az optimalizálási módosításokat."</string>
|
||||
<string name="gms_core_dialog_continue_text">Folytatás</string>
|
||||
<string name="revanced_spoof_client_title">Kliens hamisítása</string>
|
||||
<string name="revanced_spoof_client_summary">"A kliens hamisítása a lejátszási problémák elkerülése érdekében.
|
||||
|
||||
※ Az 'Adatfolyam meghamisítása' használata esetén lejátszási problémák léphetnek fel."</string>
|
||||
<string name="revanced_spoof_client_type_title">Alapértelmezett kliens</string>
|
||||
<string name="revanced_spoof_client_type_summary">"Meghatározza az alapértelmezett klienst a hamisításhoz.
|
||||
|
||||
※ Az Android kliens használata esetén ajánlott a 'Alkalmazás verziójának meghamisítása' használni."</string>
|
||||
<string name="revanced_spoof_client_type_entry_android_music_4_27">Android Music 4.27.53</string>
|
||||
<string name="revanced_spoof_client_type_entry_android_music_5_29">Android Music 5.29.53</string>
|
||||
<string name="revanced_spoof_client_type_entry_ios_music_6_21">iOS Music 6.21</string>
|
||||
<string name="revanced_spoof_streaming_data_title">Adatfolyam meghamisítása</string>
|
||||
<string name="revanced_spoof_streaming_data_summary">"A lejátszási problémák megelőzése érdekében hamisítja a streaming-adatokat.
|
||||
|
||||
※ A 'Kliens hamisítása' használata esetén lejátszási problémák léphetnek fel."</string>
|
||||
<string name="revanced_spoof_streaming_data_type_title">Alapértelmezett kliens</string>
|
||||
<string name="revanced_spoof_streaming_data_type_summary">Meghatároz egy alapértelmezett klienst, amely streaming adatokat hív le.</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Megjelenik a statisztikák kockáknakban</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary">Megmutatja a streaming adatok lekérdezésére használt klienst a Statisztikák kockáknakban.</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios">iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_music">iOS Music</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_unplugged">Android TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
|
||||
<string name="revanced_sanitize_sharing_links_title">Megosztási linkek tisztítása</string>
|
||||
<string name="revanced_sanitize_sharing_links_summary">Linkek megosztásakor eltávolítja a nyomkövetési paramétereket az URL-ekből.</string>
|
||||
<string name="revanced_default_app_settings_title">Alapértelmezett program beállítások megnyitása</string>
|
||||
<string name="revanced_default_app_settings_summary">A YouTube Music linkek megnyitásához az RVX Musicban engedélyezze a \'Támogatott linkek megnyitása\' opciót, és engedélyezze a támogatott webcímeket.</string>
|
||||
<string name="revanced_extended_settings_import_export_title">Beállítások Importálása / Exportálása</string>
|
||||
<string name="revanced_extended_settings_import_export_summary">Beállítások importálása vagy exportálása.</string>
|
||||
<string name="revanced_extended_settings_export_as_file">Beállítások exportálása egy fájlba</string>
|
||||
|
@ -368,6 +368,7 @@ API キーの発行方法については、ここをタップしてください
|
||||
<string name="revanced_change_share_sheet_summary">アプリ内共有メニューからシステムの共有メニューに置き換えます。</string>
|
||||
<string name="revanced_disable_cairo_splash_animation_title">Cairo スプラッシュアニメーションを無効にする</string>
|
||||
<string name="revanced_disable_cairo_splash_animation_summary">アプリ起動時のCairo のスプラッシュアニメーションを無効にします。</string>
|
||||
<string name="revanced_disable_drc_audio_title">DRCオーディオを無効にする</string>
|
||||
<string name="revanced_enable_debug_logging_title">デバッグログ</string>
|
||||
<string name="revanced_enable_debug_logging_summary">デバッグログを出力します。</string>
|
||||
<string name="revanced_enable_debug_buffer_logging_title">デバッグバッファログを有効化</string>
|
||||
@ -391,6 +392,9 @@ API キーの発行方法については、ここをタップしてください
|
||||
• OPUSオーディオコーデックはサポートされていない可能性があります。
|
||||
• シークバーのサムネイルが表示されない場合があります。
|
||||
• 再生履歴はブランドアカウントでは動作しません。"</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios">iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_unplugged">Android TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
|
||||
<string name="revanced_sanitize_sharing_links_title">共有リンクのクリーンアップ</string>
|
||||
<string name="revanced_sanitize_sharing_links_summary">リンクを共有する際に、URL からトラッキングクエリパラメーターを削除します。</string>
|
||||
<string name="revanced_default_app_settings_title">「デフォルトで開く」の設定</string>
|
||||
|
@ -129,7 +129,7 @@
|
||||
<string name="revanced_change_start_page_entry_library">보관함</string>
|
||||
<string name="revanced_change_start_page_entry_subscription">구독</string>
|
||||
<string name="revanced_disable_auto_captions_title">자동 자막 비활성화</string>
|
||||
<string name="revanced_disable_auto_captions_summary">자막 사용이 강제된 동영상에서 자막을 비활성화합니다.</string>
|
||||
<string name="revanced_disable_auto_captions_summary">자막이 자동으로 활성화되지 않도록 설정합니다.</string>
|
||||
<string name="revanced_disable_dislike_redirection_title">싫어요 리다이렉션 비활성화</string>
|
||||
<string name="revanced_disable_dislike_redirection_summary">\'싫어요 버튼을 누르면 다음 트랙으로 리다이렉션\'을 비활성화합니다.</string>
|
||||
<string name="revanced_enable_landscape_mode_title">가로 모드 활성화</string>
|
||||
@ -384,7 +384,7 @@ API Key를 발급받는 방법을 보려면 여기를 누르세요."</string>
|
||||
<string name="revanced_enable_opus_codec_summary">"플레이어 응답에 OPUS 코덱이 포함된 경우에는 OPUS 코덱을 활성화합니다.
|
||||
|
||||
알림:
|
||||
• 최신 YT Music 클라이언트는 기본적으로 OPUS 오디오 코덱을 사용합니다.
|
||||
• 최신 YT Music 클라이언트는 기본적으로 OPUS 코덱을 사용합니다.
|
||||
• 이 설정은 아주 오래된 클라이언트 사용자에게만 유효합니다."</string>
|
||||
<string name="gms_core_settings_title">GmsCore 열기</string>
|
||||
<string name="gms_core_settings_summary">알림 수신을 위한 클라우드 메시징 설정을 할 수 있습니다.</string>
|
||||
@ -403,14 +403,18 @@ API Key를 발급받는 방법을 보려면 여기를 누르세요."</string>
|
||||
<string name="revanced_spoof_client_title">클라이언트 변경</string>
|
||||
<string name="revanced_spoof_client_summary">"클라이언트를 변경하여 재생 문제를 방지할 수 있습니다.
|
||||
|
||||
알려진 문제점:
|
||||
• OPUS 코덱이 지원되지 않을 수 있습니다.
|
||||
• 재생바 썸네일이 표시되지 않을 수 있습니다.
|
||||
• 브랜드 계정에서는 시청 기록이 작동되지 않습니다."</string>
|
||||
※ '스트리밍 데이터 변경'과 함께 사용할 경우에 재생 문제가 발생할 수 있습니다."</string>
|
||||
<string name="revanced_spoof_client_type_title">기본 클라이언트</string>
|
||||
<string name="revanced_spoof_client_type_summary">"변경할 기본 클라이언트를 정의합니다.
|
||||
|
||||
※ Android 클라이언트를 사용할 경우에 '앱 버전 변경'과 함께 사용하는 것을 권장합니다."</string>
|
||||
<string name="revanced_spoof_client_type_entry_android_music_4_27">Android Music 4.27.53</string>
|
||||
<string name="revanced_spoof_client_type_entry_android_music_5_29">Android Music 5.29.53</string>
|
||||
<string name="revanced_spoof_client_type_entry_ios_music_6_21">iOS Music 6.21</string>
|
||||
<string name="revanced_spoof_streaming_data_title">스트리밍 데이터 변경</string>
|
||||
<string name="revanced_spoof_streaming_data_summary">"스트리밍 데이터를 변경하여 재생 문제를 방지합니다.
|
||||
|
||||
※ '클라이언트 변경'과 함께 사용하면, 재생 문제가 발생할 수 있습니다."</string>
|
||||
※ '클라이언트 변경'과 함께 사용할 경우에 재생 문제가 발생할 수 있습니다."</string>
|
||||
<string name="revanced_spoof_streaming_data_type_title">기본 클라이언트</string>
|
||||
<string name="revanced_spoof_streaming_data_type_summary">스트리밍 데이터를 가져오는 데 사용되는 기본 클라이언트를 정의할 수 있습니다.</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">동영상 통계에서 표시</string>
|
||||
|
@ -404,13 +404,15 @@ Stuknij przycisk kontynuacji i zezwól na zmiany w optymalizacji."</string>
|
||||
<string name="revanced_spoof_client_title">Oszukuj klienta</string>
|
||||
<string name="revanced_spoof_client_summary">"Oszukuj klienta, by zapobiec problemom z odtwarzaniem.
|
||||
|
||||
Ograniczenia:
|
||||
• Kodek audio OPUS może nie być wspierany
|
||||
• Miniaturki podczas przewijania mogą nie być dostępne
|
||||
• Historia oglądania nie działa na kontach firmowych
|
||||
|
||||
※ Używane równolegle z opcją 'Oszukuj strumień danych', może powodować problemy z odtwarzaniem
|
||||
"</string>
|
||||
<string name="revanced_spoof_client_type_title">Domyślny klient</string>
|
||||
<string name="revanced_spoof_client_type_summary">"Definiuje domyślnego klienta do oszukiwania.
|
||||
|
||||
※ Jeśli używasz klienta Androida, zaleca się korzystanie razem z opcją 'Oszukuj wersję aplikacji'."</string>
|
||||
<string name="revanced_spoof_client_type_entry_android_music_4_27">Android Music 4.27.53</string>
|
||||
<string name="revanced_spoof_client_type_entry_android_music_5_29">Android Music 5.29.53</string>
|
||||
<string name="revanced_spoof_client_type_entry_ios_music_6_21">iOS Music 6.21</string>
|
||||
<string name="revanced_spoof_streaming_data_title">Oszukuj strumień danych</string>
|
||||
<string name="revanced_spoof_streaming_data_summary">"Oszukuj strumień danych, by zapobiec problemom z odtwarzaniem.
|
||||
|
||||
|
@ -405,14 +405,8 @@ Toque no botão continuar e permita as alterações de otimização."</string>
|
||||
<string name="revanced_spoof_client_summary">"Falsificar o cliente para evitar problemas de reprodução.
|
||||
|
||||
※ Quando usado com 'Dados de streaming falsos', podem ocorrer problemas de reprodução."</string>
|
||||
<string name="revanced_spoof_client_legacy_title">Usar o cliente antigo</string>
|
||||
<string name="revanced_spoof_client_legacy_summary">"Falsificando com a versão 4.27.53.
|
||||
|
||||
O codec OPUS pode não funcionar."</string>
|
||||
<string name="revanced_spoof_client_type_title">Cliente padrão</string>
|
||||
<string name="revanced_spoof_client_type_summary">Define um cliente padrão para falsificar.</string>
|
||||
<string name="revanced_spoof_client_type_entry_android_music">Android Music</string>
|
||||
<string name="revanced_spoof_client_type_entry_ios_music">iOS Music</string>
|
||||
<string name="revanced_spoof_client_type_summary">"Define um cliente padrão para falsificar."</string>
|
||||
<string name="revanced_spoof_streaming_data_title">Dados de streaming falsos</string>
|
||||
<string name="revanced_spoof_streaming_data_summary">"Falsifique os dados de streaming para evitar problemas de reprodução.
|
||||
|
||||
|
@ -395,23 +395,27 @@ Hãy làm theo hướng dẫn của 'Don't kill my app!' và tiến hành cài
|
||||
|
||||
Để ứng dụng hoạt động hiệu quả nhất."</string>
|
||||
<string name="gms_core_dialog_open_website_text">Mở trang web</string>
|
||||
<string name="gms_core_dialog_not_whitelisted_using_battery_optimizations_message">"Tắt tối ưu hoá pin cho GmsCore để tránh các vấn đề phát sinh.
|
||||
<string name="gms_core_dialog_not_whitelisted_using_battery_optimizations_message">"Vui lòng tắt tối ưu hoá pin cho GmsCore để tránh phát sinh lỗi.
|
||||
|
||||
Nhấn vào nút Tiếp tục và tắt tối ưu hóa pin."</string>
|
||||
Tắt tối ưu hoá pin cho GmsCore sẽ không làm ảnh hưởng đáng kể tới thời lượng sử dụng pin.
|
||||
|
||||
Nhấn vào Tiếp tục và cho phép thay đổi lựa chọn tối ưu hoá pin."</string>
|
||||
<string name="gms_core_dialog_continue_text">Tiếp tục</string>
|
||||
<string name="revanced_spoof_client_title">Giả mạo ứng dụng khách</string>
|
||||
<string name="revanced_spoof_client_summary">"Giả mạo ứng dụng khách nhằm khắc phục sự cố phát.
|
||||
|
||||
Hạn chế:
|
||||
• Codec âm thanh OPUS có thể không được hỗ trợ.
|
||||
• Hình thu nhỏ trên thanh tiến trình có thể không hiện hữu.
|
||||
• Nhật ký xem không hoạt động đối với tài khoản thương hiệu.
|
||||
※ Khi được sử dụng đồng thời với \"Giả mạo luồng dữ liệu trực tuyến\", có thể gây ra sự cố phát."</string>
|
||||
<string name="revanced_spoof_client_type_title">Ứng dụng khách mặc định</string>
|
||||
<string name="revanced_spoof_client_type_summary">"Xác định ứng dụng khách mặc định để giả mạo.
|
||||
|
||||
※ Khi được sử dụng cùng với \"Giả mạo luồng dữ liệu trực tuyến\", có thể gây ra sự cố phát."</string>
|
||||
※ Khi sử dụng ứng dụng khách Android, tính năng này nên được sử dụng đồng thời với \"Giả mạo phiên bản ứng dụng\"."</string>
|
||||
<string name="revanced_spoof_client_type_entry_android_music_4_27">Music Android 4.27.53</string>
|
||||
<string name="revanced_spoof_client_type_entry_android_music_5_29">Music Android 5.29.53</string>
|
||||
<string name="revanced_spoof_client_type_entry_ios_music_6_21">Music iOS 6.21</string>
|
||||
<string name="revanced_spoof_streaming_data_title">Giả mạo luồng dữ liệu trực tuyến</string>
|
||||
<string name="revanced_spoof_streaming_data_summary">"Giả mạo luồng dữ liệu trực tuyến nhằm khắc phục sự cố phát.
|
||||
|
||||
※ Khi được sử dụng cùng với \"Giả mạo ứng dụng khách\", có thể gây ra sự cố phát."</string>
|
||||
※ Khi được sử dụng đồng thời với \"Giả mạo ứng dụng khách\", có thể gây ra sự cố phát."</string>
|
||||
<string name="revanced_spoof_streaming_data_type_title">Ứng dụng khách mặc định</string>
|
||||
<string name="revanced_spoof_streaming_data_type_summary">Xác định một ứng dụng khách mặc định để nạp luồng dữ liệu trực tuyến.</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Hiển thị trong Thống kê chi tiết</string>
|
||||
|
@ -235,13 +235,23 @@
|
||||
<item>HEART_TINT</item>
|
||||
<item>HIDDEN</item>
|
||||
</string-array>
|
||||
<string-array name="revanced_spoof_streaming_data_type_entries">
|
||||
<item>@string/revanced_spoof_streaming_data_type_entry_ios</item>
|
||||
<string-array name="revanced_spoof_streaming_data_type_android_entries">
|
||||
<item>@string/revanced_spoof_streaming_data_type_entry_android_unplugged</item>
|
||||
<item>@string/revanced_spoof_streaming_data_type_entry_android_vr</item>
|
||||
</string-array>
|
||||
<string-array name="revanced_spoof_streaming_data_type_entry_values">
|
||||
<string-array name="revanced_spoof_streaming_data_type_android_entry_values">
|
||||
<item>ANDROID_UNPLUGGED</item>
|
||||
<item>ANDROID_VR</item>
|
||||
</string-array>
|
||||
<string-array name="revanced_spoof_streaming_data_type_android_ios_entries">
|
||||
<item>@string/revanced_spoof_streaming_data_type_entry_ios</item>
|
||||
<item>@string/revanced_spoof_streaming_data_type_entry_ios_unplugged</item>
|
||||
<item>@string/revanced_spoof_streaming_data_type_entry_android_unplugged</item>
|
||||
<item>@string/revanced_spoof_streaming_data_type_entry_android_vr</item>
|
||||
</string-array>
|
||||
<string-array name="revanced_spoof_streaming_data_type_android_ios_entry_values">
|
||||
<item>IOS</item>
|
||||
<item>IOS_UNPLUGGED</item>
|
||||
<item>ANDROID_UNPLUGGED</item>
|
||||
<item>ANDROID_VR</item>
|
||||
</string-array>
|
||||
|
@ -1914,20 +1914,20 @@ Tap the continue button and allow optimization changes."</string>
|
||||
<string name="revanced_spoof_streaming_data_type_title">Default client</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios">iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_music">iOS Music</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_unplugged">iOS TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_creator">Android Creator</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_unplugged">Android TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_title">Spoofing side effects</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios">• Not yet found.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_skip_sync_video_length">• Videos may end 1 second early.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_unplugged">"• Audio track menu is missing.
|
||||
• Stable volume is not available."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_vr">"• Audio track menu is missing.
|
||||
• Stable volume is not available."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_title">Sync video length before playback</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_on">"Video length is synced before playback.
|
||||
Video length is exact value."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_off">"Video length is not synced before playback.
|
||||
Video length may be a rounded value."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_unplugged">• Movies or paid videos may not play.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android">"• Audio track menu is missing.
|
||||
• Stable volume is not available.
|
||||
• Disable forced auto audio tracks is not available."</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_title">Use Android clients only</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_on">Android clients are used to fetch streaming data.</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_off">Android and iOS clients are used to fetch streaming data.</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_user_dialog_message">Turning off this setting may cause video playback issues.</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Show in Stats for nerds</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Client used to fetch streaming data is shown in Stats for nerds.</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Client used to fetch streaming data is hidden in Stats for nerds.</string>
|
||||
|
@ -791,9 +791,9 @@
|
||||
<!-- SETTINGS: SPOOF_STREAMING_DATA
|
||||
<PreferenceScreen android:title="@string/revanced_preference_screen_spoof_streaming_data_title" android:key="revanced_preference_screen_spoof_streaming_data" android:summary="@string/revanced_preference_screen_spoof_streaming_data_summary">
|
||||
<SwitchPreference android:title="@string/revanced_spoof_streaming_data_title" android:key="revanced_spoof_streaming_data" android:summaryOn="@string/revanced_spoof_streaming_data_summary_on" android:summaryOff="@string/revanced_spoof_streaming_data_summary_off" />
|
||||
<ListPreference android:entries="@array/revanced_spoof_streaming_data_type_entries" android:title="@string/revanced_spoof_streaming_data_type_title" android:key="revanced_spoof_streaming_data_type" android:entryValues="@array/revanced_spoof_streaming_data_type_entry_values" android:dependency="revanced_spoof_streaming_data" />
|
||||
<app.revanced.extension.youtube.settings.preference.SpoofStreamingDataDefaultClientListPreference android:title="@string/revanced_spoof_streaming_data_type_title" android:key="revanced_spoof_streaming_data_type" />
|
||||
<app.revanced.extension.youtube.settings.preference.SpoofStreamingDataSideEffectsPreference android:title="@string/revanced_spoof_streaming_data_side_effects_title" />
|
||||
<SwitchPreference android:title="@string/revanced_spoof_streaming_data_sync_video_length_title" android:key="revanced_spoof_streaming_data_sync_video_length" android:summaryOn="@string/revanced_spoof_streaming_data_sync_video_length_summary_on" android:summaryOff="@string/revanced_spoof_streaming_data_sync_video_length_summary_off" android:dependency="revanced_spoof_streaming_data" />
|
||||
<SwitchPreference android:title="@string/revanced_spoof_streaming_data_android_only_title" android:key="revanced_spoof_streaming_data_android_only" android:summaryOn="@string/revanced_spoof_streaming_data_android_only_summary_on" android:summaryOff="@string/revanced_spoof_streaming_data_android_only_summary_off" android:dependency="revanced_spoof_streaming_data" />
|
||||
<SwitchPreference android:title="@string/revanced_spoof_streaming_data_stats_for_nerds_title" android:key="revanced_spoof_streaming_data_stats_for_nerds" android:summaryOn="@string/revanced_spoof_streaming_data_stats_for_nerds_summary_on" android:summaryOff="@string/revanced_spoof_streaming_data_stats_for_nerds_summary_off" android:dependency="revanced_spoof_streaming_data" />
|
||||
</PreferenceScreen>SETTINGS: SPOOF_STREAMING_DATA -->
|
||||
|
||||
|
@ -1786,20 +1786,19 @@
|
||||
<string name="revanced_spoof_streaming_data_type_title">العميل الافتراضي</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios">iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_music">موسيقى iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_unplugged">iOS TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_creator">Android Creator</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_unplugged">Android TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_title">التأثيرات الجانبية للتزييف</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios">• لم يتم العثور عليه بعد.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_skip_sync_video_length">• قد تنتهي الفيديوهات قبل النهاية بـ 1 ثانية.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_unplugged">"• قائمة المقطع الصوتي مفقودة.
|
||||
• مستوى الصوت الثابت غير متوفر."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_vr">"• قائمة المقطع الصوتي مفقودة.
|
||||
• مستوى الصوت الثابت غير متوفر."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_title">مزامنة مدة الفيديو قبل التشغيل</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_on">"تتم مزامنة مدة الفيديو قبل التشغيل.
|
||||
مدة الفيديو هي القيمة الدقيقة."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_off">"لا تتم مزامنة مدة الفيديو قبل التشغيل.
|
||||
قد تكون مدة الفيديو قيمة تقريبية."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_unplugged">• قد لا يتم تشغيل الأفلام أو الفيديوهات المدفوعة.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android">"• قائمة المقطع الصوتي مفقودة.
|
||||
• مستوى الصوت الثابت غير متاح.
|
||||
• تعطيل مقاطع الصوت التلقائية المفروضة غير متاح."</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_title">استخدام عملاء Android فقط</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_on">يتم استخدام عملاء Android لجلب البيانات المتدفقة.</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_off">يتم استخدام عملاء Android و iOS لجلب البيانات المتدفقة.</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>
|
||||
|
@ -1689,8 +1689,6 @@
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_unplugged">Android TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_title">Ефекти от замяната</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_unplugged">"• Липсва менюто за избор на аудио."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_vr">"• Липсва менюто за избор на аудио."</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>
|
||||
|
@ -1801,20 +1801,19 @@ Playlists
|
||||
<string name="revanced_spoof_streaming_data_type_title">Προεπιλογή</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios">iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_music">iOS Music</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_unplugged">iOS TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_creator">Android Creator</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_unplugged">Android TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_title">Παρενέργειες παραποίησης</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios">• Δεν ανακαλύφθηκαν ακόμη.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_skip_sync_video_length">• Τα βίντεο μπορεί να τελειώνουν 1 δευτερόλεπτο νωρίτερα.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_unplugged">"• Το μενού «Κομμάτι ήχου» λείπει.
|
||||
• Η λειτουργία «Σταθερή ένταση» δεν είναι διαθέσιμη."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_vr">"• Το μενού «Κομμάτι ήχου» λείπει.
|
||||
• Η λειτουργία «Σταθερή ένταση» δεν είναι διαθέσιμη."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_title">Συγχρονισμός μήκους βίντεο πριν την αναπαραγωγή</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_on">"Το μήκος του βίντεο συγχρονίζεται πριν την αναπαραγωγή.
|
||||
Το μήκος του βίντεο είναι ακριβής."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_off">"Το μήκος του βίντεο δεν συγχρονίζεται πριν την αναπαραγωγή.
|
||||
Το μήκος του βίντεο μπορεί να είναι στρογγυλεμένη τιμή."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_unplugged">• Οι ταινίες ή τα βίντεο επί πληρωμή ενδέχεται να μην αναπαράγονται.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android">"• Το μενού «Κομμάτι ήχου» λείπει.
|
||||
• Η λειτουργία «Σταθερή ένταση» δεν είναι διαθέσιμη.
|
||||
• Η λειτουργία «Απενεργοποίηση υποχρεωτικών κομματιών ήχου» δεν είναι διαθέσιμη."</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_title">Χρήση των προγραμμάτων πελάτη Android μόνο</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_on">Τα προγράμματα πελάτη Android χρησιμοποιούνται τη λήψη δεδομένων ροής.</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_off">Τα προγράμματα πελάτη Android και iOS χρησιμοποιούνται τη λήψη δεδομένων ροής.</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>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<string name="accessibility_settings_edu_opt_out_text">Tus controles se modifican porque un servicio de accesibilidad está activado.</string>
|
||||
<!-- Shared -->
|
||||
<string name="revanced_extended_settings_title">ReVanced Extended</string>
|
||||
<string name="revanced_extended_settings_search_title">Buscar %s</string>
|
||||
<string name="revanced_extended_settings_search_title">Buscar en %s</string>
|
||||
<string name="revanced_extended_reset_to_default_toast">Restablecer valores predeterminados.</string>
|
||||
<string name="revanced_preference_category_experimental_flag">Funciones Experimentales</string>
|
||||
<string name="revanced_extended_confirm_user_dialog_title">¿Quieres continuar?</string>
|
||||
@ -320,6 +320,9 @@ Limitación: Es posible que el botón Atrás de la barra de herramientas no func
|
||||
<string name="revanced_disable_splash_animation_title">Desactivar animación de bienvenida</string>
|
||||
<string name="revanced_disable_splash_animation_summary_on">La animación de bienvenida está desactivada.</string>
|
||||
<string name="revanced_disable_splash_animation_summary_off">La animación de bienvenida está activada.</string>
|
||||
<string name="revanced_disable_translucent_status_bar_title">Desactivar barra de estado translúcida</string>
|
||||
<string name="revanced_disable_translucent_status_bar_summary_on">La barra de estado es opaca.</string>
|
||||
<string name="revanced_disable_translucent_status_bar_summary_off">La barra de estado es opaca o translúcida.</string>
|
||||
<string name="revanced_enable_gradient_loading_screen_title">Activar pantalla de carga de degradado</string>
|
||||
<string name="revanced_enable_gradient_loading_screen_summary_on">La pantalla de carga de degradado está activada.</string>
|
||||
<string name="revanced_enable_gradient_loading_screen_summary_off">La pantalla de carga de degradado está desactivada.</string>
|
||||
@ -358,6 +361,8 @@ Si se desactiva más tarde, se recomienda borrar los datos de la aplicación par
|
||||
<string name="revanced_spoof_app_version_target_entry_18_33_40">18.33.40 - Restaura la antigua barra de acción de Shorts</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_18_38_45">18.38.45 - Restaura el antiguo comportamiento de la calidad predeterminada de vídeo</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_18_48_39">18.48.39 - Desactiva la actualización en tiempo real de las visualizaciones y los me gusta</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_19_26_42">19.26.42 - Desactivar icono de Cairo en la barra de navegación y herramientas</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_19_33_37">19.33.37 - Restaurar el antiguo panel desplegable de velocidad de reproducción</string>
|
||||
<!-- PreferenceScreen: General, PreferenceCategory: General, PreferenceScreen: Account menu -->
|
||||
<string name="revanced_preference_screen_account_menu_title">Menú de cuenta</string>
|
||||
<string name="revanced_preference_screen_account_menu_summary">Ocultar o mostrar elementos en el menú de la cuenta y la pestaña Tú.</string>
|
||||
@ -490,7 +495,12 @@ Nota: Al activar esto también se ocultan forzosamente los anuncios de vídeos."
|
||||
Además, los anuncios ya no se bloquearán en Shorts.
|
||||
|
||||
Si este ajuste no surte efecto, prueba a cambiar al modo incógnito."</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_light_title">Desactivar barra translúcida luminosa</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_light_summary_on">La barra de navegación en modo claro es opaca.</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_light_summary_off">.</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_dark_title">Desactivar barra translúcida oscura</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_dark_summary_on">La barra de navegación en modo oscuro es opaca.</string>
|
||||
<string name="revanced_disable_translucent_navigation_bar_dark_summary_off">La barra de navegación en modo oscuro es opaca o translúcida.</string>
|
||||
<string name="revanced_hide_navigation_bar_title">Ocultar barra de navegación</string>
|
||||
<string name="revanced_hide_navigation_bar_summary_on">La barra de navegación está oculta.</string>
|
||||
<string name="revanced_hide_navigation_bar_summary_off">La barra de navegación está visible.</string>
|
||||
@ -650,6 +660,9 @@ Nota:
|
||||
<string name="revanced_hide_info_panel_title">Ocultar paneles de información</string>
|
||||
<string name="revanced_hide_info_panel_summary_on">Los paneles de información están ocultos.</string>
|
||||
<string name="revanced_hide_info_panel_summary_off">Los paneles de información están visibles.</string>
|
||||
<string name="revanced_hide_live_chat_summary_title">Ocultar resumen del chat en chat en directo</string>
|
||||
<string name="revanced_hide_live_chat_summary_summary_on">El resumen del chat está oculto.</string>
|
||||
<string name="revanced_hide_live_chat_summary_summary_off">El resumen del chat está visible.</string>
|
||||
<string name="revanced_hide_live_chat_messages_title">Ocultar mensajes de chat en directo</string>
|
||||
<string name="revanced_hide_live_chat_messages_summary_on">Los mensajes de chat en directo están ocultos.\n\nEste ajuste se aplica también a los vídeos en directo de Shorts.</string>
|
||||
<string name="revanced_hide_live_chat_messages_summary_off">Los mensajes de chat en directo están visibles.\n\nEste ajuste se aplica también a los vídeos en directo de Shorts.</string>
|
||||
@ -981,6 +994,7 @@ Toca y mantén para deshacer.
|
||||
Información:
|
||||
• Puede que no funcione en transmisiones."</string>
|
||||
<string name="revanced_overlay_button_play_all_type_title">Generar modo de lista</string>
|
||||
<string name="revanced_overlay_button_play_all_type_entry_0">Todos los contenidos (Ordenar por tiempo, ascendente)</string>
|
||||
<string name="revanced_overlay_button_play_all_type_entry_1">Todos los contenidos (Ordenar por tiempo)</string>
|
||||
<string name="revanced_overlay_button_play_all_type_entry_2">Todos los contenidos (Ordenar por popular)</string>
|
||||
<string name="revanced_overlay_button_play_all_type_entry_3">Solo vídeos (Ordenar por tiempo)</string>
|
||||
@ -1143,6 +1157,7 @@ Información:
|
||||
<string name="revanced_hide_shorts_shelf_history_summary_off">Visible en el historial de reproducciones.</string>
|
||||
<!-- PreferenceScreen: Shorts, PreferenceCategory: Experimental Flags -->
|
||||
<string name="revanced_change_shorts_repeat_state_title">Cambiar estado de repetición de Shorts</string>
|
||||
<string name="revanced_change_shorts_background_repeat_state_title">Cambiar estado de repetición de fondo de Shorts</string>
|
||||
<string name="revanced_change_shorts_repeat_state_entry_auto_play">Reproducción automática</string>
|
||||
<string name="revanced_change_shorts_repeat_state_entry_default">Predeterminada</string>
|
||||
<string name="revanced_change_shorts_repeat_state_entry_pause">Pausar</string>
|
||||
@ -1257,6 +1272,44 @@ Información:
|
||||
<string name="revanced_shorts_double_tap_to_like_animation_entry_5">Corazón (Tinte)</string>
|
||||
<string name="revanced_shorts_double_tap_to_like_animation_entry_6">Oculto</string>
|
||||
<!-- PreferenceScreen: Shorts, PreferenceCategory: Shorts, PreferenceScreen: Shorts player, PreferenceCategory: Custom actions -->
|
||||
<string name="revanced_preference_category_custom_actions">Acciones personalizadas</string>
|
||||
<string name="revanced_enable_shorts_custom_actions_flyout_menu_title">Activar acciones personalizadas en menú desplegable</string>
|
||||
<string name="revanced_enable_shorts_custom_actions_flyout_menu_summary_on">"Las acciones personalizadas están activadas en el menú desplegable.
|
||||
|
||||
Limitaciones:
|
||||
• No funciona si la versión falsificada de la aplicación es 18.49.37 o anterior.
|
||||
• No funciona con transmisiones en directo."</string>
|
||||
<string name="revanced_enable_shorts_custom_actions_flyout_menu_summary_off">Las acciones personalizadas están desactivadas en el menú desplegable.</string>
|
||||
<string name="revanced_enable_shorts_custom_actions_toolbar_title">Activar acciones personalizadas en barra de herramientas</string>
|
||||
<string name="revanced_enable_shorts_custom_actions_toolbar_summary_on">"Las acciones personalizadas están activadas en la barra de herramientas.
|
||||
|
||||
Mantén pulsado el botón Más para mostrar el cuadro de diálogo Acciones personalizadas."</string>
|
||||
<string name="revanced_enable_shorts_custom_actions_toolbar_summary_off">Las acciones personalizadas están desactivadas en la barra de herramientas.</string>
|
||||
<string name="revanced_shorts_custom_actions_toolbar_dialog_title">Acciones personalizadas</string>
|
||||
<string name="revanced_shorts_custom_actions_copy_video_url_label">Copiar URL del vídeo</string>
|
||||
<string name="revanced_shorts_custom_actions_copy_video_url_title">Mostrar menú de copiar URL del vídeo</string>
|
||||
<string name="revanced_shorts_custom_actions_copy_video_url_summary_on">El menú de copiar URL del vídeo está visible.</string>
|
||||
<string name="revanced_shorts_custom_actions_copy_video_url_summary_off">El menú de copiar URL del vídeo está oculto.</string>
|
||||
<string name="revanced_shorts_custom_actions_copy_video_url_timestamp_label">Copiar URL con marca de tiempo</string>
|
||||
<string name="revanced_shorts_custom_actions_copy_video_url_timestamp_title">Mostrar menú de copiar URL con marca de tiempo</string>
|
||||
<string name="revanced_shorts_custom_actions_copy_video_url_timestamp_summary_on">El menú de copiar URL con marca de tiempo está visible.</string>
|
||||
<string name="revanced_shorts_custom_actions_copy_video_url_timestamp_summary_off">El menú de copiar URL con marca de tiempo está oculto.</string>
|
||||
<string name="revanced_shorts_custom_actions_external_downloader_label">Descargador externo</string>
|
||||
<string name="revanced_shorts_custom_actions_external_downloader_title">Mostrar menú de descargador externo</string>
|
||||
<string name="revanced_shorts_custom_actions_external_downloader_summary_on">El menú del descargador externo está visible.</string>
|
||||
<string name="revanced_shorts_custom_actions_external_downloader_summary_off">El menú del descargador externo está oculto.</string>
|
||||
<string name="revanced_shorts_custom_actions_open_video_label">Abrir vídeo</string>
|
||||
<string name="revanced_shorts_custom_actions_open_video_title">Mostrar menú de abrir vídeo</string>
|
||||
<string name="revanced_shorts_custom_actions_open_video_summary_on">El menú de abrir vídeo está visible.</string>
|
||||
<string name="revanced_shorts_custom_actions_open_video_summary_off">El menú de abrir vídeo está oculto.</string>
|
||||
<string name="revanced_shorts_custom_actions_repeat_state_label">Estado de repetición</string>
|
||||
<string name="revanced_shorts_custom_actions_repeat_state_title">Mostrar menú de estado de repetición</string>
|
||||
<string name="revanced_shorts_custom_actions_repeat_state_summary_on">El menú del estado de repetición está visible.</string>
|
||||
<string name="revanced_shorts_custom_actions_repeat_state_summary_off">El menú del estado de repetición está oculto.</string>
|
||||
<string name="revanced_shorts_custom_actions_about_title">Acerca de las acciones personalizadas</string>
|
||||
<string name="revanced_shorts_custom_actions_about_about_summary">"Esta función es aún experimental, por lo que no hay garantía de que funcione perfectamente.
|
||||
|
||||
La mayoría de los errores no pueden solucionarse debido a las limitaciones del lado del cliente, así que utilízala solo con fines de prueba."</string>
|
||||
<!-- PreferenceScreen: Shorts, PreferenceCategory: Shorts, PreferenceScreen: Shorts player, PreferenceCategory: Experimental Flags -->
|
||||
<string name="revanced_enable_shorts_time_stamp_title">Activar marcas de tiempo</string>
|
||||
<string name="revanced_enable_shorts_time_stamp_summary_on">"La marca de tiempo está activada.
|
||||
@ -1280,6 +1333,10 @@ Problema conocido: Al tratarse de una función en fase de desarrollo por parte d
|
||||
<string name="revanced_replace_channel_handle_title">Reemplazar nombre de usuario del canal</string>
|
||||
<string name="revanced_replace_channel_handle_summary_on">Se utiliza el nombre del canal.</string>
|
||||
<string name="revanced_replace_channel_handle_summary_off">Se utiliza el nombre de usuario del canal.</string>
|
||||
<string name="revanced_restore_shorts_old_player_layout_title">Restaurar antiguo diseño del reproductor</string>
|
||||
<string name="revanced_restore_shorts_old_player_layout_summary_on">"Se utiliza el antiguo diseño del reproductor.
|
||||
No hay márgenes en la parte superior e inferior del reproductor."</string>
|
||||
<string name="revanced_restore_shorts_old_player_layout_summary_off">No se utiliza el antiguo diseño del reproductor.</string>
|
||||
<!-- PreferenceScreen: Swipe controls -->
|
||||
<string name="revanced_preference_screen_swipe_controls_title">Controles deslizantes</string>
|
||||
<string name="revanced_enable_swipe_lowest_value_auto_brightness_title">Activar gesto de brillo automático</string>
|
||||
@ -1323,6 +1380,12 @@ Problema conocido: Al tratarse de una función en fase de desarrollo por parte d
|
||||
<string name="revanced_disable_hdr_auto_brightness_title">Desactivar brillo HDR automático</string>
|
||||
<string name="revanced_disable_hdr_auto_brightness_summary_on">El brillo HDR automático está desactivado.</string>
|
||||
<string name="revanced_disable_hdr_auto_brightness_summary_off">El brillo HDR automático está activado.</string>
|
||||
<string name="revanced_disable_watch_panel_gestures_title">Desactivar gestos del panel de visualización</string>
|
||||
<string name="revanced_disable_watch_panel_gestures_summary_on">El cambio a pantalla completa deslizando el dedo por la zona inferior del reproductor está desactivado.</string>
|
||||
<string name="revanced_disable_watch_panel_gestures_summary_off">El cambio a pantalla completa deslizando el dedo por la zona inferior del reproductor está activado.</string>
|
||||
<string name="revanced_disable_swipe_to_switch_video_title">Desactivar deslizar para cambiar el vídeo</string>
|
||||
<string name="revanced_disable_swipe_to_switch_video_summary_on">Deslizar hacia arriba / abajo no reproducirá el vídeo siguiente / anterior.</string>
|
||||
<string name="revanced_disable_swipe_to_switch_video_summary_off">Deslizar hacia arriba / abajo reproducirá el vídeo siguiente / anterior.</string>
|
||||
<string name="revanced_swipe_lowest_value_auto_brightness_overlay_text">Automático</string>
|
||||
<!-- PreferenceScreen: Video -->
|
||||
<string name="revanced_preference_screen_video_title">Vídeo</string>
|
||||
@ -1706,13 +1769,20 @@ Pulsa el botón de continuar y desactiva las optimizaciones de la batería."</st
|
||||
<string name="revanced_spoof_streaming_data_user_dialog_message">Desactivar este ajuste puede causar problemas de reproducción de vídeo.</string>
|
||||
<string name="revanced_spoof_streaming_data_type_title">Cliente predeterminado</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios">iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_music">Música iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_unplugged">iOS TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_creator">Creador de Android</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_unplugged">Android TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_title">Efectos secundarios de falsificación</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_unplugged">"• Falta el menú \"Pista de audio\".
|
||||
• \"Regular volumen\" no está disponible."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_vr">"• Falta el menú \"Pista de audio\".
|
||||
• \"Regular volumen\" no está disponible."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios">• Aún no encontrado.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_unplugged">• Las películas o vídeos de pago no pueden reproducirse.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android">"• Falta el menú de pista de audio.
|
||||
• El volumen estable no está disponible.
|
||||
• Desactivar pistas de audio automáticas forzadas no está disponible."</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_title">Utilizar solo clientes Android</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_on">Los clientes Android se utilizan para obtener datos de streaming.</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_off">Los clientes Android e iOS se utilizan para obtener datos de streaming.</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Mostrar en estadísticas para nerds</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">El cliente utilizado para obtener datos de transmisión se muestra en estadísticas para nerds.</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">El cliente utilizado para obtener datos de transmisión no se muestra en estadísticas para nerds.</string>
|
||||
|
@ -1339,6 +1339,10 @@ Limitations :
|
||||
<string name="revanced_replace_channel_handle_title">Remplacer l\'identifiant de la chaîne</string>
|
||||
<string name="revanced_replace_channel_handle_summary_on">Le nom de la chaîne est utilisé.</string>
|
||||
<string name="revanced_replace_channel_handle_summary_off">L\'identifiant de la chaîne est utilisé.</string>
|
||||
<string name="revanced_restore_shorts_old_player_layout_title">Restaurer l\'ancienne interface du lecteur</string>
|
||||
<string name="revanced_restore_shorts_old_player_layout_summary_on">"L'ancienne mise en page du lecteur est utilisée.
|
||||
Pas de marges en haut et en bas du lecteur."</string>
|
||||
<string name="revanced_restore_shorts_old_player_layout_summary_off">L\'ancienne mise en page du lecteur n\'est pas utilisée.</string>
|
||||
<!-- PreferenceScreen: Swipe controls -->
|
||||
<string name="revanced_preference_screen_swipe_controls_title">Contrôles par gestes</string>
|
||||
<string name="revanced_enable_swipe_lowest_value_auto_brightness_title">Activer les gestes de luminosité auto</string>
|
||||
@ -1385,6 +1389,7 @@ Limitations :
|
||||
<string name="revanced_disable_watch_panel_gestures_title">Désactiver les gestes inférieurs du lecteur</string>
|
||||
<string name="revanced_disable_watch_panel_gestures_summary_on">Le passage plein écran en faisant glisser vers le bas sous le lecteur vidéo est désactivé.</string>
|
||||
<string name="revanced_disable_watch_panel_gestures_summary_off">Le passage plein écran en faisant glisser vers le bas sous le lecteur vidéo est activé.</string>
|
||||
<string name="revanced_disable_swipe_to_switch_video_title">Désactiver les gestes pour changer de vidéo</string>
|
||||
<string name="revanced_disable_swipe_to_switch_video_summary_on">Glisser vers le haut / bas ne lira pas la vidéo suivante / précédente.</string>
|
||||
<string name="revanced_disable_swipe_to_switch_video_summary_off">Glisser vers le haut / bas pour lire la vidéo suivante / précédente.</string>
|
||||
<string name="revanced_swipe_lowest_value_auto_brightness_overlay_text">Auto</string>
|
||||
@ -1774,20 +1779,13 @@ Cliquez sur le bouton Continuer et autorisez les modifications d'optimisations."
|
||||
<string name="revanced_spoof_streaming_data_type_title">Client par défaut</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios">iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_music">Musique iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_unplugged">TV iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_unplugged">Android TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_title">Effets inconnus de la falsification</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios">• Pas encore trouvé.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_skip_sync_video_length">• Les vidéos peuvent se terminer avec 1 seconde d\'avance.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_unplugged">"• Le menu 'Piste Audio' est manquant.
|
||||
• Le volume stable n'es pas disponible."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_vr">"• Le menu 'Piste Audio' est manquant.
|
||||
• Le volume stable n'es pas disponible."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_title">Synchroniser la durée de la vidéo avant la lecture</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_on">"La durée de la vidéo est synchronisée avant la lecture.
|
||||
La durée a une valeur exacte."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_off">"La durée de la vidéo n'est pas synchronisée avant la lecture.
|
||||
La durée peut avoir une valeur arrondie."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios">• Les vidéos privées conçues pour enfants peuvent ne pas être lues.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_unplugged">• Les vidéos privées conçues pour enfants peuvent ne pas être lues.
|
||||
• Les films ou vidéos payantes peuvent ne pas être lues.</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Afficher dans \'Statistiques pour les nerds\'</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Le client utilisé pour récupérer les données de lecture en direct est affiché dans \'Statistiques pour les nerds\'.</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Le client utilisé pour récupérer les données de lecture en direct est masqué dans \'Statistiques pour les nerds\'.</string>
|
||||
|
@ -1755,8 +1755,6 @@ Kattintson az API-kulcs kiadás folyamatának megtekintéséhez."</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_title">Hamisítás mellékhatásai</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios">• Még nem található.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_unplugged">"• Az audiosáv menü hiányzik."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_vr">"• Az audiosáv menü hiányzik."</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Megjelenítés a statisztikában kockáknak</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Az adatfolyam lekérésére használt kliens a statisztikában kockáknak látható.</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Az adatfolyam lekérésére használt kliens a statisztikában kockáknak nem látható.</string>
|
||||
|
@ -312,9 +312,9 @@ Se l'interfaccia della schermata del riproduttore cambia a causa di modifiche la
|
||||
|
||||
Nota: il pulsante Indietro della barra degli strumenti potrebbe non funzionare."</string>
|
||||
<string name="revanced_change_start_page_type_summary_off">La pagina iniziale cambia solo una volta.</string>
|
||||
<string name="revanced_disable_auto_audio_tracks_title">Disattiva le tracce audio automatiche forzate</string>
|
||||
<string name="revanced_disable_auto_audio_tracks_summary_on">Le tracce audio automatiche forzate sono disattivate.</string>
|
||||
<string name="revanced_disable_auto_audio_tracks_summary_off">Le tracce audio automatiche forzate sono attivate.</string>
|
||||
<string name="revanced_disable_auto_audio_tracks_title">Disattiva la traccia audio automatica forzata</string>
|
||||
<string name="revanced_disable_auto_audio_tracks_summary_on">La traccia audio automatica forzata è disattivata.</string>
|
||||
<string name="revanced_disable_auto_audio_tracks_summary_off">La traccia audio automatica forzata è attivata.</string>
|
||||
<string name="revanced_disable_auto_captions_title">Disattiva i sottotitoli automatici forzati</string>
|
||||
<string name="revanced_disable_auto_captions_summary_on">I sottotitoli automatici forzati sono disattivati.</string>
|
||||
<string name="revanced_disable_auto_captions_summary_off">I sottotitoli automatici forzati sono attivati.</string>
|
||||
@ -1306,8 +1306,8 @@ Tocca e tieni premuto il pulsante Altro per visualizzare la finestra delle azion
|
||||
<string name="revanced_shorts_custom_actions_open_video_summary_off">Il menù Apri il Video è nascosto.</string>
|
||||
<string name="revanced_shorts_custom_actions_repeat_state_label">Stato di ripetizione</string>
|
||||
<string name="revanced_shorts_custom_actions_repeat_state_title">Mostra il menù Stato di Ripetizione</string>
|
||||
<string name="revanced_shorts_custom_actions_repeat_state_summary_on">Il menù Stato di Ripetizione è nascosto.</string>
|
||||
<string name="revanced_shorts_custom_actions_repeat_state_summary_off">Il menù Stato di Ripetizione è visibile.</string>
|
||||
<string name="revanced_shorts_custom_actions_repeat_state_summary_on">Il menù Stato di Ripetizione è visibile.</string>
|
||||
<string name="revanced_shorts_custom_actions_repeat_state_summary_off">Il menù Stato di Ripetizione è nascosto.</string>
|
||||
<string name="revanced_shorts_custom_actions_about_title">Informazioni sulle azioni personalizzate</string>
|
||||
<string name="revanced_shorts_custom_actions_about_about_summary">"Questa impostazione è ancora sperimentale, quindi non c'è garanzia che funzionerà perfettamente.
|
||||
|
||||
@ -1775,20 +1775,19 @@ Tocca il pulsante Continua e consenti le modifiche di ottimizzazione."</string>
|
||||
<string name="revanced_spoof_streaming_data_type_title">Client predefinito</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios">iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_music">iOS Music</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_unplugged">iOS TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_creator">Android Creator</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_unplugged">Android TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_title">Effetti collaterali del camuffamento</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios">• Nessuno ancora trovato.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_skip_sync_video_length">• I video potrebbero terminare 1 secondo prima.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_unplugged">"• Il menù Traccia Audio è mancante.
|
||||
• Il menù Volume Stabile è mancante."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_vr">"• Il menù Traccia Audio è mancante.
|
||||
• Il menù Volume Stabile è mancante."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_title">Sincronizza la lunghezza del video prima della riproduzione</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_on">"La lunghezza del video è sincronizzata prima della riproduzione.
|
||||
La lunghezza del video è il valore esatto."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_off">"La lunghezza del video non è sincronizzata prima della riproduzione.
|
||||
La lunghezza del video potrebbe essere un valore arrotondato."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_unplugged">• I film o i video a pagamento potrebbero non essere riprodotti.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android">"• Il menù Traccia Audio è mancante.
|
||||
• Il menù Volume Stabile è mancante.
|
||||
• La disattivazione della traccia audio automatica forzata non funziona."</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_title">Usa solo il client Android</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_on">Il client Android è usato per recuperare i dati in streaming.</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_off">I client Android e iOS sono usati per recuperare i dati in streaming.</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Mostra nelle statistiche per nerd</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Il client usato per recuperare i dati in streaming è visibile nelle statistiche per nerd.</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Il client usato per recuperare i dati in streaming è nascosto nelle statistiche per nerd.</string>
|
||||
|
@ -1777,20 +1777,13 @@ GmsCore の電池の最適化を無効にしても、バッテリーの使用に
|
||||
<string name="revanced_spoof_streaming_data_type_title">偽装するクライアントの種類</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios">iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_music">iOS Music</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_unplugged">iOS TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_unplugged">Android TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_title">ストリーミングデータを偽装することによる副作用</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios">・まだ見つかっていません。</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_skip_sync_video_length">・動画が 1 秒早く終了する可能性があります。</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_unplugged">"・「音声トラック」メニューは表示されません。
|
||||
・「一定音量」は使用できません。"</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_vr">"・「音声トラック」メニューは表示されません。
|
||||
・「一定音量」は使用できません。"</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_title">再生前に動画の長さを同期</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_on">"再生前に動画の長さを同期します。
|
||||
動画の長さは正確な値です。"</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_off">"再生前に動画の長さを同期します。
|
||||
動画の長さは正確な値です。"</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_unplugged">・子供向け動画は再生できない可能性があります。
|
||||
・映画や有料動画は再生できない可能性があります。</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>
|
||||
|
@ -315,11 +315,11 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요."</string>
|
||||
알려진 문제점: 툴바에서 '뒤로 가기' 버튼이 작동되지 않을 수 있습니다."</string>
|
||||
<string name="revanced_change_start_page_type_summary_off">앱 시작 페이지가 한 번만 변경됩니다.</string>
|
||||
<string name="revanced_disable_auto_audio_tracks_title">자동 오디오 트랙 비활성화하기</string>
|
||||
<string name="revanced_disable_auto_audio_tracks_summary_on">오디오 트랙 사용이 강제된 동영상에서 오디오 트랙을 비활성화합니다.</string>
|
||||
<string name="revanced_disable_auto_audio_tracks_summary_off">오디오 트랙 사용이 강제된 동영상에서 오디오 트랙을 활성화합니다.</string>
|
||||
<string name="revanced_disable_auto_audio_tracks_summary_on">자동 오디오 트랙을 비활성화합니다.</string>
|
||||
<string name="revanced_disable_auto_audio_tracks_summary_off">자동 오디오 트랙을 활성화합니다.</string>
|
||||
<string name="revanced_disable_auto_captions_title">자동 자막 비활성화하기</string>
|
||||
<string name="revanced_disable_auto_captions_summary_on">자막 사용이 강제된 동영상에서 자막을 비활성화합니다.</string>
|
||||
<string name="revanced_disable_auto_captions_summary_off">자막 사용이 강제된 동영상에서 자막을 활성화합니다.</string>
|
||||
<string name="revanced_disable_auto_captions_summary_on">자동 자막을 비활성화합니다.</string>
|
||||
<string name="revanced_disable_auto_captions_summary_off">자동 자막을 활성화합니다.</string>
|
||||
<string name="revanced_disable_splash_animation_title">스플래시 애니메이션 비활성화하기</string>
|
||||
<string name="revanced_disable_splash_animation_summary_on">앱을 시작할 때, 스플래시 애니메이션을 비활성화합니다.</string>
|
||||
<string name="revanced_disable_splash_animation_summary_off">앱을 시작할 때, 스플래시 애니메이션을 활성화합니다.</string>
|
||||
@ -410,7 +410,7 @@ DeArrow에 대해 자세히 알아보려면 여기를 누르세요."</string>
|
||||
<string name="revanced_preference_screen_miniplayer_title">미니 플레이어</string>
|
||||
<string name="revanced_preference_screen_miniplayer_summary">앱 내에서 최소화된 플레이어의 스타일을 변경할 수 있습니다.</string>
|
||||
<string name="revanced_miniplayer_type_title">미니 플레이어 유형</string>
|
||||
<string name="revanced_miniplayer_type_entry_0">비활성화됨</string>
|
||||
<string name="revanced_miniplayer_type_entry_0">사용하지 않음</string>
|
||||
<string name="revanced_miniplayer_type_entry_1">기기 기본값 사용</string>
|
||||
<string name="revanced_miniplayer_type_entry_2">최소화</string>
|
||||
<string name="revanced_miniplayer_type_entry_3">태블릿</string>
|
||||
@ -1780,18 +1780,19 @@ GmsCore를 배터리 최적화 목록에서 제외하더라도, 배터리 사용
|
||||
<string name="revanced_spoof_streaming_data_type_title">기본 클라이언트</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios">iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_music">iOS Music</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_unplugged">iOS TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_creator">Android Creator</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_unplugged">Android TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_title">알려진 문제점</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios">• 아직 발견되지 않았습니다.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_skip_sync_video_length">• 동영상이 1초 일찍 종료될 수 있습니다.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_unplugged">"• 오디오 트랙 메뉴가 표시되지 않습니다.\n• 안정적인 볼륨 메뉴가 비활성화된 채로 잠겨있습니다."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_vr">"• 오디오 트랙 메뉴가 표시되지 않습니다.\n• 안정적인 볼륨 메뉴가 비활성화된 채로 잠겨있습니다."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_title">재생 전 동영상 길이 동기화하기</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_on">"동영상 길이를 재생 전에 동기화합니다.
|
||||
동영상 길이는 정확한 값입니다."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_off">"동영상 길이를 재생 전에 동기화하지 않습니다.
|
||||
동영상 길이는 반올림된 값일 수 있습니다."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_unplugged">• 영화 또는 회원 전용 동영상과 같은 유료 동영상이 재생되지 않을 수 있습니다.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android">"• 오디오 트랙 메뉴가 표시되지 않습니다.
|
||||
• 안정적인 볼륨을 사용할 수 없습니다.
|
||||
• 자동 오디오 트랙을 비활성화할 수 없습니다."</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_title">Android 클라이언트만 사용하기</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_on">Android 클라이언트를 스트리밍 데이터를 가져오는 데 사용합니다.</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_off">Android 와 iOS 클라이언트를 스트리밍 데이터를 가져오는 데 사용합니다.</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>
|
||||
|
@ -311,10 +311,10 @@ Jeśli układ ekranu odtwarzacza zmieni się w skutek zmian po stronie serwera,
|
||||
|
||||
Ograniczenie: Przycisk wstecz na pasku narzędzi może nie działać."</string>
|
||||
<string name="revanced_change_start_page_type_summary_off">Strona główna zmienia się tylko raz</string>
|
||||
<string name="revanced_disable_auto_audio_tracks_title">Wymuszone ścieżki dźwiękowe</string>
|
||||
<string name="revanced_disable_auto_audio_tracks_title">Automatyczne wymuszanie ścieżki dźwiękowej</string>
|
||||
<string name="revanced_disable_auto_audio_tracks_summary_on">Wyłączone</string>
|
||||
<string name="revanced_disable_auto_audio_tracks_summary_off">Włączone</string>
|
||||
<string name="revanced_disable_auto_captions_title">Wymuszone napisy</string>
|
||||
<string name="revanced_disable_auto_captions_title">Automatyczne wymuszanie napisów</string>
|
||||
<string name="revanced_disable_auto_captions_summary_on">Wyłączone</string>
|
||||
<string name="revanced_disable_auto_captions_summary_off">Włączone</string>
|
||||
<string name="revanced_disable_splash_animation_title">Animacja uruchamiania aplikacji</string>
|
||||
@ -1333,6 +1333,9 @@ Ograniczenia:
|
||||
<string name="revanced_replace_channel_handle_title">Wyświetlanie tytułu kanału</string>
|
||||
<string name="revanced_replace_channel_handle_summary_on">Po nazwie</string>
|
||||
<string name="revanced_replace_channel_handle_summary_off">Po nicku</string>
|
||||
<string name="revanced_restore_shorts_old_player_layout_title">Przywrócić stary układ odtwarzacza</string>
|
||||
<string name="revanced_restore_shorts_old_player_layout_summary_on">"Włączone"</string>
|
||||
<string name="revanced_restore_shorts_old_player_layout_summary_off">Wyłączone</string>
|
||||
<!-- PreferenceScreen: Swipe controls -->
|
||||
<string name="revanced_preference_screen_swipe_controls_title">Sterowanie przesuwaniem</string>
|
||||
<string name="revanced_enable_swipe_lowest_value_auto_brightness_title">Automatyczna jasność przesuwaniem</string>
|
||||
@ -1379,6 +1382,7 @@ Ograniczenia:
|
||||
<string name="revanced_disable_watch_panel_gestures_title">Pełny ekran gestem przesunięcia</string>
|
||||
<string name="revanced_disable_watch_panel_gestures_summary_on">Wejście w tryb pełnoekranowy przesunięciem w dół poniżej odtwarzacza filmu jest wyłączone</string>
|
||||
<string name="revanced_disable_watch_panel_gestures_summary_off">Wejście w tryb pełnoekranowy przesunięciem w dół poniżej odtwarzacza filmu jest włączone</string>
|
||||
<string name="revanced_disable_swipe_to_switch_video_title">Gest zmiany filmu przesunięciem w górę lub dół </string>
|
||||
<string name="revanced_disable_swipe_to_switch_video_summary_on">Wyłączony</string>
|
||||
<string name="revanced_disable_swipe_to_switch_video_summary_off">Włączony</string>
|
||||
<string name="revanced_swipe_lowest_value_auto_brightness_overlay_text">Automatyczna</string>
|
||||
@ -1768,18 +1772,20 @@ Stuknij przycisk kontynuacji i zezwól na zmiany w optymalizacji."</string>
|
||||
<string name="revanced_spoof_streaming_data_type_title">Domyślny klient</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios">iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_music">iOS Music</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_unplugged">iOS TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_creator">Kreator Androida</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_unplugged">Android TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_title">Efekty uboczne oszukiwania</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios">• Jeszcze nie znaleziono</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_skip_sync_video_length">• Filmy mogą kończyć się o sekundę wcześniej</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_unplugged">"• Brakuje menu od ścieżki dźwiękowej
|
||||
• Stabilna głośność jest niedostępna"</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_vr">"• Brakuje menu od ścieżki dźwiękowej
|
||||
• Stabilna głośność jest niedostępna"</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_title">Synchronizuj długość filmu przez odtworzeniem</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_on">"Włączone"</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_off">"Wyłączone"</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_unplugged">• Filmy kinowe lub płatne filmy mogą się nie odtwarzać</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android">"• Brakuje menu od ścieżki dźwiękowej
|
||||
• Stabilna głośność nie jest dostępna
|
||||
• Wyłączenie automatycznego wymuszania ścieżki dźwiękowej nie jest dostępne"</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_title">Używaj wyłącznie klientów Androida</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_on">Tak</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_off">Nie</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_user_dialog_message">Wyłączenie tego ustawienia może spowodować problemy z odtwarzaniem filmów.</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Informacja w statystykach dla nerdów</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Widoczna</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Ukryta</string>
|
||||
|
@ -1775,14 +1775,6 @@ Toque no botão continuar e desative as otimizações da bateria."</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_title">Efeitos colaterais da falsificação</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios">• Ainda não encontrado.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_skip_sync_video_length">• Os vídeos podem acabar 1 segundo antes.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_unplugged">"• O menu de faixa de áudio está faltando."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_vr">"• O menu de faixa de áudio está faltando."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_title">Sincronizar duração do vídeo antes da reprodução</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_on">"A duração do vídeo é sincronizada antes da reprodução.
|
||||
A duração do vídeo é o valor exato."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_off">"A duração do vídeo não é sincronizada antes da reprodução.
|
||||
A duração do vídeo pode ser um valor arredondado."</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Exibir em Estatísticas para nerds</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">O cliente usado para buscar dados de streaming é mostrado em Estatísticas para nerds.</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">O cliente usado para buscar dados de streaming está oculto em Estatísticas para nerds.</string>
|
||||
|
@ -1352,6 +1352,10 @@ Shorts
|
||||
<string name="revanced_replace_channel_handle_title">Заменить псевдоним канала</string>
|
||||
<string name="revanced_replace_channel_handle_summary_on">Используется имя канала.</string>
|
||||
<string name="revanced_replace_channel_handle_summary_off">Используется псевдоним канала.</string>
|
||||
<string name="revanced_restore_shorts_old_player_layout_title">Старый интерфейс проигрывателя</string>
|
||||
<string name="revanced_restore_shorts_old_player_layout_summary_on">"Старый интерфейс проигрывателя включен.
|
||||
Без отступов сверху и снизу плеера."</string>
|
||||
<string name="revanced_restore_shorts_old_player_layout_summary_off">Старый интерфейс проигрывателя отключен.</string>
|
||||
<!-- PreferenceScreen: Swipe controls -->
|
||||
<string name="revanced_preference_screen_swipe_controls_title">Управление жестами</string>
|
||||
<string name="revanced_enable_swipe_lowest_value_auto_brightness_title">Управление автояркостью жестом</string>
|
||||
@ -1400,6 +1404,7 @@ Shorts
|
||||
<string name="revanced_disable_watch_panel_gestures_title">Жесты панели просмотра</string>
|
||||
<string name="revanced_disable_watch_panel_gestures_summary_on">Полноэкранный режим жестом вниз отключен.</string>
|
||||
<string name="revanced_disable_watch_panel_gestures_summary_off">Полноэкранный режим жестом вниз включен.</string>
|
||||
<string name="revanced_disable_swipe_to_switch_video_title">Переключение видео жестом</string>
|
||||
<string name="revanced_disable_swipe_to_switch_video_summary_on">Переключение видео жестами отключены.</string>
|
||||
<string name="revanced_disable_swipe_to_switch_video_summary_off">Переключение видео жестами включены.</string>
|
||||
<string name="revanced_swipe_lowest_value_auto_brightness_overlay_text">Авто</string>
|
||||
@ -1790,19 +1795,19 @@ Shorts
|
||||
<string name="revanced_spoof_streaming_data_type_title">Клиент по умолчанию</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios">iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_music">Музыка iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_unplugged">iOS TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_creator">Редактор Android</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_unplugged">Android TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_title">Эффекты от подмены</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios">• Еще не найдено.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_skip_sync_video_length">• Видео может закончиться 1 сек ранее. При подмене как iOS.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_unplugged">"• Меню \"Звуковая дорожка\" не доступно."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_vr">"• Меню \"Звуковая дорожка\" отсутствует.
|
||||
• Меню \"Постоянный уровень громкости\" недоступно."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_title">Синхронизация видео перед воспроизведением</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_on">"Синхронизация видео перед воспроизведением включена.
|
||||
Точная продолжительность видео."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_off">"Синхронизация видео перед воспроизведением отключена.
|
||||
Округленная продолжительность видео."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_unplugged">• Платные видео и фильмы могут не проигрываться.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android">"• Меню аудио дорожки отсутствует.
|
||||
• Стабильная громкость недоступна.
|
||||
• Отключить принудительные автозвуковые дорожки недоступна."</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_title">Использовать только клиенты Android</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_on">Android клиенты используются для получения потоковых данных.</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_off">Android и iOS клиенты используются для получения потоковых данных.</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>
|
||||
|
@ -1338,6 +1338,10 @@
|
||||
<string name="revanced_replace_channel_handle_title">Замінити ідентифікатор каналу</string>
|
||||
<string name="revanced_replace_channel_handle_summary_on">Використовується назву каналу.</string>
|
||||
<string name="revanced_replace_channel_handle_summary_off">Використовується ідентифікатор каналу.</string>
|
||||
<string name="revanced_restore_shorts_old_player_layout_title">Відновити старий макет плеєра</string>
|
||||
<string name="revanced_restore_shorts_old_player_layout_summary_on">"Старий макет плеєра використовується.
|
||||
Немає полів зверху та знизу плеєра."</string>
|
||||
<string name="revanced_restore_shorts_old_player_layout_summary_off">Старий макет плеєра не використовується.</string>
|
||||
<!-- PreferenceScreen: Swipe controls -->
|
||||
<string name="revanced_preference_screen_swipe_controls_title">Керування жестами</string>
|
||||
<string name="revanced_enable_swipe_lowest_value_auto_brightness_title">Увімкнути автояскравість жестом</string>
|
||||
@ -1384,6 +1388,7 @@
|
||||
<string name="revanced_disable_watch_panel_gestures_title">Вимкнути жести панелі перегляду</string>
|
||||
<string name="revanced_disable_watch_panel_gestures_summary_on">Перехід на повний екран при проведенні вниз під відеоплеєром вимкнено.</string>
|
||||
<string name="revanced_disable_watch_panel_gestures_summary_off">Перехід на повний екран при проведенні вниз під відеоплеєром увімкнено.</string>
|
||||
<string name="revanced_disable_swipe_to_switch_video_title">Вимкнути зміну відео проведенням</string>
|
||||
<string name="revanced_disable_swipe_to_switch_video_summary_on">Проведення вгору / вниз не відтворюватиме наступне / попереднє відео.</string>
|
||||
<string name="revanced_disable_swipe_to_switch_video_summary_off">Проведення вгору / вниз відтворюватиме наступне / попереднє відео.</string>
|
||||
<string name="revanced_swipe_lowest_value_auto_brightness_overlay_text">Авто</string>
|
||||
@ -1768,20 +1773,19 @@
|
||||
<string name="revanced_spoof_streaming_data_type_title">Основний клієнт</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios">iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_music">Музика iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_unplugged">iOS TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_creator">Розробник Android</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_unplugged">Android TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_title">Побічні ефекти імітування</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios">• Ще не знайдено.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_skip_sync_video_length">• Відео можуть закінчуватися на 1 секунду раніше.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_unplugged">"• Меню звукової доріжки відсутнє.
|
||||
• Стабілізація гучності недоступна."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_vr">"• Меню звукової доріжки відсутнє.
|
||||
• Стабілізація гучності недоступна."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_title">Синхронізувати тривалість відео перед відтворенням</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_on">"Довжину відео синхронізується перед відтворенням.
|
||||
Тривалість відео є точним значенням."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_off">"Довжину відео не синхронізується перед відтворенням.
|
||||
Тривалість відео може бути округленим значенням."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_unplugged">• Фільми чи платні відео можуть не відтворюватися.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android">"• Меню звукової доріжки відсутнє.
|
||||
• Стабілізація гучності недоступна.
|
||||
• Вимикання примусових звукових доріжок недоступне."</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_title">Використовувати лише клієнти Android</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_on">Використовується клієнти Android для отримання потокових даних.</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_off">Використовується клієнти Android та iOS для отримання потокових даних.</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>
|
||||
|
@ -982,7 +982,7 @@ Nhấn và giữ để sao chép URL video kèm theo dấu thời gian."</string
|
||||
Nhấn và giữ để sao chép dấu thời gian."</string>
|
||||
<string name="revanced_overlay_button_mute_volume_title">Nút Tắt tiếng</string>
|
||||
<string name="revanced_overlay_button_mute_volume_summary">Nhấn để tắt tiếng của video hiện tại. Nhấn lần nữa để bật trở lại.</string>
|
||||
<string name="revanced_overlay_button_external_downloader_title">Nút trình tải xuống bên ngoài</string>
|
||||
<string name="revanced_overlay_button_external_downloader_title">Nút Trình tải xuống bên ngoài</string>
|
||||
<string name="revanced_overlay_button_external_downloader_summary">Nhấn để khởi chạy trình tải xuống bên ngoài.</string>
|
||||
<string name="revanced_overlay_button_speed_dialog_title">Nút Tốc độ phát</string>
|
||||
<string name="revanced_overlay_button_speed_dialog_summary">"Nhấn để mở hộp thoại Tốc độ phát.
|
||||
@ -1521,7 +1521,7 @@ Nhấp vào đây để xem các bước phát hành khóa API."</string>
|
||||
<string name="revanced_return_youtube_username_youtube_data_api_v3_dialog_message">1. <a href=%1$s>Tạo dự án mới</a>.<br>2. Ấn vào <b>CREATE</b>.<br>3. Đi tới <a href=%2$s>YouTube Data API v3</a>.<br>4. Ấn vào <b>ENABLE</b>.<br>5. Ấn vào <b>CREATE CREDENTIALS</b>.<br>6. Chọn <b>Public data</b>.<br>7. Ấn vào <b>NEXT</b>.<br>8. Sao chép mã khoá API.<br><br>※ Không nên chia sẻ mã khoá API với người khác, vì vậy chúng cũng không có mặt trong mục Nhập/Xuất cài đặt.</string>
|
||||
<!-- PreferenceScreen: SponsorBlock -->
|
||||
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
||||
<string name="revanced_sb_enable_sb">Kích hoạt SponsorBlock</string>
|
||||
<string name="revanced_sb_enable_sb">SponsorBlock</string>
|
||||
<string name="revanced_sb_enable_sb_sum">SponsorBlock là một tiện ích được đóng góp bởi cộng đồng giúp bỏ qua các phần gây khó chịu trong video trên YouTube.</string>
|
||||
<!-- PreferenceScreen: SponsorBlock, PreferenceCategory: Appearance -->
|
||||
<string name="revanced_sb_appearance_category">Giao diện</string>
|
||||
@ -1778,20 +1778,19 @@ Nhấn vào Tiếp tục và cho phép thay đổi lựa chọn tối ưu hoá p
|
||||
<string name="revanced_spoof_streaming_data_type_title">Ứng dụng khách mặc định</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios">iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_music">Music iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_unplugged">TV iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_creator">Android Creator</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_unplugged">Android TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_title">Hạn chế</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios">• Chưa tìm thấy.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_skip_sync_video_length">• Video có thể kết thúc sớm hơn 1 giây.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_unplugged">"• Mục Bản âm thanh bị thiếu.
|
||||
• Âm lượng ổn định không khả dụng."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_vr">"• Mục Bản âm thanh bị thiếu.
|
||||
• Âm lượng ổn định không khả dụng."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_title">Đồng bộ thời lượng video trước khi phát</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_on">"Thời lượng video được đồng bộ trước khi phát.
|
||||
Lúc này thời lượng video là giá trị chính xác."</string>
|
||||
<string name="revanced_spoof_streaming_data_sync_video_length_summary_off">"Thời lượng video không được đồng bộ trước khi phát.
|
||||
Lúc này thời lượng video có thể đã được làm tròn."</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_unplugged">• Phim hoặc video trả phí có thể không phát được.</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android">"• Mục Bản âm thanh bị thiếu.
|
||||
• Âm lượng ổn định không khả dụng.
|
||||
• Tắt buộc bản âm thanh tự động không khả dụng."</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_title">Chỉ sử dụng ứng dụng khách Android</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_on">Ứng dụng khách Android được sử dụng để nạp luồng dữ liệu trực tuyến.</string>
|
||||
<string name="revanced_spoof_streaming_data_android_only_summary_off">Ứng dụng khách Android và iOS được sử dụng để nạp luồng dữ liệu trực tuyến.</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_title">Hiển thị trong Thống kê chi tiết</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_on">Ứng dụng khách sử dụng để nạp luồng dữ liệu trực tuyến được hiển thị trong Thống kê chi tiết.</string>
|
||||
<string name="revanced_spoof_streaming_data_stats_for_nerds_summary_off">Ứng dụng khách sử dụng để nạp luồng dữ liệu trực tuyến đã ẩn trong Thống kê chi tiết.</string>
|
||||
|
@ -1651,8 +1651,6 @@
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_unplugged">Android TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_title">伪装副作用</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_unplugged">"• 音轨菜单缺失"</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_vr">"• 音轨菜单缺失"</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>
|
||||
|
@ -1329,6 +1329,10 @@
|
||||
<string name="revanced_replace_channel_handle_title">更換頻道代號</string>
|
||||
<string name="revanced_replace_channel_handle_summary_on">頻道名稱已使用。</string>
|
||||
<string name="revanced_replace_channel_handle_summary_off">頻道代號已使用。</string>
|
||||
<string name="revanced_restore_shorts_old_player_layout_title">恢復舊版播放器介面</string>
|
||||
<string name="revanced_restore_shorts_old_player_layout_summary_on">"正在使用舊版播放器介面。
|
||||
播放器的上下邊緣無間距。"</string>
|
||||
<string name="revanced_restore_shorts_old_player_layout_summary_off">未使用舊版播放器介面。</string>
|
||||
<!-- PreferenceScreen: Swipe controls -->
|
||||
<string name="revanced_preference_screen_swipe_controls_title">滑動控制</string>
|
||||
<string name="revanced_enable_swipe_lowest_value_auto_brightness_title">啟用自動亮度手勢</string>
|
||||
@ -1372,6 +1376,12 @@
|
||||
<string name="revanced_disable_hdr_auto_brightness_title">停用 HDR 影片自動亮度</string>
|
||||
<string name="revanced_disable_hdr_auto_brightness_summary_on">HDR 影片自動亮度已停用</string>
|
||||
<string name="revanced_disable_hdr_auto_brightness_summary_off">HDR 影片自動亮度已啟用</string>
|
||||
<string name="revanced_disable_watch_panel_gestures_title">停用觀看面板手勢</string>
|
||||
<string name="revanced_disable_watch_panel_gestures_summary_on">透過滑動播放器底部區域切換到全螢幕功能已停用。</string>
|
||||
<string name="revanced_disable_watch_panel_gestures_summary_off">透過滑動播放器底部區域切換到全螢幕功能已啟用。</string>
|
||||
<string name="revanced_disable_swipe_to_switch_video_title">停用滑動切換影片功能</string>
|
||||
<string name="revanced_disable_swipe_to_switch_video_summary_on">向上/向下滑動將不會播放下一個/上一個影片。</string>
|
||||
<string name="revanced_disable_swipe_to_switch_video_summary_off">向上/向下滑動將播放下一個/上一個影片。</string>
|
||||
<string name="revanced_swipe_lowest_value_auto_brightness_overlay_text">自動</string>
|
||||
<!-- PreferenceScreen: Video -->
|
||||
<string name="revanced_preference_screen_video_title">影片</string>
|
||||
@ -1763,12 +1773,16 @@
|
||||
<string name="revanced_spoof_streaming_data_type_title">預設客戶端</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios">iOS</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_music">iOS 音樂</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_ios_unplugged">iOS TV</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_creator">Android 創作者</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_unplugged">Android 電視</string>
|
||||
<string name="revanced_spoof_streaming_data_type_entry_android_vr">Android VR</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_title">偽裝副作用</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios">• 尚未找到。</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_unplugged">"• 音軌選單遺失。"</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android_vr">"• 音軌選單遺失。"</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_ios_unplugged">• 電影或付費影片可能無法播放。</string>
|
||||
<string name="revanced_spoof_streaming_data_side_effects_android">"• 音軌選單缺失。
|
||||
• 穩定音量不可用。
|
||||
• 停用強制自動音軌不可用。"</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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user