Merge branch 'dev' into revanced-extended
@ -19,4 +19,4 @@ jobs:
|
|||||||
content: "<@&1271197877724643461>"
|
content: "<@&1271197877724643461>"
|
||||||
title: "Patches `${{ github.event.release.tag_name }}` has been released!"
|
title: "Patches `${{ github.event.release.tag_name }}` has been released!"
|
||||||
description: |
|
description: |
|
||||||
Click [here]( ${{github.event.repository.html_url }}/releases/tag/${{ github.event.release.tag_name }}) to read the changelog.
|
Click [here](${{ github.event.release.html_url }}) to read the changelog and release notes.
|
76
README.md
@ -60,7 +60,7 @@ ReVanced Extended Patches.
|
|||||||
| `Shorts components` | Adds options to hide or change components related to YouTube Shorts. | 18.29.38 ~ 19.16.39 |
|
| `Shorts components` | Adds options to hide or change components related to YouTube Shorts. | 18.29.38 ~ 19.16.39 |
|
||||||
| `SponsorBlock` | Adds options to enable and configure SponsorBlock, which can skip undesired video segments, such as sponsored content. | 18.29.38 ~ 19.16.39 |
|
| `SponsorBlock` | Adds options to enable and configure SponsorBlock, which can skip undesired video segments, such as sponsored content. | 18.29.38 ~ 19.16.39 |
|
||||||
| `Spoof app version` | Adds options to spoof the YouTube client version. This can be used to restore old UI elements and features. | 18.29.38 ~ 19.16.39 |
|
| `Spoof app version` | Adds options to spoof the YouTube client version. This can be used to restore old UI elements and features. | 18.29.38 ~ 19.16.39 |
|
||||||
| `Spoof client` | Adds options to spoof the client to allow video playback. | 18.29.38 ~ 19.16.39 |
|
| `Spoof streaming data` | Adds options to spoof the streaming data to allow video playback. | 18.29.38 ~ 19.16.39 |
|
||||||
| `Swipe controls` | Adds options for controlling volume and brightness with swiping, and whether to enter fullscreen when swiping down below the player. | 18.29.38 ~ 19.16.39 |
|
| `Swipe controls` | Adds options for controlling volume and brightness with swiping, and whether to enter fullscreen when swiping down below the player. | 18.29.38 ~ 19.16.39 |
|
||||||
| `Theme` | Changes the app's theme to the values specified in options.json. | 18.29.38 ~ 19.16.39 |
|
| `Theme` | Changes the app's theme to the values specified in options.json. | 18.29.38 ~ 19.16.39 |
|
||||||
| `Toolbar components` | Adds options to hide or change components located on the toolbar, such as toolbar buttons, search bar, and header. | 18.29.38 ~ 19.16.39 |
|
| `Toolbar components` | Adds options to hide or change components located on the toolbar, such as toolbar buttons, search bar, and header. | 18.29.38 ~ 19.16.39 |
|
||||||
@ -75,41 +75,41 @@ ReVanced Extended Patches.
|
|||||||
|
|
||||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|:--------:|:--------------:|:-----------------:|
|
|:--------:|:--------------:|:-----------------:|
|
||||||
| `Amoled` | Applies a pure black theme to some components. | 6.29.58 ~ 7.13.52 |
|
| `Amoled` | Applies a pure black theme to some components. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Bitrate default value` | Sets the audio quality to 'Always High' when you first install the app. | 6.29.58 ~ 7.13.52 |
|
| `Bitrate default value` | Sets the audio quality to 'Always High' when you first install the app. | 6.29.58 ~ 7.17.51 |
|
||||||
| `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.29.58 ~ 7.13.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.29.58 ~ 7.17.51 |
|
||||||
| `Certificate spoof` | Enables YouTube Music to work with Android Auto by spoofing the YouTube Music certificate. | 6.29.58 ~ 7.13.52 |
|
| `Certificate spoof` | Enables YouTube Music to work with Android Auto by spoofing the YouTube Music certificate. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Change share sheet` | Add option to change from in-app share sheet to system share sheet. | 6.29.58 ~ 7.13.52 |
|
| `Change share sheet` | Add option to change from in-app share sheet to system share sheet. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Change start page` | Adds an option to set which page the app opens in instead of the homepage. | 6.29.58 ~ 7.13.52 |
|
| `Change start page` | Adds an option to set which page the app opens in instead of the homepage. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Custom branding icon for YouTube Music` | Changes the YouTube Music app icon to the icon specified in options.json. | 6.29.58 ~ 7.13.52 |
|
| `Custom branding icon for YouTube Music` | Changes the YouTube Music app icon to the icon specified in options.json. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Custom branding name for YouTube Music` | Renames the YouTube Music app to the name specified in options.json. | 6.29.58 ~ 7.13.52 |
|
| `Custom branding name for YouTube Music` | Renames the YouTube Music app to the name specified in options.json. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Custom header for YouTube Music` | Applies a custom header in the top left corner within the app. | 6.29.58 ~ 7.13.52 |
|
| `Custom header for YouTube Music` | Applies a custom header in the top left corner within the app. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Disable auto captions` | Adds an option to disable captions from being automatically enabled. | 6.29.58 ~ 7.13.52 |
|
| `Disable Cairo splash animation` | Adds an option to disable Cairo splash animation. | 7.06.54 ~ 7.17.51 |
|
||||||
| `Disable dislike redirection` | Adds an option to disable redirection to the next track when clicking the Dislike button. | 6.29.58 ~ 7.13.52 |
|
| `Disable auto captions` | Adds an option to disable captions from being automatically enabled. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Enable Cairo splash animation` | Adds an option to enable Cairo splash animation. | 7.08.54 ~ 7.13.52 |
|
| `Disable dislike redirection` | Adds an option to disable redirection to the next track when clicking the Dislike button. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Enable OPUS codec` | Adds an options to enable the OPUS audio codec if the player response includes. | 6.29.58 ~ 7.13.52 |
|
| `Enable OPUS codec` | Adds an options to enable the OPUS audio codec if the player response includes. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Enable debug logging` | Adds an option to enable debug logging. | 6.29.58 ~ 7.13.52 |
|
| `Enable debug logging` | Adds an option to enable debug logging. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Enable landscape mode` | Adds an option to enable landscape mode when rotating the screen on phones. | 6.29.58 ~ 7.13.52 |
|
| `Enable landscape mode` | Adds an option to enable landscape mode when rotating the screen on phones. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Flyout menu components` | Adds options to hide or change flyout menu components. | 6.29.58 ~ 7.13.52 |
|
| `Flyout menu components` | Adds options to hide or change flyout menu components. | 6.29.58 ~ 7.17.51 |
|
||||||
| `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.29.58 ~ 7.13.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.29.58 ~ 7.17.51 |
|
||||||
| `Hide account components` | Adds options to hide components related to the account menu. | 6.29.58 ~ 7.13.52 |
|
| `Hide account components` | Adds options to hide components related to the account menu. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Hide action bar components` | Adds options to hide action bar components and replace the offline download button with an external download button. | 6.29.58 ~ 7.13.52 |
|
| `Hide action bar components` | Adds options to hide action bar components and replace the offline download button with an external download button. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Hide ads` | Adds options to hide ads. | 6.29.58 ~ 7.13.52 |
|
| `Hide ads` | Adds options to hide ads. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Hide layout components` | Adds options to hide general layout components. | 6.29.58 ~ 7.13.52 |
|
| `Hide layout components` | Adds options to hide general layout components. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Hide overlay filter` | Removes, at compile time, the dark overlay that appears when player flyout menus are open. | 6.29.58 ~ 7.13.52 |
|
| `Hide overlay filter` | Removes, at compile time, the dark overlay that appears when player flyout menus are open. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Hide player overlay filter` | Removes, at compile time, the dark overlay that appears when single-tapping in the player. | 6.29.58 ~ 7.13.52 |
|
| `Hide player overlay filter` | Removes, at compile time, the dark overlay that appears when single-tapping in the player. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Navigation bar components` | Adds options to hide or change components related to the navigation bar. | 6.29.58 ~ 7.13.52 |
|
| `Navigation bar components` | Adds options to hide or change components related to the navigation bar. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Player components` | Adds options to hide or change components related to the player. | 6.29.58 ~ 7.13.52 |
|
| `Player components` | Adds options to hide or change components related to the player. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Remove background playback restrictions` | Removes restrictions on background playback, including for kids videos. | 6.29.58 ~ 7.13.52 |
|
| `Remove background playback restrictions` | Removes restrictions on background playback, including for kids videos. | 6.29.58 ~ 7.17.51 |
|
||||||
| `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.29.58 ~ 7.13.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.29.58 ~ 7.17.51 |
|
||||||
| `Restore old style library shelf` | Adds an option to return the Library tab to the old style. | 6.29.58 ~ 7.13.52 |
|
| `Restore old style library shelf` | Adds an option to return the Library tab to the old style. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Return YouTube Dislike` | Adds an option to show the dislike count of songs using the Return YouTube Dislike API. | 6.29.58 ~ 7.13.52 |
|
| `Return YouTube Dislike` | Adds an option to show the dislike count of songs using the Return YouTube Dislike API. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Sanitize sharing links` | Adds an option to remove tracking query parameters from URLs when sharing links. | 6.29.58 ~ 7.13.52 |
|
| `Sanitize sharing links` | Adds an option to remove tracking query parameters from URLs when sharing links. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Settings for YouTube Music` | Applies mandatory patches to implement ReVanced Extended settings into the application. | 6.29.58 ~ 7.13.52 |
|
| `Settings for YouTube Music` | Applies mandatory patches to implement ReVanced Extended settings into the application. | 6.29.58 ~ 7.17.51 |
|
||||||
| `SponsorBlock` | Adds options to enable and configure SponsorBlock, which can skip undesired video segments, such as non-music sections. | 6.29.58 ~ 7.13.52 |
|
| `SponsorBlock` | Adds options to enable and configure SponsorBlock, which can skip undesired video segments, such as non-music sections. | 6.29.58 ~ 7.17.51 |
|
||||||
| `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.29.58 ~ 7.13.52 |
|
| `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.29.58 ~ 7.17.51 |
|
||||||
| `Translations for YouTube Music` | Add translations or remove string resources. | 6.29.58 ~ 7.13.52 |
|
| `Translations for YouTube Music` | Add translations or remove string resources. | 6.29.58 ~ 7.17.51 |
|
||||||
| `Video playback` | Adds options to customize settings related to video playback, such as default video quality and playback speed. | 6.29.58 ~ 7.13.52 |
|
| `Video playback` | Adds options to customize settings related to video playback, such as default video quality and playback speed. | 6.29.58 ~ 7.17.51 |
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### [📦 `com.reddit.frontpage`](https://play.google.com/store/apps/details?id=com.reddit.frontpage)
|
### [📦 `com.reddit.frontpage`](https://play.google.com/store/apps/details?id=com.reddit.frontpage)
|
||||||
@ -173,8 +173,8 @@ Example:
|
|||||||
"6.33.52",
|
"6.33.52",
|
||||||
"6.42.55",
|
"6.42.55",
|
||||||
"6.51.53",
|
"6.51.53",
|
||||||
"7.12.52",
|
"7.16.53",
|
||||||
"7.13.52"
|
"7.17.51"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
org.gradle.parallel = true
|
org.gradle.parallel = true
|
||||||
org.gradle.caching = true
|
org.gradle.caching = true
|
||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
version = 4.12.3
|
version = 4.13.1
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
revanced-patcher = "19.3.1"
|
revanced-patcher = "19.3.1"
|
||||||
smali = "3.0.5"
|
smali = "3.0.5"
|
||||||
gson = "2.11.0"
|
gson = "2.11.0"
|
||||||
kotlin = "2.0.0"
|
kotlin = "2.0.20"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
revanced-patcher = { module = "app.revanced:revanced-patcher", version.ref = "revanced-patcher" }
|
revanced-patcher = { module = "app.revanced:revanced-patcher", version.ref = "revanced-patcher" }
|
||||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,7 +1,7 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab
|
distributionSha256Sum=5b9c5eb3f9fc2c94abaea57d90bd78747ca117ddbbf96c859d3741181a12bf2a
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
1503
package-lock.json
generated
@ -3,7 +3,7 @@
|
|||||||
"@saithodev/semantic-release-backmerge": "^4.0.1",
|
"@saithodev/semantic-release-backmerge": "^4.0.1",
|
||||||
"@semantic-release/changelog": "^6.0.3",
|
"@semantic-release/changelog": "^6.0.3",
|
||||||
"@semantic-release/git": "^10.0.1",
|
"@semantic-release/git": "^10.0.1",
|
||||||
"gradle-semantic-release-plugin": "^1.9.1",
|
"gradle-semantic-release-plugin": "^1.9.2",
|
||||||
"semantic-release": "^23.0.2"
|
"semantic-release": "^24.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,5 +212,10 @@ object AdsPatch : BaseBytecodePatch(
|
|||||||
"revanced_hide_premium_renewal",
|
"revanced_hide_premium_renewal",
|
||||||
"true"
|
"true"
|
||||||
)
|
)
|
||||||
|
SettingsPatch.addSwitchPreference(
|
||||||
|
CategoryType.ADS,
|
||||||
|
"revanced_hide_promotion_alert_banner",
|
||||||
|
"true"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
package app.revanced.patches.music.general.autocaptions
|
|
||||||
|
|
||||||
import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
|
||||||
import app.revanced.patches.shared.captions.BaseAutoCaptionsPatch
|
|
||||||
|
|
||||||
object AutoCaptionsBytecodePatch : BaseAutoCaptionsPatch(GENERAL_CLASS_DESCRIPTOR, false)
|
|
@ -1,22 +1,38 @@
|
|||||||
package app.revanced.patches.music.general.autocaptions
|
package app.revanced.patches.music.general.autocaptions
|
||||||
|
|
||||||
import app.revanced.patcher.data.ResourceContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||||
|
import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||||
import app.revanced.patches.music.utils.settings.CategoryType
|
import app.revanced.patches.music.utils.settings.CategoryType
|
||||||
import app.revanced.patches.music.utils.settings.SettingsPatch
|
import app.revanced.patches.music.utils.settings.SettingsPatch
|
||||||
import app.revanced.util.patch.BaseResourcePatch
|
import app.revanced.patches.shared.fingerprints.SubtitleTrackFingerprint
|
||||||
|
import app.revanced.util.patch.BaseBytecodePatch
|
||||||
|
import app.revanced.util.resultOrThrow
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object AutoCaptionsPatch : BaseResourcePatch(
|
object AutoCaptionsPatch : BaseBytecodePatch(
|
||||||
name = "Disable auto captions",
|
name = "Disable auto captions",
|
||||||
description = "Adds an option to disable captions from being automatically enabled.",
|
description = "Adds an option to disable captions from being automatically enabled.",
|
||||||
dependencies = setOf(
|
dependencies = setOf(SettingsPatch::class),
|
||||||
AutoCaptionsBytecodePatch::class,
|
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||||
SettingsPatch::class,
|
fingerprints = setOf(SubtitleTrackFingerprint),
|
||||||
),
|
|
||||||
compatiblePackages = COMPATIBLE_PACKAGE
|
|
||||||
) {
|
) {
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
|
|
||||||
|
SubtitleTrackFingerprint.resultOrThrow().mutableMethod.apply {
|
||||||
|
val index = implementation!!.instructions.lastIndex
|
||||||
|
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||||
|
|
||||||
|
addInstructions(
|
||||||
|
index, """
|
||||||
|
invoke-static {v$register}, $GENERAL_CLASS_DESCRIPTOR->disableAutoCaptions(Z)Z
|
||||||
|
move-result v$register
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
SettingsPatch.addSwitchPreference(
|
SettingsPatch.addSwitchPreference(
|
||||||
CategoryType.GENERAL,
|
CategoryType.GENERAL,
|
||||||
|
@ -9,8 +9,10 @@ import app.revanced.patches.music.utils.settings.ResourceUtils.setIconType
|
|||||||
import app.revanced.util.ResourceGroup
|
import app.revanced.util.ResourceGroup
|
||||||
import app.revanced.util.Utils.trimIndentMultiline
|
import app.revanced.util.Utils.trimIndentMultiline
|
||||||
import app.revanced.util.copyResources
|
import app.revanced.util.copyResources
|
||||||
|
import app.revanced.util.getResourceGroup
|
||||||
import app.revanced.util.patch.BaseResourcePatch
|
import app.revanced.util.patch.BaseResourcePatch
|
||||||
import app.revanced.util.underBarOrThrow
|
import app.revanced.util.underBarOrThrow
|
||||||
|
import org.w3c.dom.Element
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
|
|
||||||
@ -71,17 +73,11 @@ object CustomBrandingIconPatch : BaseResourcePatch(
|
|||||||
"record"
|
"record"
|
||||||
).map { "$it.png" }.toTypedArray()
|
).map { "$it.png" }.toTypedArray()
|
||||||
|
|
||||||
private val launcherIconResourceGroups = mipmapDirectories.map { directory ->
|
private val launcherIconResourceGroups =
|
||||||
ResourceGroup(
|
mipmapDirectories.getResourceGroup(launcherIconResourceFileNames)
|
||||||
directory, *launcherIconResourceFileNames
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val splashIconResourceGroups = largeDrawableDirectories.map { directory ->
|
private val splashIconResourceGroups =
|
||||||
ResourceGroup(
|
largeDrawableDirectories.getResourceGroup(splashIconResourceFileNames)
|
||||||
directory, *splashIconResourceFileNames
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val AppIcon = stringPatchOption(
|
private val AppIcon = stringPatchOption(
|
||||||
key = "AppIcon",
|
key = "AppIcon",
|
||||||
@ -110,6 +106,20 @@ object CustomBrandingIconPatch : BaseResourcePatch(
|
|||||||
required = true
|
required = true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val RestoreOldSplashIcon by booleanPatchOption(
|
||||||
|
key = "RestoreOldSplashIcon",
|
||||||
|
default = false,
|
||||||
|
title = "Restore old splash icon",
|
||||||
|
description = """
|
||||||
|
Restore the old style splash icon.
|
||||||
|
|
||||||
|
If you enable both the old style splash icon and the Cairo splash animation,
|
||||||
|
|
||||||
|
Old style splash icon will appear first and then the Cairo splash animation will start.
|
||||||
|
""".trimIndentMultiline(),
|
||||||
|
required = true
|
||||||
|
)
|
||||||
|
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
|
|
||||||
// Check patch options first.
|
// Check patch options first.
|
||||||
@ -117,6 +127,7 @@ object CustomBrandingIconPatch : BaseResourcePatch(
|
|||||||
.underBarOrThrow()
|
.underBarOrThrow()
|
||||||
|
|
||||||
val appIconResourcePath = "music/branding/$appIcon"
|
val appIconResourcePath = "music/branding/$appIcon"
|
||||||
|
val youtubeMusicIconResourcePath = "music/branding/youtube_music"
|
||||||
|
|
||||||
// Check if a custom path is used in the patch options.
|
// Check if a custom path is used in the patch options.
|
||||||
if (!availableIcon.containsValue(appIcon)) {
|
if (!availableIcon.containsValue(appIcon)) {
|
||||||
@ -160,13 +171,51 @@ object CustomBrandingIconPatch : BaseResourcePatch(
|
|||||||
context.copyResources("$appIconResourcePath/monochrome", resourceGroup)
|
context.copyResources("$appIconResourcePath/monochrome", resourceGroup)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Change splash icon.
|
||||||
|
if (RestoreOldSplashIcon == true) {
|
||||||
|
var oldSplashIconNotExists: Boolean
|
||||||
|
|
||||||
|
context.xmlEditor["res/drawable/splash_screen.xml"].use { editor ->
|
||||||
|
editor.file.apply {
|
||||||
|
val node = getElementsByTagName("layer-list").item(0)
|
||||||
|
oldSplashIconNotExists = (node as Element)
|
||||||
|
.getElementsByTagName("item")
|
||||||
|
.length == 1
|
||||||
|
|
||||||
|
if (oldSplashIconNotExists) {
|
||||||
|
createElement("item").also { itemNode ->
|
||||||
|
itemNode.appendChild(
|
||||||
|
createElement("bitmap").also { bitmapNode ->
|
||||||
|
bitmapNode.setAttribute("android:gravity", "center")
|
||||||
|
bitmapNode.setAttribute("android:src", "@drawable/record")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
node.appendChild(itemNode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (oldSplashIconNotExists) {
|
||||||
|
splashIconResourceGroups.let { resourceGroups ->
|
||||||
|
resourceGroups.forEach {
|
||||||
|
context.copyResources("$youtubeMusicIconResourcePath/splash", it, createDirectoryIfNotExist = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Change splash icon.
|
// Change splash icon.
|
||||||
if (ChangeSplashIcon == true) {
|
if (ChangeSplashIcon == true) {
|
||||||
|
// Some resources have been removed in the latest YouTube Music.
|
||||||
|
// For compatibility, use try...catch.
|
||||||
|
try {
|
||||||
splashIconResourceGroups.let { resourceGroups ->
|
splashIconResourceGroups.let { resourceGroups ->
|
||||||
resourceGroups.forEach {
|
resourceGroups.forEach {
|
||||||
context.copyResources("$appIconResourcePath/splash", it)
|
context.copyResources("$appIconResourcePath/splash", it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (_: Exception) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setIconType(appIcon)
|
setIconType(appIcon)
|
||||||
|
@ -2,7 +2,6 @@ package app.revanced.patches.music.misc.splash
|
|||||||
|
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchException
|
|
||||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
import app.revanced.patches.music.misc.splash.fingerprints.CairoSplashAnimationConfigFingerprint
|
import app.revanced.patches.music.misc.splash.fingerprints.CairoSplashAnimationConfigFingerprint
|
||||||
@ -12,15 +11,15 @@ import app.revanced.patches.music.utils.settings.SettingsPatch
|
|||||||
import app.revanced.util.literalInstructionBooleanHook
|
import app.revanced.util.literalInstructionBooleanHook
|
||||||
|
|
||||||
@Patch(
|
@Patch(
|
||||||
name = "Enable Cairo splash animation",
|
name = "Disable Cairo splash animation",
|
||||||
description = "Adds an option to enable Cairo splash animation.",
|
description = "Adds an option to disable Cairo splash animation.",
|
||||||
dependencies = [SettingsPatch::class],
|
dependencies = [SettingsPatch::class],
|
||||||
compatiblePackages = [
|
compatiblePackages = [
|
||||||
CompatiblePackage(
|
CompatiblePackage(
|
||||||
"com.google.android.apps.youtube.music",
|
"com.google.android.apps.youtube.music",
|
||||||
[
|
[
|
||||||
"7.08.54",
|
"7.06.54",
|
||||||
"7.13.52",
|
"7.17.51",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
@ -34,17 +33,17 @@ object CairoSplashAnimationPatch : BytecodePatch(
|
|||||||
CairoSplashAnimationConfigFingerprint.result?.let {
|
CairoSplashAnimationConfigFingerprint.result?.let {
|
||||||
CairoSplashAnimationConfigFingerprint.literalInstructionBooleanHook(
|
CairoSplashAnimationConfigFingerprint.literalInstructionBooleanHook(
|
||||||
45635386,
|
45635386,
|
||||||
"$MISC_PATH/CairoSplashAnimationPatch;->enableCairoSplashAnimation()Z"
|
"$MISC_PATH/CairoSplashAnimationPatch;->disableCairoSplashAnimation(Z)Z"
|
||||||
)
|
)
|
||||||
|
|
||||||
SettingsPatch.addSwitchPreference(
|
SettingsPatch.addSwitchPreference(
|
||||||
CategoryType.MISC,
|
CategoryType.MISC,
|
||||||
"revanced_enable_cairo_splash_animation",
|
"revanced_disable_cairo_splash_animation",
|
||||||
"false"
|
"false"
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
?: throw PatchException("WARNING: This patch is not supported in this version. Use YouTube Music 7.08.54 or later.")
|
?: println("WARNING: This patch is not supported in this version. Use YouTube Music 7.06.54 or later.")
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,8 @@ import app.revanced.patches.music.player.components.fingerprints.QuickSeekOverla
|
|||||||
import app.revanced.patches.music.player.components.fingerprints.RemixGenericButtonFingerprint
|
import app.revanced.patches.music.player.components.fingerprints.RemixGenericButtonFingerprint
|
||||||
import app.revanced.patches.music.player.components.fingerprints.RepeatTrackFingerprint
|
import app.revanced.patches.music.player.components.fingerprints.RepeatTrackFingerprint
|
||||||
import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint
|
import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint
|
||||||
|
import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint.indexOfImageViewInstruction
|
||||||
|
import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint.indexOfOrdinalInstruction
|
||||||
import app.revanced.patches.music.player.components.fingerprints.SwipeToCloseFingerprint
|
import app.revanced.patches.music.player.components.fingerprints.SwipeToCloseFingerprint
|
||||||
import app.revanced.patches.music.player.components.fingerprints.SwitchToggleColorFingerprint
|
import app.revanced.patches.music.player.components.fingerprints.SwitchToggleColorFingerprint
|
||||||
import app.revanced.patches.music.player.components.fingerprints.ZenModeFingerprint
|
import app.revanced.patches.music.player.components.fingerprints.ZenModeFingerprint
|
||||||
@ -740,28 +742,53 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
|||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
rememberShuffleStateObjectClass = definingClass
|
rememberShuffleStateObjectClass = definingClass
|
||||||
|
|
||||||
val startIndex = it.scanResult.patternScanResult!!.startIndex
|
val constIndex = getWideLiteralInstructionIndex(45468)
|
||||||
val endIndex = it.scanResult.patternScanResult!!.endIndex
|
val iGetObjectIndex = getTargetIndexOrThrow(constIndex, Opcode.IGET_OBJECT)
|
||||||
val imageViewIndex =
|
val checkCastIndex = getTargetIndexOrThrow(iGetObjectIndex, Opcode.CHECK_CAST)
|
||||||
getTargetIndexWithFieldReferenceTypeOrThrow("Landroid/widget/ImageView;")
|
|
||||||
|
val ordinalIndex = indexOfOrdinalInstruction(this)
|
||||||
|
val imageViewIndex = indexOfImageViewInstruction(this)
|
||||||
|
|
||||||
|
val iGetObjectReference =
|
||||||
|
getInstruction<ReferenceInstruction>(iGetObjectIndex).reference
|
||||||
|
val invokeInterfaceReference =
|
||||||
|
getInstruction<ReferenceInstruction>(iGetObjectIndex + 1).reference
|
||||||
|
val checkCastReference =
|
||||||
|
getInstruction<ReferenceInstruction>(checkCastIndex).reference
|
||||||
|
val getOrdinalClassReference =
|
||||||
|
getInstruction<ReferenceInstruction>(checkCastIndex + 1).reference
|
||||||
|
val ordinalReference =
|
||||||
|
getInstruction<ReferenceInstruction>(ordinalIndex).reference
|
||||||
|
|
||||||
val shuffleReference1 = getInstruction<ReferenceInstruction>(startIndex).reference
|
|
||||||
val shuffleReference2 =
|
|
||||||
getInstruction<ReferenceInstruction>(startIndex + 1).reference
|
|
||||||
val shuffleReference3 = getInstruction<ReferenceInstruction>(endIndex).reference
|
|
||||||
val shuffleFieldReference = shuffleReference3 as FieldReference
|
|
||||||
rememberShuffleStateImageViewReference =
|
rememberShuffleStateImageViewReference =
|
||||||
getInstruction<ReferenceInstruction>(imageViewIndex).reference
|
getInstruction<ReferenceInstruction>(imageViewIndex).reference
|
||||||
|
|
||||||
rememberShuffleStateShuffleStateLabel = """
|
rememberShuffleStateShuffleStateLabel = """
|
||||||
iget-object v1, v0, $shuffleReference1
|
iget-object v1, v0, $iGetObjectReference
|
||||||
invoke-interface {v1}, $shuffleReference2
|
invoke-interface {v1}, $invokeInterfaceReference
|
||||||
move-result-object v1
|
move-result-object v1
|
||||||
check-cast v1, ${shuffleFieldReference.definingClass}
|
check-cast v1, $checkCastReference
|
||||||
iget-object v1, v1, $shuffleReference3
|
|
||||||
invoke-virtual {v1}, ${shuffleFieldReference.type}->ordinal()I
|
|
||||||
move-result v1
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
rememberShuffleStateShuffleStateLabel += if (getInstruction(checkCastIndex + 1).opcode == Opcode.INVOKE_VIRTUAL) {
|
||||||
|
// YouTube Music 7.16.52+
|
||||||
|
"""
|
||||||
|
invoke-virtual {v1}, $getOrdinalClassReference
|
||||||
|
move-result-object v1
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
} else {
|
||||||
|
"""
|
||||||
|
iget-object v1, v1, $getOrdinalClassReference
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
|
|
||||||
|
rememberShuffleStateShuffleStateLabel += """
|
||||||
|
invoke-virtual {v1}, $ordinalReference
|
||||||
|
move-result v1
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
}
|
}
|
||||||
|
|
||||||
val constructorMethod =
|
val constructorMethod =
|
||||||
@ -770,7 +797,7 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
|||||||
|
|
||||||
constructorMethod.apply {
|
constructorMethod.apply {
|
||||||
addInstruction(
|
addInstruction(
|
||||||
implementation!!.instructions.size - 1,
|
implementation!!.instructions.lastIndex,
|
||||||
"sput-object p0, $MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR->shuffleClass:$rememberShuffleStateObjectClass"
|
"sput-object p0, $MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR->shuffleClass:$rememberShuffleStateObjectClass"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -836,9 +863,10 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
|||||||
sget-object v0, $MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR->shuffleClass:$rememberShuffleStateObjectClass
|
sget-object v0, $MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR->shuffleClass:$rememberShuffleStateObjectClass
|
||||||
""" + rememberShuffleStateShuffleStateLabel + """
|
""" + rememberShuffleStateShuffleStateLabel + """
|
||||||
iget-object v3, v0, $rememberShuffleStateImageViewReference
|
iget-object v3, v0, $rememberShuffleStateImageViewReference
|
||||||
invoke-virtual {v3}, Landroid/widget/ImageView;->performClick()Z
|
if-eqz v3, :dont_shuffle
|
||||||
|
invoke-virtual {v3}, Landroid/view/View;->callOnClick()Z
|
||||||
if-eqz v1, :dont_shuffle
|
if-eqz v1, :dont_shuffle
|
||||||
invoke-virtual {v3}, Landroid/widget/ImageView;->performClick()Z
|
invoke-virtual {v3}, Landroid/view/View;->callOnClick()Z
|
||||||
:dont_shuffle
|
:dont_shuffle
|
||||||
return-void
|
return-void
|
||||||
"""
|
"""
|
||||||
|
@ -2,20 +2,38 @@ package app.revanced.patches.music.player.components.fingerprints
|
|||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint.indexOfImageViewInstruction
|
||||||
|
import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint.indexOfOrdinalInstruction
|
||||||
|
import app.revanced.util.containsWideLiteralInstructionIndex
|
||||||
|
import app.revanced.util.getReference
|
||||||
|
import app.revanced.util.indexOfFirstInstruction
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.iface.Method
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
|
|
||||||
internal object ShuffleClassReferenceFingerprint : MethodFingerprint(
|
internal object ShuffleClassReferenceFingerprint : MethodFingerprint(
|
||||||
returnType = "V",
|
returnType = "V",
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
parameters = emptyList(),
|
parameters = emptyList(),
|
||||||
opcodes = listOf(
|
strings = listOf("Unknown shuffle mode"),
|
||||||
Opcode.IGET_OBJECT,
|
customFingerprint = { methodDef, _ ->
|
||||||
Opcode.INVOKE_INTERFACE,
|
methodDef.containsWideLiteralInstructionIndex(45468) &&
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
indexOfOrdinalInstruction(methodDef) >= 0 &&
|
||||||
Opcode.CHECK_CAST,
|
indexOfImageViewInstruction(methodDef) >= 0
|
||||||
Opcode.IGET_OBJECT
|
}
|
||||||
),
|
) {
|
||||||
strings = listOf("Unknown shuffle mode")
|
fun indexOfOrdinalInstruction(methodDef: Method) =
|
||||||
)
|
methodDef.indexOfFirstInstruction {
|
||||||
|
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||||
|
getReference<MethodReference>()?.name == "ordinal"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun indexOfImageViewInstruction(methodDef: Method) =
|
||||||
|
methodDef.indexOfFirstInstruction {
|
||||||
|
opcode == Opcode.IGET_OBJECT &&
|
||||||
|
getReference<FieldReference>()?.type == "Landroid/widget/ImageView;"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -11,8 +11,8 @@ object Constants {
|
|||||||
"6.33.52", // This is the latest version with the legacy code of YouTube Music.
|
"6.33.52", // This is the latest version with the legacy code of YouTube Music.
|
||||||
"6.42.55", // This is the latest version that supports Android 7.0
|
"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
|
"6.51.53", // This is the latest version of YouTube Music 6.xx.xx
|
||||||
"7.12.52", // This was the latest version that was supported by the previous patch.
|
"7.16.53", // This was the latest version that was supported by the previous patch.
|
||||||
"7.13.52", // This is the latest version supported by the RVX patch.
|
"7.17.51", // This is the latest version supported by the RVX patch.
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -5,6 +5,7 @@ import app.revanced.patches.music.utils.fix.client.SpoofUserAgentPatch
|
|||||||
import app.revanced.patches.music.utils.fix.fileprovider.FileProviderPatch
|
import app.revanced.patches.music.utils.fix.fileprovider.FileProviderPatch
|
||||||
import app.revanced.patches.music.utils.integrations.IntegrationsPatch
|
import app.revanced.patches.music.utils.integrations.IntegrationsPatch
|
||||||
import app.revanced.patches.music.utils.mainactivity.fingerprints.MainActivityFingerprint
|
import app.revanced.patches.music.utils.mainactivity.fingerprints.MainActivityFingerprint
|
||||||
|
import app.revanced.patches.music.utils.settings.SettingsPatch
|
||||||
import app.revanced.patches.shared.gms.BaseGmsCoreSupportPatch
|
import app.revanced.patches.shared.gms.BaseGmsCoreSupportPatch
|
||||||
import app.revanced.patches.shared.gms.BaseGmsCoreSupportResourcePatch.Companion.ORIGINAL_PACKAGE_NAME_YOUTUBE_MUSIC
|
import app.revanced.patches.shared.gms.BaseGmsCoreSupportResourcePatch.Companion.ORIGINAL_PACKAGE_NAME_YOUTUBE_MUSIC
|
||||||
|
|
||||||
@ -15,7 +16,8 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
|
|||||||
integrationsPatchDependency = IntegrationsPatch::class,
|
integrationsPatchDependency = IntegrationsPatch::class,
|
||||||
dependencies = setOf(
|
dependencies = setOf(
|
||||||
SpoofUserAgentPatch::class,
|
SpoofUserAgentPatch::class,
|
||||||
FileProviderPatch::class
|
FileProviderPatch::class,
|
||||||
|
SettingsPatch::class
|
||||||
),
|
),
|
||||||
gmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch,
|
gmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch,
|
||||||
compatiblePackages = COMPATIBLE_PACKAGE
|
compatiblePackages = COMPATIBLE_PACKAGE
|
||||||
|
@ -23,7 +23,7 @@ object GmsCoreSupportResourcePatch : BaseGmsCoreSupportResourcePatch(
|
|||||||
context.addMicroGPreference(
|
context.addMicroGPreference(
|
||||||
CategoryType.MISC.value,
|
CategoryType.MISC.value,
|
||||||
"gms_core_settings",
|
"gms_core_settings",
|
||||||
GmsCoreVendorGroupId.valueOrThrow(),
|
GmsCoreVendorGroupId.valueOrThrow() + ".android.gms",
|
||||||
GMS_CORE_SETTINGS_ACTIVITY
|
GMS_CORE_SETTINGS_ACTIVITY
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import app.revanced.patcher.fingerprint.MethodFingerprintResult
|
|||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchException
|
import app.revanced.patcher.patch.PatchException
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||||
import app.revanced.patcher.util.smali.toInstructions
|
import app.revanced.patcher.util.smali.toInstructions
|
||||||
@ -22,20 +23,26 @@ import app.revanced.patches.music.video.information.fingerprints.VideoLengthFing
|
|||||||
import app.revanced.patches.music.video.information.fingerprints.VideoQualityListFingerprint
|
import app.revanced.patches.music.video.information.fingerprints.VideoQualityListFingerprint
|
||||||
import app.revanced.patches.music.video.information.fingerprints.VideoQualityTextFingerprint
|
import app.revanced.patches.music.video.information.fingerprints.VideoQualityTextFingerprint
|
||||||
import app.revanced.patches.music.video.videoid.VideoIdPatch
|
import app.revanced.patches.music.video.videoid.VideoIdPatch
|
||||||
|
import app.revanced.patches.shared.fingerprints.MdxPlayerDirectorSetVideoStageFingerprint
|
||||||
import app.revanced.util.addFieldAndInstructions
|
import app.revanced.util.addFieldAndInstructions
|
||||||
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.getTargetIndexWithFieldReferenceTypeReversedOrThrow
|
import app.revanced.util.getTargetIndexWithFieldReferenceTypeReversedOrThrow
|
||||||
import app.revanced.util.getTargetIndexWithMethodReferenceNameReversedOrThrow
|
import app.revanced.util.getTargetIndexWithMethodReferenceNameReversedOrThrow
|
||||||
import app.revanced.util.getWalkerMethod
|
import app.revanced.util.getWalkerMethod
|
||||||
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
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.FieldReference
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodImplementation
|
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodImplementation
|
||||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||||
|
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||||
|
|
||||||
@Patch(
|
@Patch(
|
||||||
dependencies = [
|
dependencies = [
|
||||||
@ -46,6 +53,7 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
|||||||
@Suppress("MemberVisibilityCanBePrivate")
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
object VideoInformationPatch : BytecodePatch(
|
object VideoInformationPatch : BytecodePatch(
|
||||||
setOf(
|
setOf(
|
||||||
|
MdxPlayerDirectorSetVideoStageFingerprint,
|
||||||
PlayerControllerSetTimeReferenceFingerprint,
|
PlayerControllerSetTimeReferenceFingerprint,
|
||||||
PlaybackSpeedParentFingerprint,
|
PlaybackSpeedParentFingerprint,
|
||||||
SeekBarConstructorFingerprint,
|
SeekBarConstructorFingerprint,
|
||||||
@ -57,6 +65,23 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||||
"$SHARED_PATH/VideoInformation;"
|
"$SHARED_PATH/VideoInformation;"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used in [VideoEndFingerprint] and [MdxPlayerDirectorSetVideoStageFingerprint].
|
||||||
|
* Since both classes are inherited from the same class,
|
||||||
|
* [VideoEndFingerprint] and [MdxPlayerDirectorSetVideoStageFingerprint] always have the same [seekSourceEnumType] and [seekSourceMethodName].
|
||||||
|
*/
|
||||||
|
private var seekSourceEnumType = ""
|
||||||
|
private var seekSourceMethodName = ""
|
||||||
|
|
||||||
|
private lateinit var videoInformationMutableClass: MutableClass
|
||||||
|
private lateinit var context: BytecodeContext
|
||||||
|
|
||||||
|
private lateinit var playerConstructorMethod: MutableMethod
|
||||||
|
private var playerConstructorInsertIndex = -1
|
||||||
|
|
||||||
|
private lateinit var mdxConstructorMethod: MutableMethod
|
||||||
|
private var mdxConstructorInsertIndex = -1
|
||||||
|
|
||||||
private lateinit var videoTimeConstructorMethod: MutableMethod
|
private lateinit var videoTimeConstructorMethod: MutableMethod
|
||||||
private var videoTimeConstructorInsertIndex = 2
|
private var videoTimeConstructorInsertIndex = 2
|
||||||
|
|
||||||
@ -64,15 +89,14 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
lateinit var rectangleFieldName: String
|
lateinit var rectangleFieldName: String
|
||||||
internal lateinit var playbackSpeedResult: MethodFingerprintResult
|
internal lateinit var playbackSpeedResult: MethodFingerprintResult
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext) {
|
private fun addSeekInterfaceMethods(
|
||||||
val videoInformationMutableClass =
|
result: MethodFingerprintResult,
|
||||||
context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass
|
seekMethodName: String,
|
||||||
|
methodName: String,
|
||||||
VideoEndFingerprint.resultOrThrow().let {
|
fieldName: String
|
||||||
it.mutableMethod.apply {
|
) {
|
||||||
val seekSourceEnumType = parameterTypes[1].toString()
|
result.mutableMethod.apply {
|
||||||
|
result.mutableClass.methods.add(
|
||||||
it.mutableClass.methods.add(
|
|
||||||
ImmutableMethod(
|
ImmutableMethod(
|
||||||
definingClass,
|
definingClass,
|
||||||
"seekTo",
|
"seekTo",
|
||||||
@ -83,8 +107,9 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
null,
|
null,
|
||||||
ImmutableMethodImplementation(
|
ImmutableMethodImplementation(
|
||||||
4, """
|
4, """
|
||||||
|
# first enum (field a) is SEEK_SOURCE_UNKNOWN
|
||||||
sget-object v0, $seekSourceEnumType->a:$seekSourceEnumType
|
sget-object v0, $seekSourceEnumType->a:$seekSourceEnumType
|
||||||
invoke-virtual {p0, p1, p2, v0}, ${definingClass}->${name}(J$seekSourceEnumType)Z
|
invoke-virtual {p0, p1, p2, v0}, ${definingClass}->$seekMethodName(J$seekSourceEnumType)Z
|
||||||
move-result p1
|
move-result p1
|
||||||
return p1
|
return p1
|
||||||
""".toInstructions(),
|
""".toInstructions(),
|
||||||
@ -107,8 +132,8 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
|
|
||||||
videoInformationMutableClass.addFieldAndInstructions(
|
videoInformationMutableClass.addFieldAndInstructions(
|
||||||
context,
|
context,
|
||||||
"overrideVideoTime",
|
methodName,
|
||||||
"videoInformationClass",
|
fieldName,
|
||||||
definingClass,
|
definingClass,
|
||||||
smaliInstructions,
|
smaliInstructions,
|
||||||
true
|
true
|
||||||
@ -116,6 +141,59 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun execute(context: BytecodeContext) {
|
||||||
|
this.context = context
|
||||||
|
videoInformationMutableClass =
|
||||||
|
context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass
|
||||||
|
|
||||||
|
VideoEndFingerprint.resultOrThrow().let {
|
||||||
|
it.mutableMethod.apply {
|
||||||
|
playerConstructorMethod =
|
||||||
|
it.mutableClass.methods.first { method -> MethodUtil.isConstructor(method) }
|
||||||
|
|
||||||
|
playerConstructorInsertIndex =
|
||||||
|
playerConstructorMethod.indexOfFirstInstructionOrThrow {
|
||||||
|
opcode == Opcode.INVOKE_DIRECT && getReference<MethodReference>()?.name == "<init>"
|
||||||
|
} + 1
|
||||||
|
|
||||||
|
// hook the player controller for use through integrations
|
||||||
|
onCreateHook(INTEGRATIONS_CLASS_DESCRIPTOR, "initialize")
|
||||||
|
|
||||||
|
seekSourceEnumType = parameterTypes[1].toString()
|
||||||
|
seekSourceMethodName = name
|
||||||
|
|
||||||
|
// Create integrations interface methods.
|
||||||
|
addSeekInterfaceMethods(
|
||||||
|
it,
|
||||||
|
seekSourceMethodName,
|
||||||
|
"overrideVideoTime",
|
||||||
|
"videoInformationClass"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MdxPlayerDirectorSetVideoStageFingerprint.resultOrThrow().let {
|
||||||
|
it.mutableMethod.apply {
|
||||||
|
mdxConstructorMethod =
|
||||||
|
it.mutableClass.methods.first { method -> MethodUtil.isConstructor(method) }
|
||||||
|
|
||||||
|
mdxConstructorInsertIndex = mdxConstructorMethod.indexOfFirstInstructionOrThrow {
|
||||||
|
opcode == Opcode.INVOKE_DIRECT && getReference<MethodReference>()?.name == "<init>"
|
||||||
|
} + 1
|
||||||
|
|
||||||
|
// hook the MDX director for use through integrations
|
||||||
|
onCreateHookMdx(INTEGRATIONS_CLASS_DESCRIPTOR, "initializeMdx")
|
||||||
|
|
||||||
|
// Create integrations interface methods.
|
||||||
|
addSeekInterfaceMethods(
|
||||||
|
it,
|
||||||
|
seekSourceMethodName,
|
||||||
|
"overrideMDXVideoTime",
|
||||||
|
"videoInformationMDXClass"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the video time method
|
* Set the video time method
|
||||||
*/
|
*/
|
||||||
@ -246,6 +324,33 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
private fun MutableMethod.insertTimeHook(insertIndex: Int, descriptor: String) =
|
private fun MutableMethod.insertTimeHook(insertIndex: Int, descriptor: String) =
|
||||||
insert(insertIndex, "p1, p2", descriptor)
|
insert(insertIndex, "p1, p2", descriptor)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook the player controller. Called when a video is opened or the current video is changed.
|
||||||
|
*
|
||||||
|
* Note: This hook is called very early and is called before the video id, video time, video length,
|
||||||
|
* and many other data fields are set.
|
||||||
|
*
|
||||||
|
* @param targetMethodClass The descriptor for the class to invoke when the player controller is created.
|
||||||
|
* @param targetMethodName The name of the static method to invoke when the player controller is created.
|
||||||
|
*/
|
||||||
|
internal fun onCreateHook(targetMethodClass: String, targetMethodName: String) =
|
||||||
|
playerConstructorMethod.addInstruction(
|
||||||
|
playerConstructorInsertIndex++,
|
||||||
|
"invoke-static { }, $targetMethodClass->$targetMethodName()V"
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook the MDX player director. Called when playing videos while casting to a big screen device.
|
||||||
|
*
|
||||||
|
* @param targetMethodClass The descriptor for the class to invoke when the player controller is created.
|
||||||
|
* @param targetMethodName The name of the static method to invoke when the player controller is created.
|
||||||
|
*/
|
||||||
|
internal fun onCreateHookMdx(targetMethodClass: String, targetMethodName: String) =
|
||||||
|
mdxConstructorMethod.addInstruction(
|
||||||
|
mdxConstructorInsertIndex++,
|
||||||
|
"invoke-static { }, $targetMethodClass->$targetMethodName()V"
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook the video time.
|
* Hook the video time.
|
||||||
* The hook is usually called once per second.
|
* The hook is usually called once per second.
|
||||||
|
@ -115,10 +115,22 @@ object VideoPlaybackPatch : BaseBytecodePatch(
|
|||||||
"revanced_remember_playback_speed_last_selected",
|
"revanced_remember_playback_speed_last_selected",
|
||||||
"true"
|
"true"
|
||||||
)
|
)
|
||||||
|
SettingsPatch.addSwitchPreference(
|
||||||
|
CategoryType.VIDEO,
|
||||||
|
"revanced_remember_playback_speed_last_selected_toast",
|
||||||
|
"true",
|
||||||
|
"revanced_remember_playback_speed_last_selected"
|
||||||
|
)
|
||||||
SettingsPatch.addSwitchPreference(
|
SettingsPatch.addSwitchPreference(
|
||||||
CategoryType.VIDEO,
|
CategoryType.VIDEO,
|
||||||
"revanced_remember_video_quality_last_selected",
|
"revanced_remember_video_quality_last_selected",
|
||||||
"true"
|
"true"
|
||||||
)
|
)
|
||||||
|
SettingsPatch.addSwitchPreference(
|
||||||
|
CategoryType.VIDEO,
|
||||||
|
"revanced_remember_video_quality_last_selected_toast",
|
||||||
|
"true",
|
||||||
|
"revanced_remember_video_quality_last_selected"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
package app.revanced.patches.shared.captions
|
|
||||||
|
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
|
||||||
import app.revanced.patcher.util.smali.ExternalLabel
|
|
||||||
import app.revanced.patches.shared.captions.fingerprints.SubtitleButtonControllerFingerprint
|
|
||||||
import app.revanced.patches.shared.captions.fingerprints.SubtitleTrackFingerprint
|
|
||||||
import app.revanced.patches.shared.fingerprints.StartVideoInformerFingerprint
|
|
||||||
import app.revanced.util.resultOrThrow
|
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
|
||||||
|
|
||||||
abstract class BaseAutoCaptionsPatch(
|
|
||||||
private val classDescriptor: String,
|
|
||||||
private val captionsButtonStatus: Boolean
|
|
||||||
) : BytecodePatch(
|
|
||||||
setOf(
|
|
||||||
StartVideoInformerFingerprint,
|
|
||||||
SubtitleButtonControllerFingerprint,
|
|
||||||
SubtitleTrackFingerprint
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
override fun execute(context: BytecodeContext) {
|
|
||||||
|
|
||||||
SubtitleTrackFingerprint.resultOrThrow().mutableMethod.apply {
|
|
||||||
if (captionsButtonStatus) {
|
|
||||||
addInstructionsWithLabels(
|
|
||||||
0, """
|
|
||||||
invoke-static {}, $classDescriptor->disableAutoCaptions()Z
|
|
||||||
move-result v0
|
|
||||||
if-eqz v0, :disabled
|
|
||||||
const/4 v0, 0x1
|
|
||||||
return v0
|
|
||||||
""", ExternalLabel("disabled", getInstruction(0))
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
val index = implementation!!.instructions.lastIndex
|
|
||||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
|
||||||
|
|
||||||
addInstructions(
|
|
||||||
index, """
|
|
||||||
invoke-static {v$register}, $classDescriptor->disableAutoCaptions(Z)Z
|
|
||||||
move-result v$register
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!captionsButtonStatus) return
|
|
||||||
|
|
||||||
mapOf(
|
|
||||||
StartVideoInformerFingerprint to 0,
|
|
||||||
SubtitleButtonControllerFingerprint to 1
|
|
||||||
).forEach { (fingerprint, enabled) ->
|
|
||||||
fingerprint.resultOrThrow().mutableMethod.addInstructions(
|
|
||||||
0, """
|
|
||||||
const/4 v0, 0x$enabled
|
|
||||||
invoke-static {v0}, $classDescriptor->setCaptionsButtonStatus(Z)V
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
package app.revanced.patches.shared.captions.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
internal object SubtitleButtonControllerFingerprint : MethodFingerprint(
|
|
||||||
returnType = "V",
|
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
|
||||||
parameters = listOf("Lcom/google/android/libraries/youtube/player/subtitles/model/SubtitleTrack;"),
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.IGET_OBJECT,
|
|
||||||
Opcode.IF_NEZ,
|
|
||||||
Opcode.RETURN_VOID,
|
|
||||||
Opcode.IGET_BOOLEAN,
|
|
||||||
Opcode.CONST_4,
|
|
||||||
Opcode.IF_NEZ,
|
|
||||||
Opcode.CONST,
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.IGET_OBJECT,
|
|
||||||
)
|
|
||||||
)
|
|
@ -1,4 +1,4 @@
|
|||||||
package app.revanced.patches.youtube.video.information.fingerprints
|
package app.revanced.patches.shared.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package app.revanced.patches.shared.captions.fingerprints
|
package app.revanced.patches.shared.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
@ -45,9 +45,9 @@ abstract class BaseGmsCoreSupportResourcePatch(
|
|||||||
default = true,
|
default = true,
|
||||||
title = "Check GmsCore",
|
title = "Check GmsCore",
|
||||||
description = """
|
description = """
|
||||||
Check if GmsCore is installed on the device when the app starts.
|
Check if GmsCore is installed on the device and has battery optimizations disabled when the app starts.
|
||||||
|
|
||||||
If GmsCore is not installed on the device, the app won't work, so don't disable it if possible.
|
If GmsCore is not installed the app will not work, so disabling this is not recommended.
|
||||||
""".trimIndentMultiline(),
|
""".trimIndentMultiline(),
|
||||||
required = true,
|
required = true,
|
||||||
)
|
)
|
||||||
|
@ -170,10 +170,10 @@ object LithoFilterPatch : BytecodePatch(
|
|||||||
addFilter = { classDescriptor ->
|
addFilter = { classDescriptor ->
|
||||||
addInstructions(
|
addInstructions(
|
||||||
0, """
|
0, """
|
||||||
new-instance v1, $classDescriptor
|
new-instance v0, $classDescriptor
|
||||||
invoke-direct {v1}, $classDescriptor-><init>()V
|
invoke-direct {v0}, $classDescriptor-><init>()V
|
||||||
const/16 v2, ${filterCount++}
|
const/16 v3, ${filterCount++}
|
||||||
aput-object v1, v0, v2
|
aput-object v0, v2, v3
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -184,8 +184,9 @@ object LithoFilterPatch : BytecodePatch(
|
|||||||
override fun close() = LithoFilterPatchConstructorFingerprint.result!!
|
override fun close() = LithoFilterPatchConstructorFingerprint.result!!
|
||||||
.mutableMethod.addInstructions(
|
.mutableMethod.addInstructions(
|
||||||
0, """
|
0, """
|
||||||
const/16 v0, $filterCount
|
const/16 v1, $filterCount
|
||||||
new-array v0, v0, [$INTEGRATIONS_FILER_CLASS_DESCRIPTOR
|
new-array v2, v1, [$INTEGRATIONS_FILER_CLASS_DESCRIPTOR
|
||||||
|
const/4 v1, 0x1
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -7,7 +7,7 @@ import com.android.tools.smali.dexlib2.AccessFlags
|
|||||||
|
|
||||||
internal object LithoFilterPatchConstructorFingerprint : MethodFingerprint(
|
internal object LithoFilterPatchConstructorFingerprint : MethodFingerprint(
|
||||||
returnType = "V",
|
returnType = "V",
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.CONSTRUCTOR,
|
accessFlags = AccessFlags.STATIC or AccessFlags.CONSTRUCTOR,
|
||||||
customFingerprint = { methodDef, _ ->
|
customFingerprint = { methodDef, _ ->
|
||||||
methodDef.definingClass == "$COMPONENTS_PATH/LithoFilterPatch;"
|
methodDef.definingClass == "$COMPONENTS_PATH/LithoFilterPatch;"
|
||||||
}
|
}
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.general.autocaptions
|
|
||||||
|
|
||||||
import app.revanced.patches.shared.captions.BaseAutoCaptionsPatch
|
|
||||||
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
|
||||||
|
|
||||||
object AutoCaptionsBytecodePatch : BaseAutoCaptionsPatch(GENERAL_CLASS_DESCRIPTOR, true)
|
|
@ -1,24 +1,57 @@
|
|||||||
package app.revanced.patches.youtube.general.autocaptions
|
package app.revanced.patches.youtube.general.autocaptions
|
||||||
|
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
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.util.smali.ExternalLabel
|
||||||
|
import app.revanced.patches.shared.fingerprints.SubtitleTrackFingerprint
|
||||||
|
import app.revanced.patches.youtube.general.autocaptions.fingerprints.StoryboardRendererDecoderRecommendedLevelFingerprint
|
||||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||||
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
|
import app.revanced.patches.youtube.utils.fingerprints.StartVideoInformerFingerprint
|
||||||
|
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||||
import app.revanced.util.patch.BaseBytecodePatch
|
import app.revanced.util.patch.BaseBytecodePatch
|
||||||
|
import app.revanced.util.resultOrThrow
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object AutoCaptionsPatch : BaseBytecodePatch(
|
object AutoCaptionsPatch : BaseBytecodePatch(
|
||||||
name = "Disable auto captions",
|
name = "Disable auto captions",
|
||||||
description = "Adds an option to disable captions from being automatically enabled.",
|
description = "Adds an option to disable captions from being automatically enabled.",
|
||||||
dependencies = setOf(
|
dependencies = setOf(SettingsPatch::class),
|
||||||
AutoCaptionsBytecodePatch::class,
|
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||||
PlayerTypeHookPatch::class,
|
fingerprints = setOf(
|
||||||
SettingsPatch::class
|
SubtitleTrackFingerprint,
|
||||||
),
|
StartVideoInformerFingerprint,
|
||||||
compatiblePackages = COMPATIBLE_PACKAGE
|
StoryboardRendererDecoderRecommendedLevelFingerprint,
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
|
|
||||||
|
SubtitleTrackFingerprint.resultOrThrow().mutableMethod.apply {
|
||||||
|
addInstructionsWithLabels(
|
||||||
|
0, """
|
||||||
|
invoke-static {}, $GENERAL_CLASS_DESCRIPTOR->disableAutoCaptions()Z
|
||||||
|
move-result v0
|
||||||
|
if-eqz v0, :disabled
|
||||||
|
const/4 v0, 0x1
|
||||||
|
return v0
|
||||||
|
""", ExternalLabel("disabled", getInstruction(0))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
mapOf(
|
||||||
|
StartVideoInformerFingerprint to 0,
|
||||||
|
StoryboardRendererDecoderRecommendedLevelFingerprint to 1
|
||||||
|
).forEach { (fingerprint, enabled) ->
|
||||||
|
fingerprint.resultOrThrow().mutableMethod.addInstructions(
|
||||||
|
0, """
|
||||||
|
const/4 v0, 0x$enabled
|
||||||
|
invoke-static {v0}, $GENERAL_CLASS_DESCRIPTOR->setCaptionsButtonStatus(Z)V
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add settings
|
* Add settings
|
||||||
*/
|
*/
|
||||||
|
@ -1,23 +1,12 @@
|
|||||||
package app.revanced.patches.youtube.utils.storyboard.fingerprints
|
package app.revanced.patches.youtube.general.autocaptions.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolves to the same method as [StoryboardRendererDecoderSpecFingerprint].
|
|
||||||
*/
|
|
||||||
internal object StoryboardRendererDecoderRecommendedLevelFingerprint : MethodFingerprint(
|
internal object StoryboardRendererDecoderRecommendedLevelFingerprint : MethodFingerprint(
|
||||||
returnType = "V",
|
returnType = "V",
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
parameters = listOf("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"),
|
parameters = listOf("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"),
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.INVOKE_INTERFACE,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.IPUT_OBJECT,
|
|
||||||
Opcode.INVOKE_INTERFACE,
|
|
||||||
Opcode.MOVE_RESULT
|
|
||||||
),
|
|
||||||
strings = listOf("#-1#")
|
strings = listOf("#-1#")
|
||||||
)
|
)
|
@ -125,7 +125,8 @@ object DownloadActionsPatch : BaseBytecodePatch(
|
|||||||
reference?.definingClass == OFFLINE_PLAYLIST_ENDPOINT_OUTER_CLASS_DESCRIPTOR &&
|
reference?.definingClass == OFFLINE_PLAYLIST_ENDPOINT_OUTER_CLASS_DESCRIPTOR &&
|
||||||
reference.type == "Ljava/lang/String;"
|
reference.type == "Ljava/lang/String;"
|
||||||
}
|
}
|
||||||
val playlistIdReference = getInstruction<ReferenceInstruction>(playlistIdIndex).reference
|
val playlistIdReference =
|
||||||
|
getInstruction<ReferenceInstruction>(playlistIdIndex).reference
|
||||||
|
|
||||||
val targetIndex = indexOfFirstInstructionOrThrow {
|
val targetIndex = indexOfFirstInstructionOrThrow {
|
||||||
opcode == Opcode.CHECK_CAST &&
|
opcode == Opcode.CHECK_CAST &&
|
||||||
@ -134,13 +135,15 @@ object DownloadActionsPatch : BaseBytecodePatch(
|
|||||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||||
|
|
||||||
addInstructionsWithLabels(
|
addInstructionsWithLabels(
|
||||||
targetIndex + 1, """
|
targetIndex + 1,
|
||||||
|
"""
|
||||||
iget-object v$freeRegister, v$targetRegister, $playlistIdReference
|
iget-object v$freeRegister, v$targetRegister, $playlistIdReference
|
||||||
invoke-static {v$freeRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->inAppPlaylistDownloadMenuOnClick(Ljava/lang/String;)Z
|
invoke-static {v$freeRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->inAppPlaylistDownloadMenuOnClick(Ljava/lang/String;)Z
|
||||||
move-result v$freeRegister
|
move-result v$freeRegister
|
||||||
if-eqz v$freeRegister, :show_native_downloader
|
if-eqz v$freeRegister, :show_native_downloader
|
||||||
return-void
|
return-void
|
||||||
""", ExternalLabel("show_native_downloader", getInstruction(targetIndex + 1))
|
""",
|
||||||
|
ExternalLabel("show_native_downloader", getInstruction(targetIndex + 1))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import app.revanced.util.Utils.trimIndentMultiline
|
|||||||
import app.revanced.util.copyFile
|
import app.revanced.util.copyFile
|
||||||
import app.revanced.util.copyResources
|
import app.revanced.util.copyResources
|
||||||
import app.revanced.util.copyXmlNode
|
import app.revanced.util.copyXmlNode
|
||||||
|
import app.revanced.util.getResourceGroup
|
||||||
import app.revanced.util.patch.BaseResourcePatch
|
import app.revanced.util.patch.BaseResourcePatch
|
||||||
import app.revanced.util.underBarOrThrow
|
import app.revanced.util.underBarOrThrow
|
||||||
|
|
||||||
@ -73,12 +74,6 @@ object CustomBrandingIconPatch : BaseResourcePatch(
|
|||||||
"avd_anim"
|
"avd_anim"
|
||||||
).map { "$it.xml" }.toTypedArray()
|
).map { "$it.xml" }.toTypedArray()
|
||||||
|
|
||||||
private fun List<String>.getResourceGroup(fileNames: Array<String>) = map { directory ->
|
|
||||||
ResourceGroup(
|
|
||||||
directory, *fileNames
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val launcherIconResourceGroups =
|
private val launcherIconResourceGroups =
|
||||||
mipmapDirectories.getResourceGroup(launcherIconResourceFileNames)
|
mipmapDirectories.getResourceGroup(launcherIconResourceFileNames)
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ object TranslationsPatch : BaseResourcePatch(
|
|||||||
) {
|
) {
|
||||||
// Array of supported translations, each represented by its language code.
|
// Array of supported translations, each represented by its language code.
|
||||||
private val TRANSLATIONS = arrayOf(
|
private val TRANSLATIONS = arrayOf(
|
||||||
"ar", "el-rGR", "es-rES", "de-rDE", "fr-rFR", "hu-rHU", "it-rIT", "ja-rJP", "ko-rKR",
|
"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"
|
"pl-rPL", "pt-rBR", "ru-rRU", "tr-rTR", "uk-rUA", "vi-rVN", "zh-rCN", "zh-rTW"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -276,7 +276,7 @@ object VisualPreferencesIconsPatch : BaseResourcePatch(
|
|||||||
"revanced_preference_screen_seekbar",
|
"revanced_preference_screen_seekbar",
|
||||||
"revanced_preference_screen_settings_menu",
|
"revanced_preference_screen_settings_menu",
|
||||||
"revanced_preference_screen_shorts_player",
|
"revanced_preference_screen_shorts_player",
|
||||||
"revanced_preference_screen_spoof_client",
|
"revanced_preference_screen_spoof_streaming_data",
|
||||||
"revanced_preference_screen_toolbar",
|
"revanced_preference_screen_toolbar",
|
||||||
"revanced_preference_screen_video_description",
|
"revanced_preference_screen_video_description",
|
||||||
"revanced_preference_screen_video_filter",
|
"revanced_preference_screen_video_filter",
|
||||||
|
@ -13,6 +13,7 @@ import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PAC
|
|||||||
import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH
|
import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH
|
||||||
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
|
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
|
||||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||||
|
import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
||||||
import app.revanced.util.getWalkerMethod
|
import app.revanced.util.getWalkerMethod
|
||||||
import app.revanced.util.patch.BaseBytecodePatch
|
import app.revanced.util.patch.BaseBytecodePatch
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
@ -26,6 +27,7 @@ object BackgroundPlaybackPatch : BaseBytecodePatch(
|
|||||||
description = "Removes restrictions on background playback, including for music and kids videos.",
|
description = "Removes restrictions on background playback, including for music and kids videos.",
|
||||||
dependencies = setOf(
|
dependencies = setOf(
|
||||||
PlayerTypeHookPatch::class,
|
PlayerTypeHookPatch::class,
|
||||||
|
VideoInformationPatch::class,
|
||||||
SettingsPatch::class
|
SettingsPatch::class
|
||||||
),
|
),
|
||||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||||
|
@ -9,7 +9,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
|||||||
import app.revanced.patcher.patch.PatchException
|
import app.revanced.patcher.patch.PatchException
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
import app.revanced.patcher.util.smali.ExternalLabel
|
import app.revanced.patcher.util.smali.ExternalLabel
|
||||||
import app.revanced.patches.shared.fingerprints.StartVideoInformerFingerprint
|
|
||||||
import app.revanced.patches.shared.litho.LithoFilterPatch
|
import app.revanced.patches.shared.litho.LithoFilterPatch
|
||||||
import app.revanced.patches.youtube.player.components.fingerprints.CrowdfundingBoxFingerprint
|
import app.revanced.patches.youtube.player.components.fingerprints.CrowdfundingBoxFingerprint
|
||||||
import app.revanced.patches.youtube.player.components.fingerprints.EngagementPanelControllerFingerprint
|
import app.revanced.patches.youtube.player.components.fingerprints.EngagementPanelControllerFingerprint
|
||||||
@ -34,6 +33,7 @@ import app.revanced.patches.youtube.player.components.fingerprints.WatermarkPare
|
|||||||
import app.revanced.patches.youtube.player.speedoverlay.SpeedOverlayPatch
|
import app.revanced.patches.youtube.player.speedoverlay.SpeedOverlayPatch
|
||||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||||
import app.revanced.patches.youtube.utils.controlsoverlay.ControlsOverlayConfigPatch
|
import app.revanced.patches.youtube.utils.controlsoverlay.ControlsOverlayConfigPatch
|
||||||
|
import app.revanced.patches.youtube.utils.fingerprints.StartVideoInformerFingerprint
|
||||||
import app.revanced.patches.youtube.utils.fingerprints.YouTubeControlsOverlayFingerprint
|
import app.revanced.patches.youtube.utils.fingerprints.YouTubeControlsOverlayFingerprint
|
||||||
import app.revanced.patches.youtube.utils.fix.suggestedvideoendscreen.SuggestedVideoEndScreenPatch
|
import app.revanced.patches.youtube.utils.fix.suggestedvideoendscreen.SuggestedVideoEndScreenPatch
|
||||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH
|
import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH
|
||||||
@ -46,6 +46,7 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.Scrim
|
|||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.SeekUndoEduOverlayStub
|
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.SeekUndoEduOverlayStub
|
||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TapBloomView
|
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TapBloomView
|
||||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||||
|
import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
||||||
import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT
|
import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT
|
||||||
import app.revanced.util.getTargetIndexOrThrow
|
import app.revanced.util.getTargetIndexOrThrow
|
||||||
import app.revanced.util.getTargetIndexReversedOrThrow
|
import app.revanced.util.getTargetIndexReversedOrThrow
|
||||||
@ -73,6 +74,7 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
|||||||
SharedResourceIdPatch::class,
|
SharedResourceIdPatch::class,
|
||||||
SpeedOverlayPatch::class,
|
SpeedOverlayPatch::class,
|
||||||
SuggestedVideoEndScreenPatch::class,
|
SuggestedVideoEndScreenPatch::class,
|
||||||
|
VideoInformationPatch::class
|
||||||
),
|
),
|
||||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||||
fingerprints = setOf(
|
fingerprints = setOf(
|
||||||
@ -172,6 +174,12 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
|||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
|
// region patch for disable auto switch mix playlists
|
||||||
|
|
||||||
|
VideoInformationPatch.hook("$PLAYER_CLASS_DESCRIPTOR->disableAutoSwitchMixPlaylists(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZ)V")
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
// region patch for hide channel watermark
|
// region patch for hide channel watermark
|
||||||
|
|
||||||
WatermarkFingerprint.resolve(
|
WatermarkFingerprint.resolve(
|
||||||
|
@ -36,8 +36,9 @@ object OverlayButtonsPatch : BaseResourcePatch(
|
|||||||
),
|
),
|
||||||
compatiblePackages = COMPATIBLE_PACKAGE
|
compatiblePackages = COMPATIBLE_PACKAGE
|
||||||
) {
|
) {
|
||||||
private const val DEFAULT_MARGIN = "0.0dip"
|
private const val MARGIN_NONE = "0.0dip"
|
||||||
private const val WIDER_MARGIN = "6.0dip"
|
private const val MARGIN_DEFAULT = "2.5dip"
|
||||||
|
private const val MARGIN_WIDER = "5.0dip"
|
||||||
|
|
||||||
private const val DEFAULT_ICON = "bold"
|
private const val DEFAULT_ICON = "bold"
|
||||||
|
|
||||||
@ -58,10 +59,11 @@ object OverlayButtonsPatch : BaseResourcePatch(
|
|||||||
// Option to set bottom margin
|
// Option to set bottom margin
|
||||||
private val BottomMargin = stringPatchOption(
|
private val BottomMargin = stringPatchOption(
|
||||||
key = "BottomMargin",
|
key = "BottomMargin",
|
||||||
default = DEFAULT_MARGIN,
|
default = MARGIN_DEFAULT,
|
||||||
values = mapOf(
|
values = mapOf(
|
||||||
"Wider" to WIDER_MARGIN,
|
"Default" to MARGIN_DEFAULT,
|
||||||
"Default" to DEFAULT_MARGIN
|
"None" to MARGIN_NONE,
|
||||||
|
"Wider" to MARGIN_WIDER,
|
||||||
),
|
),
|
||||||
title = "Bottom margin",
|
title = "Bottom margin",
|
||||||
description = "The bottom margin for the overlay buttons and timestamp.",
|
description = "The bottom margin for the overlay buttons and timestamp.",
|
||||||
@ -233,6 +235,7 @@ object OverlayButtonsPatch : BaseResourcePatch(
|
|||||||
ResourceGroup(
|
ResourceGroup(
|
||||||
"drawable-$dpi",
|
"drawable-$dpi",
|
||||||
"yt_outline_gear_white_24.png",
|
"yt_outline_gear_white_24.png",
|
||||||
|
"yt_outline_chevron_down_white_24.png",
|
||||||
"quantum_ic_closed_caption_off_grey600_24.png",
|
"quantum_ic_closed_caption_off_grey600_24.png",
|
||||||
"quantum_ic_closed_caption_off_white_24.png",
|
"quantum_ic_closed_caption_off_white_24.png",
|
||||||
"quantum_ic_closed_caption_white_24.png"
|
"quantum_ic_closed_caption_white_24.png"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package app.revanced.patches.shared.fingerprints
|
package app.revanced.patches.youtube.utils.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
@ -1,496 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.fix.client
|
|
||||||
|
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.patch.PatchException
|
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
|
||||||
import app.revanced.patcher.util.smali.ExternalLabel
|
|
||||||
import app.revanced.patches.shared.fingerprints.CreatePlayerRequestBodyWithModelFingerprint
|
|
||||||
import app.revanced.patches.shared.fingerprints.CreatePlayerRequestBodyWithModelFingerprint.indexOfModelInstruction
|
|
||||||
import app.revanced.patches.youtube.misc.backgroundplayback.BackgroundPlaybackPatch
|
|
||||||
import app.revanced.patches.youtube.utils.compatibility.Constants
|
|
||||||
import app.revanced.patches.youtube.utils.fingerprints.PlaybackRateBottomSheetBuilderFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.fix.client.fingerprints.BuildInitPlaybackRequestFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.fix.client.fingerprints.BuildPlaybackStatsRequestURIFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.fix.client.fingerprints.BuildPlayerRequestURIFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.fix.client.fingerprints.CreatePlaybackSpeedMenuItemFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.fix.client.fingerprints.CreatePlayerRequestBodyFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.fix.client.fingerprints.CreatePlayerRequestBodyWithVersionReleaseFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.fix.client.fingerprints.CreatePlayerRequestBodyWithVersionReleaseFingerprint.indexOfBuildInstruction
|
|
||||||
import app.revanced.patches.youtube.utils.fix.client.fingerprints.NerdsStatsVideoFormatBuilderFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.fix.client.fingerprints.OrganicPlaybackContextModelFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.fix.client.fingerprints.PlayerGestureConfigSyntheticFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.fix.client.fingerprints.PlayerResponseModelBackgroundAudioPlaybackFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.fix.client.fingerprints.SetPlayerRequestClientTypeFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.fix.client.fingerprints.UserAgentHeaderBuilderFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH
|
|
||||||
import app.revanced.patches.youtube.utils.integrations.Constants.PATCH_STATUS_CLASS_DESCRIPTOR
|
|
||||||
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
|
|
||||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
|
||||||
import app.revanced.patches.youtube.utils.storyboard.StoryboardHookPatch
|
|
||||||
import app.revanced.patches.youtube.utils.trackingurlhook.TrackingUrlHookPatch
|
|
||||||
import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
|
||||||
import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch
|
|
||||||
import app.revanced.util.getReference
|
|
||||||
import app.revanced.util.getStringInstructionIndex
|
|
||||||
import app.revanced.util.getWalkerMethod
|
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
|
||||||
import app.revanced.util.patch.BaseBytecodePatch
|
|
||||||
import app.revanced.util.resultOrThrow
|
|
||||||
import app.revanced.util.updatePatchStatus
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
|
|
||||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
|
||||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
|
||||||
|
|
||||||
object SpoofClientPatch : BaseBytecodePatch(
|
|
||||||
name = "Spoof client",
|
|
||||||
description = "Adds options to spoof the client to allow video playback.",
|
|
||||||
dependencies = setOf(
|
|
||||||
// Required since iOS livestream fix partially enables background playback.
|
|
||||||
BackgroundPlaybackPatch::class,
|
|
||||||
PlayerTypeHookPatch::class,
|
|
||||||
|
|
||||||
TrackingUrlHookPatch::class,
|
|
||||||
PlayerResponseMethodHookPatch::class,
|
|
||||||
SettingsPatch::class,
|
|
||||||
VideoInformationPatch::class,
|
|
||||||
SpoofUserAgentPatch::class,
|
|
||||||
StoryboardHookPatch::class,
|
|
||||||
),
|
|
||||||
compatiblePackages = Constants.COMPATIBLE_PACKAGE,
|
|
||||||
fingerprints = setOf(
|
|
||||||
// Client type spoof.
|
|
||||||
BuildInitPlaybackRequestFingerprint,
|
|
||||||
BuildPlayerRequestURIFingerprint,
|
|
||||||
SetPlayerRequestClientTypeFingerprint,
|
|
||||||
CreatePlayerRequestBodyFingerprint,
|
|
||||||
CreatePlayerRequestBodyWithModelFingerprint,
|
|
||||||
CreatePlayerRequestBodyWithVersionReleaseFingerprint,
|
|
||||||
UserAgentHeaderBuilderFingerprint,
|
|
||||||
|
|
||||||
// Player gesture config.
|
|
||||||
PlayerGestureConfigSyntheticFingerprint,
|
|
||||||
|
|
||||||
// Player speed menu item.
|
|
||||||
CreatePlaybackSpeedMenuItemFingerprint,
|
|
||||||
PlaybackRateBottomSheetBuilderFingerprint,
|
|
||||||
|
|
||||||
// Livestream audio only background playback.
|
|
||||||
PlayerResponseModelBackgroundAudioPlaybackFingerprint,
|
|
||||||
|
|
||||||
// Watch history.
|
|
||||||
BuildPlaybackStatsRequestURIFingerprint,
|
|
||||||
OrganicPlaybackContextModelFingerprint,
|
|
||||||
|
|
||||||
// Nerds stats video format.
|
|
||||||
NerdsStatsVideoFormatBuilderFingerprint,
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
|
||||||
"$MISC_PATH/SpoofClientPatch;"
|
|
||||||
private const val CLIENT_INFO_CLASS_DESCRIPTOR =
|
|
||||||
"Lcom/google/protos/youtube/api/innertube/InnertubeContext\$ClientInfo;"
|
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext) {
|
|
||||||
|
|
||||||
var settingArray = arrayOf(
|
|
||||||
"SETTINGS: SPOOF_CLIENT"
|
|
||||||
)
|
|
||||||
|
|
||||||
// region Block /initplayback requests to fall back to /get_watch requests.
|
|
||||||
|
|
||||||
BuildInitPlaybackRequestFingerprint.resultOrThrow().let {
|
|
||||||
it.mutableMethod.apply {
|
|
||||||
val moveUriStringIndex = it.scanResult.patternScanResult!!.startIndex
|
|
||||||
val targetRegister =
|
|
||||||
getInstruction<OneRegisterInstruction>(moveUriStringIndex).registerA
|
|
||||||
|
|
||||||
addInstructions(
|
|
||||||
moveUriStringIndex + 1,
|
|
||||||
"""
|
|
||||||
invoke-static { v$targetRegister }, $INTEGRATIONS_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.resultOrThrow().let {
|
|
||||||
it.mutableMethod.apply {
|
|
||||||
val invokeToStringIndex = it.scanResult.patternScanResult!!.startIndex
|
|
||||||
val uriRegister =
|
|
||||||
getInstruction<FiveRegisterInstruction>(invokeToStringIndex).registerC
|
|
||||||
|
|
||||||
addInstructions(
|
|
||||||
invokeToStringIndex,
|
|
||||||
"""
|
|
||||||
invoke-static { v$uriRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->blockGetWatchRequest(Landroid/net/Uri;)Landroid/net/Uri;
|
|
||||||
move-result-object v$uriRegister
|
|
||||||
""",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Get field references to be used below.
|
|
||||||
|
|
||||||
val (clientInfoField, clientInfoClientTypeField, clientInfoClientVersionField) =
|
|
||||||
SetPlayerRequestClientTypeFingerprint.resultOrThrow().let { result ->
|
|
||||||
with(result.mutableMethod) {
|
|
||||||
// Field in the player request object that holds the client info object.
|
|
||||||
val clientInfoField = getInstructions().find { instruction ->
|
|
||||||
// requestMessage.clientInfo = clientInfoBuilder.build();
|
|
||||||
instruction.opcode == Opcode.IPUT_OBJECT &&
|
|
||||||
instruction.getReference<FieldReference>()?.type == CLIENT_INFO_CLASS_DESCRIPTOR
|
|
||||||
}?.getReference<FieldReference>()
|
|
||||||
?: throw PatchException("Could not find clientInfoField")
|
|
||||||
|
|
||||||
// Client info object's client type field.
|
|
||||||
val clientInfoClientTypeField =
|
|
||||||
getInstruction(result.scanResult.patternScanResult!!.endIndex)
|
|
||||||
.getReference<FieldReference>()
|
|
||||||
?: throw PatchException("Could not find clientInfoClientTypeField")
|
|
||||||
|
|
||||||
val clientInfoVersionIndex = getStringInstructionIndex("10.29")
|
|
||||||
val clientInfoVersionRegister =
|
|
||||||
getInstruction<OneRegisterInstruction>(clientInfoVersionIndex).registerA
|
|
||||||
val clientInfoClientVersionFieldIndex = implementation!!.instructions.let {
|
|
||||||
clientInfoVersionIndex + it.subList(clientInfoVersionIndex, it.size - 1)
|
|
||||||
.indexOfFirst { instruction ->
|
|
||||||
instruction.opcode == Opcode.IPUT_OBJECT
|
|
||||||
&& (instruction as TwoRegisterInstruction).registerA == clientInfoVersionRegister
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Client info object's client version field.
|
|
||||||
val clientInfoClientVersionField =
|
|
||||||
getInstruction(clientInfoClientVersionFieldIndex)
|
|
||||||
.getReference<FieldReference>()
|
|
||||||
?: throw PatchException("Could not find clientInfoClientVersionField")
|
|
||||||
|
|
||||||
Triple(clientInfoField, clientInfoClientTypeField, clientInfoClientVersionField)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val clientInfoClientModelField =
|
|
||||||
CreatePlayerRequestBodyWithModelFingerprint.resultOrThrow().mutableMethod.let {
|
|
||||||
val instructions = it.getInstructions()
|
|
||||||
val getClientModelIndex = indexOfModelInstruction(it)
|
|
||||||
|
|
||||||
// The next IPUT_OBJECT instruction after getting the client model is setting the client model field.
|
|
||||||
instructions.subList(
|
|
||||||
getClientModelIndex,
|
|
||||||
instructions.size,
|
|
||||||
).find { instruction ->
|
|
||||||
val reference = instruction.getReference<FieldReference>()
|
|
||||||
instruction.opcode == Opcode.IPUT_OBJECT
|
|
||||||
&& reference?.definingClass == CLIENT_INFO_CLASS_DESCRIPTOR
|
|
||||||
&& reference.type == "Ljava/lang/String;"
|
|
||||||
}?.getReference<FieldReference>()
|
|
||||||
?: throw PatchException("Could not find clientInfoClientModelField")
|
|
||||||
}
|
|
||||||
|
|
||||||
val clientInfoOsVersionField =
|
|
||||||
CreatePlayerRequestBodyWithVersionReleaseFingerprint.resultOrThrow().mutableMethod.let {
|
|
||||||
val buildIndex = indexOfBuildInstruction(it)
|
|
||||||
val instructions = it.getInstructions()
|
|
||||||
|
|
||||||
instructions.subList(
|
|
||||||
buildIndex - 5,
|
|
||||||
buildIndex,
|
|
||||||
).find { instruction ->
|
|
||||||
val reference = instruction.getReference<FieldReference>()
|
|
||||||
instruction.opcode == Opcode.IPUT_OBJECT
|
|
||||||
&& reference?.definingClass == CLIENT_INFO_CLASS_DESCRIPTOR
|
|
||||||
&& reference.type == "Ljava/lang/String;"
|
|
||||||
}?.getReference<FieldReference>()
|
|
||||||
?: throw PatchException("Could not find clientInfoOsVersionField")
|
|
||||||
}
|
|
||||||
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Spoof client type for /player requests.
|
|
||||||
|
|
||||||
CreatePlayerRequestBodyFingerprint.resultOrThrow().let {
|
|
||||||
it.mutableMethod.apply {
|
|
||||||
val setClientInfoMethodName = "setClientInfo"
|
|
||||||
val checkCastIndex = it.scanResult.patternScanResult!!.startIndex
|
|
||||||
|
|
||||||
val checkCastInstruction = getInstruction<OneRegisterInstruction>(checkCastIndex)
|
|
||||||
val requestMessageInstanceRegister = checkCastInstruction.registerA
|
|
||||||
val clientInfoContainerClassName =
|
|
||||||
checkCastInstruction.getReference<TypeReference>()!!.type
|
|
||||||
|
|
||||||
addInstruction(
|
|
||||||
checkCastIndex + 1,
|
|
||||||
"invoke-static { v$requestMessageInstanceRegister }," +
|
|
||||||
" $definingClass->$setClientInfoMethodName($clientInfoContainerClassName)V",
|
|
||||||
)
|
|
||||||
|
|
||||||
// Change client info to use the spoofed values.
|
|
||||||
// Do this in a helper method, to remove the need of picking out multiple free registers from the hooked code.
|
|
||||||
it.mutableClass.methods.add(
|
|
||||||
ImmutableMethod(
|
|
||||||
definingClass,
|
|
||||||
setClientInfoMethodName,
|
|
||||||
listOf(
|
|
||||||
ImmutableMethodParameter(
|
|
||||||
clientInfoContainerClassName,
|
|
||||||
annotations,
|
|
||||||
"clientInfoContainer"
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"V",
|
|
||||||
AccessFlags.PRIVATE or AccessFlags.STATIC,
|
|
||||||
annotations,
|
|
||||||
null,
|
|
||||||
MutableMethodImplementation(3),
|
|
||||||
).toMutable().apply {
|
|
||||||
addInstructions(
|
|
||||||
"""
|
|
||||||
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->isClientSpoofingEnabled()Z
|
|
||||||
move-result v0
|
|
||||||
if-eqz v0, :disabled
|
|
||||||
|
|
||||||
iget-object v0, p0, $clientInfoField
|
|
||||||
|
|
||||||
# Set client type to the spoofed value.
|
|
||||||
iget v1, v0, $clientInfoClientTypeField
|
|
||||||
invoke-static { v1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->getClientTypeId(I)I
|
|
||||||
move-result v1
|
|
||||||
iput v1, v0, $clientInfoClientTypeField
|
|
||||||
|
|
||||||
# Set client model to the spoofed value.
|
|
||||||
iget-object v1, v0, $clientInfoClientModelField
|
|
||||||
invoke-static { v1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->getClientModel(Ljava/lang/String;)Ljava/lang/String;
|
|
||||||
move-result-object v1
|
|
||||||
iput-object v1, v0, $clientInfoClientModelField
|
|
||||||
|
|
||||||
# Set client version to the spoofed value.
|
|
||||||
iget-object v1, v0, $clientInfoClientVersionField
|
|
||||||
invoke-static { v1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->getClientVersion(Ljava/lang/String;)Ljava/lang/String;
|
|
||||||
move-result-object v1
|
|
||||||
iput-object v1, v0, $clientInfoClientVersionField
|
|
||||||
|
|
||||||
# Set client os version to the spoofed value.
|
|
||||||
iget-object v1, v0, $clientInfoOsVersionField
|
|
||||||
invoke-static { v1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->getOsVersion(Ljava/lang/String;)Ljava/lang/String;
|
|
||||||
move-result-object v1
|
|
||||||
iput-object v1, v0, $clientInfoOsVersionField
|
|
||||||
|
|
||||||
:disabled
|
|
||||||
return-void
|
|
||||||
""",
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Spoof user-agent
|
|
||||||
|
|
||||||
UserAgentHeaderBuilderFingerprint.resultOrThrow().mutableMethod.apply {
|
|
||||||
val insertIndex = implementation!!.instructions.lastIndex
|
|
||||||
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
|
||||||
|
|
||||||
addInstructions(
|
|
||||||
insertIndex, """
|
|
||||||
invoke-static { v$insertRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getUserAgent(Ljava/lang/String;)Ljava/lang/String;
|
|
||||||
move-result-object v$insertRegister
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region check whether video is Shorts or Clips.
|
|
||||||
|
|
||||||
PlayerResponseMethodHookPatch += PlayerResponseMethodHookPatch.Hook.PlayerParameter(
|
|
||||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->setPlayerResponseVideoId(" +
|
|
||||||
"Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;",
|
|
||||||
)
|
|
||||||
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region fix player gesture.
|
|
||||||
|
|
||||||
PlayerGestureConfigSyntheticFingerprint.resultOrThrow().let {
|
|
||||||
val endIndex = it.scanResult.patternScanResult!!.endIndex
|
|
||||||
val downAndOutLandscapeAllowedIndex = endIndex - 3
|
|
||||||
val downAndOutPortraitAllowedIndex = endIndex - 9
|
|
||||||
|
|
||||||
arrayOf(
|
|
||||||
downAndOutLandscapeAllowedIndex,
|
|
||||||
downAndOutPortraitAllowedIndex,
|
|
||||||
).forEach { index ->
|
|
||||||
val gestureAllowedMethod = it.getWalkerMethod(context, index)
|
|
||||||
|
|
||||||
gestureAllowedMethod.apply {
|
|
||||||
val isAllowedIndex = getInstructions().lastIndex
|
|
||||||
val isAllowed = getInstruction<OneRegisterInstruction>(isAllowedIndex).registerA
|
|
||||||
|
|
||||||
addInstructions(
|
|
||||||
isAllowedIndex,
|
|
||||||
"""
|
|
||||||
invoke-static { v$isAllowed }, $INTEGRATIONS_CLASS_DESCRIPTOR->enablePlayerGesture(Z)Z
|
|
||||||
move-result v$isAllowed
|
|
||||||
""",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region fix playback speed menu item.
|
|
||||||
|
|
||||||
// fix for iOS, Android Testsuite
|
|
||||||
CreatePlaybackSpeedMenuItemFingerprint.resultOrThrow().let {
|
|
||||||
val scanResult = it.scanResult.patternScanResult!!
|
|
||||||
if (scanResult.startIndex != 0) throw PatchException("Unexpected start index: ${scanResult.startIndex}")
|
|
||||||
|
|
||||||
it.mutableMethod.apply {
|
|
||||||
// Find the conditional check if the playback speed menu item is not created.
|
|
||||||
val shouldCreateMenuIndex =
|
|
||||||
indexOfFirstInstructionOrThrow(scanResult.endIndex) { opcode == Opcode.IF_EQZ }
|
|
||||||
val shouldCreateMenuRegister =
|
|
||||||
getInstruction<OneRegisterInstruction>(shouldCreateMenuIndex).registerA
|
|
||||||
|
|
||||||
addInstructions(
|
|
||||||
shouldCreateMenuIndex,
|
|
||||||
"""
|
|
||||||
invoke-static { v$shouldCreateMenuRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->forceCreatePlaybackSpeedMenu(Z)Z
|
|
||||||
move-result v$shouldCreateMenuRegister
|
|
||||||
""",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fix for Android TV
|
|
||||||
PlaybackRateBottomSheetBuilderFingerprint.resultOrThrow().let {
|
|
||||||
it.mutableMethod.apply {
|
|
||||||
val targetIndex = it.scanResult.patternScanResult!!.endIndex
|
|
||||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
|
||||||
|
|
||||||
addInstructions(
|
|
||||||
targetIndex,
|
|
||||||
"""
|
|
||||||
invoke-static { v$targetRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->forceCreatePlaybackSpeedMenuReversed(Z)Z
|
|
||||||
move-result v$targetRegister
|
|
||||||
""",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region fix background playback in live stream, if spoofing to iOS
|
|
||||||
// This force enables audio background playback.
|
|
||||||
PlayerResponseModelBackgroundAudioPlaybackFingerprint.resultOrThrow().mutableMethod.apply {
|
|
||||||
addInstructionsWithLabels(
|
|
||||||
0, """
|
|
||||||
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->overrideBackgroundAudioPlayback()Z
|
|
||||||
move-result v0
|
|
||||||
if-eqz v0, :disabled
|
|
||||||
return v0
|
|
||||||
""", ExternalLabel("disabled", getInstruction(0))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region watch history if spoofing to iOS
|
|
||||||
|
|
||||||
if (!SettingsPatch.upward1839) {
|
|
||||||
BuildPlaybackStatsRequestURIFingerprint.resultOrThrow().let {
|
|
||||||
val walkerMethod =
|
|
||||||
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex)
|
|
||||||
|
|
||||||
walkerMethod.addInstructions(
|
|
||||||
0, """
|
|
||||||
invoke-static {p0}, $INTEGRATIONS_CLASS_DESCRIPTOR->overrideTrackingUrl(Landroid/net/Uri;)Landroid/net/Uri;
|
|
||||||
move-result-object p0
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
OrganicPlaybackContextModelFingerprint.resultOrThrow().let {
|
|
||||||
it.mutableMethod.apply {
|
|
||||||
val insertIndex = it.scanResult.patternScanResult!!.endIndex
|
|
||||||
val insertRegister =
|
|
||||||
getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
|
||||||
|
|
||||||
addInstruction(
|
|
||||||
insertIndex,
|
|
||||||
"invoke-static { v$insertRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->setCpn(Ljava/lang/String;)V"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TrackingUrlHookPatch.hookTrackingUrl("$INTEGRATIONS_CLASS_DESCRIPTOR->setTrackingUriParameter(Landroid/net/Uri;)V")
|
|
||||||
}
|
|
||||||
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region append spoof info.
|
|
||||||
|
|
||||||
NerdsStatsVideoFormatBuilderFingerprint.resultOrThrow().mutableMethod.apply {
|
|
||||||
for (index in implementation!!.instructions.size - 1 downTo 0) {
|
|
||||||
val instruction = getInstruction(index)
|
|
||||||
if (instruction.opcode != Opcode.RETURN_OBJECT)
|
|
||||||
continue
|
|
||||||
|
|
||||||
val register = (instruction as OneRegisterInstruction).registerA
|
|
||||||
|
|
||||||
addInstructions(
|
|
||||||
index, """
|
|
||||||
invoke-static {v$register}, $INTEGRATIONS_CLASS_DESCRIPTOR->appendSpoofedClient(Ljava/lang/String;)Ljava/lang/String;
|
|
||||||
move-result-object v$register
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region hook storyboard.
|
|
||||||
|
|
||||||
StoryboardHookPatch.hook(INTEGRATIONS_CLASS_DESCRIPTOR)
|
|
||||||
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
if (!SettingsPatch.upward1839) {
|
|
||||||
settingArray += "SETTINGS: IOS_CLIENT_SIDE_EFFECT_1838"
|
|
||||||
} else {
|
|
||||||
settingArray += "SETTINGS: IOS_CLIENT_SIDE_EFFECT_1839"
|
|
||||||
|
|
||||||
context.updatePatchStatus(PATCH_STATUS_CLASS_DESCRIPTOR, "SpoofClient")
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add settings
|
|
||||||
*/
|
|
||||||
SettingsPatch.addPreference(settingArray)
|
|
||||||
|
|
||||||
SettingsPatch.updatePatchStatus(this)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.fix.client.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
internal object BuildPlaybackStatsRequestURIFingerprint : MethodFingerprint(
|
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
|
||||||
returnType = "L",
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.INVOKE_STATIC,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.CONST_STRING,
|
|
||||||
),
|
|
||||||
strings = listOf("event", "streamingstats"),
|
|
||||||
)
|
|
@ -1,20 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.fix.client.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
internal object BuildPlayerRequestURIFingerprint : MethodFingerprint(
|
|
||||||
returnType = "Ljava/lang/String;",
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.INVOKE_VIRTUAL, // Register holds player request URI.
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.IPUT_OBJECT,
|
|
||||||
Opcode.IGET_OBJECT,
|
|
||||||
Opcode.MONITOR_EXIT,
|
|
||||||
Opcode.RETURN_OBJECT,
|
|
||||||
),
|
|
||||||
strings = listOf(
|
|
||||||
"key",
|
|
||||||
"asig",
|
|
||||||
),
|
|
||||||
)
|
|
@ -1,34 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.fix.client.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
internal object CreatePlaybackSpeedMenuItemFingerprint : MethodFingerprint(
|
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
|
||||||
returnType = "V",
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.IGET_OBJECT, // First instruction of the method
|
|
||||||
Opcode.IGET_OBJECT,
|
|
||||||
Opcode.IGET_OBJECT,
|
|
||||||
Opcode.CONST_4,
|
|
||||||
Opcode.IF_EQZ,
|
|
||||||
Opcode.INVOKE_INTERFACE,
|
|
||||||
null // MOVE_RESULT or MOVE_RESULT_OBJECT, Return value controls the creation of the playback speed menu item.
|
|
||||||
),
|
|
||||||
// 19.01 and earlier is missing the second parameter.
|
|
||||||
// Since this fingerprint is somewhat weak, work around by checking for both method parameter signatures.
|
|
||||||
customFingerprint = custom@{ methodDef, _ ->
|
|
||||||
// 19.01 and earlier parameters are: "[L"
|
|
||||||
// 19.02+ parameters are "[L", "F"
|
|
||||||
val parameterTypes = methodDef.parameterTypes
|
|
||||||
val firstParameter = parameterTypes.firstOrNull()
|
|
||||||
|
|
||||||
if (firstParameter == null || !firstParameter.startsWith("[L")) {
|
|
||||||
return@custom false
|
|
||||||
}
|
|
||||||
|
|
||||||
parameterTypes.size == 1 || (parameterTypes.size == 2 && parameterTypes[1] == "F")
|
|
||||||
},
|
|
||||||
)
|
|
@ -1,15 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.fix.client.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
internal object CreatePlayerRequestBodyFingerprint : MethodFingerprint(
|
|
||||||
returnType = "V",
|
|
||||||
parameters = listOf("L"),
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.CHECK_CAST,
|
|
||||||
Opcode.IGET,
|
|
||||||
Opcode.AND_INT_LIT16,
|
|
||||||
),
|
|
||||||
strings = listOf("ms"),
|
|
||||||
)
|
|
@ -1,30 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.fix.client.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.fix.client.fingerprints.CreatePlayerRequestBodyWithVersionReleaseFingerprint.indexOfBuildInstruction
|
|
||||||
import app.revanced.util.getReference
|
|
||||||
import app.revanced.util.indexOfFirstInstruction
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
import com.android.tools.smali.dexlib2.iface.Method
|
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
|
||||||
|
|
||||||
internal object CreatePlayerRequestBodyWithVersionReleaseFingerprint : MethodFingerprint(
|
|
||||||
returnType = "V",
|
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
|
||||||
parameters = listOf("L"),
|
|
||||||
strings = listOf("Google Inc."),
|
|
||||||
customFingerprint = { methodDef, _ ->
|
|
||||||
indexOfBuildInstruction(methodDef) >= 0
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
fun indexOfBuildInstruction(methodDef: Method) =
|
|
||||||
methodDef.indexOfFirstInstruction {
|
|
||||||
val reference = getReference<MethodReference>()
|
|
||||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
|
||||||
reference?.name == "build" &&
|
|
||||||
reference.parameterTypes.isEmpty() &&
|
|
||||||
reference.returnType.startsWith("L")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.fix.client.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
internal object OrganicPlaybackContextModelFingerprint : MethodFingerprint(
|
|
||||||
returnType = "V",
|
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
|
||||||
parameters = listOf(
|
|
||||||
"Ljava/lang/String;", // cpn
|
|
||||||
"Z",
|
|
||||||
"Z",
|
|
||||||
"Z",
|
|
||||||
"Z"
|
|
||||||
),
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.INVOKE_DIRECT,
|
|
||||||
Opcode.IF_EQZ,
|
|
||||||
Opcode.IPUT_OBJECT,
|
|
||||||
),
|
|
||||||
strings = listOf("Null contentCpn")
|
|
||||||
)
|
|
@ -1,55 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.fix.client.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
|
|
||||||
import app.revanced.util.getReference
|
|
||||||
import app.revanced.util.indexOfFirstInstruction
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
import com.android.tools.smali.dexlib2.iface.Method
|
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [FuzzyPatternScanMethod] was added to maintain compatibility for YouTube v18.29.38 to v18.32.39.
|
|
||||||
* TODO: Remove this annotation if support for YouTube v18.29.38 to v18.32.39 is dropped.
|
|
||||||
*/
|
|
||||||
@FuzzyPatternScanMethod(5)
|
|
||||||
internal object PlayerGestureConfigSyntheticFingerprint : MethodFingerprint(
|
|
||||||
returnType = "V",
|
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
|
||||||
parameters = listOf("Ljava/lang/Object;"),
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.SGET_OBJECT,
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT,
|
|
||||||
Opcode.IF_EQZ,
|
|
||||||
Opcode.IF_EQZ,
|
|
||||||
Opcode.IGET_OBJECT,
|
|
||||||
Opcode.INVOKE_INTERFACE,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.INVOKE_VIRTUAL, // playerGestureConfig.downAndOutLandscapeAllowed.
|
|
||||||
Opcode.MOVE_RESULT,
|
|
||||||
Opcode.CHECK_CAST,
|
|
||||||
Opcode.IPUT_BOOLEAN,
|
|
||||||
Opcode.INVOKE_INTERFACE,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.INVOKE_VIRTUAL, // playerGestureConfig.downAndOutPortraitAllowed.
|
|
||||||
Opcode.MOVE_RESULT,
|
|
||||||
Opcode.IPUT_BOOLEAN,
|
|
||||||
Opcode.RETURN_VOID,
|
|
||||||
),
|
|
||||||
customFingerprint = { methodDef, classDef ->
|
|
||||||
fun indexOfDownAndOutAllowedInstruction(methodDef: Method) =
|
|
||||||
methodDef.indexOfFirstInstruction {
|
|
||||||
val reference = getReference<MethodReference>()
|
|
||||||
reference?.definingClass == "Lcom/google/android/libraries/youtube/innertube/model/media/PlayerConfigModel;" &&
|
|
||||||
reference.parameterTypes.isEmpty() &&
|
|
||||||
reference.returnType == "Z"
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method is always called "a" because this kind of class always has a single method.
|
|
||||||
methodDef.name == "a" && classDef.methods.count() == 2 &&
|
|
||||||
indexOfDownAndOutAllowedInstruction(methodDef) >= 0
|
|
||||||
},
|
|
||||||
)
|
|
@ -1,43 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.fix.client.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
/**
|
|
||||||
* On iOS clients, this method always returns false in live streams.
|
|
||||||
*
|
|
||||||
* This fingerprint seems to break easily because there are many [Opcode] patterns, but it is not.
|
|
||||||
* This fingerprint has been tested on all versions from YouTube 17.34.36 to YouTube 19.29.42.
|
|
||||||
*/
|
|
||||||
internal object PlayerResponseModelBackgroundAudioPlaybackFingerprint : MethodFingerprint(
|
|
||||||
returnType = "Z",
|
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
|
||||||
parameters = listOf("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"),
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.CONST_4,
|
|
||||||
Opcode.IF_EQZ,
|
|
||||||
Opcode.INVOKE_INTERFACE,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.IF_EQZ,
|
|
||||||
Opcode.INVOKE_INTERFACE,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.INVOKE_STATIC,
|
|
||||||
Opcode.MOVE_RESULT,
|
|
||||||
Opcode.IF_EQZ,
|
|
||||||
Opcode.INVOKE_INTERFACE,
|
|
||||||
Opcode.MOVE_RESULT,
|
|
||||||
Opcode.CONST_4,
|
|
||||||
Opcode.IF_EQZ,
|
|
||||||
Opcode.INVOKE_INTERFACE,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT,
|
|
||||||
Opcode.IF_NEZ,
|
|
||||||
Opcode.GOTO,
|
|
||||||
Opcode.RETURN,
|
|
||||||
null, // Opcode.CONST_4 or Opcode.MOVE
|
|
||||||
Opcode.RETURN,
|
|
||||||
),
|
|
||||||
)
|
|
@ -1,12 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.fix.client.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
internal object SetPlayerRequestClientTypeFingerprint : MethodFingerprint(
|
|
||||||
strings = listOf("10.29"),
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.IGET,
|
|
||||||
Opcode.IPUT, // Sets ClientInfo.clientId.
|
|
||||||
),
|
|
||||||
)
|
|
@ -1,19 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.fix.client.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the fingerprint used in the 'client-spoof' patch around 2022.
|
|
||||||
* (Integrated into 'UserAgentClientSpoofPatch' now.)
|
|
||||||
*
|
|
||||||
* This method is modified by 'UserAgentClientSpoofPatch', so the fingerprint does not check the [Opcode].
|
|
||||||
*/
|
|
||||||
internal object UserAgentHeaderBuilderFingerprint : MethodFingerprint(
|
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
|
||||||
returnType = "Ljava/lang/String;",
|
|
||||||
parameters = listOf("Landroid/content/Context;", "Ljava/lang/String;", "Ljava/lang/String;"),
|
|
||||||
strings = listOf("(Linux; U; Android "),
|
|
||||||
)
|
|
@ -1,53 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.fix.parameter
|
|
||||||
|
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
|
||||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
|
||||||
import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH
|
|
||||||
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
|
|
||||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
|
||||||
import app.revanced.patches.youtube.utils.storyboard.StoryboardHookPatch
|
|
||||||
import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
|
||||||
import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch
|
|
||||||
import app.revanced.util.patch.BaseBytecodePatch
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
@Deprecated("This patch will be removed in the future.")
|
|
||||||
object SpoofPlayerParameterPatch : BaseBytecodePatch(
|
|
||||||
// name = "Spoof player parameters",
|
|
||||||
description = "Adds options to spoof player parameters to prevent playback issues.",
|
|
||||||
dependencies = setOf(
|
|
||||||
PlayerTypeHookPatch::class,
|
|
||||||
PlayerResponseMethodHookPatch::class,
|
|
||||||
SettingsPatch::class,
|
|
||||||
VideoInformationPatch::class,
|
|
||||||
StoryboardHookPatch::class,
|
|
||||||
),
|
|
||||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
|
||||||
use = false
|
|
||||||
) {
|
|
||||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
|
||||||
"$MISC_PATH/SpoofPlayerParameterPatch;"
|
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext) {
|
|
||||||
|
|
||||||
// Hook the player parameters.
|
|
||||||
PlayerResponseMethodHookPatch += PlayerResponseMethodHookPatch.Hook.PlayerParameter(
|
|
||||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->spoofParameter(Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Hook storyboard.
|
|
||||||
StoryboardHookPatch.hook(INTEGRATIONS_CLASS_DESCRIPTOR)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add settings
|
|
||||||
*/
|
|
||||||
SettingsPatch.addPreference(
|
|
||||||
arrayOf(
|
|
||||||
"PREFERENCE_CATEGORY: MISC_EXPERIMENTAL_FLAGS",
|
|
||||||
"SETTINGS: SPOOF_PLAYER_PARAMETER"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
SettingsPatch.updatePatchStatus(this)
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,234 @@
|
|||||||
|
package app.revanced.patches.youtube.utils.fix.streamingdata
|
||||||
|
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
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.getInstructions
|
||||||
|
import app.revanced.patcher.patch.PatchException
|
||||||
|
import app.revanced.patcher.util.smali.ExternalLabel
|
||||||
|
import app.revanced.patches.youtube.utils.compatibility.Constants
|
||||||
|
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.BuildBrowseRequestFingerprint
|
||||||
|
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.BuildInitPlaybackRequestFingerprint
|
||||||
|
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.BuildMediaDataSourceFingerprint
|
||||||
|
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.CreateStreamingDataFingerprint
|
||||||
|
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.NerdsStatsVideoFormatBuilderFingerprint
|
||||||
|
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.ProtobufClassParseByteBufferFingerprint
|
||||||
|
import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH
|
||||||
|
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||||
|
import app.revanced.patches.youtube.video.videoid.VideoIdPatch
|
||||||
|
import app.revanced.util.getReference
|
||||||
|
import app.revanced.util.patch.BaseBytecodePatch
|
||||||
|
import app.revanced.util.resultOrThrow
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||||
|
|
||||||
|
object SpoofStreamingDataPatch : BaseBytecodePatch(
|
||||||
|
name = "Spoof streaming data",
|
||||||
|
description = "Adds options to spoof the streaming data to allow video playback.",
|
||||||
|
dependencies = setOf(
|
||||||
|
SettingsPatch::class,
|
||||||
|
SpoofUserAgentPatch::class,
|
||||||
|
VideoIdPatch::class,
|
||||||
|
),
|
||||||
|
compatiblePackages = Constants.COMPATIBLE_PACKAGE,
|
||||||
|
fingerprints = setOf(
|
||||||
|
BuildBrowseRequestFingerprint,
|
||||||
|
BuildInitPlaybackRequestFingerprint,
|
||||||
|
BuildMediaDataSourceFingerprint,
|
||||||
|
CreateStreamingDataFingerprint,
|
||||||
|
ProtobufClassParseByteBufferFingerprint,
|
||||||
|
|
||||||
|
// Nerds stats video format.
|
||||||
|
NerdsStatsVideoFormatBuilderFingerprint,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||||
|
"$MISC_PATH/SpoofStreamingDataPatch;"
|
||||||
|
|
||||||
|
override fun execute(context: BytecodeContext) {
|
||||||
|
|
||||||
|
// region Block /initplayback requests to fall back to /get_watch requests.
|
||||||
|
|
||||||
|
BuildInitPlaybackRequestFingerprint.resultOrThrow().let {
|
||||||
|
it.mutableMethod.apply {
|
||||||
|
val moveUriStringIndex = it.scanResult.patternScanResult!!.startIndex
|
||||||
|
val targetRegister =
|
||||||
|
getInstruction<OneRegisterInstruction>(moveUriStringIndex).registerA
|
||||||
|
|
||||||
|
addInstructions(
|
||||||
|
moveUriStringIndex + 1,
|
||||||
|
"""
|
||||||
|
invoke-static { v$targetRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String;
|
||||||
|
move-result-object v$targetRegister
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Copy request headers for streaming data fetch.
|
||||||
|
|
||||||
|
BuildBrowseRequestFingerprint.resultOrThrow().let { result ->
|
||||||
|
result.mutableMethod.apply {
|
||||||
|
val newRequestBuilderIndex =
|
||||||
|
BuildBrowseRequestFingerprint.indexOfNewUrlRequestBuilderInstruction(this)
|
||||||
|
val urlRegister =
|
||||||
|
getInstruction<FiveRegisterInstruction>(newRequestBuilderIndex).registerD
|
||||||
|
|
||||||
|
val entrySetIndex = BuildBrowseRequestFingerprint.indexOfEntrySetInstruction(this)
|
||||||
|
val mapRegister = if (entrySetIndex < 0)
|
||||||
|
urlRegister + 1
|
||||||
|
else
|
||||||
|
getInstruction<FiveRegisterInstruction>(entrySetIndex).registerC
|
||||||
|
|
||||||
|
var smaliInstructions =
|
||||||
|
"invoke-static { v$urlRegister, v$mapRegister }, " +
|
||||||
|
"$INTEGRATIONS_CLASS_DESCRIPTOR->" +
|
||||||
|
"setFetchHeaders(Ljava/lang/String;Ljava/util/Map;)V"
|
||||||
|
|
||||||
|
if (entrySetIndex < 0) smaliInstructions = """
|
||||||
|
move-object/from16 v$mapRegister, p1
|
||||||
|
|
||||||
|
""" + smaliInstructions
|
||||||
|
|
||||||
|
// Copy request headers for streaming data fetch.
|
||||||
|
addInstructions(newRequestBuilderIndex + 2, smaliInstructions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Replace the streaming data.
|
||||||
|
|
||||||
|
CreateStreamingDataFingerprint.resultOrThrow().let { result ->
|
||||||
|
result.mutableMethod.apply {
|
||||||
|
val setStreamingDataIndex = result.scanResult.patternScanResult!!.startIndex
|
||||||
|
val setStreamingDataField =
|
||||||
|
getInstruction(setStreamingDataIndex).getReference<FieldReference>().toString()
|
||||||
|
|
||||||
|
val playerProtoClass =
|
||||||
|
getInstruction(setStreamingDataIndex + 1).getReference<FieldReference>()!!.definingClass
|
||||||
|
val protobufClass =
|
||||||
|
ProtobufClassParseByteBufferFingerprint.resultOrThrow().mutableMethod.definingClass
|
||||||
|
|
||||||
|
val getStreamingDataField = getInstructions().find { instruction ->
|
||||||
|
instruction.opcode == Opcode.IGET_OBJECT &&
|
||||||
|
instruction.getReference<FieldReference>()?.definingClass == playerProtoClass
|
||||||
|
}?.getReference<FieldReference>()
|
||||||
|
?: throw PatchException("Could not find getStreamingDataField")
|
||||||
|
|
||||||
|
val videoDetailsIndex = result.scanResult.patternScanResult!!.endIndex
|
||||||
|
val videoDetailsClass =
|
||||||
|
getInstruction(videoDetailsIndex).getReference<FieldReference>()!!.type
|
||||||
|
|
||||||
|
val insertIndex = videoDetailsIndex + 1
|
||||||
|
val videoDetailsRegister =
|
||||||
|
getInstruction<TwoRegisterInstruction>(videoDetailsIndex).registerA
|
||||||
|
|
||||||
|
val overrideRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||||
|
val freeRegister = implementation!!.registerCount - parameters.size - 2
|
||||||
|
|
||||||
|
addInstructionsWithLabels(
|
||||||
|
insertIndex,
|
||||||
|
"""
|
||||||
|
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->isSpoofingEnabled()Z
|
||||||
|
move-result v$freeRegister
|
||||||
|
if-eqz v$freeRegister, :disabled
|
||||||
|
|
||||||
|
# Get video id.
|
||||||
|
# From YouTube 17.34.36 to YouTube 19.16.39, the field names and field types are the same.
|
||||||
|
iget-object v$freeRegister, v$videoDetailsRegister, $videoDetailsClass->c:Ljava/lang/String;
|
||||||
|
if-eqz v$freeRegister, :disabled
|
||||||
|
|
||||||
|
# Get streaming data.
|
||||||
|
invoke-static { v$freeRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getStreamingData(Ljava/lang/String;)Ljava/nio/ByteBuffer;
|
||||||
|
move-result-object v$freeRegister
|
||||||
|
if-eqz v$freeRegister, :disabled
|
||||||
|
|
||||||
|
# Parse streaming data.
|
||||||
|
sget-object v$overrideRegister, $playerProtoClass->a:$playerProtoClass
|
||||||
|
invoke-static { v$overrideRegister, v$freeRegister }, $protobufClass->parseFrom(${protobufClass}Ljava/nio/ByteBuffer;)$protobufClass
|
||||||
|
move-result-object v$freeRegister
|
||||||
|
check-cast v$freeRegister, $playerProtoClass
|
||||||
|
|
||||||
|
# Set streaming data.
|
||||||
|
iget-object v$freeRegister, v$freeRegister, $getStreamingDataField
|
||||||
|
if-eqz v0, :disabled
|
||||||
|
iput-object v$freeRegister, p0, $setStreamingDataField
|
||||||
|
""",
|
||||||
|
ExternalLabel("disabled", getInstruction(insertIndex))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Remove /videoplayback request body to fix playback.
|
||||||
|
// This is needed when using iOS client as streaming data source.
|
||||||
|
|
||||||
|
BuildMediaDataSourceFingerprint.resultOrThrow().let {
|
||||||
|
it.mutableMethod.apply {
|
||||||
|
val targetIndex = getInstructions().lastIndex
|
||||||
|
|
||||||
|
addInstructions(
|
||||||
|
targetIndex,
|
||||||
|
"""
|
||||||
|
# Field a: Stream uri.
|
||||||
|
# Field c: Http method.
|
||||||
|
# Field d: Post data.
|
||||||
|
# From YouTube 17.34.36 to YouTube 19.16.39, the field names and field types are the same.
|
||||||
|
move-object/from16 v0, p0
|
||||||
|
iget-object v1, v0, $definingClass->a:Landroid/net/Uri;
|
||||||
|
iget v2, v0, $definingClass->c:I
|
||||||
|
iget-object v3, v0, $definingClass->d:[B
|
||||||
|
invoke-static { v1, v2, v3 }, $INTEGRATIONS_CLASS_DESCRIPTOR->removeVideoPlaybackPostBody(Landroid/net/Uri;I[B)[B
|
||||||
|
move-result-object v1
|
||||||
|
iput-object v1, v0, $definingClass->d:[B
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Append spoof info.
|
||||||
|
|
||||||
|
NerdsStatsVideoFormatBuilderFingerprint.resultOrThrow().mutableMethod.apply {
|
||||||
|
for (index in implementation!!.instructions.size - 1 downTo 0) {
|
||||||
|
val instruction = getInstruction(index)
|
||||||
|
if (instruction.opcode != Opcode.RETURN_OBJECT)
|
||||||
|
continue
|
||||||
|
|
||||||
|
val register = (instruction as OneRegisterInstruction).registerA
|
||||||
|
|
||||||
|
addInstructions(
|
||||||
|
index, """
|
||||||
|
invoke-static {v$register}, $INTEGRATIONS_CLASS_DESCRIPTOR->appendSpoofedClient(Ljava/lang/String;)Ljava/lang/String;
|
||||||
|
move-result-object v$register
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// Prefetch streaming data.
|
||||||
|
VideoIdPatch.hookPlayerResponseVideoId("$INTEGRATIONS_CLASS_DESCRIPTOR->fetchStreamingData(Ljava/lang/String;Z)V")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add settings
|
||||||
|
*/
|
||||||
|
SettingsPatch.addPreference(
|
||||||
|
arrayOf(
|
||||||
|
"SETTINGS: SPOOF_STREAMING_DATA"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
SettingsPatch.updatePatchStatus(this)
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package app.revanced.patches.youtube.utils.fix.client
|
package app.revanced.patches.youtube.utils.fix.streamingdata
|
||||||
|
|
||||||
import app.revanced.patches.shared.spoofuseragent.BaseSpoofUserAgentPatch
|
import app.revanced.patches.shared.spoofuseragent.BaseSpoofUserAgentPatch
|
||||||
|
|
@ -0,0 +1,42 @@
|
|||||||
|
package app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.BuildBrowseRequestFingerprint.indexOfEntrySetInstruction
|
||||||
|
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.BuildBrowseRequestFingerprint.indexOfNewUrlRequestBuilderInstruction
|
||||||
|
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.BuildBrowseRequestFingerprint.indexOfRequestFinishedListenerInstruction
|
||||||
|
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 object BuildBrowseRequestFingerprint : MethodFingerprint(
|
||||||
|
customFingerprint = { methodDef, _ ->
|
||||||
|
methodDef.implementation != null &&
|
||||||
|
indexOfRequestFinishedListenerInstruction(methodDef) >= 0 &&
|
||||||
|
!methodDef.definingClass.startsWith("Lorg/") &&
|
||||||
|
indexOfNewUrlRequestBuilderInstruction(methodDef) >= 0 &&
|
||||||
|
// YouTube 17.34.36 ~ YouTube 18.35.36
|
||||||
|
(indexOfEntrySetInstruction(methodDef) >= 0 ||
|
||||||
|
// YouTube 18.36.39 ~
|
||||||
|
methodDef.parameters[1].type == "Ljava/util/Map;")
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
fun indexOfRequestFinishedListenerInstruction(methodDef: Method) =
|
||||||
|
methodDef.indexOfFirstInstruction {
|
||||||
|
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||||
|
getReference<MethodReference>().toString() == "Lorg/chromium/net/ExperimentalUrlRequest${'$'}Builder;->setRequestFinishedListener(Lorg/chromium/net/RequestFinishedInfo${'$'}Listener;)Lorg/chromium/net/ExperimentalUrlRequest${'$'}Builder;"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun indexOfNewUrlRequestBuilderInstruction(methodDef: Method) =
|
||||||
|
methodDef.indexOfFirstInstruction {
|
||||||
|
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||||
|
getReference<MethodReference>().toString() == "Lorg/chromium/net/CronetEngine;->newUrlRequestBuilder(Ljava/lang/String;Lorg/chromium/net/UrlRequest${'$'}Callback;Ljava/util/concurrent/Executor;)Lorg/chromium/net/UrlRequest${'$'}Builder;"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun indexOfEntrySetInstruction(methodDef: Method) =
|
||||||
|
methodDef.indexOfFirstInstruction {
|
||||||
|
opcode == Opcode.INVOKE_INTERFACE &&
|
||||||
|
getReference<MethodReference>().toString() == "Ljava/util/Map;->entrySet()Ljava/util/Set;"
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package app.revanced.patches.youtube.utils.fix.client.fingerprints
|
package app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
@ -0,0 +1,22 @@
|
|||||||
|
package app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
internal object BuildMediaDataSourceFingerprint : MethodFingerprint(
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||||
|
returnType = "V",
|
||||||
|
parameters = listOf(
|
||||||
|
"Landroid/net/Uri;",
|
||||||
|
"J",
|
||||||
|
"I",
|
||||||
|
"[B",
|
||||||
|
"Ljava/util/Map;",
|
||||||
|
"J",
|
||||||
|
"J",
|
||||||
|
"Ljava/lang/String;",
|
||||||
|
"I",
|
||||||
|
"Ljava/lang/Object;"
|
||||||
|
)
|
||||||
|
)
|
@ -0,0 +1,28 @@
|
|||||||
|
package app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import app.revanced.util.getReference
|
||||||
|
import app.revanced.util.indexOfFirstInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||||
|
|
||||||
|
internal object CreateStreamingDataFingerprint : MethodFingerprint(
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||||
|
returnType = "V",
|
||||||
|
parameters = listOf("L"),
|
||||||
|
opcodes = listOf(
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.IPUT_OBJECT
|
||||||
|
),
|
||||||
|
customFingerprint = { methodDef, _ ->
|
||||||
|
methodDef.indexOfFirstInstruction {
|
||||||
|
opcode == Opcode.SGET_OBJECT &&
|
||||||
|
getReference<FieldReference>()?.name == "playerThreedRenderer"
|
||||||
|
} >= 0
|
||||||
|
},
|
||||||
|
)
|
@ -1,4 +1,4 @@
|
|||||||
package app.revanced.patches.youtube.utils.fix.client.fingerprints
|
package app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
@ -0,0 +1,19 @@
|
|||||||
|
package app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
|
internal object ProtobufClassParseByteBufferFingerprint : MethodFingerprint(
|
||||||
|
accessFlags = AccessFlags.PROTECTED or AccessFlags.STATIC,
|
||||||
|
parameters = listOf("L", "Ljava/nio/ByteBuffer;"),
|
||||||
|
returnType = "L",
|
||||||
|
opcodes = listOf(
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.RETURN_OBJECT,
|
||||||
|
),
|
||||||
|
customFingerprint = { methodDef, _ -> methodDef.name == "parseFrom" },
|
||||||
|
)
|
@ -3,8 +3,8 @@ package app.revanced.patches.youtube.utils.gms
|
|||||||
import app.revanced.patches.shared.gms.BaseGmsCoreSupportPatch
|
import app.revanced.patches.shared.gms.BaseGmsCoreSupportPatch
|
||||||
import app.revanced.patches.shared.gms.BaseGmsCoreSupportResourcePatch.Companion.ORIGINAL_PACKAGE_NAME_YOUTUBE
|
import app.revanced.patches.shared.gms.BaseGmsCoreSupportResourcePatch.Companion.ORIGINAL_PACKAGE_NAME_YOUTUBE
|
||||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||||
import app.revanced.patches.youtube.utils.fix.client.SpoofClientPatch
|
import app.revanced.patches.youtube.utils.fix.streamingdata.SpoofStreamingDataPatch
|
||||||
import app.revanced.patches.youtube.utils.fix.client.SpoofUserAgentPatch
|
import app.revanced.patches.youtube.utils.fix.streamingdata.SpoofUserAgentPatch
|
||||||
import app.revanced.patches.youtube.utils.integrations.IntegrationsPatch
|
import app.revanced.patches.youtube.utils.integrations.IntegrationsPatch
|
||||||
import app.revanced.patches.youtube.utils.mainactivity.fingerprints.MainActivityFingerprint
|
import app.revanced.patches.youtube.utils.mainactivity.fingerprints.MainActivityFingerprint
|
||||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||||
@ -15,7 +15,7 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
|
|||||||
mainActivityOnCreateFingerprint = MainActivityFingerprint,
|
mainActivityOnCreateFingerprint = MainActivityFingerprint,
|
||||||
integrationsPatchDependency = IntegrationsPatch::class,
|
integrationsPatchDependency = IntegrationsPatch::class,
|
||||||
dependencies = setOf(
|
dependencies = setOf(
|
||||||
SpoofClientPatch::class,
|
SpoofStreamingDataPatch::class,
|
||||||
SpoofUserAgentPatch::class,
|
SpoofUserAgentPatch::class,
|
||||||
SettingsPatch::class
|
SettingsPatch::class
|
||||||
),
|
),
|
||||||
|
@ -1,154 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.storyboard
|
|
||||||
|
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
|
||||||
import app.revanced.patcher.util.smali.ExternalLabel
|
|
||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
|
||||||
import app.revanced.patches.youtube.utils.storyboard.fingerprints.PlayerResponseModelGeneralStoryboardRendererFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.storyboard.fingerprints.PlayerResponseModelLiveStreamStoryboardRendererFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.storyboard.fingerprints.PlayerResponseModelStoryboardRecommendedLevelFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.storyboard.fingerprints.StoryboardRendererDecoderRecommendedLevelFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.storyboard.fingerprints.StoryboardRendererDecoderSpecFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.storyboard.fingerprints.StoryboardRendererSpecFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.storyboard.fingerprints.StoryboardThumbnailFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.storyboard.fingerprints.StoryboardThumbnailParentFingerprint
|
|
||||||
import app.revanced.util.resultOrThrow
|
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
|
||||||
|
|
||||||
@Patch(
|
|
||||||
description = "Force inject the Storyboard by fetching YouTube API.",
|
|
||||||
dependencies = [SharedResourceIdPatch::class],
|
|
||||||
)
|
|
||||||
object StoryboardHookPatch : BytecodePatch(
|
|
||||||
setOf(
|
|
||||||
PlayerResponseModelGeneralStoryboardRendererFingerprint,
|
|
||||||
PlayerResponseModelLiveStreamStoryboardRendererFingerprint,
|
|
||||||
PlayerResponseModelStoryboardRecommendedLevelFingerprint,
|
|
||||||
StoryboardRendererDecoderRecommendedLevelFingerprint,
|
|
||||||
StoryboardRendererDecoderSpecFingerprint,
|
|
||||||
StoryboardRendererSpecFingerprint,
|
|
||||||
StoryboardThumbnailParentFingerprint,
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
private lateinit var context: BytecodeContext
|
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext) {
|
|
||||||
this.context = context
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun hook(classDescriptor: String) {
|
|
||||||
|
|
||||||
// Force the seekbar time and chapters to always show up.
|
|
||||||
// This is used if the storyboard spec fetch fails, for viewing paid videos,
|
|
||||||
// or if storyboard spoofing is turned off.
|
|
||||||
StoryboardThumbnailFingerprint.resolve(
|
|
||||||
context,
|
|
||||||
StoryboardThumbnailParentFingerprint.resultOrThrow().classDef
|
|
||||||
)
|
|
||||||
StoryboardThumbnailFingerprint.resultOrThrow().let {
|
|
||||||
it.mutableMethod.apply {
|
|
||||||
val targetIndex = it.scanResult.patternScanResult!!.endIndex
|
|
||||||
val targetRegister =
|
|
||||||
getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
|
||||||
|
|
||||||
// Since this is end of the method must replace one line then add the rest.
|
|
||||||
addInstructions(
|
|
||||||
targetIndex + 1,
|
|
||||||
"""
|
|
||||||
invoke-static {}, $classDescriptor->getSeekbarThumbnailOverrideValue()Z
|
|
||||||
move-result v$targetRegister
|
|
||||||
return v$targetRegister
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
removeInstruction(targetIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hook storyboard renderer url.
|
|
||||||
arrayOf(
|
|
||||||
PlayerResponseModelGeneralStoryboardRendererFingerprint,
|
|
||||||
PlayerResponseModelLiveStreamStoryboardRendererFingerprint
|
|
||||||
).forEach { fingerprint ->
|
|
||||||
fingerprint.resultOrThrow().let {
|
|
||||||
it.mutableMethod.apply {
|
|
||||||
val getStoryboardIndex = it.scanResult.patternScanResult!!.endIndex
|
|
||||||
val getStoryboardRegister =
|
|
||||||
getInstruction<OneRegisterInstruction>(getStoryboardIndex).registerA
|
|
||||||
|
|
||||||
addInstructions(
|
|
||||||
getStoryboardIndex,
|
|
||||||
"""
|
|
||||||
invoke-static { v$getStoryboardRegister }, $classDescriptor->getStoryboardRendererSpec(Ljava/lang/String;)Ljava/lang/String;
|
|
||||||
move-result-object v$getStoryboardRegister
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hook recommended seekbar thumbnails quality level.
|
|
||||||
StoryboardRendererDecoderRecommendedLevelFingerprint.resultOrThrow().let {
|
|
||||||
it.mutableMethod.apply {
|
|
||||||
val moveOriginalRecommendedValueIndex = it.scanResult.patternScanResult!!.endIndex
|
|
||||||
val originalValueRegister =
|
|
||||||
getInstruction<OneRegisterInstruction>(moveOriginalRecommendedValueIndex).registerA
|
|
||||||
|
|
||||||
addInstructions(
|
|
||||||
moveOriginalRecommendedValueIndex + 1, """
|
|
||||||
invoke-static { v$originalValueRegister }, $classDescriptor->getStoryboardRecommendedLevel(I)I
|
|
||||||
move-result v$originalValueRegister
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hook the recommended precise seeking thumbnails quality level.
|
|
||||||
PlayerResponseModelStoryboardRecommendedLevelFingerprint.resultOrThrow().let {
|
|
||||||
it.mutableMethod.apply {
|
|
||||||
val moveOriginalRecommendedValueIndex = it.scanResult.patternScanResult!!.endIndex
|
|
||||||
val originalValueRegister =
|
|
||||||
getInstruction<OneRegisterInstruction>(moveOriginalRecommendedValueIndex).registerA
|
|
||||||
|
|
||||||
addInstructions(
|
|
||||||
moveOriginalRecommendedValueIndex, """
|
|
||||||
invoke-static { v$originalValueRegister }, $classDescriptor->getStoryboardRecommendedLevel(I)I
|
|
||||||
move-result v$originalValueRegister
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StoryboardRendererSpecFingerprint.resultOrThrow().let {
|
|
||||||
it.mutableMethod.apply {
|
|
||||||
val storyBoardUrlParams = 0
|
|
||||||
|
|
||||||
addInstructionsWithLabels(
|
|
||||||
0, """
|
|
||||||
if-nez p$storyBoardUrlParams, :ignore
|
|
||||||
invoke-static { p$storyBoardUrlParams }, $classDescriptor->getStoryboardRendererSpec(Ljava/lang/String;)Ljava/lang/String;
|
|
||||||
move-result-object p$storyBoardUrlParams
|
|
||||||
""", ExternalLabel("ignore", getInstruction(0))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hook the seekbar thumbnail decoder and use a NULL spec for live streams.
|
|
||||||
StoryboardRendererDecoderSpecFingerprint.resultOrThrow().let {
|
|
||||||
val storyBoardUrlIndex = it.scanResult.patternScanResult!!.startIndex + 1
|
|
||||||
val storyboardUrlRegister =
|
|
||||||
it.mutableMethod.getInstruction<OneRegisterInstruction>(storyBoardUrlIndex).registerA
|
|
||||||
|
|
||||||
it.mutableMethod.addInstructions(
|
|
||||||
storyBoardUrlIndex + 1, """
|
|
||||||
invoke-static { v$storyboardUrlRegister }, $classDescriptor->getStoryboardDecoderRendererSpec(Ljava/lang/String;)Ljava/lang/String;
|
|
||||||
move-result-object v$storyboardUrlRegister
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.storyboard.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import app.revanced.util.containsWideLiteralInstructionIndex
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
internal object PlayerResponseModelGeneralStoryboardRendererFingerprint : MethodFingerprint(
|
|
||||||
returnType = "Ljava/lang/String;",
|
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
|
||||||
parameters = emptyList(),
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.RETURN_OBJECT,
|
|
||||||
Opcode.CONST_4,
|
|
||||||
Opcode.RETURN_OBJECT
|
|
||||||
),
|
|
||||||
customFingerprint = handler@{ methodDef, _ ->
|
|
||||||
if (!methodDef.definingClass.endsWith("/PlayerResponseModelImpl;"))
|
|
||||||
return@handler false
|
|
||||||
|
|
||||||
methodDef.containsWideLiteralInstructionIndex(55735497)
|
|
||||||
}
|
|
||||||
)
|
|
@ -1,24 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.storyboard.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import app.revanced.util.containsWideLiteralInstructionIndex
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
internal object PlayerResponseModelLiveStreamStoryboardRendererFingerprint : MethodFingerprint(
|
|
||||||
returnType = "Ljava/lang/String;",
|
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
|
||||||
parameters = emptyList(),
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.RETURN_OBJECT,
|
|
||||||
Opcode.CONST_4,
|
|
||||||
Opcode.RETURN_OBJECT
|
|
||||||
),
|
|
||||||
customFingerprint = handler@{ methodDef, _ ->
|
|
||||||
if (!methodDef.definingClass.endsWith("/PlayerResponseModelImpl;"))
|
|
||||||
return@handler false
|
|
||||||
|
|
||||||
methodDef.containsWideLiteralInstructionIndex(70276274)
|
|
||||||
}
|
|
||||||
)
|
|
@ -1,24 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.storyboard.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import app.revanced.util.containsWideLiteralInstructionIndex
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
internal object PlayerResponseModelStoryboardRecommendedLevelFingerprint : MethodFingerprint(
|
|
||||||
returnType = "I",
|
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
|
||||||
parameters = emptyList(),
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.SGET_OBJECT,
|
|
||||||
Opcode.IGET,
|
|
||||||
Opcode.RETURN
|
|
||||||
),
|
|
||||||
customFingerprint = handler@{ methodDef, _ ->
|
|
||||||
if (!methodDef.definingClass.endsWith("/PlayerResponseModelImpl;"))
|
|
||||||
return@handler false
|
|
||||||
|
|
||||||
methodDef.containsWideLiteralInstructionIndex(55735497)
|
|
||||||
}
|
|
||||||
)
|
|
@ -1,23 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.storyboard.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolves to the same method as [StoryboardRendererDecoderRecommendedLevelFingerprint].
|
|
||||||
*/
|
|
||||||
internal object StoryboardRendererDecoderSpecFingerprint : MethodFingerprint(
|
|
||||||
returnType = "V",
|
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
|
||||||
parameters = listOf("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"),
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.INVOKE_INTERFACE, // First instruction of the method.
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.CONST_4,
|
|
||||||
Opcode.CONST_4,
|
|
||||||
Opcode.IF_NEZ,
|
|
||||||
),
|
|
||||||
strings = listOf("#-1#")
|
|
||||||
)
|
|
@ -1,12 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.storyboard.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
|
|
||||||
internal object StoryboardRendererSpecFingerprint : MethodFingerprint(
|
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
|
||||||
returnType = "L",
|
|
||||||
parameters = listOf("Ljava/lang/String;", "J"),
|
|
||||||
strings = listOf("\\|"),
|
|
||||||
)
|
|
@ -1,23 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.storyboard.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolves using the class found in [StoryboardThumbnailParentFingerprint].
|
|
||||||
*/
|
|
||||||
internal object StoryboardThumbnailFingerprint : MethodFingerprint(
|
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
|
||||||
returnType = "Z",
|
|
||||||
parameters = listOf(),
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.MOVE_RESULT,
|
|
||||||
Opcode.IF_GTZ,
|
|
||||||
Opcode.GOTO,
|
|
||||||
Opcode.CONST_4,
|
|
||||||
Opcode.RETURN,
|
|
||||||
Opcode.RETURN, // Last instruction of method.
|
|
||||||
),
|
|
||||||
)
|
|
@ -1,17 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.storyboard.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Here lies code that creates the seekbar thumbnails.
|
|
||||||
*
|
|
||||||
* An additional change here might force the thumbnails to be created,
|
|
||||||
* or possibly a change somewhere else (maybe involving YouTube 18.23.35 class `hte`)
|
|
||||||
*/
|
|
||||||
internal object StoryboardThumbnailParentFingerprint : MethodFingerprint(
|
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
|
||||||
returnType = "Landroid/graphics/Bitmap;",
|
|
||||||
strings = listOf("Storyboard regionDecoder.decodeRegion exception - "),
|
|
||||||
)
|
|
@ -14,13 +14,13 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
|
|||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||||
import app.revanced.patcher.util.smali.toInstructions
|
import app.revanced.patcher.util.smali.toInstructions
|
||||||
|
import app.revanced.patches.shared.fingerprints.MdxPlayerDirectorSetVideoStageFingerprint
|
||||||
import app.revanced.patches.youtube.utils.fingerprints.VideoEndFingerprint
|
import app.revanced.patches.youtube.utils.fingerprints.VideoEndFingerprint
|
||||||
import app.revanced.patches.youtube.utils.integrations.Constants.SHARED_PATH
|
import app.revanced.patches.youtube.utils.integrations.Constants.SHARED_PATH
|
||||||
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
|
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
|
||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||||
import app.revanced.patches.youtube.video.information.fingerprints.ChannelIdFingerprint
|
import app.revanced.patches.youtube.video.information.fingerprints.ChannelIdFingerprint
|
||||||
import app.revanced.patches.youtube.video.information.fingerprints.ChannelNameFingerprint
|
import app.revanced.patches.youtube.video.information.fingerprints.ChannelNameFingerprint
|
||||||
import app.revanced.patches.youtube.video.information.fingerprints.MdxPlayerDirectorSetVideoStageFingerprint
|
|
||||||
import app.revanced.patches.youtube.video.information.fingerprints.OnPlaybackSpeedItemClickFingerprint
|
import app.revanced.patches.youtube.video.information.fingerprints.OnPlaybackSpeedItemClickFingerprint
|
||||||
import app.revanced.patches.youtube.video.information.fingerprints.PlaybackInitializationFingerprint
|
import app.revanced.patches.youtube.video.information.fingerprints.PlaybackInitializationFingerprint
|
||||||
import app.revanced.patches.youtube.video.information.fingerprints.PlaybackSpeedClassFingerprint
|
import app.revanced.patches.youtube.video.information.fingerprints.PlaybackSpeedClassFingerprint
|
||||||
@ -361,7 +361,7 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
// Call before any other video id hooks,
|
// Call before any other video id hooks,
|
||||||
// so they can use VideoInformation and check if the video id is for a Short.
|
// so they can use VideoInformation and check if the video id is for a Short.
|
||||||
PlayerResponseMethodHookPatch += PlayerResponseMethodHookPatch.Hook.PlayerParameterBeforeVideoId(
|
PlayerResponseMethodHookPatch += PlayerResponseMethodHookPatch.Hook.PlayerParameterBeforeVideoId(
|
||||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->newPlayerResponseParameter(Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;"
|
"$INTEGRATIONS_CLASS_DESCRIPTOR->newPlayerResponseParameter(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;"
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -176,6 +176,7 @@ object VideoPlaybackPatch : BaseBytecodePatch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
VideoInformationPatch.hookBackgroundPlay("$INTEGRATIONS_PLAYBACK_SPEED_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZ)V")
|
VideoInformationPatch.hookBackgroundPlay("$INTEGRATIONS_PLAYBACK_SPEED_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZ)V")
|
||||||
|
VideoIdPatch.hookPlayerResponseVideoId("$INTEGRATIONS_PLAYBACK_SPEED_CLASS_DESCRIPTOR->fetchPlaylistData(Ljava/lang/String;Z)V")
|
||||||
|
|
||||||
context.updatePatchStatus(PATCH_STATUS_CLASS_DESCRIPTOR, "RememberPlaybackSpeed")
|
context.updatePatchStatus(PATCH_STATUS_CLASS_DESCRIPTOR, "RememberPlaybackSpeed")
|
||||||
|
|
||||||
|
@ -18,12 +18,14 @@ object PlayerResponseMethodHookPatch :
|
|||||||
// Parameter numbers of the patched method.
|
// Parameter numbers of the patched method.
|
||||||
private var PARAMETER_VIDEO_ID = 1
|
private var PARAMETER_VIDEO_ID = 1
|
||||||
private var PARAMETER_PLAYER_PARAMETER = 3
|
private var PARAMETER_PLAYER_PARAMETER = 3
|
||||||
|
private var PARAMETER_PLAYLIST_ID = 4
|
||||||
private var PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING by Delegates.notNull<Int>()
|
private var PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING by Delegates.notNull<Int>()
|
||||||
|
|
||||||
// Registers used to pass the parameters to integrations.
|
// Registers used to pass the parameters to integrations.
|
||||||
private var playerResponseMethodCopyRegisters = false
|
private var playerResponseMethodCopyRegisters = false
|
||||||
private lateinit var REGISTER_VIDEO_ID: String
|
private lateinit var REGISTER_VIDEO_ID: String
|
||||||
private lateinit var REGISTER_PLAYER_PARAMETER: String
|
private lateinit var REGISTER_PLAYER_PARAMETER: String
|
||||||
|
private lateinit var REGISTER_PLAYLIST_ID: String
|
||||||
private lateinit var REGISTER_IS_SHORT_AND_OPENING_OR_PLAYING: String
|
private lateinit var REGISTER_IS_SHORT_AND_OPENING_OR_PLAYING: String
|
||||||
|
|
||||||
private lateinit var playerResponseMethod: MutableMethod
|
private lateinit var playerResponseMethod: MutableMethod
|
||||||
@ -46,10 +48,12 @@ object PlayerResponseMethodHookPatch :
|
|||||||
if (playerResponseMethodCopyRegisters) {
|
if (playerResponseMethodCopyRegisters) {
|
||||||
REGISTER_VIDEO_ID = "v0"
|
REGISTER_VIDEO_ID = "v0"
|
||||||
REGISTER_PLAYER_PARAMETER = "v1"
|
REGISTER_PLAYER_PARAMETER = "v1"
|
||||||
REGISTER_IS_SHORT_AND_OPENING_OR_PLAYING = "v2"
|
REGISTER_PLAYLIST_ID = "v2"
|
||||||
|
REGISTER_IS_SHORT_AND_OPENING_OR_PLAYING = "v3"
|
||||||
} else {
|
} else {
|
||||||
REGISTER_VIDEO_ID = "p$PARAMETER_VIDEO_ID"
|
REGISTER_VIDEO_ID = "p$PARAMETER_VIDEO_ID"
|
||||||
REGISTER_PLAYER_PARAMETER = "p$PARAMETER_PLAYER_PARAMETER"
|
REGISTER_PLAYER_PARAMETER = "p$PARAMETER_PLAYER_PARAMETER"
|
||||||
|
REGISTER_PLAYLIST_ID = "p$PARAMETER_PLAYLIST_ID"
|
||||||
REGISTER_IS_SHORT_AND_OPENING_OR_PLAYING = "p$PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING"
|
REGISTER_IS_SHORT_AND_OPENING_OR_PLAYING = "p$PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,7 +70,7 @@ object PlayerResponseMethodHookPatch :
|
|||||||
fun hookPlayerParameter(hook: Hook) {
|
fun hookPlayerParameter(hook: Hook) {
|
||||||
playerResponseMethod.addInstructions(
|
playerResponseMethod.addInstructions(
|
||||||
0, """
|
0, """
|
||||||
invoke-static {$REGISTER_VIDEO_ID, $REGISTER_PLAYER_PARAMETER, $REGISTER_IS_SHORT_AND_OPENING_OR_PLAYING}, $hook
|
invoke-static {$REGISTER_VIDEO_ID, $REGISTER_PLAYER_PARAMETER, $REGISTER_PLAYLIST_ID, $REGISTER_IS_SHORT_AND_OPENING_OR_PLAYING}, $hook
|
||||||
move-result-object $REGISTER_PLAYER_PARAMETER
|
move-result-object $REGISTER_PLAYER_PARAMETER
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
@ -90,11 +94,12 @@ object PlayerResponseMethodHookPatch :
|
|||||||
"""
|
"""
|
||||||
move-object/from16 $REGISTER_VIDEO_ID, p$PARAMETER_VIDEO_ID
|
move-object/from16 $REGISTER_VIDEO_ID, p$PARAMETER_VIDEO_ID
|
||||||
move-object/from16 $REGISTER_PLAYER_PARAMETER, p$PARAMETER_PLAYER_PARAMETER
|
move-object/from16 $REGISTER_PLAYER_PARAMETER, p$PARAMETER_PLAYER_PARAMETER
|
||||||
|
move-object/from16 $REGISTER_PLAYLIST_ID, p$PARAMETER_PLAYLIST_ID
|
||||||
move/from16 $REGISTER_IS_SHORT_AND_OPENING_OR_PLAYING, p$PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING
|
move/from16 $REGISTER_IS_SHORT_AND_OPENING_OR_PLAYING, p$PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING
|
||||||
""",
|
""",
|
||||||
)
|
)
|
||||||
|
|
||||||
numberOfInstructionsAdded += 3
|
numberOfInstructionsAdded += 4
|
||||||
|
|
||||||
// Move the modified register back.
|
// Move the modified register back.
|
||||||
addInstruction(
|
addInstruction(
|
||||||
|
@ -604,13 +604,35 @@ fun MutableMethod.getTargetIndexWithReferenceReversed(startIndex: Int, reference
|
|||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
fun MethodFingerprintResult.getWalkerMethod(context: BytecodeContext, index: Int) =
|
fun MethodFingerprintResult.getWalkerMethod(context: BytecodeContext, offset: Int) =
|
||||||
mutableMethod.getWalkerMethod(context, index)
|
mutableMethod.getWalkerMethod(context, offset)
|
||||||
|
|
||||||
fun MutableMethod.getWalkerMethod(context: BytecodeContext, index: Int) =
|
/**
|
||||||
context.toMethodWalker(this)
|
* MethodWalker structural limitations cause incorrect class to be found
|
||||||
.nextMethod(index, true)
|
*
|
||||||
.getMethod() as MutableMethod
|
* MethodReference to find in YouTube 18.29.38:
|
||||||
|
* 'Lng;->d(Lou;)Z'
|
||||||
|
*
|
||||||
|
* Class found by MethodWalker in YouTube 18.29.38:
|
||||||
|
* 'Lcom/google/android/gms/maps/model/LatLng;'
|
||||||
|
*
|
||||||
|
* The reason this error occurs is because [BytecodeContext.findClass] checks whether className is included or not
|
||||||
|
*
|
||||||
|
* In ReVanced Patcher 19.3.1:
|
||||||
|
* fun findClass(className: String) = findClass { it.type.contains(className) }
|
||||||
|
*
|
||||||
|
* (Class 'Lcom/google/android/gms/maps/model/LatLng;' is returned because class 'Lcom/google/android/gms/maps/model/LatLng;' contains keyword 'Lng;')
|
||||||
|
*
|
||||||
|
* As a workaround, redefine MethodWalker here
|
||||||
|
*/
|
||||||
|
fun MutableMethod.getWalkerMethod(context: BytecodeContext, offset: Int): MutableMethod {
|
||||||
|
val newMethod = getInstruction<ReferenceInstruction>(offset).reference as MethodReference
|
||||||
|
return context.findClass { classDef -> classDef.type == newMethod.definingClass }
|
||||||
|
?.mutableClass
|
||||||
|
?.methods
|
||||||
|
?.first { method -> MethodUtil.methodSignaturesMatch(method, newMethod) }
|
||||||
|
?: throw PatchException("This method can not be walked at offset $offset inside the method $name")
|
||||||
|
}
|
||||||
|
|
||||||
fun MutableClass.addFieldAndInstructions(
|
fun MutableClass.addFieldAndInstructions(
|
||||||
context: BytecodeContext,
|
context: BytecodeContext,
|
||||||
|
@ -63,6 +63,12 @@ fun String.startsWithAny(vararg prefixes: String): Boolean {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun List<String>.getResourceGroup(fileNames: Array<String>) = map { directory ->
|
||||||
|
ResourceGroup(
|
||||||
|
directory, *fileNames
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun ResourceContext.copyFile(
|
fun ResourceContext.copyFile(
|
||||||
resourceGroup: List<ResourceGroup>,
|
resourceGroup: List<ResourceGroup>,
|
||||||
path: String,
|
path: String,
|
||||||
@ -98,16 +104,25 @@ fun ResourceContext.copyFile(
|
|||||||
*
|
*
|
||||||
* @param sourceResourceDirectory The source resource directory name.
|
* @param sourceResourceDirectory The source resource directory name.
|
||||||
* @param resources The resources to copy.
|
* @param resources The resources to copy.
|
||||||
|
* @param createDirectoryIfNotExist Whether to create a new directory if it does not exist.
|
||||||
*/
|
*/
|
||||||
fun ResourceContext.copyResources(
|
fun ResourceContext.copyResources(
|
||||||
sourceResourceDirectory: String,
|
sourceResourceDirectory: String,
|
||||||
vararg resources: ResourceGroup,
|
vararg resources: ResourceGroup,
|
||||||
|
createDirectoryIfNotExist: Boolean = false,
|
||||||
) {
|
) {
|
||||||
val targetResourceDirectory = this["res"]
|
val targetResourceDirectory = this["res"]
|
||||||
|
|
||||||
for (resourceGroup in resources) {
|
for (resourceGroup in resources) {
|
||||||
resourceGroup.resources.forEach { resource ->
|
resourceGroup.resources.forEach { resource ->
|
||||||
val resourceFile = "${resourceGroup.resourceDirectoryName}/$resource"
|
val resourceDirectoryName = resourceGroup.resourceDirectoryName
|
||||||
|
|
||||||
|
if (createDirectoryIfNotExist) {
|
||||||
|
val targetDirectory = targetResourceDirectory.resolve(resourceDirectoryName)
|
||||||
|
if (!targetDirectory.isDirectory) Files.createDirectories(targetDirectory.toPath())
|
||||||
|
}
|
||||||
|
|
||||||
|
val resourceFile = "$resourceDirectoryName/$resource"
|
||||||
|
|
||||||
inputStreamFromBundledResource(
|
inputStreamFromBundledResource(
|
||||||
sourceResourceDirectory,
|
sourceResourceDirectory,
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 3.5 KiB |
@ -73,6 +73,8 @@ If it is disabled, fullscreen ads are blocked. (there may be side effects)"</str
|
|||||||
<string name="revanced_hide_premium_promotion_summary">Hides premium promotion popups.</string>
|
<string name="revanced_hide_premium_promotion_summary">Hides premium promotion popups.</string>
|
||||||
<string name="revanced_hide_premium_renewal_title">Hide premium renewal banner</string>
|
<string name="revanced_hide_premium_renewal_title">Hide premium renewal banner</string>
|
||||||
<string name="revanced_hide_premium_renewal_summary">Hides the premium renewal banner.</string>
|
<string name="revanced_hide_premium_renewal_summary">Hides the premium renewal banner.</string>
|
||||||
|
<string name="revanced_hide_promotion_alert_banner_title">Hide promotion alert banner</string>
|
||||||
|
<string name="revanced_hide_promotion_alert_banner_summary">Hides the promotion alert banner.</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- PreferenceScreen: Flyout -->
|
<!-- PreferenceScreen: Flyout -->
|
||||||
@ -271,8 +273,12 @@ Some features may not work properly in the old player layout."</string>
|
|||||||
<string name="revanced_custom_playback_speeds_summary">Add or change available playback speeds.</string>
|
<string name="revanced_custom_playback_speeds_summary">Add or change available playback speeds.</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_title">Remember playback speed changes</string>
|
<string name="revanced_remember_playback_speed_last_selected_title">Remember playback speed changes</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_summary">Remembers the last playback speed selected.</string>
|
<string name="revanced_remember_playback_speed_last_selected_summary">Remembers the last playback speed selected.</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_title">Show a toast</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_summary">Show a toast when changing the default playback speed.</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_title">Remember video quality changes</string>
|
<string name="revanced_remember_video_quality_last_selected_title">Remember video quality changes</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_summary">Remembers the last video quality selected.</string>
|
<string name="revanced_remember_video_quality_last_selected_summary">Remembers the last video quality selected.</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_title">Show a toast</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_summary">Show a toast when changing the default video quality.</string>
|
||||||
<string name="revanced_custom_playback_speeds_invalid">Custom speeds must be less than %sx. Using default values.</string>
|
<string name="revanced_custom_playback_speeds_invalid">Custom speeds must be less than %sx. Using default values.</string>
|
||||||
<string name="revanced_custom_playback_speeds_parse_exception">Invalid custom playback speeds. Using default values.</string>
|
<string name="revanced_custom_playback_speeds_parse_exception">Invalid custom playback speeds. Using default values.</string>
|
||||||
<string name="revanced_remember_playback_speed_toast">Changing default speed to %s.</string>
|
<string name="revanced_remember_playback_speed_toast">Changing default speed to %s.</string>
|
||||||
@ -299,7 +305,6 @@ Some features may not work properly in the old player layout."</string>
|
|||||||
<string name="revanced_ryd_failure_connection_status_code">Dislikes are unavailable (status %d).</string>
|
<string name="revanced_ryd_failure_connection_status_code">Dislikes are unavailable (status %d).</string>
|
||||||
<string name="revanced_ryd_failure_client_rate_limit_requested">Dislikes are unavailable (client API limit reached).</string>
|
<string name="revanced_ryd_failure_client_rate_limit_requested">Dislikes are unavailable (client API limit reached).</string>
|
||||||
<string name="revanced_ryd_failure_generic">Dislikes are unavailable (%s).</string>
|
<string name="revanced_ryd_failure_generic">Dislikes are unavailable (%s).</string>
|
||||||
<string name="revanced_ryd_video_likes_hidden_by_video_owner">Hidden</string>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- PreferenceScreen: SponsorBlock -->
|
<!-- PreferenceScreen: SponsorBlock -->
|
||||||
@ -373,8 +378,8 @@ Some features may not work properly in the old player layout."</string>
|
|||||||
<string name="revanced_bypass_image_region_restrictions_summary">Replaces the domain that is blocked in some regions so that playlist thumbnails, channel avatars, etc. can be received.</string>
|
<string name="revanced_bypass_image_region_restrictions_summary">Replaces the domain that is blocked in some regions so that playlist thumbnails, channel avatars, etc. can be received.</string>
|
||||||
<string name="revanced_change_share_sheet_title">Change share sheet</string>
|
<string name="revanced_change_share_sheet_title">Change share sheet</string>
|
||||||
<string name="revanced_change_share_sheet_summary">Change from in-app share sheet to system share sheet.</string>
|
<string name="revanced_change_share_sheet_summary">Change from in-app share sheet to system share sheet.</string>
|
||||||
<string name="revanced_enable_cairo_splash_animation_title">Enable Cairo splash animation</string>
|
<string name="revanced_disable_cairo_splash_animation_title">Disable Cairo splash animation</string>
|
||||||
<string name="revanced_enable_cairo_splash_animation_summary">Enables Cairo splash animation when the app starts up.</string>
|
<string name="revanced_disable_cairo_splash_animation_summary">Disables Cairo splash animation when the app starts up.</string>
|
||||||
<string name="revanced_enable_debug_logging_title">Enable debug logging</string>
|
<string name="revanced_enable_debug_logging_title">Enable debug logging</string>
|
||||||
<string name="revanced_enable_debug_logging_summary">Prints the debug log.</string>
|
<string name="revanced_enable_debug_logging_summary">Prints the debug log.</string>
|
||||||
<string name="revanced_enable_debug_buffer_logging_title">Enable debug buffer logging</string>
|
<string name="revanced_enable_debug_buffer_logging_title">Enable debug buffer logging</string>
|
||||||
|
@ -1,31 +1,198 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Shared PreferenceScreen -->
|
<!-- Shared PreferenceScreen -->
|
||||||
|
<string name="revanced_extended_settings_title">ReVanced Extended</string>
|
||||||
<!-- Shared Category -->
|
<!-- Shared Category -->
|
||||||
|
<string name="revanced_extended_restart_first_run">Рестартирайте, за да заредите оформлението нормално</string>
|
||||||
|
<string name="revanced_extended_restart_message">Опреснете и рестартирайте</string>
|
||||||
<!-- PreferenceScreen: Account -->
|
<!-- PreferenceScreen: Account -->
|
||||||
|
<string name="revanced_preference_screen_account_title">Акаунт</string>
|
||||||
|
<string name="revanced_hide_account_menu_title">Скриване на менюто на акаунта</string>
|
||||||
|
<string name="revanced_hide_account_menu_summary">Скрива елементи от менюто на акаунта в персонализиран филтър.</string>
|
||||||
|
<string name="revanced_hide_account_menu_filter_strings_title">Промяна на филтъра на менюто на акаунта</string>
|
||||||
|
<string name="revanced_hide_account_menu_filter_strings_summary">Списък с имена на менюта на акаунти за филтриране, разделени с нови редове.</string>
|
||||||
|
<string name="revanced_hide_account_menu_empty_component_title">Скриване на празни компоненти</string>
|
||||||
|
<string name="revanced_hide_account_menu_empty_component_summary">Скрива празните компоненти в менюто на акаунта.</string>
|
||||||
<string name="revanced_hide_handle_title">Скриване на връзки</string>
|
<string name="revanced_hide_handle_title">Скриване на връзки</string>
|
||||||
|
<string name="revanced_hide_handle_summary">Скрива имейл/@ник в менюто за промяна на акаунта.</string>
|
||||||
|
<string name="revanced_hide_terms_container_title">Скриване на информацията за поверителност</string>
|
||||||
|
<string name="revanced_hide_terms_container_summary">Скриване на подробностите за поверителност / правила и условия.</string>
|
||||||
<!-- PreferenceScreen: Action Bar -->
|
<!-- PreferenceScreen: Action Bar -->
|
||||||
|
<string name="revanced_preference_screen_action_bar_title">Лента с действия</string>
|
||||||
|
<string name="revanced_hide_action_button_like_dislike_title">Скриване на бутоните за харесване и нехаресване</string>
|
||||||
|
<string name="revanced_hide_action_button_like_dislike_summary">Скрива бутоните „Харесвам“ и „Не харесвам“. Не работи в стария интерфейс на плейъра.</string>
|
||||||
|
<string name="revanced_hide_action_button_comment_title">Скриване на бутона за коментари</string>
|
||||||
|
<string name="revanced_hide_action_button_comment_summary">Скрийте бутона „Коментари“.</string>
|
||||||
|
<string name="revanced_hide_action_button_add_to_playlist_title">Бутон \"Запазване\"</string>
|
||||||
|
<string name="revanced_hide_action_button_add_to_playlist_summary">Скрива бутона \"Запазване\".</string>
|
||||||
|
<string name="revanced_hide_action_button_download_title">Скриване на бутона за изтегляне</string>
|
||||||
|
<string name="revanced_hide_action_button_download_summary">Скрива бутона „Изтегляне“.</string>
|
||||||
|
<string name="revanced_hide_action_button_share_title">Скриване на бутона за споделяне</string>
|
||||||
|
<string name="revanced_hide_action_button_share_summary">Скрива бутона „Споделяне“.</string>
|
||||||
|
<string name="revanced_hide_action_button_radio_title">Скрийте бутона \"Радио\"</string>
|
||||||
|
<string name="revanced_hide_action_button_radio_summary">Скрива бутона \"Радио\".</string>
|
||||||
|
<string name="revanced_hide_action_button_label_title">Скриване на етикетите на бутоните за действие</string>
|
||||||
|
<string name="revanced_hide_action_button_label_summary">Скрива. етикетите на бутоните за действие.</string>
|
||||||
|
<string name="revanced_external_downloader_action_title">Замяна на бутона за изтегляне</string>
|
||||||
|
<string name="revanced_external_downloader_action_summary">"Бутонът \"Изтегляне\" отваря външната програма за изтегляне.
|
||||||
|
|
||||||
|
• Заменя само бутона за изтегляне в плейъра.
|
||||||
|
• Не отменя бутона за изтегляне в изскачащото меню или библиотеката."</string>
|
||||||
<string name="revanced_external_downloader_package_name_title">Име на пакета на външно приложение за изтегляне</string>
|
<string name="revanced_external_downloader_package_name_title">Име на пакета на външно приложение за изтегляне</string>
|
||||||
<string name="revanced_external_downloader_package_name_summary">Име на пакета на приложението за изтегляне като NewPipe или YTDLnis.</string>
|
<string name="revanced_external_downloader_package_name_summary">Име на пакета на приложението за изтегляне като NewPipe или YTDLnis.</string>
|
||||||
|
<string name="revanced_external_downloader_dialog_title">Външна програма за изтегляне</string>
|
||||||
|
<string name="revanced_external_downloader_not_installed_dialog_title">Внимание</string>
|
||||||
|
<string name="revanced_external_downloader_not_installed_dialog_message">"%1$s не е инсталиран.
|
||||||
|
Моля, изтеглете %2$s от уебсайта."</string>
|
||||||
<string name="revanced_external_downloader_not_installed_warning">%s не е инсталирано. Моля инсталирайте го.</string>
|
<string name="revanced_external_downloader_not_installed_warning">%s не е инсталирано. Моля инсталирайте го.</string>
|
||||||
<!-- PreferenceScreen: Ads -->
|
<!-- PreferenceScreen: Ads -->
|
||||||
|
<string name="revanced_preference_screen_ads_title">Реклами</string>
|
||||||
|
<string name="revanced_hide_fullscreen_ads_title">Скриване на рекламите в режим на цял екран</string>
|
||||||
|
<string name="revanced_hide_fullscreen_ads_summary">Скриване на рекламите в режим на цял екран.</string>
|
||||||
|
<string name="revanced_hide_fullscreen_ads_type_title">Как да затворите реклами на цял екран</string>
|
||||||
|
<string name="revanced_hide_fullscreen_ads_type_summary">"Ако е активирана, рекламата на цял екран се затваря чрез бутона Затвори.
|
||||||
|
Ако е деактивирано, рекламата на цял екран е блокирана. (могат да възникнат нежелани реакции)"</string>
|
||||||
|
<string name="revanced_hide_fullscreen_ads_blocked_success">Рекламите на цял екран са блокирани. (Тип на диалоговия прозорец: %s)</string>
|
||||||
|
<string name="revanced_hide_fullscreen_ads_closed_success">Рекламите на цял екран са затворени.</string>
|
||||||
|
<string name="revanced_hide_general_ads_title">Скриване на общите реклами</string>
|
||||||
|
<string name="revanced_hide_general_ads_summary">Скриване на общите реклами.</string>
|
||||||
|
<string name="revanced_hide_music_ads_title">Скриване на музикални реклами</string>
|
||||||
|
<string name="revanced_hide_music_ads_summary">Скрива реклами преди възпроизвеждане на музика.</string>
|
||||||
|
<string name="revanced_hide_paid_promotion_label_title">Скриване на платените промоции</string>
|
||||||
|
<string name="revanced_hide_paid_promotion_label_summary">Скриване на платените промоции.</string>
|
||||||
|
<string name="revanced_hide_premium_promotion_title">Скриване на изскачащи реклами Premium</string>
|
||||||
|
<string name="revanced_hide_premium_promotion_summary">Скрива изскачащи реклами Premium.</string>
|
||||||
|
<string name="revanced_hide_premium_renewal_title">Скриване на банера за подновяване на Premium</string>
|
||||||
|
<string name="revanced_hide_premium_renewal_summary">Скриване на банера за подновяване на Premium.</string>
|
||||||
<!-- PreferenceScreen: Flyout -->
|
<!-- PreferenceScreen: Flyout -->
|
||||||
|
<string name="revanced_preference_screen_flyout_title">Падащо меню</string>
|
||||||
|
<string name="revanced_enable_compact_dialog_title">Компактен изглед на прозореца</string>
|
||||||
|
<string name="revanced_enable_compact_dialog_summary">"Активира компактно изскачащо меню на телефони.
|
||||||
|
|
||||||
|
Известни проблеми:
|
||||||
|
• Скрийнсейвърите на албуми в раздела \"Библиотека\" стават по-малки в мрежа.
|
||||||
|
• Интерфейсът за автоматично изключване може да изглежда необичайно."</string>
|
||||||
|
<string name="revanced_enable_trim_silence_title">Добавете опция „Скриване на мълчанията“</string>
|
||||||
|
<string name="revanced_enable_trim_silence_summary">"Добавя „Скриване на мълчанията“ към падащото меню „Скорост на възпроизвеждане“.
|
||||||
|
|
||||||
|
Информация:
|
||||||
|
• Тази функция е предназначена за подкасти.
|
||||||
|
• Тази функция все още е в процес на разработка, така че може да е нестабилна."</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_like_dislike_title">Скриване на бутоните за харесване и нехаресване</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_3_column_component_title">Скриване на компонента с 3 колони</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_add_to_queue_title">Скрийте бутона „Добавяне към опашката“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_captions_title">Скриване на менюто за субтитри</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_delete_playlist_title">Скрийте менюто „Изтриване на плейлист“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_dismiss_queue_title">Скрийте менюто „Изтриване на опашката“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_download_title">Скрийте менюто „Изтегляне“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_edit_playlist_title">Скрийте менюто „Редактиране на плейлист“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_go_to_album_title">Скрийте менюто „Отиди на албум“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_go_to_artist_title">Скрийте менюто „Отидете на страницата на изпълнителя“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_go_to_episode_title">Скрийте менюто „Отидете на епизод“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_go_to_podcast_title">Скрийте менюто „Отидете на подкаст“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_help_title">Скриване на менюто & за помощ</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_play_next_title">Скрийте менюто „Пусни следващия клип“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_quality_title">Скрийте менюто „Качество“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_remove_from_library_title">Скрийте менюто „Премахване от библиотеката“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_remove_from_playlist_title">Скрийте менюто „Изтриване на плейлист“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_report_title">Меню за докладване</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_save_episode_for_later_title">Скрийте менюто „Запазване за гледане по-късно“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_save_to_library_title">Скрийте менюто „Запазване в библиотеката“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_save_to_playlist_title">Скрийте менюто „Запазване в плейлист“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_share_title">Скрийте менюто „Споделяне“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_shuffle_play_title">Скрийте бутона „Разбъркване“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_sleep_timer_title">Скрийте менюто „Изчакване на заспиване“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_start_radio_title">Скрийте менюто „Стартиране на радио“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_stats_for_nerds_title">Меню \"Статистика за сис. администратори\"</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_subscribe_title">Скрийте менюто „Абониране“ / „Отписване“</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_view_song_credit_title">Скрийте менюто „Подробности за заглавие“</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_dismiss_queue_continue_watch_title">Продължете да гледате</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_dismiss_queue_continue_watch_summary">Видеото продължава от текущото време на гледане, когато отидете в YouTube.</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_dismiss_queue_watch_on_youtube_label">Гледайте в YouTube</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_dismiss_queue_watch_on_youtube_warning">Невалиден Url адрес на видеото.</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_dismiss_queue_title">Заменете менюто „Премахване от опашката“</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_dismiss_queue_summary">Заменя менюто „Премахване от опашката“ с менюто „Гледайте в YouTube“.</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_report_title">Заменете менюто „Докладвай“</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_report_summary">Заменя менюто Доклад с менюто Скорост на възпроизвеждане.</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_report_only_player_title">Запазете доклада в коментарите</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_report_only_player_summary">Запазва менюто Доклад в раздела за коментари непокътнато.</string>
|
||||||
<!-- PreferenceScreen: General -->
|
<!-- PreferenceScreen: General -->
|
||||||
|
<string name="revanced_preference_screen_general_title">Главни</string>
|
||||||
|
<string name="revanced_change_start_page_title">Промяна на началната страница</string>
|
||||||
|
<string name="revanced_change_start_page_summary">Изберете на коя страница да се отвори приложението.</string>
|
||||||
|
<string name="revanced_change_start_page_entry_chart">Хит-парад</string>
|
||||||
|
<string name="revanced_change_start_page_entry_explore">Преглед</string>
|
||||||
|
<string name="revanced_change_start_page_entry_home">Начало</string>
|
||||||
|
<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_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">Désactiver la redirection du bouton \"Je n\'aime pas\"</string>
|
||||||
|
<string name="revanced_disable_dislike_redirection_summary">Деактивира пренасочването към следващата песен, когато щракнете върху бутона „Не харесвам“.</string>
|
||||||
<string name="revanced_enable_landscape_mode_title">Позволи Пейзажен Режим</string>
|
<string name="revanced_enable_landscape_mode_title">Позволи Пейзажен Режим</string>
|
||||||
|
<string name="revanced_enable_landscape_mode_summary">Активира пейзажен режим при завъртане на телефона.</string>
|
||||||
<string name="revanced_custom_filter_title">Вкл. на филтър по избор</string>
|
<string name="revanced_custom_filter_title">Вкл. на филтър по избор</string>
|
||||||
<string name="revanced_custom_filter_summary">Активира персонализиран филтър за скриване на компонентите на оформлението.</string>
|
<string name="revanced_custom_filter_summary">Активира персонализиран филтър за скриване на компонентите на оформлението.</string>
|
||||||
<string name="revanced_custom_filter_strings_title">Редактиране на потребителския филтъра</string>
|
<string name="revanced_custom_filter_strings_title">Редактиране на потребителския филтъра</string>
|
||||||
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
|
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
|
||||||
<string name="revanced_custom_filter_strings_summary">Филтриране на компонентите по имена.</string>
|
<string name="revanced_custom_filter_strings_summary">Филтриране на компонентите по имена.</string>
|
||||||
|
<string name="revanced_custom_filter_toast_invalid_syntax">Невалиден потребителски филтър: %s.</string>
|
||||||
|
<string name="revanced_hide_settings_menu_title">Скрийте менюто „Настройки“</string>
|
||||||
|
<string name="revanced_hide_settings_menu_summary">"Скриване на елементи от менюто с настройки.
|
||||||
|
Това не само скрива менюто с настройки на YT Music, но и менюто с разширени настройки на ReVanced."</string>
|
||||||
|
<string name="revanced_hide_settings_menu_filter_strings_title">Филтър на менюто „Настройки“</string>
|
||||||
|
<string name="revanced_hide_settings_menu_filter_strings_summary">Списък с имена на менюта на параметри за филтриране, разделени с нов ред.</string>
|
||||||
|
<string name="revanced_hide_button_shelf_title">Скриване на секцията с бутони</string>
|
||||||
|
<string name="revanced_hide_button_shelf_summary">Скриване на секцията с бутони в емисията.</string>
|
||||||
|
<string name="revanced_hide_carousel_shelf_title">Скриване на рафта с Препоръчани</string>
|
||||||
|
<string name="revanced_hide_carousel_shelf_summary">Скриване на рафтовете с предложения в емисиите.</string>
|
||||||
|
<string name="revanced_hide_playlist_card_shelf_title">Скрийте рафтовете „Списъци за изпълнение“</string>
|
||||||
|
<string name="revanced_hide_playlist_card_shelf_summary">Скрива рафтовете с карти „Списъци за изпълнение“ в емисии.</string>
|
||||||
|
<string name="revanced_hide_samples_shelf_title">Скрийте рафта „Семпли“</string>
|
||||||
|
<string name="revanced_hide_samples_shelf_summary">Скриване на рафтовете с Семпли в емисиите.</string>
|
||||||
|
<string name="revanced_hide_cast_button_title">Скриване на бутона за предаване на Тв</string>
|
||||||
|
<string name="revanced_hide_cast_button_summary">Скрива бутона \"Излъчване\".</string>
|
||||||
|
<string name="revanced_hide_category_bar_title">Скриване на панела с Категории</string>
|
||||||
|
<string name="revanced_hide_category_bar_summary">Скриване на панела с категории.</string>
|
||||||
|
<string name="revanced_hide_floating_button_title">Скриване на изскачащ бутон</string>
|
||||||
|
<string name="revanced_hide_floating_button_summary">Скрива плаващите бутони в библиотеката.</string>
|
||||||
|
<string name="revanced_hide_tap_to_update_button_title">Скрийте бутона „Докоснете за актуализиране“</string>
|
||||||
|
<string name="revanced_hide_tap_to_update_button_summary">Скриване на бутона „Докоснете за актуализиране“.</string>
|
||||||
|
<string name="revanced_hide_history_button_title">Скрийте бутона \"История\"</string>
|
||||||
|
<string name="revanced_hide_history_button_summary">Скрива бутона \"История\" от лентата с инструменти.</string>
|
||||||
|
<string name="revanced_hide_notification_button_title">Бутон за Известия</string>
|
||||||
|
<string name="revanced_hide_notification_button_summary">Скрива бутона „Известие“ от лентата с инструменти.</string>
|
||||||
|
<string name="revanced_hide_sound_search_button_title">Бутон за \"Звуково търсене\"</string>
|
||||||
|
<string name="revanced_hide_sound_search_button_summary">Скрива бутона „звуково търсене на музика“ от лентата за търсене.</string>
|
||||||
|
<string name="revanced_hide_voice_search_button_title">Бутон за \"гласово търсене\"</string>
|
||||||
|
<string name="revanced_hide_voice_search_button_summary">Скрива бутона „Гласово търсене“ от лентата за търсене.</string>
|
||||||
|
<string name="revanced_restore_old_style_library_shelf_title">Възстановете стария стил на рафта „Библиотека“</string>
|
||||||
|
<string name="revanced_restore_old_style_library_shelf_summary">Възстановява стария стил на рафт \"Библиотека\". (Експериментално)</string>
|
||||||
|
<string name="revanced_remove_viewer_discretion_dialog_title">Скриване на прозореца за възрастово ограничение</string>
|
||||||
|
<string name="revanced_remove_viewer_discretion_dialog_summary">"Премахва диалоговите прозорци. Това не заобикаля възрастовите ограничения, но ги приема автоматично."</string>
|
||||||
|
<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>
|
||||||
|
<string name="revanced_spoof_app_version_target_entry_4_27_53">4.27.53 - Деактивира радио режима в регионите на Канада</string>
|
||||||
|
<string name="revanced_spoof_app_version_target_entry_6_11_52">6.11.52 -Изключва речта в реално време</string>
|
||||||
<!-- PreferenceScreen: Navigation Bar -->
|
<!-- PreferenceScreen: Navigation Bar -->
|
||||||
|
<string name="revanced_preference_screen_navigation_title">Лента за навигация</string>
|
||||||
<string name="revanced_enable_black_navigation_bar_title">Включване на черна навигационна лента</string>
|
<string name="revanced_enable_black_navigation_bar_title">Включване на черна навигационна лента</string>
|
||||||
<string name="revanced_enable_black_navigation_bar_summary">Задава цвета на лентата за навигация на черен.</string>
|
<string name="revanced_enable_black_navigation_bar_summary">Задава цвета на лентата за навигация на черен.</string>
|
||||||
|
<string name="revanced_hide_navigation_home_button_title">Скриване на бутон за Начало</string>
|
||||||
|
<string name="revanced_hide_navigation_home_button_summary">Скрива бутона \"Начало\".</string>
|
||||||
|
<string name="revanced_hide_navigation_explore_button_title">Скриване на бутона \"навигация\"</string>
|
||||||
|
<string name="revanced_hide_navigation_explore_button_summary">Скрива. бутона за Преглед.</string>
|
||||||
|
<string name="revanced_hide_navigation_library_button_title">Бутона за Библиотека</string>
|
||||||
<string name="revanced_hide_navigation_bar_title">Скриване лентата за навигация</string>
|
<string name="revanced_hide_navigation_bar_title">Скриване лентата за навигация</string>
|
||||||
<string name="revanced_hide_navigation_bar_summary">Скриване лентата за навигация.</string>
|
<string name="revanced_hide_navigation_bar_summary">Скриване лентата за навигация.</string>
|
||||||
<string name="revanced_hide_navigation_label_title">Скриване на навигационен панел</string>
|
<string name="revanced_hide_navigation_label_title">Скриване на навигационен панел</string>
|
||||||
<!-- PreferenceScreen: Player -->
|
<!-- PreferenceScreen: Player -->
|
||||||
|
<string name="revanced_preference_screen_player_title">Плеър</string>
|
||||||
<string name="revanced_enable_color_match_player_title">A játékos színmegfelelésének engedélyezése</string>
|
<string name="revanced_enable_color_match_player_title">A játékos színmegfelelésének engedélyezése</string>
|
||||||
<string name="revanced_enable_color_match_player_summary">Цветът на плейъра на цял екран съответства с цвета на минимизирания.</string>
|
<string name="revanced_enable_color_match_player_summary">Цветът на плейъра на цял екран съответства с цвета на минимизирания.</string>
|
||||||
<string name="revanced_enable_force_minimized_player_title">Kapcsolja be az állandó összeomlott lejátszót</string>
|
<string name="revanced_enable_force_minimized_player_title">Kapcsolja be az állandó összeomlott lejátszót</string>
|
||||||
@ -42,7 +209,6 @@
|
|||||||
<string name="revanced_ryd_about">Относно</string>
|
<string name="revanced_ryd_about">Относно</string>
|
||||||
<string name="revanced_ryd_attribution_summary">Данните за нехаресване са от Return YouTube Dislike API. Докоснете за да научите повече.</string>
|
<string name="revanced_ryd_attribution_summary">Данните за нехаресване са от Return YouTube Dislike API. Докоснете за да научите повече.</string>
|
||||||
<string name="revanced_ryd_failure_client_rate_limit_requested">Нехаресванията не са достъпни (достигнат лимит на API).</string>
|
<string name="revanced_ryd_failure_client_rate_limit_requested">Нехаресванията не са достъпни (достигнат лимит на API).</string>
|
||||||
<string name="revanced_ryd_video_likes_hidden_by_video_owner">Скрит</string>
|
|
||||||
<!-- PreferenceScreen: SponsorBlock -->
|
<!-- PreferenceScreen: SponsorBlock -->
|
||||||
<!-- PreferenceScreen: Miscellaneous -->
|
<!-- PreferenceScreen: Miscellaneous -->
|
||||||
<string name="revanced_enable_debug_logging_title">Вкл. отчети за грешки</string>
|
<string name="revanced_enable_debug_logging_title">Вкл. отчети за грешки</string>
|
||||||
|
@ -66,7 +66,6 @@
|
|||||||
<string name="revanced_ryd_about">সম্পর্কে</string>
|
<string name="revanced_ryd_about">সম্পর্কে</string>
|
||||||
<string name="revanced_ryd_attribution_summary">তথ্য প্রদান করা হয় Return YouTube Dislike API দ্বারা। আরও জানতে আলতো চাপুন।</string>
|
<string name="revanced_ryd_attribution_summary">তথ্য প্রদান করা হয় Return YouTube Dislike API দ্বারা। আরও জানতে আলতো চাপুন।</string>
|
||||||
<string name="revanced_ryd_failure_client_rate_limit_requested">অপছন্দ পাওয়া যাচ্ছে না (ক্লায়েন্ট API সর্বোচ্চ সীমা পৌঁছেছে)</string>
|
<string name="revanced_ryd_failure_client_rate_limit_requested">অপছন্দ পাওয়া যাচ্ছে না (ক্লায়েন্ট API সর্বোচ্চ সীমা পৌঁছেছে)</string>
|
||||||
<string name="revanced_ryd_video_likes_hidden_by_video_owner">লুকায়িত</string>
|
|
||||||
<!-- PreferenceScreen: SponsorBlock -->
|
<!-- PreferenceScreen: SponsorBlock -->
|
||||||
<!-- PreferenceScreen: Miscellaneous -->
|
<!-- PreferenceScreen: Miscellaneous -->
|
||||||
<string name="revanced_enable_debug_logging_title">ডিবাগ লগ সক্রিয় করুন</string>
|
<string name="revanced_enable_debug_logging_title">ডিবাগ লগ সক্রিয় করুন</string>
|
||||||
|
@ -64,6 +64,8 @@
|
|||||||
<string name="revanced_hide_premium_promotion_summary">Απόκρυψη των αναδυόμενων παραθύρων προώθησης Premium.</string>
|
<string name="revanced_hide_premium_promotion_summary">Απόκρυψη των αναδυόμενων παραθύρων προώθησης Premium.</string>
|
||||||
<string name="revanced_hide_premium_renewal_title">Απόκρυψη διαφημιστικού ανανέωσης Premium</string>
|
<string name="revanced_hide_premium_renewal_title">Απόκρυψη διαφημιστικού ανανέωσης Premium</string>
|
||||||
<string name="revanced_hide_premium_renewal_summary">Απόκρυψη του διαφημιστικού ανανέωσης YT Premium.</string>
|
<string name="revanced_hide_premium_renewal_summary">Απόκρυψη του διαφημιστικού ανανέωσης YT Premium.</string>
|
||||||
|
<string name="revanced_hide_promotion_alert_banner_title">Απόκρυψη ετικετών προειδοποίησης προώθησης</string>
|
||||||
|
<string name="revanced_hide_promotion_alert_banner_summary">Απόκρυψη των ετικετών προειδοποίησης προώθησης.</string>
|
||||||
<!-- PreferenceScreen: Flyout -->
|
<!-- PreferenceScreen: Flyout -->
|
||||||
<string name="revanced_preference_screen_flyout_title">Αναδυόμενο μενού ρυθμίσεων</string>
|
<string name="revanced_preference_screen_flyout_title">Αναδυόμενο μενού ρυθμίσεων</string>
|
||||||
<string name="revanced_enable_compact_dialog_title">Αναδυόμενο μενού μικρότερου στυλ</string>
|
<string name="revanced_enable_compact_dialog_title">Αναδυόμενο μενού μικρότερου στυλ</string>
|
||||||
@ -247,8 +249,12 @@
|
|||||||
<string name="revanced_custom_playback_speeds_summary">Ρύθμιση των διαθέσιμων ταχυτήτων αναπαραγωγής.</string>
|
<string name="revanced_custom_playback_speeds_summary">Ρύθμιση των διαθέσιμων ταχυτήτων αναπαραγωγής.</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_title">Απομνημόνευση αλλαγών ταχύτητας αναπαραγωγής</string>
|
<string name="revanced_remember_playback_speed_last_selected_title">Απομνημόνευση αλλαγών ταχύτητας αναπαραγωγής</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_summary">Απομνημόνευση της τελευταίας ταχύτητας αναπαραγωγής που επιλέχθηκε.</string>
|
<string name="revanced_remember_playback_speed_last_selected_summary">Απομνημόνευση της τελευταίας ταχύτητας αναπαραγωγής που επιλέχθηκε.</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_title">Εμφάνιση μηνύματος</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_summary">Εμφάνιση μηνύματος στο κάτω μέρος της οθόνης κατά την αλλαγή προεπιλεγμένης ταχύτητας αναπαραγωγής.</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_title">Απομνημόνευση αλλαγών ποιότητας βίντεο</string>
|
<string name="revanced_remember_video_quality_last_selected_title">Απομνημόνευση αλλαγών ποιότητας βίντεο</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_summary">Απομνημόνευση της τελευταίας ποιότητας βίντεο που επιλέχθηκε.</string>
|
<string name="revanced_remember_video_quality_last_selected_summary">Απομνημόνευση της τελευταίας ποιότητας βίντεο που επιλέχθηκε.</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_title">Εμφάνιση μηνύματος</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_summary">Εμφάνιση μηνύματος στο κάτω μέρος της οθόνης κατά την αλλαγή προεπιλεγμένης ποιότητας βίντεο.</string>
|
||||||
<string name="revanced_custom_playback_speeds_invalid">Οι ταχύτητες πρέπει να είναι μικρότερες από %sx, επαναφέρθηκαν.</string>
|
<string name="revanced_custom_playback_speeds_invalid">Οι ταχύτητες πρέπει να είναι μικρότερες από %sx, επαναφέρθηκαν.</string>
|
||||||
<string name="revanced_custom_playback_speeds_parse_exception">Μη έγκυρες ταχύτητες αναπαραγωγής, επαναφέρθηκαν.</string>
|
<string name="revanced_custom_playback_speeds_parse_exception">Μη έγκυρες ταχύτητες αναπαραγωγής, επαναφέρθηκαν.</string>
|
||||||
<string name="revanced_remember_playback_speed_toast">Η προεπιλεγμένη ταχύτητα άλλαξε σε %s.</string>
|
<string name="revanced_remember_playback_speed_toast">Η προεπιλεγμένη ταχύτητα άλλαξε σε %s.</string>
|
||||||
@ -272,7 +278,6 @@
|
|||||||
<string name="revanced_ryd_failure_connection_status_code">Δεδομένα dislike μη διαθέσιμα (κατάσταση %d).</string>
|
<string name="revanced_ryd_failure_connection_status_code">Δεδομένα dislike μη διαθέσιμα (κατάσταση %d).</string>
|
||||||
<string name="revanced_ryd_failure_client_rate_limit_requested">Δεδομένα dislike μη διαθέσιμα (το όριο API έχει επιτευχθεί).</string>
|
<string name="revanced_ryd_failure_client_rate_limit_requested">Δεδομένα dislike μη διαθέσιμα (το όριο API έχει επιτευχθεί).</string>
|
||||||
<string name="revanced_ryd_failure_generic">Δεδομένα dislike μη διαθέσιμα (%s).</string>
|
<string name="revanced_ryd_failure_generic">Δεδομένα dislike μη διαθέσιμα (%s).</string>
|
||||||
<string name="revanced_ryd_video_likes_hidden_by_video_owner">Κρυμμένα</string>
|
|
||||||
<!-- PreferenceScreen: SponsorBlock -->
|
<!-- PreferenceScreen: SponsorBlock -->
|
||||||
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
||||||
<string name="revanced_sb_enabled">Ενεργοποίηση του SponsorBlock</string>
|
<string name="revanced_sb_enabled">Ενεργοποίηση του SponsorBlock</string>
|
||||||
@ -335,8 +340,8 @@
|
|||||||
<string name="revanced_bypass_image_region_restrictions_summary">Αντικατάσταση του domain για την φόρτωση εικόνων όπου είναι μπλοκαρισμένες σε ορισμένες περιοχές ώστε να μπορούν να ληφθούν μικρογραφίες βίντεο, εικόνες δημοσιεύσεων, κλπ.</string>
|
<string name="revanced_bypass_image_region_restrictions_summary">Αντικατάσταση του domain για την φόρτωση εικόνων όπου είναι μπλοκαρισμένες σε ορισμένες περιοχές ώστε να μπορούν να ληφθούν μικρογραφίες βίντεο, εικόνες δημοσιεύσεων, κλπ.</string>
|
||||||
<string name="revanced_change_share_sheet_title">Αλλαγή μενού κοινοποίησης</string>
|
<string name="revanced_change_share_sheet_title">Αλλαγή μενού κοινοποίησης</string>
|
||||||
<string name="revanced_change_share_sheet_summary">Αλλαγή του μενού κοινοποίησης σε αυτό του συστήματος σας αντί του YouTube.</string>
|
<string name="revanced_change_share_sheet_summary">Αλλαγή του μενού κοινοποίησης σε αυτό του συστήματος σας αντί του YouTube.</string>
|
||||||
<string name="revanced_enable_cairo_splash_animation_title">Εφέ εκκίνησης θέματος Cairo</string>
|
<string name="revanced_disable_cairo_splash_animation_title">Απενεργοποίηση εφέ εκκίνησης θέματος Cairo</string>
|
||||||
<string name="revanced_enable_cairo_splash_animation_summary">Ενεργοποίηση των εφέ θέματος Cairo κατά την εκκίνηση της εφαρμογής.</string>
|
<string name="revanced_disable_cairo_splash_animation_summary">Απενεργοποίηση των εφέ θέματος Cairo κατά την εκκίνηση της εφαρμογής.</string>
|
||||||
<string name="revanced_enable_debug_logging_title">Ενεργοποίηση καταγραφής σφαλμάτων</string>
|
<string name="revanced_enable_debug_logging_title">Ενεργοποίηση καταγραφής σφαλμάτων</string>
|
||||||
<string name="revanced_enable_debug_logging_summary">Εκτύπωση του αρχείου καταγραφής σφαλμάτων.</string>
|
<string name="revanced_enable_debug_logging_summary">Εκτύπωση του αρχείου καταγραφής σφαλμάτων.</string>
|
||||||
<string name="revanced_enable_debug_buffer_logging_title">Συμπερίληψη του buffer στην καταγραφή</string>
|
<string name="revanced_enable_debug_buffer_logging_title">Συμπερίληψη του buffer στην καταγραφή</string>
|
||||||
|
@ -1,81 +1,267 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Shared PreferenceScreen -->
|
<!-- Shared PreferenceScreen -->
|
||||||
|
<string name="revanced_extended_settings_title">ReVanced Extended</string>
|
||||||
<!-- Shared Category -->
|
<!-- Shared Category -->
|
||||||
|
<string name="revanced_extended_restart_first_run">Reiniciar para cargar el diseño normalmente</string>
|
||||||
|
<string name="revanced_extended_restart_message">Actualizar y reiniciar</string>
|
||||||
<!-- PreferenceScreen: Account -->
|
<!-- PreferenceScreen: Account -->
|
||||||
|
<string name="revanced_preference_screen_account_title">Cuenta</string>
|
||||||
<string name="revanced_hide_account_menu_title">Ocultar menú de cuenta</string>
|
<string name="revanced_hide_account_menu_title">Ocultar menú de cuenta</string>
|
||||||
<string name="revanced_hide_account_menu_summary">Ocultar elementos del menú de la cuenta.</string>
|
<string name="revanced_hide_account_menu_summary">Oculta elementos del menú de la cuenta.</string>
|
||||||
|
<string name="revanced_hide_account_menu_filter_strings_title">Filtro de menú de cuenta</string>
|
||||||
|
<string name="revanced_hide_account_menu_filter_strings_summary">Lista de nombres del menú de la cuenta a filtrar separados por una nueva línea.</string>
|
||||||
<string name="revanced_hide_account_menu_empty_component_title">Ocultar componente vacío</string>
|
<string name="revanced_hide_account_menu_empty_component_title">Ocultar componente vacío</string>
|
||||||
<string name="revanced_hide_account_menu_empty_component_summary">Oculta componentes vacíos en el menú de la cuenta</string>
|
<string name="revanced_hide_account_menu_empty_component_summary">Oculta componentes vacíos en el menú de la cuenta.</string>
|
||||||
<string name="revanced_hide_handle_title">Ocultar asa</string>
|
<string name="revanced_hide_handle_title">Ocultar asa</string>
|
||||||
<string name="revanced_hide_handle_summary">Oculta el asa en el conmutador de cuenta.</string>
|
<string name="revanced_hide_handle_summary">Oculta el asa en el conmutador de cuenta.</string>
|
||||||
<string name="revanced_hide_terms_container_title">Ocultar contenedor de términos</string>
|
<string name="revanced_hide_terms_container_title">Ocultar contenedor de términos</string>
|
||||||
<string name="revanced_hide_terms_container_summary">Oculta los términos del contenedor de servicio.</string>
|
<string name="revanced_hide_terms_container_summary">Oculta los términos del contenedor de servicio.</string>
|
||||||
<!-- PreferenceScreen: Action Bar -->
|
<!-- PreferenceScreen: Action Bar -->
|
||||||
|
<string name="revanced_preference_screen_action_bar_title">Barra de Acción</string>
|
||||||
|
<string name="revanced_hide_action_button_like_dislike_title">Ocultar botones Me gusta y No me gusta</string>
|
||||||
|
<string name="revanced_hide_action_button_like_dislike_summary">Oculta los botones \"Me gusta\" y \"no me gusta\". No funciona en el diseño del reproductor antiguo.</string>
|
||||||
|
<string name="revanced_hide_action_button_comment_title">Ocultar botón de comentarios</string>
|
||||||
|
<string name="revanced_hide_action_button_comment_summary">Oculta botón de comentarios.</string>
|
||||||
|
<string name="revanced_hide_action_button_add_to_playlist_title">Ocultar botón Guardar</string>
|
||||||
|
<string name="revanced_hide_action_button_add_to_playlist_summary">Oculta botón Guardar.</string>
|
||||||
|
<string name="revanced_hide_action_button_download_title">Ocultar botón Descargar</string>
|
||||||
|
<string name="revanced_hide_action_button_download_summary">Oculta el botón Descargar.</string>
|
||||||
|
<string name="revanced_hide_action_button_share_title">Ocultar botón de compartir</string>
|
||||||
|
<string name="revanced_hide_action_button_share_summary">Oculta el botón Compartir.</string>
|
||||||
|
<string name="revanced_hide_action_button_radio_title">Ocultar botón de emisoras de radio</string>
|
||||||
|
<string name="revanced_hide_action_button_radio_summary">Oculta el botón Radio.</string>
|
||||||
|
<string name="revanced_hide_action_button_label_title">Ocultar etiquetas de botón de acción</string>
|
||||||
|
<string name="revanced_hide_action_button_label_summary">Oculta las etiquetas de los botones de acción.</string>
|
||||||
|
<string name="revanced_external_downloader_action_title">Reemplazar botón de acción de Descarga</string>
|
||||||
|
<string name="revanced_external_downloader_action_summary">"El botón Descargar abre su descargador externo.
|
||||||
|
|
||||||
|
• Solo anula el botón de acción Descargar en el reproductor.
|
||||||
|
• No anula el botón Descargar en el menú desplegable o en la pestaña Biblioteca."</string>
|
||||||
<string name="revanced_external_downloader_package_name_title">Nombre del paquete del descargador externo</string>
|
<string name="revanced_external_downloader_package_name_title">Nombre del paquete del descargador externo</string>
|
||||||
<string name="revanced_external_downloader_package_name_summary">Nombre del paquete de su aplicación de descargas externas instalada, como NewPipe o YTDLnis.</string>
|
<string name="revanced_external_downloader_package_name_summary">Nombre del paquete de su aplicación de descargas externas instalada, como NewPipe o YTDLnis.</string>
|
||||||
|
<string name="revanced_external_downloader_dialog_title">Descargador externo</string>
|
||||||
|
<string name="revanced_external_downloader_not_installed_dialog_title">Advertencia</string>
|
||||||
|
<string name="revanced_external_downloader_not_installed_dialog_message">"%1$s no está instalado.
|
||||||
|
Descarga %2$s desde el sitio web."</string>
|
||||||
<string name="revanced_external_downloader_not_installed_warning">%s no está instalado. Por favor, instálelo.</string>
|
<string name="revanced_external_downloader_not_installed_warning">%s no está instalado. Por favor, instálelo.</string>
|
||||||
<!-- PreferenceScreen: Ads -->
|
<!-- PreferenceScreen: Ads -->
|
||||||
|
<string name="revanced_preference_screen_ads_title">Anuncios</string>
|
||||||
|
<string name="revanced_hide_fullscreen_ads_title">Ocultar anuncios en pantalla completa</string>
|
||||||
|
<string name="revanced_hide_fullscreen_ads_summary">Oculta anuncios en pantalla completa.</string>
|
||||||
|
<string name="revanced_hide_fullscreen_ads_type_title">Cerrar anuncios en pantalla completa</string>
|
||||||
|
<string name="revanced_hide_fullscreen_ads_type_summary">"Si está habilitado, los anuncios a pantalla completa se cierran mediante el botón Cerrar.
|
||||||
|
Si está deshabilitado, se bloquean los anuncios a pantalla completa. (puede haber efectos secundarios)"</string>
|
||||||
|
<string name="revanced_hide_fullscreen_ads_blocked_success">Se han bloqueado anuncios en pantalla completa. (Tipo de diálogo: %s)</string>
|
||||||
|
<string name="revanced_hide_fullscreen_ads_closed_success">Se han cerrado anuncios en pantalla completa.</string>
|
||||||
|
<string name="revanced_hide_general_ads_title">Ocultar anuncios generales</string>
|
||||||
|
<string name="revanced_hide_general_ads_summary">Oculta anuncios generales.</string>
|
||||||
<string name="revanced_hide_music_ads_title">Ocultar anuncios de música</string>
|
<string name="revanced_hide_music_ads_title">Ocultar anuncios de música</string>
|
||||||
<string name="revanced_hide_music_ads_summary">Oculta los anuncios antes de reproducir una pista.</string>
|
<string name="revanced_hide_music_ads_summary">Oculta los anuncios antes de reproducir una pista.</string>
|
||||||
|
<string name="revanced_hide_paid_promotion_label_title">Ocultar etiqueta de promoción pagada</string>
|
||||||
|
<string name="revanced_hide_paid_promotion_label_summary">Oculta etiqueta de promoción pagada.</string>
|
||||||
|
<string name="revanced_hide_premium_promotion_title">Ocultar popups de promoción premium</string>
|
||||||
|
<string name="revanced_hide_premium_promotion_summary">Oculta popups de promoción premium.</string>
|
||||||
|
<string name="revanced_hide_premium_renewal_title">Ocultar banner de renovación premium</string>
|
||||||
|
<string name="revanced_hide_premium_renewal_summary">Oculta banner de renovación premium.</string>
|
||||||
<!-- PreferenceScreen: Flyout -->
|
<!-- PreferenceScreen: Flyout -->
|
||||||
|
<string name="revanced_preference_screen_flyout_title">Menú desplegable</string>
|
||||||
<string name="revanced_enable_compact_dialog_title">Activar diálogo compacto</string>
|
<string name="revanced_enable_compact_dialog_title">Activar diálogo compacto</string>
|
||||||
<string name="revanced_enable_compact_dialog_summary">"Activa el diálogo compacto en el teléfono.
|
<string name="revanced_enable_compact_dialog_summary">"Activa el diálogo compacto en el teléfono.
|
||||||
|
|
||||||
Problemas conocidos:
|
Problemas conocidos:
|
||||||
- La carátula del álbum en la estantería de la biblioteca también se hace más pequeña.
|
- La carátula del álbum en la estantería de la biblioteca también se hace más pequeña.
|
||||||
- El diseño del temporizador puede parecer inusual."</string>
|
- El diseño del temporizador puede parecer inusual."</string>
|
||||||
|
<string name="revanced_enable_trim_silence_title">Añadir interruptor para recortar silencios</string>
|
||||||
|
<string name="revanced_enable_trim_silence_summary">"Añade un interruptor para recortar silencios en el menú desplegable de velocidad de reproducción.
|
||||||
|
|
||||||
|
Información:
|
||||||
|
Esta función es para podcasts.
|
||||||
|
Esta función aún está en desarrollo, por lo que puede ser inestable."</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_like_dislike_title">Ocultar botones Me gusta y No me gusta</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_3_column_component_title">Ocultar componente de 3 columnas</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_add_to_queue_title">Ocultar menú de Añadir a la cola</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_captions_title">Ocultar menú de Subtítulos</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_delete_playlist_title">Ocultar menú Borrar lista de reproducción</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_dismiss_queue_title">Ocultar menú de Descartar cola</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_download_title">Ocultar menú de Descarga</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_edit_playlist_title">Ocultar menú Editar lista de reproducción</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_go_to_album_title">Ocultar menú de ir al álbum</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_go_to_artist_title">Ocultar menú de ir al artista</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_go_to_episode_title">Ocultar menú de ir a episodios</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_go_to_podcast_title">Ocultar menú de ir al podcast</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_help_title">Ocultar menú Ayuda & Comentarios</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_play_next_title">Ocultar menú de reproducción siguiente</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_quality_title">Ocultar menú de calidad</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_remove_from_library_title">Ocultar menú de eliminar de la biblioteca</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_remove_from_playlist_title">Ocultar menú de quitar de la lista de reproducción</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_report_title">Ocultar menú Denunciar</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_save_episode_for_later_title">Ocultar menú de Guardar episodio para más tarde</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_save_to_library_title">Ocultar menú de Guardar en biblioteca</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_save_to_playlist_title">Ocultar menú de Guardar en lista de reproducción</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_share_title">Ocultar menú de Compartir</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_shuffle_play_title">Ocultar menú de Reproducción aleatoria</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_sleep_timer_title">Ocultar menú de Temporizador de sueño</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_start_radio_title">Ocultar menú de Iniciar radio</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_stats_for_nerds_title">Ocultar menú Estadísticas para Nerds</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_subscribe_title">Ocultar menú Suscribirse / Desuscribirse</string>
|
||||||
|
<string name="revanced_hide_flyout_menu_view_song_credit_title">Ocultar menú de vista de créditos de canción</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_dismiss_queue_continue_watch_title">Continuar viendo</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_dismiss_queue_continue_watch_summary">Continúa el vídeo desde el tiempo actual cuando se cambia a YouTube.</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_dismiss_queue_watch_on_youtube_label">Ver en YouTube</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_dismiss_queue_watch_on_youtube_warning">Url del video no válida.</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_dismiss_queue_title">Reemplazar el menú descartar cola</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_dismiss_queue_summary">Reemplaza el menú de descartar cola por el de ver en YouTube.</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_report_title">Reemplazar menú Denunciar</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_report_summary">Reemplaza el menú Denunciar con el menú Velocidad de reproducción.</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_report_only_player_title">Mantener Denunciar en comentarios</string>
|
||||||
|
<string name="revanced_replace_flyout_menu_report_only_player_summary">Mantiene intacto el menú Denunciar en la sección de comentarios.</string>
|
||||||
<!-- PreferenceScreen: General -->
|
<!-- PreferenceScreen: General -->
|
||||||
|
<string name="revanced_preference_screen_general_title">General</string>
|
||||||
|
<string name="revanced_change_start_page_title">Cambiar página de inicio</string>
|
||||||
|
<string name="revanced_change_start_page_summary">Seleccione en qué página se abre la aplicación.</string>
|
||||||
|
<string name="revanced_change_start_page_entry_chart">Ranking</string>
|
||||||
|
<string name="revanced_change_start_page_entry_explore">Explorar</string>
|
||||||
|
<string name="revanced_change_start_page_entry_home">Inicio</string>
|
||||||
|
<string name="revanced_change_start_page_entry_library">Biblioteca</string>
|
||||||
|
<string name="revanced_change_start_page_entry_subscription">Suscripciones</string>
|
||||||
<string name="revanced_disable_auto_captions_title">Desactivar subtítulos automáticos</string>
|
<string name="revanced_disable_auto_captions_title">Desactivar subtítulos automáticos</string>
|
||||||
<string name="revanced_disable_auto_captions_summary">Desactiva la activación automática de los subtítulos forzados en el reproductor de vídeo.</string>
|
<string name="revanced_disable_auto_captions_summary">Desactiva la activación automática de los subtítulos forzados en el reproductor de vídeo.</string>
|
||||||
|
<string name="revanced_disable_dislike_redirection_title">Desactivar redirección de No me Gusta</string>
|
||||||
|
<string name="revanced_disable_dislike_redirection_summary">Deshabilita la redirección a la siguiente pista al hacer clic en el botón No me Gusta.</string>
|
||||||
<string name="revanced_enable_landscape_mode_title">Activar modo horizontal</string>
|
<string name="revanced_enable_landscape_mode_title">Activar modo horizontal</string>
|
||||||
<string name="revanced_enable_landscape_mode_summary">Permite entrar en modo horizontal mediante la rotación de la pantalla del teléfono.</string>
|
<string name="revanced_enable_landscape_mode_summary">Permite entrar en modo horizontal mediante la rotación de la pantalla del teléfono.</string>
|
||||||
<string name="revanced_custom_filter_title">Activar filtro personalizado</string>
|
<string name="revanced_custom_filter_title">Activar filtro personalizado</string>
|
||||||
<string name="revanced_custom_filter_summary">Activa los filtros personalizados</string>
|
<string name="revanced_custom_filter_summary">Habilita el filtro personalizado para ocultar los componentes de diseño.</string>
|
||||||
<string name="revanced_custom_filter_strings_title">Editar filtro personalizado</string>
|
<string name="revanced_custom_filter_strings_title">Editar filtro personalizado</string>
|
||||||
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
|
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
|
||||||
<string name="revanced_custom_filter_strings_summary">Filtra los nombres de los componentes separados por líneas</string>
|
<string name="revanced_custom_filter_strings_summary">Filtra los nombres de los componentes, separados por líneas.</string>
|
||||||
|
<string name="revanced_custom_filter_toast_invalid_syntax">Filtro personalizado no válido: %s.</string>
|
||||||
|
<string name="revanced_hide_settings_menu_title">Ocultar menú de configuración</string>
|
||||||
|
<string name="revanced_hide_settings_menu_summary">"Oculta elementos del menú de configuración.
|
||||||
|
Esto oculta no solo el menú de ajustes de YT Music, sino también el menú de ajustes de ReVanced Extended."</string>
|
||||||
|
<string name="revanced_hide_settings_menu_filter_strings_title">Filtro de menú de configuración</string>
|
||||||
|
<string name="revanced_hide_settings_menu_filter_strings_summary">Lista de nombres del menú de configuración de YouTube a filtrar separados por una nueva línea.</string>
|
||||||
<string name="revanced_hide_button_shelf_title">Ocultar estante de botones</string>
|
<string name="revanced_hide_button_shelf_title">Ocultar estante de botones</string>
|
||||||
<string name="revanced_hide_button_shelf_summary">Oculta el estante de botones de la página de inicio y del explorador.</string>
|
<string name="revanced_hide_button_shelf_summary">Oculta el estante de botones de la página de inicio y del explorador.</string>
|
||||||
<string name="revanced_hide_carousel_shelf_title">Ocultar estante de carrusel</string>
|
<string name="revanced_hide_carousel_shelf_title">Ocultar estante de carrusel</string>
|
||||||
<string name="revanced_hide_carousel_shelf_summary">Oculta el estante de carrusel de la página de inicio y del explorador.</string>
|
<string name="revanced_hide_carousel_shelf_summary">Oculta el estante de carrusel de la página de inicio y del explorador.</string>
|
||||||
|
<string name="revanced_hide_playlist_card_shelf_title">Ocultar tarjeta de lista de reproducción</string>
|
||||||
|
<string name="revanced_hide_playlist_card_shelf_summary">Oculta la tarjeta de lista de reproducción del feed.</string>
|
||||||
|
<string name="revanced_hide_samples_shelf_title">Ocultar estante de Samples</string>
|
||||||
|
<string name="revanced_hide_samples_shelf_summary">Oculta estante de Samples en el feed.</string>
|
||||||
<string name="revanced_hide_cast_button_title">Ocultar botón de transmisión</string>
|
<string name="revanced_hide_cast_button_title">Ocultar botón de transmisión</string>
|
||||||
<string name="revanced_hide_cast_button_summary">Oculta el botón de trasmisión en la parte superior de la página de inicio y en la parte superior del reproductor.</string>
|
<string name="revanced_hide_cast_button_summary">Oculta el botón de trasmisión en la parte superior de la página de inicio y en la parte superior del reproductor.</string>
|
||||||
<string name="revanced_hide_category_bar_title">Ocultar barra de categorías</string>
|
<string name="revanced_hide_category_bar_title">Ocultar barra de categorías</string>
|
||||||
<string name="revanced_hide_category_bar_summary">Oculta la barra de categorías musicales de la parte superior de la página de inicio.</string>
|
<string name="revanced_hide_category_bar_summary">Oculta la barra de categorías musicales de la parte superior de la página de inicio.</string>
|
||||||
|
<string name="revanced_hide_floating_button_title">Ocultar botón flotante</string>
|
||||||
|
<string name="revanced_hide_floating_button_summary">Oculta el botón flotante en la pestaña Biblioteca.</string>
|
||||||
|
<string name="revanced_hide_tap_to_update_button_title">Ocultar el botón Toque para actualizar</string>
|
||||||
|
<string name="revanced_hide_tap_to_update_button_summary">Oculta el botón Toque para actualizar.</string>
|
||||||
<string name="revanced_hide_history_button_title">Ocultar botón de historial</string>
|
<string name="revanced_hide_history_button_title">Ocultar botón de historial</string>
|
||||||
<string name="revanced_hide_history_button_summary">Oculta el botón de historial en la barra de herramientas.</string>
|
<string name="revanced_hide_history_button_summary">Oculta el botón de historial en la barra de herramientas.</string>
|
||||||
|
<string name="revanced_hide_notification_button_title">Ocultar botón de Notificaciones</string>
|
||||||
|
<string name="revanced_hide_notification_button_summary">Oculta el botón de notificaciones en la barra de herramientas.</string>
|
||||||
|
<string name="revanced_hide_sound_search_button_title">Ocultar botón de búsqueda de sonido</string>
|
||||||
|
<string name="revanced_hide_sound_search_button_summary">Oculta el botón de búsqueda de sonido en la barra de búsqueda.</string>
|
||||||
|
<string name="revanced_hide_voice_search_button_title">Ocultar botón de búsqueda por voz</string>
|
||||||
|
<string name="revanced_hide_voice_search_button_summary">Oculta el botón de búsqueda por voz en la barra de búsqueda.</string>
|
||||||
|
<string name="revanced_restore_old_style_library_shelf_title">Restaurar el estante de la biblioteca de estilo antiguo</string>
|
||||||
|
<string name="revanced_restore_old_style_library_shelf_summary">Devuelve la pestaña Biblioteca al estilo antiguo. (Experimental)</string>
|
||||||
|
<string name="revanced_remove_viewer_discretion_dialog_title">Eliminar diálogo de discreción del espectador</string>
|
||||||
|
<string name="revanced_remove_viewer_discretion_dialog_summary">"Elimina el diálogo de discreción del espectador.
|
||||||
|
Esto no evita la restricción de edad. Solo la acepta automáticamente."</string>
|
||||||
<string name="revanced_spoof_app_version_title">Modificar versión de aplicación</string>
|
<string name="revanced_spoof_app_version_title">Modificar versión de aplicación</string>
|
||||||
<string name="revanced_spoof_app_version_summary">"Modificación de la versión del cliente a la versión antigua
|
<string name="revanced_spoof_app_version_summary">"Modificación de la versión del cliente a la versión antigua.
|
||||||
|
|
||||||
- Esto cambiará la apariencia de la aplicación, pero pueden producirse efectos secundarios desconocidos
|
- Esto cambiará la apariencia de la aplicación, pero pueden producirse efectos secundarios desconocidos.
|
||||||
- Si más tarde se desactiva, la antigua interfaz de usuario puede permanecer hasta que se borren los datos de la aplicación"</string>
|
- Si más tarde se desactiva, la antigua interfaz de usuario puede permanecer hasta que se borren los datos de la aplicación."</string>
|
||||||
<string name="revanced_spoof_app_version_target_title">Objetivo de la versión de la app a modificar</string>
|
<string name="revanced_spoof_app_version_target_title">Objetivo de la versión de la app a modificar</string>
|
||||||
<string name="revanced_spoof_app_version_target_summary">Seleccione el objetivo de la versión de la app a modificar</string>
|
<string name="revanced_spoof_app_version_target_summary">Seleccione el objetivo de la versión de la app a modificar.</string>
|
||||||
<string name="revanced_spoof_app_version_target_entry_4_27_53">4.27.53 - Desactivar el modo radio en las regiones canadienses</string>
|
<string name="revanced_spoof_app_version_target_entry_4_27_53">4.27.53 - Desactivar el modo radio en las regiones canadienses</string>
|
||||||
|
<string name="revanced_spoof_app_version_target_entry_6_11_52">6.11.52 - Desactivar letras en tiempo real</string>
|
||||||
<!-- PreferenceScreen: Navigation Bar -->
|
<!-- PreferenceScreen: Navigation Bar -->
|
||||||
|
<string name="revanced_preference_screen_navigation_title">Barra de navegación</string>
|
||||||
<string name="revanced_enable_black_navigation_bar_title">Activar barra de navegación negra</string>
|
<string name="revanced_enable_black_navigation_bar_title">Activar barra de navegación negra</string>
|
||||||
<string name="revanced_enable_black_navigation_bar_summary">Establece el color de la barra de navegación en negro.</string>
|
<string name="revanced_enable_black_navigation_bar_summary">Establece el color de la barra de navegación en negro.</string>
|
||||||
|
<string name="revanced_hide_navigation_home_button_title">Ocultar botón de Inicio</string>
|
||||||
|
<string name="revanced_hide_navigation_home_button_summary">Oculta el botón de Inicio.</string>
|
||||||
|
<string name="revanced_hide_navigation_samples_button_title">Ocultar botón de Samples</string>
|
||||||
|
<string name="revanced_hide_navigation_samples_button_summary">Oculta el botón de Samples.</string>
|
||||||
|
<string name="revanced_hide_navigation_explore_button_title">Ocultar botón de Explorar</string>
|
||||||
|
<string name="revanced_hide_navigation_explore_button_summary">Oculta el botón Explorar.</string>
|
||||||
|
<string name="revanced_hide_navigation_library_button_title">Ocultar botón de Biblioteca</string>
|
||||||
|
<string name="revanced_hide_navigation_library_button_summary">Oculta el botón de la biblioteca.</string>
|
||||||
|
<string name="revanced_hide_navigation_upgrade_button_title">Ocultar botón de Actualización</string>
|
||||||
|
<string name="revanced_hide_navigation_upgrade_button_summary">Oculta el botón de Actualización.</string>
|
||||||
<string name="revanced_hide_navigation_bar_title">Ocultar barra de navegación</string>
|
<string name="revanced_hide_navigation_bar_title">Ocultar barra de navegación</string>
|
||||||
<string name="revanced_hide_navigation_bar_summary">Ocultar barra de navegación.</string>
|
<string name="revanced_hide_navigation_bar_summary">Oculta barra de navegación.</string>
|
||||||
<string name="revanced_hide_navigation_label_title">Ocultar etiquetas en barra de navegación</string>
|
<string name="revanced_hide_navigation_label_title">Ocultar etiquetas en barra de navegación</string>
|
||||||
<string name="revanced_hide_navigation_label_summary">Oculta las etiquetas en la barra de navegación.</string>
|
<string name="revanced_hide_navigation_label_summary">Oculta las etiquetas en la barra de navegación.</string>
|
||||||
<!-- PreferenceScreen: Player -->
|
<!-- PreferenceScreen: Player -->
|
||||||
|
<string name="revanced_preference_screen_player_title">Reproductor</string>
|
||||||
|
<string name="revanced_disable_mini_player_gesture_title">Desactivar gesto de minireproductor</string>
|
||||||
|
<string name="revanced_disable_mini_player_gesture_summary">Desactivar el gesto de deslizar para cambiar de pista en el minireproductor.</string>
|
||||||
|
<string name="revanced_disable_player_gesture_title">Desactivar gesto del reproductor</string>
|
||||||
|
<string name="revanced_disable_player_gesture_summary">Desactivar el gesto de deslizar para cambiar de pista en el reproductor.</string>
|
||||||
|
<string name="revanced_enable_black_player_background_title">Activar fondo de reproductor negro</string>
|
||||||
|
<string name="revanced_enable_black_player_background_summary">Cambia el color de fondo del reproductor a negro.</string>
|
||||||
<string name="revanced_enable_color_match_player_title">Activar coincidencia de color de reproductores</string>
|
<string name="revanced_enable_color_match_player_title">Activar coincidencia de color de reproductores</string>
|
||||||
<string name="revanced_enable_color_match_player_summary">Hace coincidir el color del reproductor a pantalla completa con el de minimizado.</string>
|
<string name="revanced_enable_color_match_player_summary">Hace coincidir el color del reproductor a pantalla completa con el de minimizado.</string>
|
||||||
<string name="revanced_enable_force_minimized_player_title">Activar reproductor minimizado forzado</string>
|
<string name="revanced_enable_force_minimized_player_title">Activar reproductor minimizado forzado</string>
|
||||||
<string name="revanced_enable_force_minimized_player_summary">Mantiene el reproductor permanentemente minimizado incluso si se reproduce otra pista.</string>
|
<string name="revanced_enable_force_minimized_player_summary">Mantiene el reproductor permanentemente minimizado incluso si se reproduce otra pista.</string>
|
||||||
|
<string name="revanced_enable_mini_player_next_button_title">Añadir botón siguiente al minireproductor</string>
|
||||||
|
<string name="revanced_enable_mini_player_next_button_summary">Añadir botón siguiente pista al minireproductor.</string>
|
||||||
|
<string name="revanced_enable_mini_player_previous_button_title">Añadir botón anterior al minireproductor</string>
|
||||||
|
<string name="revanced_enable_mini_player_previous_button_summary">Añadir botón pista anterior al minireproductor.</string>
|
||||||
|
<string name="revanced_enable_swipe_to_dismiss_mini_player_title">Activar deslizar para descartar el minireproductor</string>
|
||||||
|
<string name="revanced_enable_swipe_to_dismiss_mini_player_summary">Permite deslizar hacia abajo para descartar el minireproductor.</string>
|
||||||
<string name="revanced_enable_zen_mode_title">Activar modo zen</string>
|
<string name="revanced_enable_zen_mode_title">Activar modo zen</string>
|
||||||
<string name="revanced_enable_zen_mode_summary">Añade un tinte gris al reproductor de vídeo para reducir la fatiga visual.</string>
|
<string name="revanced_enable_zen_mode_summary">Añade un tinte gris al reproductor de vídeo para reducir la fatiga visual.</string>
|
||||||
|
<string name="revanced_enable_zen_mode_podcast_title">Activar el modo Zen en podcasts</string>
|
||||||
|
<string name="revanced_enable_zen_mode_podcast_summary">También activa el modo Zen para podcasts.</string>
|
||||||
|
<string name="revanced_hide_audio_video_switch_toggle_title">Ocultar Interruptor de Audio / Video</string>
|
||||||
|
<string name="revanced_hide_audio_video_switch_toggle_summary">Oculta el interruptor de Audio / Video en el reproductor.</string>
|
||||||
|
<string name="revanced_hide_comment_channel_guidelines_title">Ocultar normas del canal</string>
|
||||||
|
<string name="revanced_hide_comment_channel_guidelines_summary">Oculta las normas del canal en la parte superior de la sección de comentarios.</string>
|
||||||
|
<string name="revanced_hide_comment_timestamp_and_emoji_buttons_title">Ocultar botones de marca de tiempo y emoji</string>
|
||||||
|
<string name="revanced_hide_comment_timestamp_and_emoji_buttons_summary">Oculta los botones marca de tiempo y emoji al escribir comentarios.</string>
|
||||||
|
<string name="revanced_hide_double_tap_overlay_filter_title">Oculta la capa que aparece al tocar dos veces</string>
|
||||||
|
<string name="revanced_hide_double_tap_overlay_filter_summary">Oculta la superposición oscura que aparece al tocar dos veces para buscar.</string>
|
||||||
|
<string name="revanced_hide_fullscreen_share_button_title">Ocultar el botón Compartir en pantalla completa</string>
|
||||||
|
<string name="revanced_hide_fullscreen_share_button_summary">Oculta el botón Compartir en el reproductor de pantalla completa.</string>
|
||||||
<string name="revanced_remember_repeat_state_title">Recordar estado de repetición</string>
|
<string name="revanced_remember_repeat_state_title">Recordar estado de repetición</string>
|
||||||
<string name="revanced_remember_repeat_state_summary">Recuerda el estado de la repetición.</string>
|
<string name="revanced_remember_repeat_state_summary">Recuerda el estado de la repetición.</string>
|
||||||
<string name="revanced_remember_shuffle_state_title">Recordar estado del aleatorio</string>
|
<string name="revanced_remember_shuffle_state_title">Recordar estado aleatorio</string>
|
||||||
<string name="revanced_remember_shuffle_state_summary">Recuerda el estado del aleatorio.</string>
|
<string name="revanced_remember_shuffle_state_summary">Recuerda el estado del aleatorio (shuffle).</string>
|
||||||
|
<string name="revanced_restore_old_comments_popup_panels_title">Restaurar paneles emergentes de comentarios antiguos</string>
|
||||||
|
<string name="revanced_restore_old_comments_popup_panels_summary">Devuelve los paneles emergentes de comentarios al estilo antiguo.</string>
|
||||||
|
<string name="revanced_restore_old_player_background_title">Restaurar el fondo del reproductor antiguo</string>
|
||||||
|
<string name="revanced_restore_old_player_background_summary">Devuelve el fondo del reproductor al estilo antiguo.</string>
|
||||||
|
<string name="revanced_restore_old_player_layout_title">Activar diseño antiguo del reproductor</string>
|
||||||
|
<string name="revanced_restore_old_player_layout_summary">"Devuelve el diseño del reproductor al estilo antiguo.
|
||||||
|
Algunas características pueden no funcionar correctamente en la disposición del reproductor antiguo."</string>
|
||||||
<!-- PreferenceScreen: Video -->
|
<!-- PreferenceScreen: Video -->
|
||||||
|
<string name="revanced_preference_screen_video_title">Video</string>
|
||||||
<string name="revanced_custom_playback_speeds_title">Editar velocidades de reproducción personalizadas</string>
|
<string name="revanced_custom_playback_speeds_title">Editar velocidades de reproducción personalizadas</string>
|
||||||
<string name="revanced_custom_playback_speeds_summary">Agregar o cambiar las velocidades de reproducción disponibles</string>
|
<string name="revanced_custom_playback_speeds_summary">Agregar o cambiar las velocidades de reproducción disponibles.</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_title">Recordar cambios de velocidad de reproducción</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_summary">Recuerda la última velocidad de reproducción seleccionada.</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_title">Mostrar un mensaje</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_summary">Mostrar un mensaje al cambiar la velocidad de reproducción predeterminada.</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_title">Recordar cambios de calidad de vídeo</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_summary">Recuerda la última calidad de vídeo seleccionada.</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_title">Mostrar un mensaje</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_summary">Mostrar un mensaje al cambiar la calidad de vídeo por defecto.</string>
|
||||||
<string name="revanced_custom_playback_speeds_invalid">Las velocidades de reproducción personalizadas no son válidas. Restablezca a los valores predeterminados.</string>
|
<string name="revanced_custom_playback_speeds_invalid">Las velocidades de reproducción personalizadas no son válidas. Restablezca a los valores predeterminados.</string>
|
||||||
|
<string name="revanced_custom_playback_speeds_parse_exception">Velocidades de reproducción personalizadas no válidas. Utilizando valores predeterminados.</string>
|
||||||
|
<string name="revanced_remember_playback_speed_toast">Cambiando la velocidad predeterminada a %s.</string>
|
||||||
|
<string name="revanced_remember_video_quality_mobile">Cambiando la calidad predeterminada con datos móviles a %s.</string>
|
||||||
|
<string name="revanced_remember_video_quality_none">Error al establecer calidad.</string>
|
||||||
|
<string name="revanced_remember_video_quality_wifi">Cambiando la calidad predeterminada con Wi-Fi a %s.</string>
|
||||||
<!-- PreferenceScreen: Return YouTube Dislike -->
|
<!-- PreferenceScreen: Return YouTube Dislike -->
|
||||||
|
<string name="revanced_preference_screen_ryd_title">Return YouTube Dislike</string>
|
||||||
|
<string name="revanced_ryd_enabled_title">Activar Return YouTube Dislike</string>
|
||||||
<string name="revanced_ryd_enabled_summary">Muestra el número de vídeos que no te gustan.</string>
|
<string name="revanced_ryd_enabled_summary">Muestra el número de vídeos que no te gustan.</string>
|
||||||
<string name="revanced_ryd_dislike_percentage_title">Porcentaje de No Me Gusta</string>
|
<string name="revanced_ryd_dislike_percentage_title">Porcentaje de No Me Gusta</string>
|
||||||
<string name="revanced_ryd_dislike_percentage_summary">En lugar del número de no me gusta, se muestra el porcentaje de no me gusta.</string>
|
<string name="revanced_ryd_dislike_percentage_summary">En lugar del número de no me gusta, se muestra el porcentaje de no me gusta.</string>
|
||||||
@ -84,18 +270,94 @@ Problemas conocidos:
|
|||||||
<string name="revanced_ryd_toast_on_connection_error_title">Mostrar mensaje si la API no está disponible</string>
|
<string name="revanced_ryd_toast_on_connection_error_title">Mostrar mensaje si la API no está disponible</string>
|
||||||
<string name="revanced_ryd_toast_on_connection_error_summary">Se muestra el mensaje si la API de ReturnYouTubeDislike no está disponible.</string>
|
<string name="revanced_ryd_toast_on_connection_error_summary">Se muestra el mensaje si la API de ReturnYouTubeDislike no está disponible.</string>
|
||||||
<string name="revanced_ryd_about">Acerca de</string>
|
<string name="revanced_ryd_about">Acerca de</string>
|
||||||
|
<string name="revanced_ryd_attribution_title">ReturnYouTubeDislike.com</string>
|
||||||
<string name="revanced_ryd_attribution_summary">Los datos son proporcionados por la API Return YouTube Dislike. Pulse aquí para obtener más información.</string>
|
<string name="revanced_ryd_attribution_summary">Los datos son proporcionados por la API Return YouTube Dislike. Pulse aquí para obtener más información.</string>
|
||||||
<string name="revanced_ryd_failure_connection_timeout">Los no me gusta están temporalmente no disponibles (la API no responde).</string>
|
<string name="revanced_ryd_failure_connection_timeout">Los no me gusta están temporalmente no disponibles (la API no responde).</string>
|
||||||
<string name="revanced_ryd_failure_connection_status_code">Los no me gusta no están disponibles (estado %d).</string>
|
<string name="revanced_ryd_failure_connection_status_code">Los no me gusta no están disponibles (estado %d).</string>
|
||||||
<string name="revanced_ryd_failure_client_rate_limit_requested">Los No Me Gusta no están disponibles (se alcanzó el límite de la API del cliente)</string>
|
<string name="revanced_ryd_failure_client_rate_limit_requested">Los No Me Gusta no están disponibles (se alcanzó el límite de la API del cliente).</string>
|
||||||
<string name="revanced_ryd_failure_generic">Los no me gusta no están disponibles (%s).</string>
|
<string name="revanced_ryd_failure_generic">Los no me gusta no están disponibles (%s).</string>
|
||||||
<string name="revanced_ryd_video_likes_hidden_by_video_owner">Oculto</string>
|
|
||||||
<!-- PreferenceScreen: SponsorBlock -->
|
<!-- PreferenceScreen: SponsorBlock -->
|
||||||
|
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
||||||
|
<string name="revanced_sb_enabled">Activar SponsorBlock</string>
|
||||||
|
<string name="revanced_sb_enabled_sum">SponsorBlock es un sistema colaborativo para omitir partes molestas en vídeos de YouTube.</string>
|
||||||
|
<string name="revanced_sb_toast_on_connection_error">Mostrar mensaje si la API no está disponible</string>
|
||||||
|
<string name="revanced_sb_toast_on_connection_error_sum">Muestra un mensaje si la API de SponsorBlock no está disponible.</string>
|
||||||
|
<string name="revanced_sb_toast_on_skip">Mostrar mensaje al omitir segmento automáticamente</string>
|
||||||
|
<string name="revanced_sb_toast_on_skip_sum">Mensaje emergente que se muestra cuando se salta un segmento automáticamente.</string>
|
||||||
|
<string name="revanced_sb_api_url">Cambiar URL de la API</string>
|
||||||
|
<string name="revanced_sb_api_url_sum">Dirección que el SponsorBlock utiliza para hacer llamadas al servidor. No cambie esto a menos que sepa qué está haciendo.</string>
|
||||||
|
<string name="revanced_sb_api_url_reset">Restablecer la URL de la API.</string>
|
||||||
|
<string name="revanced_sb_api_url_invalid">La URL de la API no es válida.</string>
|
||||||
|
<string name="revanced_sb_api_url_changed">URL de API cambiada.</string>
|
||||||
|
<string name="revanced_sb_diff_segments">Cambiar el comportamiento del segmento</string>
|
||||||
|
<string name="revanced_sb_segments_sponsor">Patrocinador</string>
|
||||||
|
<string name="revanced_sb_segments_sponsor_sum">Promoción pagada, referencias pagadas y anuncios directos. No es para promoción propia ni para menciones gratuitas a causas, creadores, sitios web o productos que les gusten.</string>
|
||||||
|
<string name="revanced_sb_segments_selfpromo">Promoción no remunerada/autopromoción</string>
|
||||||
|
<string name="revanced_sb_segments_selfpromo_sum">Cuando hay una autopromoción o no remunerada. Esto incluye secciones específicas sobre mercancía, donaciones o información sobre con quién colaboraron.</string>
|
||||||
|
<string name="revanced_sb_segments_interaction">Recordatorio de interacción (Suscribirse)</string>
|
||||||
|
<string name="revanced_sb_segments_interaction_sum">Un breve recordatorio para dar me gusta, suscribirse o seguirlos en medio del contenido. Si es largo o sobre algo específico, debe estar en la sección de autopromoción.</string>
|
||||||
|
<string name="revanced_sb_segments_intro">Intermedio / Animación de introducción</string>
|
||||||
|
<string name="revanced_sb_segments_intro_sum">Un intervalo sin contenido real. Puede ser una pausa, un fotograma estático o una animación que se repite. No incluye transiciones que contengan información.</string>
|
||||||
|
<string name="revanced_sb_segments_outro">Tarjetas finales / Créditos</string>
|
||||||
|
<string name="revanced_sb_segments_outro_sum">Créditos o cuando aparecen las tarjetas finales de YouTube. No para conclusiones con información.</string>
|
||||||
|
<string name="revanced_sb_segments_preview">Vista previa / Resumen / Gancho</string>
|
||||||
|
<string name="revanced_sb_segments_preview_sum">Colección de clips que muestran lo que está por venir o lo que sucedió en el vídeo o en otros vídeos de una serie, donde toda la información se repite en otra parte.</string>
|
||||||
|
<string name="revanced_sb_segments_filler">Tangente de relleno / Chistes</string>
|
||||||
|
<string name="revanced_sb_segments_filler_sum">Escenas tangenciales añadidas solo para relleno o humor que no son necesarias para entender el contenido principal del vídeo. No incluye segmentos que proporcionen contexto o detalles de fondo.</string>
|
||||||
|
<string name="revanced_sb_segments_nomusic">Música: Sección sin música</string>
|
||||||
|
<string name="revanced_sb_segments_nomusic_sum">Solo para usar en vídeos musicales. Secciones de vídeos musicales sin música, que no estén ya cubiertas por otra categoría.</string>
|
||||||
|
<string name="revanced_sb_skipped_sponsor">Patrocinador omitido.</string>
|
||||||
|
<string name="revanced_sb_skipped_selfpromo">Autopromoción omitida.</string>
|
||||||
|
<string name="revanced_sb_skipped_interaction">Recordatorio molesto omitido.</string>
|
||||||
|
<string name="revanced_sb_skipped_intro_beginning">Introducción omitida.</string>
|
||||||
|
<string name="revanced_sb_skipped_intro_middle">Intermisión omitida.</string>
|
||||||
|
<string name="revanced_sb_skipped_intro_end">Intermisión omitida.</string>
|
||||||
|
<string name="revanced_sb_skipped_outro">Créditos omitidos.</string>
|
||||||
|
<string name="revanced_sb_skipped_preview_beginning">Vista previa omitida.</string>
|
||||||
|
<string name="revanced_sb_skipped_preview_middle">Vista previa omitida.</string>
|
||||||
|
<string name="revanced_sb_skipped_preview_end">Resumen omitido.</string>
|
||||||
|
<string name="revanced_sb_skipped_filler">Relleno omitido.</string>
|
||||||
|
<string name="revanced_sb_skipped_nomusic">Se omitió una sección sin música.</string>
|
||||||
|
<string name="revanced_sb_skipped_multiple_segments">Varios segmentos omitidos.</string>
|
||||||
|
<string name="revanced_sb_skip_automatically">Omitir automáticamente</string>
|
||||||
|
<string name="revanced_sb_skip_ignore">Deshabilitar</string>
|
||||||
|
<string name="revanced_sb_sponsorblock_connection_failure_generic">SponsorBlock no está disponible temporalmente.</string>
|
||||||
|
<string name="revanced_sb_sponsorblock_connection_failure_status">SponsorBlock no está disponible temporalmente. (estado %d).</string>
|
||||||
|
<string name="revanced_sb_sponsorblock_connection_failure_timeout">SponsorBlock no está disponible temporalmente. (la API no responde).</string>
|
||||||
|
<string name="revanced_sb_color_dot_label">Color:</string>
|
||||||
|
<string name="revanced_sb_color_changed">Color cambiado.</string>
|
||||||
|
<string name="revanced_sb_color_reset">Restablecer color.</string>
|
||||||
|
<string name="revanced_sb_color_invalid">Código de color inválido. Restablecimiento de color predeterminado.</string>
|
||||||
|
<string name="revanced_sb_reset_color">Restablecer color</string>
|
||||||
|
<string name="revanced_sb_about_api_sum">Los datos son proporcionados por la API de SponsorBlock. Pulsa aquí para aprender más y ver las descargas para otras plataformas.</string>
|
||||||
|
<string name="revanced_sb_about">Acerca de</string>
|
||||||
|
<string name="revanced_sb_about_api">sponsor.ajay.app</string>
|
||||||
<!-- PreferenceScreen: Miscellaneous -->
|
<!-- PreferenceScreen: Miscellaneous -->
|
||||||
|
<string name="revanced_preference_screen_misc_title">Otros</string>
|
||||||
|
<string name="revanced_bypass_image_region_restrictions_title">Eludir las restricciones regionales de imágenes</string>
|
||||||
|
<string name="revanced_bypass_image_region_restrictions_summary">Reemplaza el dominio que está bloqueado en algunas regiones para que las miniaturas de la lista de reproducción, avatares de canales, etc. puedan ser recibidas.</string>
|
||||||
|
<string name="revanced_change_share_sheet_title">Cambiar la hoja de compartir</string>
|
||||||
|
<string name="revanced_change_share_sheet_summary">Cambia la hoja de compartir en la app a la hoja de compartir del sistema.</string>
|
||||||
<string name="revanced_enable_debug_logging_title">Activar registro de depuración</string>
|
<string name="revanced_enable_debug_logging_title">Activar registro de depuración</string>
|
||||||
<string name="revanced_enable_debug_logging_summary">Imprime el registro de depuración</string>
|
<string name="revanced_enable_debug_logging_summary">Imprime el registro de depuración.</string>
|
||||||
|
<string name="revanced_enable_debug_buffer_logging_title">Incluir búfer en registro de depuración</string>
|
||||||
|
<string name="revanced_enable_debug_buffer_logging_summary">Incluye el búfer en el registro de depuración.</string>
|
||||||
<string name="revanced_enable_opus_codec_title">Activar códec opus</string>
|
<string name="revanced_enable_opus_codec_title">Activar códec opus</string>
|
||||||
<string name="revanced_enable_opus_codec_summary">"Activa el códec Opus 250/251 al reproducir audio."</string>
|
<string name="revanced_enable_opus_codec_summary">"Activa el códec Opus 250/251 al reproducir audio."</string>
|
||||||
|
<string name="gms_core_settings_title">Abrir GmsCore</string>
|
||||||
|
<string name="gms_core_settings_summary">Activa los ajustes de mensajería en la nube para recibir notificaciones.</string>
|
||||||
|
<string name="gms_core_toast_not_installed_message">GmsCore no está instalado. Instálalo.</string>
|
||||||
|
<string name="gms_core_dialog_title">Acción necesaria</string>
|
||||||
|
<string name="gms_core_dialog_not_whitelisted_not_allowed_in_background_message">"GmsCore no tiene permiso para ejecutarse en segundo plano.
|
||||||
|
|
||||||
|
Sigue la guía \"Don't kill my app!\" para tu dispositivo y aplica las instrucciones a tu instalación de GmsCore.
|
||||||
|
|
||||||
|
Esto es necesario para que la aplicación funcione."</string>
|
||||||
|
<string name="gms_core_dialog_open_website_text">Abrir página Web</string>
|
||||||
|
<string name="gms_core_dialog_not_whitelisted_using_battery_optimizations_message">"Las optimizaciones de la batería para GmsCore deben estar desactivadas para evitar problemas.
|
||||||
|
|
||||||
|
Pulsa el botón de continuar y desactiva las optimizaciones de la batería."</string>
|
||||||
|
<string name="gms_core_dialog_continue_text">Continuar</string>
|
||||||
<string name="revanced_sanitize_sharing_links_title">Desinfectar enlaces compartidos</string>
|
<string name="revanced_sanitize_sharing_links_title">Desinfectar enlaces compartidos</string>
|
||||||
<string name="revanced_sanitize_sharing_links_summary">Elimina los parámetros de consulta de seguimiento de las URL al compartir enlaces.</string>
|
<string name="revanced_sanitize_sharing_links_summary">Elimina los parámetros de consulta de seguimiento de las URL al compartir enlaces.</string>
|
||||||
<string name="revanced_extended_settings_import_export_title">Importar / Exportar</string>
|
<string name="revanced_extended_settings_import_export_title">Importar / Exportar</string>
|
||||||
@ -107,8 +369,9 @@ Problemas conocidos:
|
|||||||
<string name="revanced_extended_settings_export_success">Los ajustes se han exportado correctamente.</string>
|
<string name="revanced_extended_settings_export_success">Los ajustes se han exportado correctamente.</string>
|
||||||
<string name="revanced_extended_settings_import">Importar</string>
|
<string name="revanced_extended_settings_import">Importar</string>
|
||||||
<string name="revanced_extended_settings_import_copy">Copiar</string>
|
<string name="revanced_extended_settings_import_copy">Copiar</string>
|
||||||
<string name="revanced_extended_settings_import_failed">Error de importación: %s.</string>
|
<string name="revanced_extended_settings_import_failed">Error de importación: %s</string>
|
||||||
<string name="revanced_extended_settings_import_reset">Configuración restablecida por defecto</string>
|
<string name="revanced_extended_settings_import_reset">La configuración se restableció a los valores predeterminados.</string>
|
||||||
<string name="revanced_extended_settings_import_success">Configuración importada de %d</string>
|
<string name="revanced_extended_settings_import_success">Configuración importada de %d.</string>
|
||||||
|
<string name="revanced_extended_settings_reset">Restablecer</string>
|
||||||
<string name="revanced_share_copy_settings_success">Ajustes copiados en el portapapeles.</string>
|
<string name="revanced_share_copy_settings_success">Ajustes copiados en el portapapeles.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -64,6 +64,8 @@ Si désactivé, Les publicités en plein écran seront bloquées. (peut avoir de
|
|||||||
<string name="revanced_hide_premium_promotion_summary">Masque les publicités pour YouTube Premium.</string>
|
<string name="revanced_hide_premium_promotion_summary">Masque les publicités pour YouTube Premium.</string>
|
||||||
<string name="revanced_hide_premium_renewal_title">Masquer la bannière \"Renouveler votre abonnement Premium\"</string>
|
<string name="revanced_hide_premium_renewal_title">Masquer la bannière \"Renouveler votre abonnement Premium\"</string>
|
||||||
<string name="revanced_hide_premium_renewal_summary">Masque la bannière \"Renouveler votre abonnement Premium\".</string>
|
<string name="revanced_hide_premium_renewal_summary">Masque la bannière \"Renouveler votre abonnement Premium\".</string>
|
||||||
|
<string name="revanced_hide_promotion_alert_banner_title">Masquer la bannière d\'alerte de promotion</string>
|
||||||
|
<string name="revanced_hide_promotion_alert_banner_summary">Masque la bannière d\'alerte de promotion.</string>
|
||||||
<!-- PreferenceScreen: Flyout -->
|
<!-- PreferenceScreen: Flyout -->
|
||||||
<string name="revanced_preference_screen_flyout_title">Menu déroulant</string>
|
<string name="revanced_preference_screen_flyout_title">Menu déroulant</string>
|
||||||
<string name="revanced_enable_compact_dialog_title">Activer la boîte de dialogue compacte</string>
|
<string name="revanced_enable_compact_dialog_title">Activer la boîte de dialogue compacte</string>
|
||||||
@ -247,8 +249,12 @@ Certaines fonctions peuvent ne pas fonctionner sur l'ancienne mise en page."</st
|
|||||||
<string name="revanced_custom_playback_speeds_summary">Ajoute ou modifie les vitesses de lecture disponibles.</string>
|
<string name="revanced_custom_playback_speeds_summary">Ajoute ou modifie les vitesses de lecture disponibles.</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_title">Enregistrer la modification de la vitesse de lecture</string>
|
<string name="revanced_remember_playback_speed_last_selected_title">Enregistrer la modification de la vitesse de lecture</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_summary">Enregistre la dernière vitesse de lecture sélectionnée.</string>
|
<string name="revanced_remember_playback_speed_last_selected_summary">Enregistre la dernière vitesse de lecture sélectionnée.</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_title">Afficher un message</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_summary">Afficher un message lorsque vous modifiez la vitesse de lecture par défaut.</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_title">Enregistrer la modification de la résolution</string>
|
<string name="revanced_remember_video_quality_last_selected_title">Enregistrer la modification de la résolution</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_summary">Enregistre la dernière qualité vidéo sélectionnée.</string>
|
<string name="revanced_remember_video_quality_last_selected_summary">Enregistre la dernière qualité vidéo sélectionnée.</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_title">Afficher un message</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_summary">Afficher un message lorsque vous modifiez la qualité vidéo par défaut.</string>
|
||||||
<string name="revanced_custom_playback_speeds_invalid">Les vitesses personnalisées doivent être inférieures à %sx. Valeur réinitialisée par défaut.</string>
|
<string name="revanced_custom_playback_speeds_invalid">Les vitesses personnalisées doivent être inférieures à %sx. Valeur réinitialisée par défaut.</string>
|
||||||
<string name="revanced_custom_playback_speeds_parse_exception">Vitesses de lecture invalides. Valeur réinitialisée par défaut.</string>
|
<string name="revanced_custom_playback_speeds_parse_exception">Vitesses de lecture invalides. Valeur réinitialisée par défaut.</string>
|
||||||
<string name="revanced_remember_playback_speed_toast">Vitesse de lecture modifiée par %s.</string>
|
<string name="revanced_remember_playback_speed_toast">Vitesse de lecture modifiée par %s.</string>
|
||||||
@ -272,7 +278,6 @@ Certaines fonctions peuvent ne pas fonctionner sur l'ancienne mise en page."</st
|
|||||||
<string name="revanced_ryd_failure_connection_status_code">Les \"Je n\'aime pas\" sont indisponible (status %d).</string>
|
<string name="revanced_ryd_failure_connection_status_code">Les \"Je n\'aime pas\" sont indisponible (status %d).</string>
|
||||||
<string name="revanced_ryd_failure_client_rate_limit_requested">Les \"Je n\'aime pas\" sont indisponibles (le client a atteint la limite de l\'API).</string>
|
<string name="revanced_ryd_failure_client_rate_limit_requested">Les \"Je n\'aime pas\" sont indisponibles (le client a atteint la limite de l\'API).</string>
|
||||||
<string name="revanced_ryd_failure_generic">Les \"Je n\'aime pas\" sont indisponible (%s).</string>
|
<string name="revanced_ryd_failure_generic">Les \"Je n\'aime pas\" sont indisponible (%s).</string>
|
||||||
<string name="revanced_ryd_video_likes_hidden_by_video_owner">Masqué</string>
|
|
||||||
<!-- PreferenceScreen: SponsorBlock -->
|
<!-- PreferenceScreen: SponsorBlock -->
|
||||||
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
||||||
<string name="revanced_sb_enabled">Activer Sponsorblock</string>
|
<string name="revanced_sb_enabled">Activer Sponsorblock</string>
|
||||||
@ -335,8 +340,6 @@ Certaines fonctions peuvent ne pas fonctionner sur l'ancienne mise en page."</st
|
|||||||
<string name="revanced_bypass_image_region_restrictions_summary">Remplace le domaine qui est bloqué dans certaines régions afin que les miniatures des listes de lecture, les avatars des chaînes, etc. puissent être reçus.</string>
|
<string name="revanced_bypass_image_region_restrictions_summary">Remplace le domaine qui est bloqué dans certaines régions afin que les miniatures des listes de lecture, les avatars des chaînes, etc. puissent être reçus.</string>
|
||||||
<string name="revanced_change_share_sheet_title">Modifier la fiche de partage</string>
|
<string name="revanced_change_share_sheet_title">Modifier la fiche de partage</string>
|
||||||
<string name="revanced_change_share_sheet_summary">Remplace la fiche de partage de l\'appli par celui du système.</string>
|
<string name="revanced_change_share_sheet_summary">Remplace la fiche de partage de l\'appli par celui du système.</string>
|
||||||
<string name="revanced_enable_cairo_splash_animation_title">Activer l\'animation Cairo au démarrage</string>
|
|
||||||
<string name="revanced_enable_cairo_splash_animation_summary">Active l\'animation Cairo lors du démarrage de l\'application.</string>
|
|
||||||
<string name="revanced_enable_debug_logging_title">Activer le journal de débogage</string>
|
<string name="revanced_enable_debug_logging_title">Activer le journal de débogage</string>
|
||||||
<string name="revanced_enable_debug_logging_summary">Enregistrer le journal de débogage.</string>
|
<string name="revanced_enable_debug_logging_summary">Enregistrer le journal de débogage.</string>
|
||||||
<string name="revanced_enable_debug_buffer_logging_title">Activer les informations sur la mémoire tampon dans le journal de débogage</string>
|
<string name="revanced_enable_debug_buffer_logging_title">Activer les informations sur la mémoire tampon dans le journal de débogage</string>
|
||||||
|
@ -272,7 +272,6 @@ Előfordulhat, hogy egyes funkciók nem működnek megfelelően a régi lejátsz
|
|||||||
<string name="revanced_ryd_failure_connection_status_code">A nem tetszik funkció nem elérhető (állapot: %d).</string>
|
<string name="revanced_ryd_failure_connection_status_code">A nem tetszik funkció nem elérhető (állapot: %d).</string>
|
||||||
<string name="revanced_ryd_failure_client_rate_limit_requested">Nem tetszések nem érhetőek el (kliens API limit elérve).</string>
|
<string name="revanced_ryd_failure_client_rate_limit_requested">Nem tetszések nem érhetőek el (kliens API limit elérve).</string>
|
||||||
<string name="revanced_ryd_failure_generic">A nem tetszik funkció nem elérhető (%s).</string>
|
<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: SponsorBlock -->
|
<!-- PreferenceScreen: SponsorBlock -->
|
||||||
<string name="revanced_preference_screen_sb_title">Szponzor Blokk</string>
|
<string name="revanced_preference_screen_sb_title">Szponzor Blokk</string>
|
||||||
<string name="revanced_sb_enabled">SzponsorBlokk engedélyezése</string>
|
<string name="revanced_sb_enabled">SzponsorBlokk engedélyezése</string>
|
||||||
@ -335,8 +334,6 @@ 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_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_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_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_enable_cairo_splash_animation_title">Betöltési animáció engedélyezése</string>
|
|
||||||
<string name="revanced_enable_cairo_splash_animation_summary">Engedélyezi a betöltési animációt amikor az app indul.</string>
|
|
||||||
<string name="revanced_enable_debug_logging_title">Hibanaplók engedélyezése</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_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>
|
<string name="revanced_enable_debug_buffer_logging_title">Hibakeresési puffer naplózásának engedélyezése</string>
|
||||||
|
@ -8,61 +8,61 @@
|
|||||||
<!-- PreferenceScreen: Account -->
|
<!-- PreferenceScreen: Account -->
|
||||||
<string name="revanced_preference_screen_account_title">Akun</string>
|
<string name="revanced_preference_screen_account_title">Akun</string>
|
||||||
<string name="revanced_hide_account_menu_title">Sembunyikan menu akun</string>
|
<string name="revanced_hide_account_menu_title">Sembunyikan menu akun</string>
|
||||||
<string name="revanced_hide_account_menu_summary">Menyembunyikan elemen menu akun menggunakan filter kustom.</string>
|
<string name="revanced_hide_account_menu_summary">Menyembunyikan elemen menu akun menggunakan filter custom.</string>
|
||||||
<string name="revanced_hide_account_menu_filter_strings_title">Filter menu Akun</string>
|
<string name="revanced_hide_account_menu_filter_strings_title">Filter menu Akun</string>
|
||||||
<string name="revanced_hide_account_menu_filter_strings_summary">Daftar dari nama-nama menu akun ke filter, terpisah oleh garis baru.</string>
|
<string name="revanced_hide_account_menu_filter_strings_summary">Daftar dari nama-nama menu akun ke filter, terpisah oleh garis baru.</string>
|
||||||
<string name="revanced_hide_account_menu_empty_component_title">Sembunyikan komponen kosong</string>
|
<string name="revanced_hide_account_menu_empty_component_title">Sembunyikan komponen kosong</string>
|
||||||
<string name="revanced_hide_account_menu_empty_component_summary">Menyembunyikan komponen kosong di menu akun.</string>
|
<string name="revanced_hide_account_menu_empty_component_summary">Menyembunyikan komponen kosong di menu akun.</string>
|
||||||
<string name="revanced_hide_handle_title">Sembunyikan handle</string>
|
<string name="revanced_hide_handle_title">Sembunyikan handle</string>
|
||||||
<string name="revanced_hide_handle_summary">Menyembunyikan handle di kelola akun.</string>
|
<string name="revanced_hide_handle_summary">Menyembunyikan handle di menu akun.</string>
|
||||||
<string name="revanced_hide_terms_container_title">Sembunyikan container ketentuan</string>
|
<string name="revanced_hide_terms_container_title">Sembunyikan kontainer ketentuan</string>
|
||||||
<string name="revanced_hide_terms_container_summary">Menyembunyikan container ketentuan layanan.</string>
|
<string name="revanced_hide_terms_container_summary">Menyembunyikan kontainer ketentuan layanan.</string>
|
||||||
<!-- PreferenceScreen: Action Bar -->
|
<!-- PreferenceScreen: Action Bar -->
|
||||||
<string name="revanced_preference_screen_action_bar_title">Bilah Tindakan</string>
|
<string name="revanced_preference_screen_action_bar_title">Bilah Tindakan</string>
|
||||||
<string name="revanced_hide_action_button_like_dislike_title">Sembunyikan tombol Like dan Dislike</string>
|
<string name="revanced_hide_action_button_like_dislike_title">Sembunyikan tombol Like dan Dislike</string>
|
||||||
<string name="revanced_hide_action_button_like_dislike_summary">Menyembunyikan tombol Like dan Dislike. Itu tidak akan work di layout player lawas.</string>
|
<string name="revanced_hide_action_button_like_dislike_summary">Menyembunyikan tombol Like dan Dislike. Itu tidak akan bekerja di layout player lama.</string>
|
||||||
<string name="revanced_hide_action_button_comment_title">Sembunyikan tombol Komentar</string>
|
<string name="revanced_hide_action_button_comment_title">Sembunyikan tombol Komentar</string>
|
||||||
<string name="revanced_hide_action_button_comment_summary">Menyembunyikan tombol Komentar.</string>
|
<string name="revanced_hide_action_button_comment_summary">Menyembunyikan tombol Komentar.</string>
|
||||||
<string name="revanced_hide_action_button_add_to_playlist_title">Sembunyikan tombol Save</string>
|
<string name="revanced_hide_action_button_add_to_playlist_title">Sembunyikan tombol Save</string>
|
||||||
<string name="revanced_hide_action_button_add_to_playlist_summary">Menyembunyikan tombol Save.</string>
|
<string name="revanced_hide_action_button_add_to_playlist_summary">Menyembunyikan tombol Simpan.</string>
|
||||||
<string name="revanced_hide_action_button_download_title">Sembunyikan tombol Download</string>
|
<string name="revanced_hide_action_button_download_title">Sembunyikan tombol Unduh</string>
|
||||||
<string name="revanced_hide_action_button_download_summary">Menyembunyikan tombol Download.</string>
|
<string name="revanced_hide_action_button_download_summary">Menyembunyikan tombol Unduh.</string>
|
||||||
<string name="revanced_hide_action_button_share_title">Sembunyikan tombol Share</string>
|
<string name="revanced_hide_action_button_share_title">Sembunyikan tombol Bagikan</string>
|
||||||
<string name="revanced_hide_action_button_share_summary">Menyembunyikan tombol Share.</string>
|
<string name="revanced_hide_action_button_share_summary">Menyembunyikan tombol Bagikan.</string>
|
||||||
<string name="revanced_hide_action_button_radio_title">Sembunyikan tombol Radio</string>
|
<string name="revanced_hide_action_button_radio_title">Sembunyikan tombol Radio</string>
|
||||||
<string name="revanced_hide_action_button_radio_summary">Menyembunyikan tombol Radio.</string>
|
<string name="revanced_hide_action_button_radio_summary">Menyembunyikan tombol Radio.</string>
|
||||||
<string name="revanced_hide_action_button_label_title">Sembunyikan tombol bilah tindakan</string>
|
<string name="revanced_hide_action_button_label_title">Sembunyikan tombol bilah tindakan</string>
|
||||||
<string name="revanced_hide_action_button_label_summary">Menyembunyikan bilah dari tombol tindakan.</string>
|
<string name="revanced_hide_action_button_label_summary">Menyembunyikan bilah dari tombol tindakan.</string>
|
||||||
<string name="revanced_external_downloader_action_title">Ganti tombol tindakan Download</string>
|
<string name="revanced_external_downloader_action_title">Ganti tombol tindakan Unduh</string>
|
||||||
<string name="revanced_external_downloader_action_summary">"Tombol Download membuka Downloader eksternal mu.
|
<string name="revanced_external_downloader_action_summary">"Tombol Unduh membuka Downloader eksternal kamu.
|
||||||
|
|
||||||
• Hanya menggantikan tombol Download di player.
|
• Hanya menggantikan tombol Unduh di player.
|
||||||
• Tidak bisa menggantikan tombol download di menu flyout atau tab Library."</string>
|
• Tidak bisa menggantikan tombol Unduh di menu flyout atau tab Library."</string>
|
||||||
<string name="revanced_external_downloader_package_name_title">Nama paket downloader eksternal</string>
|
<string name="revanced_external_downloader_package_name_title">Nama paket downloader eksternal</string>
|
||||||
<string name="revanced_external_downloader_package_name_summary">Nama paket aplikasi downloader eksternal yang terinstal, seperti NewPipe atau YTDLnis.</string>
|
<string name="revanced_external_downloader_package_name_summary">Nama paket aplikasi downloader eksternal yang terinstal, seperti NewPipe atau YTDLnis.</string>
|
||||||
<string name="revanced_external_downloader_dialog_title">Downloader eksternal</string>
|
<string name="revanced_external_downloader_dialog_title">Downloader eksternal</string>
|
||||||
<string name="revanced_external_downloader_not_installed_dialog_title">Peringatan</string>
|
<string name="revanced_external_downloader_not_installed_dialog_title">Peringatan</string>
|
||||||
<string name="revanced_external_downloader_not_installed_dialog_message">"%1$s belum terinstall.
|
<string name="revanced_external_downloader_not_installed_dialog_message">"%1$s belum terinstall.
|
||||||
Segera download %2$s dari website."</string>
|
Download %2$s dari website."</string>
|
||||||
<string name="revanced_external_downloader_not_installed_warning">%s tidak diinstal. Silakan instal.</string>
|
<string name="revanced_external_downloader_not_installed_warning">%s tidak diinstal. Silakan instal.</string>
|
||||||
<!-- PreferenceScreen: Ads -->
|
<!-- PreferenceScreen: Ads -->
|
||||||
<string name="revanced_preference_screen_ads_title">Iklan</string>
|
<string name="revanced_preference_screen_ads_title">Iklan</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_title">Sembunyikan iklan fullscreen</string>
|
<string name="revanced_hide_fullscreen_ads_title">Sembunyikan iklan fullscreen</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary">Menyembunyikan iklan fullscreen.</string>
|
<string name="revanced_hide_fullscreen_ads_summary">Menyembunyikan iklan fullscreen.</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_type_title">Tutup iklan fullscreen</string>
|
<string name="revanced_hide_fullscreen_ads_type_title">Tutup iklan fullscreen</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_type_summary">"Jika Diaktifkan, iklan fullscreen akan ditutup lewat tombol Close.
|
<string name="revanced_hide_fullscreen_ads_type_summary">"Jika diaktifkan, iklan fullscreen akan ditutup lewat tombol Close.
|
||||||
Jika dimatikan, ikan fullscreen akan di block. (kemungkinan akan ada side effect)"</string>
|
Jika dimatikan, iklan fullscreen akan di block. (kemungkinan akan ada side effect)"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_blocked_success">Iklan fullscreen telah diblok. (Blokir: %s)</string>
|
<string name="revanced_hide_fullscreen_ads_blocked_success">Iklan fullscreen telah diblok. (Blokir: %s)</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_closed_success">Iklan fullscreen telah ditutup.</string>
|
<string name="revanced_hide_fullscreen_ads_closed_success">Iklan fullscreen telah ditutup.</string>
|
||||||
<string name="revanced_hide_general_ads_title">Sembunyikan Iklan Umum</string>
|
<string name="revanced_hide_general_ads_title">Sembunyikan Iklan Umum</string>
|
||||||
<string name="revanced_hide_general_ads_summary">Sembunyikan Iklan Umum.</string>
|
<string name="revanced_hide_general_ads_summary">Menyembunyikan Iklan Umum.</string>
|
||||||
<string name="revanced_hide_music_ads_title">Sembunyikan iklan musik</string>
|
<string name="revanced_hide_music_ads_title">Sembunyikan iklan musik</string>
|
||||||
<string name="revanced_hide_music_ads_summary">Menyembunyikan iklan sebelum memutar musik.</string>
|
<string name="revanced_hide_music_ads_summary">Menyembunyikan iklan sebelum memutar musik.</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Hide paid promotion label</string>
|
<string name="revanced_hide_paid_promotion_label_title">Sembunyikan label promosi berbayar</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary">Hides the paid promotion label.</string>
|
<string name="revanced_hide_paid_promotion_label_summary">Menyembunyikan label promosi berbayar.</string>
|
||||||
<string name="revanced_hide_premium_promotion_title">Sembunykan popup promosi premium</string>
|
<string name="revanced_hide_premium_promotion_title">Sembunyikan popup promosi premium</string>
|
||||||
<string name="revanced_hide_premium_promotion_summary">Menyembunyikan popup promosi premium.</string>
|
<string name="revanced_hide_premium_promotion_summary">Menyembunyikan popup promosi premium.</string>
|
||||||
<string name="revanced_hide_premium_renewal_title">Sembunykan banner pembaruan premium</string>
|
<string name="revanced_hide_premium_renewal_title">Sembunyikan banner pembaruan premium</string>
|
||||||
<string name="revanced_hide_premium_renewal_summary">Menyembunyikan banner pembaruan premium.</string>
|
<string name="revanced_hide_premium_renewal_summary">Menyembunyikan banner pembaruan premium.</string>
|
||||||
<!-- PreferenceScreen: Flyout -->
|
<!-- PreferenceScreen: Flyout -->
|
||||||
<string name="revanced_preference_screen_flyout_title">Menu flyout</string>
|
<string name="revanced_preference_screen_flyout_title">Menu flyout</string>
|
||||||
@ -73,49 +73,49 @@ Masalah yang diketahui:
|
|||||||
• Gambar album di Tab library juga menjadi lebih kecil.
|
• Gambar album di Tab library juga menjadi lebih kecil.
|
||||||
• Tata letak pengatur waktu tidur mungkin terlihat tidak biasa."</string>
|
• Tata letak pengatur waktu tidur mungkin terlihat tidak biasa."</string>
|
||||||
<string name="revanced_enable_trim_silence_title">Tambah switch Trim silence</string>
|
<string name="revanced_enable_trim_silence_title">Tambah switch Trim silence</string>
|
||||||
<string name="revanced_enable_trim_silence_summary">"Adds a Trim silence switch to the playback speed flyout menu.
|
<string name="revanced_enable_trim_silence_summary">"Menambahkan tombol Trim silence ke menu flyout playback speed.
|
||||||
|
|
||||||
Info:
|
Info:
|
||||||
• This feature is for podcasts.
|
• Fitur ini hanya untuk podcast.
|
||||||
• This feature is still in development, so it may be unstable."</string>
|
• Fitur ini masih dalam pengembangan, jadi ini tidak akan stabil."</string>
|
||||||
<string name="revanced_hide_flyout_menu_like_dislike_title">Hide Like and Dislike buttons</string>
|
<string name="revanced_hide_flyout_menu_like_dislike_title">Sembunyikan tombol Like dan Dislike</string>
|
||||||
<string name="revanced_hide_flyout_menu_3_column_component_title">Hide 3-column component</string>
|
<string name="revanced_hide_flyout_menu_3_column_component_title">Sembunyikan komponen 3-kolom</string>
|
||||||
<string name="revanced_hide_flyout_menu_add_to_queue_title">Hide Add to queue menu</string>
|
<string name="revanced_hide_flyout_menu_add_to_queue_title">Sembunyikan menu tambahkan ke antrean</string>
|
||||||
<string name="revanced_hide_flyout_menu_captions_title">Hide Captions menu</string>
|
<string name="revanced_hide_flyout_menu_captions_title">Sembunyikan menu teks</string>
|
||||||
<string name="revanced_hide_flyout_menu_delete_playlist_title">Hide Delete playlist menu</string>
|
<string name="revanced_hide_flyout_menu_delete_playlist_title">Sembunyikan menu hapus playlist</string>
|
||||||
<string name="revanced_hide_flyout_menu_dismiss_queue_title">Hide Dismiss queue menu</string>
|
<string name="revanced_hide_flyout_menu_dismiss_queue_title">Sembunyikan menu abaikan antrean</string>
|
||||||
<string name="revanced_hide_flyout_menu_download_title">Hide Download menu</string>
|
<string name="revanced_hide_flyout_menu_download_title">Sembunyikan menu Unduh</string>
|
||||||
<string name="revanced_hide_flyout_menu_edit_playlist_title">Hide Edit playlist menu</string>
|
<string name="revanced_hide_flyout_menu_edit_playlist_title">Sembunyikan menu edit playlist</string>
|
||||||
<string name="revanced_hide_flyout_menu_go_to_album_title">Hide Go to album menu</string>
|
<string name="revanced_hide_flyout_menu_go_to_album_title">Sembunyikan menu Pergi ke album</string>
|
||||||
<string name="revanced_hide_flyout_menu_go_to_artist_title">Hide Go to artist menu</string>
|
<string name="revanced_hide_flyout_menu_go_to_artist_title">Sembunyikan menu Pergi ke artis</string>
|
||||||
<string name="revanced_hide_flyout_menu_go_to_episode_title">Hide Go to episode menu</string>
|
<string name="revanced_hide_flyout_menu_go_to_episode_title">Sembunyikan menu Pergi ke episode</string>
|
||||||
<string name="revanced_hide_flyout_menu_go_to_podcast_title">Hide Go to podcast menu</string>
|
<string name="revanced_hide_flyout_menu_go_to_podcast_title">Sembunyikan menu Pergi ke podcast</string>
|
||||||
<string name="revanced_hide_flyout_menu_help_title">Hide Help & feedback menu</string>
|
<string name="revanced_hide_flyout_menu_help_title">Sembunyikan menu bantuan & saran</string>
|
||||||
<string name="revanced_hide_flyout_menu_play_next_title">Hide Play next menu</string>
|
<string name="revanced_hide_flyout_menu_play_next_title">Sembunyikan menu putar berikutnya</string>
|
||||||
<string name="revanced_hide_flyout_menu_quality_title">Hide Quality menu</string>
|
<string name="revanced_hide_flyout_menu_quality_title">Hide menu Kualitas</string>
|
||||||
<string name="revanced_hide_flyout_menu_remove_from_library_title">Hide Remove from library menu</string>
|
<string name="revanced_hide_flyout_menu_remove_from_library_title">Sembunyikan menu hapus dari koleksi</string>
|
||||||
<string name="revanced_hide_flyout_menu_remove_from_playlist_title">Hide Remove from playlist menu</string>
|
<string name="revanced_hide_flyout_menu_remove_from_playlist_title">Sembunyikan hapus dari menu playlist</string>
|
||||||
<string name="revanced_hide_flyout_menu_report_title">Hide Report menu</string>
|
<string name="revanced_hide_flyout_menu_report_title">Sembunyikan menu laporkan</string>
|
||||||
<string name="revanced_hide_flyout_menu_save_episode_for_later_title">Hide Save episode for later menu</string>
|
<string name="revanced_hide_flyout_menu_save_episode_for_later_title">Sembunyikan menu simpan episode untuk ditonton nanti</string>
|
||||||
<string name="revanced_hide_flyout_menu_save_to_library_title">Hide Save to library menu</string>
|
<string name="revanced_hide_flyout_menu_save_to_library_title">Sembunyikan menu simpan ke koleksi</string>
|
||||||
<string name="revanced_hide_flyout_menu_save_to_playlist_title">Hide Save to playlist menu</string>
|
<string name="revanced_hide_flyout_menu_save_to_playlist_title">Sembunyikan menu simpan ke playlist</string>
|
||||||
<string name="revanced_hide_flyout_menu_share_title">Hide Share menu</string>
|
<string name="revanced_hide_flyout_menu_share_title">Sembunyikan menu bagikan</string>
|
||||||
<string name="revanced_hide_flyout_menu_shuffle_play_title">Hide Shuffle play menu</string>
|
<string name="revanced_hide_flyout_menu_shuffle_play_title">Sembunyikan menu putar acak</string>
|
||||||
<string name="revanced_hide_flyout_menu_sleep_timer_title">Hide Sleep timer menu</string>
|
<string name="revanced_hide_flyout_menu_sleep_timer_title">Sembunyikan menu waktu tidur</string>
|
||||||
<string name="revanced_hide_flyout_menu_start_radio_title">Hide Start radio menu</string>
|
<string name="revanced_hide_flyout_menu_start_radio_title">Sembunyikan menu mulai radio</string>
|
||||||
<string name="revanced_hide_flyout_menu_stats_for_nerds_title">Hide Stats for nerds menu</string>
|
<string name="revanced_hide_flyout_menu_stats_for_nerds_title">Sembunyikan menu statistik untuk nerds</string>
|
||||||
<string name="revanced_hide_flyout_menu_subscribe_title">Hide Subscribe / Unsubscribe menu</string>
|
<string name="revanced_hide_flyout_menu_subscribe_title">Sembunyikan menu Subscribe / Unsubscribe</string>
|
||||||
<string name="revanced_hide_flyout_menu_view_song_credit_title">Hide View song credits menu</string>
|
<string name="revanced_hide_flyout_menu_view_song_credit_title">Sembunyikan menu kredit lagu</string>
|
||||||
<string name="revanced_replace_flyout_menu_dismiss_queue_continue_watch_title">Continue watching</string>
|
<string name="revanced_replace_flyout_menu_dismiss_queue_continue_watch_title">Lanjutkan menonton</string>
|
||||||
<string name="revanced_replace_flyout_menu_dismiss_queue_continue_watch_summary">Continues the video from the current time when switching to YouTube.</string>
|
<string name="revanced_replace_flyout_menu_dismiss_queue_continue_watch_summary">Melanjutkan video dari waktu saat ini ketika berlaih ke YouTube.</string>
|
||||||
<string name="revanced_replace_flyout_menu_dismiss_queue_watch_on_youtube_label">Watch on YouTube</string>
|
<string name="revanced_replace_flyout_menu_dismiss_queue_watch_on_youtube_label">Tonton di YouTube</string>
|
||||||
<string name="revanced_replace_flyout_menu_dismiss_queue_watch_on_youtube_warning">Invalid video url.</string>
|
<string name="revanced_replace_flyout_menu_dismiss_queue_watch_on_youtube_warning">Url video tidak valid.</string>
|
||||||
<string name="revanced_replace_flyout_menu_dismiss_queue_title">Replace Dismiss queue menu</string>
|
<string name="revanced_replace_flyout_menu_dismiss_queue_title">Ganti menu hapus antrean</string>
|
||||||
<string name="revanced_replace_flyout_menu_dismiss_queue_summary">Replaces the Dismiss queue menu with the Watch on YouTube menu.</string>
|
<string name="revanced_replace_flyout_menu_dismiss_queue_summary">Menggantikan menu hapus antrean menjadi tonton di YouTube.</string>
|
||||||
<string name="revanced_replace_flyout_menu_report_title">Replace Report menu</string>
|
<string name="revanced_replace_flyout_menu_report_title">Ganti menu laporkan</string>
|
||||||
<string name="revanced_replace_flyout_menu_report_summary">Replaces the Report menu with the Playback speed menu.</string>
|
<string name="revanced_replace_flyout_menu_report_summary">Menggantikan menu laporkan dengan menu Kecepatan pemutaran.</string>
|
||||||
<string name="revanced_replace_flyout_menu_report_only_player_title">Keep Report in comments</string>
|
<string name="revanced_replace_flyout_menu_report_only_player_title">Simpan laporkan di komentar</string>
|
||||||
<string name="revanced_replace_flyout_menu_report_only_player_summary">Keeps the Report menu in the comments section intact.</string>
|
<string name="revanced_replace_flyout_menu_report_only_player_summary">Mempertahankan menu laporkan di bagian komentar.</string>
|
||||||
<!-- PreferenceScreen: General -->
|
<!-- PreferenceScreen: General -->
|
||||||
<string name="revanced_preference_screen_general_title">Umum</string>
|
<string name="revanced_preference_screen_general_title">Umum</string>
|
||||||
<string name="revanced_change_start_page_title">Ganti Halaman Awal</string>
|
<string name="revanced_change_start_page_title">Ganti Halaman Awal</string>
|
||||||
@ -247,8 +247,12 @@ Some features may not work properly in the old player layout."</string>
|
|||||||
<string name="revanced_custom_playback_speeds_summary">Menambah atau mengubah kecepatan pemutaran yang tersedia.</string>
|
<string name="revanced_custom_playback_speeds_summary">Menambah atau mengubah kecepatan pemutaran yang tersedia.</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_title">Remember playback speed changes</string>
|
<string name="revanced_remember_playback_speed_last_selected_title">Remember playback speed changes</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_summary">Remembers the last playback speed selected.</string>
|
<string name="revanced_remember_playback_speed_last_selected_summary">Remembers the last playback speed selected.</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_title">Tampilkan toast</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_summary">Menunjukkan toast ketika mengubah playback speed semula.</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_title">Remember video quality changes</string>
|
<string name="revanced_remember_video_quality_last_selected_title">Remember video quality changes</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_summary">Remembers the last video quality selected.</string>
|
<string name="revanced_remember_video_quality_last_selected_summary">Remembers the last video quality selected.</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_title">Tampilkan toast</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_summary">Menunjukkan toast ketika mengubah playback speed semula.</string>
|
||||||
<string name="revanced_custom_playback_speeds_invalid">Kecepatan pemutaran kustom tidak valid. Atur ulang ke nilai default.</string>
|
<string name="revanced_custom_playback_speeds_invalid">Kecepatan pemutaran kustom tidak valid. Atur ulang ke nilai default.</string>
|
||||||
<string name="revanced_custom_playback_speeds_parse_exception">Invalid custom playback speeds. Using default values.</string>
|
<string name="revanced_custom_playback_speeds_parse_exception">Invalid custom playback speeds. Using default values.</string>
|
||||||
<string name="revanced_remember_playback_speed_toast">Changing default speed to %s.</string>
|
<string name="revanced_remember_playback_speed_toast">Changing default speed to %s.</string>
|
||||||
@ -272,7 +276,6 @@ Some features may not work properly in the old player layout."</string>
|
|||||||
<string name="revanced_ryd_failure_connection_status_code">Dislikes are unavailable (status %d).</string>
|
<string name="revanced_ryd_failure_connection_status_code">Dislikes are unavailable (status %d).</string>
|
||||||
<string name="revanced_ryd_failure_client_rate_limit_requested">Dislike tidak tersedia (batas API client tercapai).</string>
|
<string name="revanced_ryd_failure_client_rate_limit_requested">Dislike tidak tersedia (batas API client tercapai).</string>
|
||||||
<string name="revanced_ryd_failure_generic">Dislikes are unavailable (%s).</string>
|
<string name="revanced_ryd_failure_generic">Dislikes are unavailable (%s).</string>
|
||||||
<string name="revanced_ryd_video_likes_hidden_by_video_owner">Sembunyikan</string>
|
|
||||||
<!-- PreferenceScreen: SponsorBlock -->
|
<!-- PreferenceScreen: SponsorBlock -->
|
||||||
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
||||||
<string name="revanced_sb_enabled">Enable SponsorBlock</string>
|
<string name="revanced_sb_enabled">Enable SponsorBlock</string>
|
||||||
@ -335,8 +338,6 @@ Some features may not work properly in the old player layout."</string>
|
|||||||
<string name="revanced_bypass_image_region_restrictions_summary">Mengganti domain yang ke blokir di negara tertentu sehingga playlist thumbnail, channel avatar, dll bisa di terima.</string>
|
<string name="revanced_bypass_image_region_restrictions_summary">Mengganti domain yang ke blokir di negara tertentu sehingga playlist thumbnail, channel avatar, dll bisa di terima.</string>
|
||||||
<string name="revanced_change_share_sheet_title">Ubah lembar berbagi</string>
|
<string name="revanced_change_share_sheet_title">Ubah lembar berbagi</string>
|
||||||
<string name="revanced_change_share_sheet_summary">Mengubah dari lembar berbagi dalam aplikasi ke lembar berbagi sistem.</string>
|
<string name="revanced_change_share_sheet_summary">Mengubah dari lembar berbagi dalam aplikasi ke lembar berbagi sistem.</string>
|
||||||
<string name="revanced_enable_cairo_splash_animation_title">Aktifkan animasi splash Cairo</string>
|
|
||||||
<string name="revanced_enable_cairo_splash_animation_summary">Mengaktifkan Animasi splash Cairo ketika app dibuka.</string>
|
|
||||||
<string name="revanced_enable_debug_logging_title">Aktifkan pencatatan debug</string>
|
<string name="revanced_enable_debug_logging_title">Aktifkan pencatatan debug</string>
|
||||||
<string name="revanced_enable_debug_logging_summary">Mencetak catatan debug.</string>
|
<string name="revanced_enable_debug_logging_summary">Mencetak catatan debug.</string>
|
||||||
<string name="revanced_enable_debug_buffer_logging_title">Enable debug buffer logging</string>
|
<string name="revanced_enable_debug_buffer_logging_title">Enable debug buffer logging</string>
|
||||||
|
@ -8,61 +8,61 @@
|
|||||||
<!-- PreferenceScreen: Account -->
|
<!-- PreferenceScreen: Account -->
|
||||||
<string name="revanced_preference_screen_account_title">Akun</string>
|
<string name="revanced_preference_screen_account_title">Akun</string>
|
||||||
<string name="revanced_hide_account_menu_title">Sembunyikan menu akun</string>
|
<string name="revanced_hide_account_menu_title">Sembunyikan menu akun</string>
|
||||||
<string name="revanced_hide_account_menu_summary">Menyembunyikan elemen menu akun menggunakan filter kustom.</string>
|
<string name="revanced_hide_account_menu_summary">Menyembunyikan elemen menu akun menggunakan filter custom.</string>
|
||||||
<string name="revanced_hide_account_menu_filter_strings_title">Filter menu Akun</string>
|
<string name="revanced_hide_account_menu_filter_strings_title">Filter menu Akun</string>
|
||||||
<string name="revanced_hide_account_menu_filter_strings_summary">Daftar dari nama-nama menu akun ke filter, terpisah oleh garis baru.</string>
|
<string name="revanced_hide_account_menu_filter_strings_summary">Daftar dari nama-nama menu akun ke filter, terpisah oleh garis baru.</string>
|
||||||
<string name="revanced_hide_account_menu_empty_component_title">Sembunyikan komponen kosong</string>
|
<string name="revanced_hide_account_menu_empty_component_title">Sembunyikan komponen kosong</string>
|
||||||
<string name="revanced_hide_account_menu_empty_component_summary">Menyembunyikan komponen kosong di menu akun.</string>
|
<string name="revanced_hide_account_menu_empty_component_summary">Menyembunyikan komponen kosong di menu akun.</string>
|
||||||
<string name="revanced_hide_handle_title">Sembunyikan handle</string>
|
<string name="revanced_hide_handle_title">Sembunyikan handle</string>
|
||||||
<string name="revanced_hide_handle_summary">Menyembunyikan handle di kelola akun.</string>
|
<string name="revanced_hide_handle_summary">Menyembunyikan handle di menu akun.</string>
|
||||||
<string name="revanced_hide_terms_container_title">Sembunyikan container ketentuan</string>
|
<string name="revanced_hide_terms_container_title">Sembunyikan kontainer ketentuan</string>
|
||||||
<string name="revanced_hide_terms_container_summary">Menyembunyikan container ketentuan layanan.</string>
|
<string name="revanced_hide_terms_container_summary">Menyembunyikan kontainer ketentuan layanan.</string>
|
||||||
<!-- PreferenceScreen: Action Bar -->
|
<!-- PreferenceScreen: Action Bar -->
|
||||||
<string name="revanced_preference_screen_action_bar_title">Bilah Tindakan</string>
|
<string name="revanced_preference_screen_action_bar_title">Bilah Tindakan</string>
|
||||||
<string name="revanced_hide_action_button_like_dislike_title">Sembunyikan tombol Like dan Dislike</string>
|
<string name="revanced_hide_action_button_like_dislike_title">Sembunyikan tombol Like dan Dislike</string>
|
||||||
<string name="revanced_hide_action_button_like_dislike_summary">Menyembunyikan tombol Like dan Dislike. Itu tidak akan work di layout player lawas.</string>
|
<string name="revanced_hide_action_button_like_dislike_summary">Menyembunyikan tombol Like dan Dislike. Itu tidak akan bekerja di layout player lama.</string>
|
||||||
<string name="revanced_hide_action_button_comment_title">Sembunyikan tombol Komentar</string>
|
<string name="revanced_hide_action_button_comment_title">Sembunyikan tombol Komentar</string>
|
||||||
<string name="revanced_hide_action_button_comment_summary">Menyembunyikan tombol Komentar.</string>
|
<string name="revanced_hide_action_button_comment_summary">Menyembunyikan tombol Komentar.</string>
|
||||||
<string name="revanced_hide_action_button_add_to_playlist_title">Sembunyikan tombol Save</string>
|
<string name="revanced_hide_action_button_add_to_playlist_title">Sembunyikan tombol Save</string>
|
||||||
<string name="revanced_hide_action_button_add_to_playlist_summary">Menyembunyikan tombol Save.</string>
|
<string name="revanced_hide_action_button_add_to_playlist_summary">Menyembunyikan tombol Simpan.</string>
|
||||||
<string name="revanced_hide_action_button_download_title">Sembunyikan tombol Download</string>
|
<string name="revanced_hide_action_button_download_title">Sembunyikan tombol Unduh</string>
|
||||||
<string name="revanced_hide_action_button_download_summary">Menyembunyikan tombol Download.</string>
|
<string name="revanced_hide_action_button_download_summary">Menyembunyikan tombol Unduh.</string>
|
||||||
<string name="revanced_hide_action_button_share_title">Sembunyikan tombol Share</string>
|
<string name="revanced_hide_action_button_share_title">Sembunyikan tombol Bagikan</string>
|
||||||
<string name="revanced_hide_action_button_share_summary">Menyembunyikan tombol Share.</string>
|
<string name="revanced_hide_action_button_share_summary">Menyembunyikan tombol Bagikan.</string>
|
||||||
<string name="revanced_hide_action_button_radio_title">Sembunyikan tombol Radio</string>
|
<string name="revanced_hide_action_button_radio_title">Sembunyikan tombol Radio</string>
|
||||||
<string name="revanced_hide_action_button_radio_summary">Menyembunyikan tombol Radio.</string>
|
<string name="revanced_hide_action_button_radio_summary">Menyembunyikan tombol Radio.</string>
|
||||||
<string name="revanced_hide_action_button_label_title">Sembunyikan tombol bilah tindakan</string>
|
<string name="revanced_hide_action_button_label_title">Sembunyikan tombol bilah tindakan</string>
|
||||||
<string name="revanced_hide_action_button_label_summary">Menyembunyikan bilah dari tombol tindakan.</string>
|
<string name="revanced_hide_action_button_label_summary">Menyembunyikan bilah dari tombol tindakan.</string>
|
||||||
<string name="revanced_external_downloader_action_title">Ganti tombol tindakan Download</string>
|
<string name="revanced_external_downloader_action_title">Ganti tombol tindakan Unduh</string>
|
||||||
<string name="revanced_external_downloader_action_summary">"Tombol Download membuka Downloader eksternal mu.
|
<string name="revanced_external_downloader_action_summary">"Tombol Unduh membuka Downloader eksternal kamu.
|
||||||
|
|
||||||
• Hanya menggantikan tombol Download di player.
|
• Hanya menggantikan tombol Unduh di player.
|
||||||
• Tidak bisa menggantikan tombol download di menu flyout atau tab Library."</string>
|
• Tidak bisa menggantikan tombol Unduh di menu flyout atau tab Library."</string>
|
||||||
<string name="revanced_external_downloader_package_name_title">Nama paket downloader eksternal</string>
|
<string name="revanced_external_downloader_package_name_title">Nama paket downloader eksternal</string>
|
||||||
<string name="revanced_external_downloader_package_name_summary">Nama paket aplikasi downloader eksternal yang terinstal, seperti NewPipe atau YTDLnis.</string>
|
<string name="revanced_external_downloader_package_name_summary">Nama paket aplikasi downloader eksternal yang terinstal, seperti NewPipe atau YTDLnis.</string>
|
||||||
<string name="revanced_external_downloader_dialog_title">Downloader eksternal</string>
|
<string name="revanced_external_downloader_dialog_title">Downloader eksternal</string>
|
||||||
<string name="revanced_external_downloader_not_installed_dialog_title">Peringatan</string>
|
<string name="revanced_external_downloader_not_installed_dialog_title">Peringatan</string>
|
||||||
<string name="revanced_external_downloader_not_installed_dialog_message">"%1$s belum terinstall.
|
<string name="revanced_external_downloader_not_installed_dialog_message">"%1$s belum terinstall.
|
||||||
Segera download %2$s dari website."</string>
|
Download %2$s dari website."</string>
|
||||||
<string name="revanced_external_downloader_not_installed_warning">%s tidak diinstal. Silakan instal.</string>
|
<string name="revanced_external_downloader_not_installed_warning">%s tidak diinstal. Silakan instal.</string>
|
||||||
<!-- PreferenceScreen: Ads -->
|
<!-- PreferenceScreen: Ads -->
|
||||||
<string name="revanced_preference_screen_ads_title">Iklan</string>
|
<string name="revanced_preference_screen_ads_title">Iklan</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_title">Sembunyikan iklan fullscreen</string>
|
<string name="revanced_hide_fullscreen_ads_title">Sembunyikan iklan fullscreen</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_summary">Menyembunyikan iklan fullscreen.</string>
|
<string name="revanced_hide_fullscreen_ads_summary">Menyembunyikan iklan fullscreen.</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_type_title">Tutup iklan fullscreen</string>
|
<string name="revanced_hide_fullscreen_ads_type_title">Tutup iklan fullscreen</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_type_summary">"Jika Diaktifkan, iklan fullscreen akan ditutup lewat tombol Close.
|
<string name="revanced_hide_fullscreen_ads_type_summary">"Jika diaktifkan, iklan fullscreen akan ditutup lewat tombol Close.
|
||||||
Jika dimatikan, ikan fullscreen akan di block. (kemungkinan akan ada side effect)"</string>
|
Jika dimatikan, iklan fullscreen akan di block. (kemungkinan akan ada side effect)"</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_blocked_success">Iklan fullscreen telah diblok. (Blokir: %s)</string>
|
<string name="revanced_hide_fullscreen_ads_blocked_success">Iklan fullscreen telah diblok. (Blokir: %s)</string>
|
||||||
<string name="revanced_hide_fullscreen_ads_closed_success">Iklan fullscreen telah ditutup.</string>
|
<string name="revanced_hide_fullscreen_ads_closed_success">Iklan fullscreen telah ditutup.</string>
|
||||||
<string name="revanced_hide_general_ads_title">Sembunyikan Iklan Umum</string>
|
<string name="revanced_hide_general_ads_title">Sembunyikan Iklan Umum</string>
|
||||||
<string name="revanced_hide_general_ads_summary">Sembunyikan Iklan Umum.</string>
|
<string name="revanced_hide_general_ads_summary">Menyembunyikan Iklan Umum.</string>
|
||||||
<string name="revanced_hide_music_ads_title">Sembunyikan iklan musik</string>
|
<string name="revanced_hide_music_ads_title">Sembunyikan iklan musik</string>
|
||||||
<string name="revanced_hide_music_ads_summary">Menyembunyikan iklan sebelum memutar musik.</string>
|
<string name="revanced_hide_music_ads_summary">Menyembunyikan iklan sebelum memutar musik.</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_title">Hide paid promotion label</string>
|
<string name="revanced_hide_paid_promotion_label_title">Sembunyikan label promosi berbayar</string>
|
||||||
<string name="revanced_hide_paid_promotion_label_summary">Hides the paid promotion label.</string>
|
<string name="revanced_hide_paid_promotion_label_summary">Menyembunyikan label promosi berbayar.</string>
|
||||||
<string name="revanced_hide_premium_promotion_title">Sembunykan popup promosi premium</string>
|
<string name="revanced_hide_premium_promotion_title">Sembunyikan popup promosi premium</string>
|
||||||
<string name="revanced_hide_premium_promotion_summary">Menyembunyikan popup promosi premium.</string>
|
<string name="revanced_hide_premium_promotion_summary">Menyembunyikan popup promosi premium.</string>
|
||||||
<string name="revanced_hide_premium_renewal_title">Sembunykan banner pembaruan premium</string>
|
<string name="revanced_hide_premium_renewal_title">Sembunyikan banner pembaruan premium</string>
|
||||||
<string name="revanced_hide_premium_renewal_summary">Menyembunyikan banner pembaruan premium.</string>
|
<string name="revanced_hide_premium_renewal_summary">Menyembunyikan banner pembaruan premium.</string>
|
||||||
<!-- PreferenceScreen: Flyout -->
|
<!-- PreferenceScreen: Flyout -->
|
||||||
<string name="revanced_preference_screen_flyout_title">Menu flyout</string>
|
<string name="revanced_preference_screen_flyout_title">Menu flyout</string>
|
||||||
@ -73,49 +73,49 @@ Masalah yang diketahui:
|
|||||||
• Gambar album di Tab library juga menjadi lebih kecil.
|
• Gambar album di Tab library juga menjadi lebih kecil.
|
||||||
• Tata letak pengatur waktu tidur mungkin terlihat tidak biasa."</string>
|
• Tata letak pengatur waktu tidur mungkin terlihat tidak biasa."</string>
|
||||||
<string name="revanced_enable_trim_silence_title">Tambah switch Trim silence</string>
|
<string name="revanced_enable_trim_silence_title">Tambah switch Trim silence</string>
|
||||||
<string name="revanced_enable_trim_silence_summary">"Adds a Trim silence switch to the playback speed flyout menu.
|
<string name="revanced_enable_trim_silence_summary">"Menambahkan tombol Trim silence ke menu flyout playback speed.
|
||||||
|
|
||||||
Info:
|
Info:
|
||||||
• This feature is for podcasts.
|
• Fitur ini hanya untuk podcast.
|
||||||
• This feature is still in development, so it may be unstable."</string>
|
• Fitur ini masih dalam pengembangan, jadi ini tidak akan stabil."</string>
|
||||||
<string name="revanced_hide_flyout_menu_like_dislike_title">Hide Like and Dislike buttons</string>
|
<string name="revanced_hide_flyout_menu_like_dislike_title">Sembunyikan tombol Like dan Dislike</string>
|
||||||
<string name="revanced_hide_flyout_menu_3_column_component_title">Hide 3-column component</string>
|
<string name="revanced_hide_flyout_menu_3_column_component_title">Sembunyikan komponen 3-kolom</string>
|
||||||
<string name="revanced_hide_flyout_menu_add_to_queue_title">Hide Add to queue menu</string>
|
<string name="revanced_hide_flyout_menu_add_to_queue_title">Sembunyikan menu tambahkan ke antrean</string>
|
||||||
<string name="revanced_hide_flyout_menu_captions_title">Hide Captions menu</string>
|
<string name="revanced_hide_flyout_menu_captions_title">Sembunyikan menu teks</string>
|
||||||
<string name="revanced_hide_flyout_menu_delete_playlist_title">Hide Delete playlist menu</string>
|
<string name="revanced_hide_flyout_menu_delete_playlist_title">Sembunyikan menu hapus playlist</string>
|
||||||
<string name="revanced_hide_flyout_menu_dismiss_queue_title">Hide Dismiss queue menu</string>
|
<string name="revanced_hide_flyout_menu_dismiss_queue_title">Sembunyikan menu abaikan antrean</string>
|
||||||
<string name="revanced_hide_flyout_menu_download_title">Hide Download menu</string>
|
<string name="revanced_hide_flyout_menu_download_title">Sembunyikan menu Unduh</string>
|
||||||
<string name="revanced_hide_flyout_menu_edit_playlist_title">Hide Edit playlist menu</string>
|
<string name="revanced_hide_flyout_menu_edit_playlist_title">Sembunyikan menu edit playlist</string>
|
||||||
<string name="revanced_hide_flyout_menu_go_to_album_title">Hide Go to album menu</string>
|
<string name="revanced_hide_flyout_menu_go_to_album_title">Sembunyikan menu Pergi ke album</string>
|
||||||
<string name="revanced_hide_flyout_menu_go_to_artist_title">Hide Go to artist menu</string>
|
<string name="revanced_hide_flyout_menu_go_to_artist_title">Sembunyikan menu Pergi ke artis</string>
|
||||||
<string name="revanced_hide_flyout_menu_go_to_episode_title">Hide Go to episode menu</string>
|
<string name="revanced_hide_flyout_menu_go_to_episode_title">Sembunyikan menu Pergi ke episode</string>
|
||||||
<string name="revanced_hide_flyout_menu_go_to_podcast_title">Hide Go to podcast menu</string>
|
<string name="revanced_hide_flyout_menu_go_to_podcast_title">Sembunyikan menu Pergi ke podcast</string>
|
||||||
<string name="revanced_hide_flyout_menu_help_title">Hide Help & feedback menu</string>
|
<string name="revanced_hide_flyout_menu_help_title">Sembunyikan menu bantuan & saran</string>
|
||||||
<string name="revanced_hide_flyout_menu_play_next_title">Hide Play next menu</string>
|
<string name="revanced_hide_flyout_menu_play_next_title">Sembunyikan menu putar berikutnya</string>
|
||||||
<string name="revanced_hide_flyout_menu_quality_title">Hide Quality menu</string>
|
<string name="revanced_hide_flyout_menu_quality_title">Hide menu Kualitas</string>
|
||||||
<string name="revanced_hide_flyout_menu_remove_from_library_title">Hide Remove from library menu</string>
|
<string name="revanced_hide_flyout_menu_remove_from_library_title">Sembunyikan menu hapus dari koleksi</string>
|
||||||
<string name="revanced_hide_flyout_menu_remove_from_playlist_title">Hide Remove from playlist menu</string>
|
<string name="revanced_hide_flyout_menu_remove_from_playlist_title">Sembunyikan hapus dari menu playlist</string>
|
||||||
<string name="revanced_hide_flyout_menu_report_title">Hide Report menu</string>
|
<string name="revanced_hide_flyout_menu_report_title">Sembunyikan menu laporkan</string>
|
||||||
<string name="revanced_hide_flyout_menu_save_episode_for_later_title">Hide Save episode for later menu</string>
|
<string name="revanced_hide_flyout_menu_save_episode_for_later_title">Sembunyikan menu simpan episode untuk ditonton nanti</string>
|
||||||
<string name="revanced_hide_flyout_menu_save_to_library_title">Hide Save to library menu</string>
|
<string name="revanced_hide_flyout_menu_save_to_library_title">Sembunyikan menu simpan ke koleksi</string>
|
||||||
<string name="revanced_hide_flyout_menu_save_to_playlist_title">Hide Save to playlist menu</string>
|
<string name="revanced_hide_flyout_menu_save_to_playlist_title">Sembunyikan menu simpan ke playlist</string>
|
||||||
<string name="revanced_hide_flyout_menu_share_title">Hide Share menu</string>
|
<string name="revanced_hide_flyout_menu_share_title">Sembunyikan menu bagikan</string>
|
||||||
<string name="revanced_hide_flyout_menu_shuffle_play_title">Hide Shuffle play menu</string>
|
<string name="revanced_hide_flyout_menu_shuffle_play_title">Sembunyikan menu putar acak</string>
|
||||||
<string name="revanced_hide_flyout_menu_sleep_timer_title">Hide Sleep timer menu</string>
|
<string name="revanced_hide_flyout_menu_sleep_timer_title">Sembunyikan menu waktu tidur</string>
|
||||||
<string name="revanced_hide_flyout_menu_start_radio_title">Hide Start radio menu</string>
|
<string name="revanced_hide_flyout_menu_start_radio_title">Sembunyikan menu mulai radio</string>
|
||||||
<string name="revanced_hide_flyout_menu_stats_for_nerds_title">Hide Stats for nerds menu</string>
|
<string name="revanced_hide_flyout_menu_stats_for_nerds_title">Sembunyikan menu statistik untuk nerds</string>
|
||||||
<string name="revanced_hide_flyout_menu_subscribe_title">Hide Subscribe / Unsubscribe menu</string>
|
<string name="revanced_hide_flyout_menu_subscribe_title">Sembunyikan menu Subscribe / Unsubscribe</string>
|
||||||
<string name="revanced_hide_flyout_menu_view_song_credit_title">Hide View song credits menu</string>
|
<string name="revanced_hide_flyout_menu_view_song_credit_title">Sembunyikan menu kredit lagu</string>
|
||||||
<string name="revanced_replace_flyout_menu_dismiss_queue_continue_watch_title">Continue watching</string>
|
<string name="revanced_replace_flyout_menu_dismiss_queue_continue_watch_title">Lanjutkan menonton</string>
|
||||||
<string name="revanced_replace_flyout_menu_dismiss_queue_continue_watch_summary">Continues the video from the current time when switching to YouTube.</string>
|
<string name="revanced_replace_flyout_menu_dismiss_queue_continue_watch_summary">Melanjutkan video dari waktu saat ini ketika berlaih ke YouTube.</string>
|
||||||
<string name="revanced_replace_flyout_menu_dismiss_queue_watch_on_youtube_label">Watch on YouTube</string>
|
<string name="revanced_replace_flyout_menu_dismiss_queue_watch_on_youtube_label">Tonton di YouTube</string>
|
||||||
<string name="revanced_replace_flyout_menu_dismiss_queue_watch_on_youtube_warning">Invalid video url.</string>
|
<string name="revanced_replace_flyout_menu_dismiss_queue_watch_on_youtube_warning">Url video tidak valid.</string>
|
||||||
<string name="revanced_replace_flyout_menu_dismiss_queue_title">Replace Dismiss queue menu</string>
|
<string name="revanced_replace_flyout_menu_dismiss_queue_title">Ganti menu hapus antrean</string>
|
||||||
<string name="revanced_replace_flyout_menu_dismiss_queue_summary">Replaces the Dismiss queue menu with the Watch on YouTube menu.</string>
|
<string name="revanced_replace_flyout_menu_dismiss_queue_summary">Menggantikan menu hapus antrean menjadi tonton di YouTube.</string>
|
||||||
<string name="revanced_replace_flyout_menu_report_title">Replace Report menu</string>
|
<string name="revanced_replace_flyout_menu_report_title">Ganti menu laporkan</string>
|
||||||
<string name="revanced_replace_flyout_menu_report_summary">Replaces the Report menu with the Playback speed menu.</string>
|
<string name="revanced_replace_flyout_menu_report_summary">Menggantikan menu laporkan dengan menu Kecepatan pemutaran.</string>
|
||||||
<string name="revanced_replace_flyout_menu_report_only_player_title">Keep Report in comments</string>
|
<string name="revanced_replace_flyout_menu_report_only_player_title">Simpan laporkan di komentar</string>
|
||||||
<string name="revanced_replace_flyout_menu_report_only_player_summary">Keeps the Report menu in the comments section intact.</string>
|
<string name="revanced_replace_flyout_menu_report_only_player_summary">Mempertahankan menu laporkan di bagian komentar.</string>
|
||||||
<!-- PreferenceScreen: General -->
|
<!-- PreferenceScreen: General -->
|
||||||
<string name="revanced_preference_screen_general_title">Umum</string>
|
<string name="revanced_preference_screen_general_title">Umum</string>
|
||||||
<string name="revanced_change_start_page_title">Ganti Halaman Awal</string>
|
<string name="revanced_change_start_page_title">Ganti Halaman Awal</string>
|
||||||
@ -247,8 +247,12 @@ Some features may not work properly in the old player layout."</string>
|
|||||||
<string name="revanced_custom_playback_speeds_summary">Menambah atau mengubah kecepatan pemutaran yang tersedia.</string>
|
<string name="revanced_custom_playback_speeds_summary">Menambah atau mengubah kecepatan pemutaran yang tersedia.</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_title">Remember playback speed changes</string>
|
<string name="revanced_remember_playback_speed_last_selected_title">Remember playback speed changes</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_summary">Remembers the last playback speed selected.</string>
|
<string name="revanced_remember_playback_speed_last_selected_summary">Remembers the last playback speed selected.</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_title">Tampilkan toast</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_summary">Menunjukkan toast ketika mengubah playback speed semula.</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_title">Remember video quality changes</string>
|
<string name="revanced_remember_video_quality_last_selected_title">Remember video quality changes</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_summary">Remembers the last video quality selected.</string>
|
<string name="revanced_remember_video_quality_last_selected_summary">Remembers the last video quality selected.</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_title">Tampilkan toast</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_summary">Menunjukkan toast ketika mengubah playback speed semula.</string>
|
||||||
<string name="revanced_custom_playback_speeds_invalid">Kecepatan pemutaran kustom tidak valid. Atur ulang ke nilai default.</string>
|
<string name="revanced_custom_playback_speeds_invalid">Kecepatan pemutaran kustom tidak valid. Atur ulang ke nilai default.</string>
|
||||||
<string name="revanced_custom_playback_speeds_parse_exception">Invalid custom playback speeds. Using default values.</string>
|
<string name="revanced_custom_playback_speeds_parse_exception">Invalid custom playback speeds. Using default values.</string>
|
||||||
<string name="revanced_remember_playback_speed_toast">Changing default speed to %s.</string>
|
<string name="revanced_remember_playback_speed_toast">Changing default speed to %s.</string>
|
||||||
@ -272,7 +276,6 @@ Some features may not work properly in the old player layout."</string>
|
|||||||
<string name="revanced_ryd_failure_connection_status_code">Dislikes are unavailable (status %d).</string>
|
<string name="revanced_ryd_failure_connection_status_code">Dislikes are unavailable (status %d).</string>
|
||||||
<string name="revanced_ryd_failure_client_rate_limit_requested">Dislike tidak tersedia (batas API client tercapai).</string>
|
<string name="revanced_ryd_failure_client_rate_limit_requested">Dislike tidak tersedia (batas API client tercapai).</string>
|
||||||
<string name="revanced_ryd_failure_generic">Dislikes are unavailable (%s).</string>
|
<string name="revanced_ryd_failure_generic">Dislikes are unavailable (%s).</string>
|
||||||
<string name="revanced_ryd_video_likes_hidden_by_video_owner">Sembunyikan</string>
|
|
||||||
<!-- PreferenceScreen: SponsorBlock -->
|
<!-- PreferenceScreen: SponsorBlock -->
|
||||||
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
||||||
<string name="revanced_sb_enabled">Enable SponsorBlock</string>
|
<string name="revanced_sb_enabled">Enable SponsorBlock</string>
|
||||||
@ -335,8 +338,6 @@ Some features may not work properly in the old player layout."</string>
|
|||||||
<string name="revanced_bypass_image_region_restrictions_summary">Mengganti domain yang ke blokir di negara tertentu sehingga playlist thumbnail, channel avatar, dll bisa di terima.</string>
|
<string name="revanced_bypass_image_region_restrictions_summary">Mengganti domain yang ke blokir di negara tertentu sehingga playlist thumbnail, channel avatar, dll bisa di terima.</string>
|
||||||
<string name="revanced_change_share_sheet_title">Ubah lembar berbagi</string>
|
<string name="revanced_change_share_sheet_title">Ubah lembar berbagi</string>
|
||||||
<string name="revanced_change_share_sheet_summary">Mengubah dari lembar berbagi dalam aplikasi ke lembar berbagi sistem.</string>
|
<string name="revanced_change_share_sheet_summary">Mengubah dari lembar berbagi dalam aplikasi ke lembar berbagi sistem.</string>
|
||||||
<string name="revanced_enable_cairo_splash_animation_title">Aktifkan animasi splash Cairo</string>
|
|
||||||
<string name="revanced_enable_cairo_splash_animation_summary">Mengaktifkan Animasi splash Cairo ketika app dibuka.</string>
|
|
||||||
<string name="revanced_enable_debug_logging_title">Aktifkan pencatatan debug</string>
|
<string name="revanced_enable_debug_logging_title">Aktifkan pencatatan debug</string>
|
||||||
<string name="revanced_enable_debug_logging_summary">Mencetak catatan debug.</string>
|
<string name="revanced_enable_debug_logging_summary">Mencetak catatan debug.</string>
|
||||||
<string name="revanced_enable_debug_buffer_logging_title">Enable debug buffer logging</string>
|
<string name="revanced_enable_debug_buffer_logging_title">Enable debug buffer logging</string>
|
||||||
|
@ -61,7 +61,6 @@
|
|||||||
<string name="revanced_ryd_about">Informazioni</string>
|
<string name="revanced_ryd_about">Informazioni</string>
|
||||||
<string name="revanced_ryd_attribution_summary">I dati vengono forniti dall\'API Return YouTube Dislike. Tocca qui per saperne di più.</string>
|
<string name="revanced_ryd_attribution_summary">I dati vengono forniti dall\'API Return YouTube Dislike. Tocca qui per saperne di più.</string>
|
||||||
<string name="revanced_ryd_failure_client_rate_limit_requested">\"Non mi piace\" non disponibile (limite API client raggiunto)</string>
|
<string name="revanced_ryd_failure_client_rate_limit_requested">\"Non mi piace\" non disponibile (limite API client raggiunto)</string>
|
||||||
<string name="revanced_ryd_video_likes_hidden_by_video_owner">Nascosto</string>
|
|
||||||
<!-- PreferenceScreen: SponsorBlock -->
|
<!-- PreferenceScreen: SponsorBlock -->
|
||||||
<!-- PreferenceScreen: Miscellaneous -->
|
<!-- PreferenceScreen: Miscellaneous -->
|
||||||
<string name="revanced_enable_debug_logging_title">Abilita la registrazione del debug</string>
|
<string name="revanced_enable_debug_logging_title">Abilita la registrazione del debug</string>
|
||||||
|
@ -200,6 +200,10 @@ YT Music の設定だけでなく、ReVanced Extended の設定も非表示に
|
|||||||
<string name="revanced_hide_navigation_label_summary">ナビゲーションバーのラベルを非表示にします。</string>
|
<string name="revanced_hide_navigation_label_summary">ナビゲーションバーのラベルを非表示にします。</string>
|
||||||
<!-- PreferenceScreen: Player -->
|
<!-- PreferenceScreen: Player -->
|
||||||
<string name="revanced_preference_screen_player_title">プレーヤー</string>
|
<string name="revanced_preference_screen_player_title">プレーヤー</string>
|
||||||
|
<string name="revanced_disable_mini_player_gesture_title">ミニプレーヤージェスチャーを無効にする</string>
|
||||||
|
<string name="revanced_disable_mini_player_gesture_summary">ミニプレーヤーでスワイプによる曲の変更を無効にします</string>
|
||||||
|
<string name="revanced_disable_player_gesture_title">プレイヤージェスチャーを無効にする</string>
|
||||||
|
<string name="revanced_disable_player_gesture_summary">プレイヤーでスワイプによる曲の変更を無効にします。</string>
|
||||||
<string name="revanced_enable_black_player_background_title">黒のプレイヤー背景を有効化</string>
|
<string name="revanced_enable_black_player_background_title">黒のプレイヤー背景を有効化</string>
|
||||||
<string name="revanced_enable_black_player_background_summary">プレイヤーの背景の色を黒に固定します。</string>
|
<string name="revanced_enable_black_player_background_summary">プレイヤーの背景の色を黒に固定します。</string>
|
||||||
<string name="revanced_enable_color_match_player_title">カラーマッチプレーヤーを有効化</string>
|
<string name="revanced_enable_color_match_player_title">カラーマッチプレーヤーを有効化</string>
|
||||||
@ -243,8 +247,12 @@ YT Music の設定だけでなく、ReVanced Extended の設定も非表示に
|
|||||||
<string name="revanced_custom_playback_speeds_summary">利用可能な再生速度を編集します。</string>
|
<string name="revanced_custom_playback_speeds_summary">利用可能な再生速度を編集します。</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_title">再生速度の変更を保存</string>
|
<string name="revanced_remember_playback_speed_last_selected_title">再生速度の変更を保存</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_summary">再生速度を変更するたびに、再生速度を保存します。</string>
|
<string name="revanced_remember_playback_speed_last_selected_summary">再生速度を変更するたびに、再生速度を保存します。</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_title">トーストを表示</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_summary">デフォルトの再生速度を変更するときにトーストを表示します。</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_title">ビデオ画質の変更を保存</string>
|
<string name="revanced_remember_video_quality_last_selected_title">ビデオ画質の変更を保存</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_summary">画質を変更するたびに、画質を保存します。</string>
|
<string name="revanced_remember_video_quality_last_selected_summary">画質を変更するたびに、画質を保存します。</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_title">トーストを表示</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_summary">デフォルトの画質を変更するときにトーストを表示します。</string>
|
||||||
<string name="revanced_custom_playback_speeds_invalid">無効なカスタム再生速度です。デフォルト値にリセットします。</string>
|
<string name="revanced_custom_playback_speeds_invalid">無効なカスタム再生速度です。デフォルト値にリセットします。</string>
|
||||||
<string name="revanced_custom_playback_speeds_parse_exception">無効なカスタム再生速度です。デフォルトの値を使用します。</string>
|
<string name="revanced_custom_playback_speeds_parse_exception">無効なカスタム再生速度です。デフォルトの値を使用します。</string>
|
||||||
<string name="revanced_remember_playback_speed_toast">デフォルトの再生速度を %s に変更しました。</string>
|
<string name="revanced_remember_playback_speed_toast">デフォルトの再生速度を %s に変更しました。</string>
|
||||||
@ -268,7 +276,6 @@ YT Music の設定だけでなく、ReVanced Extended の設定も非表示に
|
|||||||
<string name="revanced_ryd_failure_connection_status_code">低評価数は一時的に利用できません。(ステータス %d)</string>
|
<string name="revanced_ryd_failure_connection_status_code">低評価数は一時的に利用できません。(ステータス %d)</string>
|
||||||
<string name="revanced_ryd_failure_client_rate_limit_requested">低評価数は利用できません (クライアント API 制限)</string>
|
<string name="revanced_ryd_failure_client_rate_limit_requested">低評価数は利用できません (クライアント API 制限)</string>
|
||||||
<string name="revanced_ryd_failure_generic">低評価数は一時的に利用できません。(%s)</string>
|
<string name="revanced_ryd_failure_generic">低評価数は一時的に利用できません。(%s)</string>
|
||||||
<string name="revanced_ryd_video_likes_hidden_by_video_owner">非表示</string>
|
|
||||||
<!-- PreferenceScreen: SponsorBlock -->
|
<!-- PreferenceScreen: SponsorBlock -->
|
||||||
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
||||||
<string name="revanced_sb_enabled">Sponsor Block を有効化</string>
|
<string name="revanced_sb_enabled">Sponsor Block を有効化</string>
|
||||||
@ -329,8 +336,8 @@ YT Music の設定だけでなく、ReVanced Extended の設定も非表示に
|
|||||||
<string name="revanced_preference_screen_misc_title">その他</string>
|
<string name="revanced_preference_screen_misc_title">その他</string>
|
||||||
<string name="revanced_bypass_image_region_restrictions_title">画像表示の地域制限を回避</string>
|
<string name="revanced_bypass_image_region_restrictions_title">画像表示の地域制限を回避</string>
|
||||||
<string name="revanced_bypass_image_region_restrictions_summary">プレイリストのサムネイルやチャンネルアバターなどを受信できるように、一部の地域でブロックされているドメインを置き換えます。</string>
|
<string name="revanced_bypass_image_region_restrictions_summary">プレイリストのサムネイルやチャンネルアバターなどを受信できるように、一部の地域でブロックされているドメインを置き換えます。</string>
|
||||||
<string name="revanced_enable_cairo_splash_animation_title">Cairo のスプラッシュアニメーションを有効化</string>
|
<string name="revanced_change_share_sheet_title">共有メニューを変更</string>
|
||||||
<string name="revanced_enable_cairo_splash_animation_summary">アプリ起動時にCairo のスプラッシュアニメーションを有効にします。</string>
|
<string name="revanced_change_share_sheet_summary">アプリ内共有メニューからシステムの共有メニューに置き換えます。</string>
|
||||||
<string name="revanced_enable_debug_logging_title">デバッグログ</string>
|
<string name="revanced_enable_debug_logging_title">デバッグログ</string>
|
||||||
<string name="revanced_enable_debug_logging_summary">デバッグログを出力します。</string>
|
<string name="revanced_enable_debug_logging_summary">デバッグログを出力します。</string>
|
||||||
<string name="revanced_enable_debug_buffer_logging_title">デバッグバッファログを有効化</string>
|
<string name="revanced_enable_debug_buffer_logging_title">デバッグバッファログを有効化</string>
|
||||||
|
@ -64,6 +64,8 @@
|
|||||||
<string name="revanced_hide_premium_promotion_summary">YouTube Premium 팝업 광고를 숨깁니다.</string>
|
<string name="revanced_hide_premium_promotion_summary">YouTube Premium 팝업 광고를 숨깁니다.</string>
|
||||||
<string name="revanced_hide_premium_renewal_title">YouTube Premium 갱신 배너 제거</string>
|
<string name="revanced_hide_premium_renewal_title">YouTube Premium 갱신 배너 제거</string>
|
||||||
<string name="revanced_hide_premium_renewal_summary">YouTube Premium 갱신 배너를 숨깁니다.</string>
|
<string name="revanced_hide_premium_renewal_summary">YouTube Premium 갱신 배너를 숨깁니다.</string>
|
||||||
|
<string name="revanced_hide_promotion_alert_banner_title">프로모션 알림 배너 제거</string>
|
||||||
|
<string name="revanced_hide_promotion_alert_banner_summary">프로모션 알림 배너를 숨깁니다.</string>
|
||||||
<!-- PreferenceScreen: Flyout -->
|
<!-- PreferenceScreen: Flyout -->
|
||||||
<string name="revanced_preference_screen_flyout_title">메뉴 구성요소</string>
|
<string name="revanced_preference_screen_flyout_title">메뉴 구성요소</string>
|
||||||
<string name="revanced_enable_compact_dialog_title">소형 다이얼로그 활성화</string>
|
<string name="revanced_enable_compact_dialog_title">소형 다이얼로그 활성화</string>
|
||||||
@ -202,9 +204,9 @@ YT Music 설정 메뉴뿐만 아니라 ReVanced Extended 설정 메뉴도 숨겨
|
|||||||
<!-- PreferenceScreen: Player -->
|
<!-- PreferenceScreen: Player -->
|
||||||
<string name="revanced_preference_screen_player_title">플레이어</string>
|
<string name="revanced_preference_screen_player_title">플레이어</string>
|
||||||
<string name="revanced_disable_mini_player_gesture_title">미니 플레이어 제스처 비활성화</string>
|
<string name="revanced_disable_mini_player_gesture_title">미니 플레이어 제스처 비활성화</string>
|
||||||
<string name="revanced_disable_mini_player_gesture_summary">미니 플레이어에서 트랙을 변경하기 위해 스와이프를 비활성화합니다.</string>
|
<string name="revanced_disable_mini_player_gesture_summary">미니 플레이어에서 \'스와이프 제스처로 트랙 변경\'을 비활성화합니다.</string>
|
||||||
<string name="revanced_disable_player_gesture_title">플레이어 제스처 비활성화</string>
|
<string name="revanced_disable_player_gesture_title">플레이어 제스처 비활성화</string>
|
||||||
<string name="revanced_disable_player_gesture_summary">플레이어에서 트랙을 변경하기 위해 스와이프를 비활성화합니다.</string>
|
<string name="revanced_disable_player_gesture_summary">플레이어에서 \'스와이프 제스처로 트랙 변경\'을 비활성화합니다.</string>
|
||||||
<string name="revanced_enable_black_player_background_title">검정 플레이어 배경 활성화</string>
|
<string name="revanced_enable_black_player_background_title">검정 플레이어 배경 활성화</string>
|
||||||
<string name="revanced_enable_black_player_background_summary">플레이어 배경 색상을 검정으로 설정합니다.</string>
|
<string name="revanced_enable_black_player_background_summary">플레이어 배경 색상을 검정으로 설정합니다.</string>
|
||||||
<string name="revanced_enable_color_match_player_title">색상 일치 플레이어 활성화</string>
|
<string name="revanced_enable_color_match_player_title">색상 일치 플레이어 활성화</string>
|
||||||
@ -248,8 +250,12 @@ YT Music 설정 메뉴뿐만 아니라 ReVanced Extended 설정 메뉴도 숨겨
|
|||||||
<string name="revanced_custom_playback_speeds_summary">사용하고 싶은 재생 속도 값을 추가하거나 변경할 수 있습니다.</string>
|
<string name="revanced_custom_playback_speeds_summary">사용하고 싶은 재생 속도 값을 추가하거나 변경할 수 있습니다.</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_title">재생 속도 저장 활성화</string>
|
<string name="revanced_remember_playback_speed_last_selected_title">재생 속도 저장 활성화</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_summary">재생 속도 값을 변경할 때마다 저장합니다.</string>
|
<string name="revanced_remember_playback_speed_last_selected_summary">재생 속도 값을 변경할 때마다 저장합니다.</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_title">팝업 메시지 표시하기</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_summary">기본 동영상 재생 속도 값으로 변경되었을 때, 팝업 메시지를 표시합니다.</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_title">동영상 품질 저장 활성화</string>
|
<string name="revanced_remember_video_quality_last_selected_title">동영상 품질 저장 활성화</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_summary">동영상 품질 값을 변경할 때마다 저장합니다.</string>
|
<string name="revanced_remember_video_quality_last_selected_summary">동영상 품질 값을 변경할 때마다 저장합니다.</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_title">팝업 메시지 표시하기</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_summary">기본 동영상 화질 값으로 변경되었을 때, 팝업 메시지를 표시합니다.</string>
|
||||||
<string name="revanced_custom_playback_speeds_invalid">사용자 정의 재생 속도는 %s배속보다 작아야 하므로 기본값으로 초기화합니다.</string>
|
<string name="revanced_custom_playback_speeds_invalid">사용자 정의 재생 속도는 %s배속보다 작아야 하므로 기본값으로 초기화합니다.</string>
|
||||||
<string name="revanced_custom_playback_speeds_parse_exception">잘못된 재생 속도 값이므로 기본값으로 초기화합니다.</string>
|
<string name="revanced_custom_playback_speeds_parse_exception">잘못된 재생 속도 값이므로 기본값으로 초기화합니다.</string>
|
||||||
<string name="revanced_remember_playback_speed_toast">기본 재생 속도 값을 %s으로 변경합니다.</string>
|
<string name="revanced_remember_playback_speed_toast">기본 재생 속도 값을 %s으로 변경합니다.</string>
|
||||||
@ -273,7 +279,6 @@ YT Music 설정 메뉴뿐만 아니라 ReVanced Extended 설정 메뉴도 숨겨
|
|||||||
<string name="revanced_ryd_failure_connection_status_code">싫어요 개수를 표시할 수 없습니다 (상태 코드: %d).</string>
|
<string name="revanced_ryd_failure_connection_status_code">싫어요 개수를 표시할 수 없습니다 (상태 코드: %d).</string>
|
||||||
<string name="revanced_ryd_failure_client_rate_limit_requested">싫어요 개수를 표시할 수 없습니다. (클라이언트 API 제한 도달)</string>
|
<string name="revanced_ryd_failure_client_rate_limit_requested">싫어요 개수를 표시할 수 없습니다. (클라이언트 API 제한 도달)</string>
|
||||||
<string name="revanced_ryd_failure_generic">싫어요 개수를 표시할 수 없습니다 (%s).</string>
|
<string name="revanced_ryd_failure_generic">싫어요 개수를 표시할 수 없습니다 (%s).</string>
|
||||||
<string name="revanced_ryd_video_likes_hidden_by_video_owner">숨겨짐</string>
|
|
||||||
<!-- PreferenceScreen: SponsorBlock -->
|
<!-- PreferenceScreen: SponsorBlock -->
|
||||||
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
||||||
<string name="revanced_sb_enabled">SponsorBlock 활성화</string>
|
<string name="revanced_sb_enabled">SponsorBlock 활성화</string>
|
||||||
@ -336,8 +341,8 @@ YT Music 설정 메뉴뿐만 아니라 ReVanced Extended 설정 메뉴도 숨겨
|
|||||||
<string name="revanced_bypass_image_region_restrictions_summary">이미지 도메인을 변경하여 일부 국가에서 차단된 재생목록 썸네일, 채널 프로필 사진, 커뮤니티 게시물 이미지 등을 수신할 수 있습니다.</string>
|
<string name="revanced_bypass_image_region_restrictions_summary">이미지 도메인을 변경하여 일부 국가에서 차단된 재생목록 썸네일, 채널 프로필 사진, 커뮤니티 게시물 이미지 등을 수신할 수 있습니다.</string>
|
||||||
<string name="revanced_change_share_sheet_title">공유 시트 변경</string>
|
<string name="revanced_change_share_sheet_title">공유 시트 변경</string>
|
||||||
<string name="revanced_change_share_sheet_summary">YT Music 기본 공유 시트에서 Android 기본 공유 시트로 변경합니다.\n\n• 공유 버튼으로 바로 Android 기본 공유 메뉴를 실행할 수 있습니다.</string>
|
<string name="revanced_change_share_sheet_summary">YT Music 기본 공유 시트에서 Android 기본 공유 시트로 변경합니다.\n\n• 공유 버튼으로 바로 Android 기본 공유 메뉴를 실행할 수 있습니다.</string>
|
||||||
<string name="revanced_enable_cairo_splash_animation_title">Cairo 스플래시 애니메이션 활성화</string>
|
<string name="revanced_disable_cairo_splash_animation_title">Cairo 스플래시 애니메이션 비활성화</string>
|
||||||
<string name="revanced_enable_cairo_splash_animation_summary">앱을 시작할 때, Cairo 스플래시 애니메이션을 활성화합니다.</string>
|
<string name="revanced_disable_cairo_splash_animation_summary">앱을 시작할 때, Cairo 스플래시 애니메이션을 비활성화합니다.</string>
|
||||||
<string name="revanced_enable_debug_logging_title">디버그 로깅 활성화</string>
|
<string name="revanced_enable_debug_logging_title">디버그 로깅 활성화</string>
|
||||||
<string name="revanced_enable_debug_logging_summary">디버그 로그를 출력합니다.</string>
|
<string name="revanced_enable_debug_logging_summary">디버그 로그를 출력합니다.</string>
|
||||||
<string name="revanced_enable_debug_buffer_logging_title">디버그 버퍼 로깅 활성화</string>
|
<string name="revanced_enable_debug_buffer_logging_title">디버그 버퍼 로깅 활성화</string>
|
||||||
|
@ -182,7 +182,6 @@ Bekende problemen:
|
|||||||
<string name="revanced_ryd_failure_connection_status_code">Dislikes niet beschikbaar (status %d).</string>
|
<string name="revanced_ryd_failure_connection_status_code">Dislikes niet beschikbaar (status %d).</string>
|
||||||
<string name="revanced_ryd_failure_client_rate_limit_requested">Vind ik niet leuk is niet beschikbaar (client API limiet bereikt)</string>
|
<string name="revanced_ryd_failure_client_rate_limit_requested">Vind ik niet leuk is niet beschikbaar (client API limiet bereikt)</string>
|
||||||
<string name="revanced_ryd_failure_generic">Dislikes niet beschikbaar (%s).</string>
|
<string name="revanced_ryd_failure_generic">Dislikes niet beschikbaar (%s).</string>
|
||||||
<string name="revanced_ryd_video_likes_hidden_by_video_owner">Verborgen</string>
|
|
||||||
<!-- PreferenceScreen: SponsorBlock -->
|
<!-- PreferenceScreen: SponsorBlock -->
|
||||||
<!-- PreferenceScreen: Miscellaneous -->
|
<!-- PreferenceScreen: Miscellaneous -->
|
||||||
<string name="revanced_enable_debug_logging_title">Debug logging aanzetten</string>
|
<string name="revanced_enable_debug_logging_title">Debug logging aanzetten</string>
|
||||||
|
@ -64,6 +64,8 @@ Jeśli opcja jest wyłączona, pełnoekranowe reklamy są blokowane (mogą wyst
|
|||||||
<string name="revanced_hide_premium_promotion_summary">Ukrywa wyskakujące okienka promocyjne Premium.</string>
|
<string name="revanced_hide_premium_promotion_summary">Ukrywa wyskakujące okienka promocyjne Premium.</string>
|
||||||
<string name="revanced_hide_premium_renewal_title">Ukryj baner odnawiania Premium</string>
|
<string name="revanced_hide_premium_renewal_title">Ukryj baner odnawiania Premium</string>
|
||||||
<string name="revanced_hide_premium_renewal_summary">Ukrywa baner odnawiania Premium.</string>
|
<string name="revanced_hide_premium_renewal_summary">Ukrywa baner odnawiania Premium.</string>
|
||||||
|
<string name="revanced_hide_promotion_alert_banner_title">Ukryj banery z alertami promocyjnymi</string>
|
||||||
|
<string name="revanced_hide_promotion_alert_banner_summary">Ukrywa banery z alertami promocyjnymi.</string>
|
||||||
<!-- PreferenceScreen: Flyout -->
|
<!-- PreferenceScreen: Flyout -->
|
||||||
<string name="revanced_preference_screen_flyout_title">Menu ustawień utworu</string>
|
<string name="revanced_preference_screen_flyout_title">Menu ustawień utworu</string>
|
||||||
<string name="revanced_enable_compact_dialog_title">Włącz kompaktowe dialogi</string>
|
<string name="revanced_enable_compact_dialog_title">Włącz kompaktowe dialogi</string>
|
||||||
@ -242,13 +244,17 @@ Nie pomija to ograniczeń wiekowych, lecz akceptuje je automatycznie."</string>
|
|||||||
<string name="revanced_restore_old_player_layout_summary">"Przywraca układ odtwarzacza do starego wyglądu.
|
<string name="revanced_restore_old_player_layout_summary">"Przywraca układ odtwarzacza do starego wyglądu.
|
||||||
Niektóre ustawienia mogą nie działać poprawnie ze starym układem odtwarzacza."</string>
|
Niektóre ustawienia mogą nie działać poprawnie ze starym układem odtwarzacza."</string>
|
||||||
<!-- PreferenceScreen: Video -->
|
<!-- PreferenceScreen: Video -->
|
||||||
<string name="revanced_preference_screen_video_title">Filmy</string>
|
<string name="revanced_preference_screen_video_title">Teledyski</string>
|
||||||
<string name="revanced_custom_playback_speeds_title">Edytuj niestandardowe prędkości odtwarzania</string>
|
<string name="revanced_custom_playback_speeds_title">Edytuj niestandardowe prędkości odtwarzania</string>
|
||||||
<string name="revanced_custom_playback_speeds_summary">Skonfiguruj dostępne prędkości odtwarzania.</string>
|
<string name="revanced_custom_playback_speeds_summary">Skonfiguruj dostępne prędkości odtwarzania.</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_title">Zapamiętuj zmiany prędkości odtwarzania</string>
|
<string name="revanced_remember_playback_speed_last_selected_title">Zapamiętuj zmiany prędkości odtwarzania</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_summary">Zapisuje ostatnią wybraną prędkość odtwarzania.</string>
|
<string name="revanced_remember_playback_speed_last_selected_summary">Zapisuje ostatnią wybraną prędkość odtwarzania.</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_title">Zapamiętuj zmiany jakości filmu</string>
|
<string name="revanced_remember_playback_speed_last_selected_toast_title">Komunikaty o zmianie domyślnej prędkości odtwarzania</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_summary">Zapisuje ostatnią wybraną jakość filmu.</string>
|
<string name="revanced_remember_playback_speed_last_selected_toast_summary">Komunikaty będą wyświetlane po zmianie domyślnej prędkości odtwarzania.</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_title">Zapamiętuj zmiany jakości teledysku</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_summary">Zapisuje ostatnią wybraną jakość teledysku.</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_title">Komunikaty o zmianie domyślnej jakości teledysków</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_summary">Komunikaty będą wyświetlane po zmianie domyślnej jakości teledysków.</string>
|
||||||
<string name="revanced_custom_playback_speeds_invalid">Nieprawidłowe niestandardowe prędkości odtwarzania. Przywrócono domyślne wartości.</string>
|
<string name="revanced_custom_playback_speeds_invalid">Nieprawidłowe niestandardowe prędkości odtwarzania. Przywrócono domyślne wartości.</string>
|
||||||
<string name="revanced_custom_playback_speeds_parse_exception">Nieprawidłowe niestandardowe prędkości odtwarzania. Przywrócono domyślne wartości.</string>
|
<string name="revanced_custom_playback_speeds_parse_exception">Nieprawidłowe niestandardowe prędkości odtwarzania. Przywrócono domyślne wartości.</string>
|
||||||
<string name="revanced_remember_playback_speed_toast">Zmieniono domyślną prędkość odtwarzania na %s.</string>
|
<string name="revanced_remember_playback_speed_toast">Zmieniono domyślną prędkość odtwarzania na %s.</string>
|
||||||
@ -272,7 +278,6 @@ Niektóre ustawienia mogą nie działać poprawnie ze starym układem odtwarzacz
|
|||||||
<string name="revanced_ryd_failure_connection_status_code">Liczba łapek w dół nie jest dostępna (status %d).</string>
|
<string name="revanced_ryd_failure_connection_status_code">Liczba łapek w dół nie jest dostępna (status %d).</string>
|
||||||
<string name="revanced_ryd_failure_client_rate_limit_requested">Łapki w dół nie są dostępne (limit API użytkownika został osiągnięty).</string>
|
<string name="revanced_ryd_failure_client_rate_limit_requested">Łapki w dół nie są dostępne (limit API użytkownika został osiągnięty).</string>
|
||||||
<string name="revanced_ryd_failure_generic">Liczba łapek w dół nie jest dostępna (%s).</string>
|
<string name="revanced_ryd_failure_generic">Liczba łapek w dół nie jest dostępna (%s).</string>
|
||||||
<string name="revanced_ryd_video_likes_hidden_by_video_owner">Ukryte</string>
|
|
||||||
<!-- PreferenceScreen: SponsorBlock -->
|
<!-- PreferenceScreen: SponsorBlock -->
|
||||||
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
||||||
<string name="revanced_sb_enabled">Włącz SponsorBlock</string>
|
<string name="revanced_sb_enabled">Włącz SponsorBlock</string>
|
||||||
@ -335,8 +340,8 @@ Niektóre ustawienia mogą nie działać poprawnie ze starym układem odtwarzacz
|
|||||||
<string name="revanced_bypass_image_region_restrictions_summary">Zastępuje domenę, która jest blokowana w niektórych regionach, aby można było otrzymywać miniaturki playlist, awatary kanałów itp.</string>
|
<string name="revanced_bypass_image_region_restrictions_summary">Zastępuje domenę, która jest blokowana w niektórych regionach, aby można było otrzymywać miniaturki playlist, awatary kanałów itp.</string>
|
||||||
<string name="revanced_change_share_sheet_title">Zmień wygląd panelu udostępniania</string>
|
<string name="revanced_change_share_sheet_title">Zmień wygląd panelu udostępniania</string>
|
||||||
<string name="revanced_change_share_sheet_summary">Zmienia wygląd panelu udostępniania z natywnego aplikacji na systemowy.</string>
|
<string name="revanced_change_share_sheet_summary">Zmienia wygląd panelu udostępniania z natywnego aplikacji na systemowy.</string>
|
||||||
<string name="revanced_enable_cairo_splash_animation_title">Włącz animację uruchamiania aplikacji</string>
|
<string name="revanced_disable_cairo_splash_animation_title">Wyłącz animację uruchamiania aplikacji</string>
|
||||||
<string name="revanced_enable_cairo_splash_animation_summary">Włącza animację ładowania aplikacji związaną z motywem Cairo podczas otwierania aplikacji.</string>
|
<string name="revanced_disable_cairo_splash_animation_summary">Wyłącza animację ładowania aplikacji związaną z motywem Cairo podczas otwierania aplikacji.</string>
|
||||||
<string name="revanced_enable_debug_logging_title">Włącz logowanie debugowania</string>
|
<string name="revanced_enable_debug_logging_title">Włącz logowanie debugowania</string>
|
||||||
<string name="revanced_enable_debug_logging_summary">Wyświetla log od debugowania.</string>
|
<string name="revanced_enable_debug_logging_summary">Wyświetla log od debugowania.</string>
|
||||||
<string name="revanced_enable_debug_buffer_logging_title">Logi do debugowania buforu</string>
|
<string name="revanced_enable_debug_buffer_logging_title">Logi do debugowania buforu</string>
|
||||||
|
@ -64,6 +64,8 @@ Se estiver desativado, os anúncios em tela cheia serão bloqueados. (pode haver
|
|||||||
<string name="revanced_hide_premium_promotion_summary">Oculta pop-ups de promoção premium.</string>
|
<string name="revanced_hide_premium_promotion_summary">Oculta pop-ups de promoção premium.</string>
|
||||||
<string name="revanced_hide_premium_renewal_title">Ocultar banner de renovação premium</string>
|
<string name="revanced_hide_premium_renewal_title">Ocultar banner de renovação premium</string>
|
||||||
<string name="revanced_hide_premium_renewal_summary">Oculta o banner de renovação premium.</string>
|
<string name="revanced_hide_premium_renewal_summary">Oculta o banner de renovação premium.</string>
|
||||||
|
<string name="revanced_hide_promotion_alert_banner_title">Ocultar banner de alerta de promoção</string>
|
||||||
|
<string name="revanced_hide_promotion_alert_banner_summary">Oculta o banner de alerta de promoção.</string>
|
||||||
<!-- PreferenceScreen: Flyout -->
|
<!-- PreferenceScreen: Flyout -->
|
||||||
<string name="revanced_preference_screen_flyout_title">Menu flutuante</string>
|
<string name="revanced_preference_screen_flyout_title">Menu flutuante</string>
|
||||||
<string name="revanced_enable_compact_dialog_title">Ativar diálogo compacto</string>
|
<string name="revanced_enable_compact_dialog_title">Ativar diálogo compacto</string>
|
||||||
@ -247,8 +249,12 @@ Alguns recursos podem não funcionar corretamente no layout antigo do reprodutor
|
|||||||
<string name="revanced_custom_playback_speeds_summary">Adicionar ou alterar as velocidades de reprodução disponíveis.</string>
|
<string name="revanced_custom_playback_speeds_summary">Adicionar ou alterar as velocidades de reprodução disponíveis.</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_title">Lembrar mudança na velocidade de reprodução</string>
|
<string name="revanced_remember_playback_speed_last_selected_title">Lembrar mudança na velocidade de reprodução</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_summary">Lembra a última velocidade de reprodução selecionada.</string>
|
<string name="revanced_remember_playback_speed_last_selected_summary">Lembra a última velocidade de reprodução selecionada.</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_title">Exibir uma notificação flutuante</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_summary">Exibir uma notificação flutuante quando alterar a velocidade padrão de reprodução.</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_title">Lembrar mudança na qualidade do vídeo</string>
|
<string name="revanced_remember_video_quality_last_selected_title">Lembrar mudança na qualidade do vídeo</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_summary">Lembra a última qualidade de vídeo selecionada.</string>
|
<string name="revanced_remember_video_quality_last_selected_summary">Lembra a última qualidade de vídeo selecionada.</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_title">Exibir uma notificação flutuante</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_summary">Exibir uma notificação flutuante quando alterar a qualidade padrão do vídeo.</string>
|
||||||
<string name="revanced_custom_playback_speeds_invalid">Velocidades personalizadas devem ser menores que %sx. Usando valores padrão.</string>
|
<string name="revanced_custom_playback_speeds_invalid">Velocidades personalizadas devem ser menores que %sx. Usando valores padrão.</string>
|
||||||
<string name="revanced_custom_playback_speeds_parse_exception">Velocidade personalizada de reprodução inválida. Usando valores padrão.</string>
|
<string name="revanced_custom_playback_speeds_parse_exception">Velocidade personalizada de reprodução inválida. Usando valores padrão.</string>
|
||||||
<string name="revanced_remember_playback_speed_toast">Alterando a velocidade padrão para %s.</string>
|
<string name="revanced_remember_playback_speed_toast">Alterando a velocidade padrão para %s.</string>
|
||||||
@ -272,13 +278,12 @@ Alguns recursos podem não funcionar corretamente no layout antigo do reprodutor
|
|||||||
<string name="revanced_ryd_failure_connection_status_code">Deslikes indisponível (status %d).</string>
|
<string name="revanced_ryd_failure_connection_status_code">Deslikes indisponível (status %d).</string>
|
||||||
<string name="revanced_ryd_failure_client_rate_limit_requested">Dislikes indisponível (limite de API do cliente atingido).</string>
|
<string name="revanced_ryd_failure_client_rate_limit_requested">Dislikes indisponível (limite de API do cliente atingido).</string>
|
||||||
<string name="revanced_ryd_failure_generic">Deslikes indisponível (%s).</string>
|
<string name="revanced_ryd_failure_generic">Deslikes indisponível (%s).</string>
|
||||||
<string name="revanced_ryd_video_likes_hidden_by_video_owner">Oculto</string>
|
|
||||||
<!-- PreferenceScreen: SponsorBlock -->
|
<!-- PreferenceScreen: SponsorBlock -->
|
||||||
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
||||||
<string name="revanced_sb_enabled">Ativar SponsorBlock</string>
|
<string name="revanced_sb_enabled">Ativar SponsorBlock</string>
|
||||||
<string name="revanced_sb_enabled_sum">SponsorBlock é um sistema coletivo para pular partes irritantes de vídeos do YouTube.</string>
|
<string name="revanced_sb_enabled_sum">SponsorBlock é um sistema coletivo para pular partes irritantes de vídeos do YouTube.</string>
|
||||||
<string name="revanced_sb_toast_on_connection_error">Exibir uma notificação flutuante se a API não estiver disponível</string>
|
<string name="revanced_sb_toast_on_connection_error">Exibir uma notificação flutuante se a API não estiver disponível</string>
|
||||||
<string name="revanced_sb_toast_on_connection_error_sum">Mostra uma notificação flutuante se a API SponsorBlock não estiver disponível.</string>
|
<string name="revanced_sb_toast_on_connection_error_sum">Exibe uma notificação flutuante se a API SponsorBlock não estiver disponível.</string>
|
||||||
<string name="revanced_sb_toast_on_skip">Exibir uma notificação flutuante quando pular automaticamente</string>
|
<string name="revanced_sb_toast_on_skip">Exibir uma notificação flutuante quando pular automaticamente</string>
|
||||||
<string name="revanced_sb_toast_on_skip_sum">Uma notificação flutuante é exibida quando um segmento é ignorado automaticamente.</string>
|
<string name="revanced_sb_toast_on_skip_sum">Uma notificação flutuante é exibida quando um segmento é ignorado automaticamente.</string>
|
||||||
<string name="revanced_sb_api_url">Alterar URL da API</string>
|
<string name="revanced_sb_api_url">Alterar URL da API</string>
|
||||||
@ -335,8 +340,6 @@ Alguns recursos podem não funcionar corretamente no layout antigo do reprodutor
|
|||||||
<string name="revanced_bypass_image_region_restrictions_summary">Substitui o domínio que está bloqueado em algumas regiões para que miniaturas para playlists, avatares de canais, etc. possam ser recebidos.</string>
|
<string name="revanced_bypass_image_region_restrictions_summary">Substitui o domínio que está bloqueado em algumas regiões para que miniaturas para playlists, avatares de canais, etc. possam ser recebidos.</string>
|
||||||
<string name="revanced_change_share_sheet_title">Alterar menu de compartilhamento</string>
|
<string name="revanced_change_share_sheet_title">Alterar menu de compartilhamento</string>
|
||||||
<string name="revanced_change_share_sheet_summary">Alterar o menu de compartilhamento do app para o meno de compartilhamento do sistema.</string>
|
<string name="revanced_change_share_sheet_summary">Alterar o menu de compartilhamento do app para o meno de compartilhamento do sistema.</string>
|
||||||
<string name="revanced_enable_cairo_splash_animation_title">Ativar animação inicial do Cairo</string>
|
|
||||||
<string name="revanced_enable_cairo_splash_animation_summary">Ativa a animação inicial do Cairo quando o aplicativo é iniciado.</string>
|
|
||||||
<string name="revanced_enable_debug_logging_title">Ativar o relatório de depuração</string>
|
<string name="revanced_enable_debug_logging_title">Ativar o relatório de depuração</string>
|
||||||
<string name="revanced_enable_debug_logging_summary">Imprime o relatório de depuração</string>
|
<string name="revanced_enable_debug_logging_summary">Imprime o relatório de depuração</string>
|
||||||
<string name="revanced_enable_debug_buffer_logging_title">Ativar o registro de depuração do buffer</string>
|
<string name="revanced_enable_debug_buffer_logging_title">Ativar o registro de depuração do buffer</string>
|
||||||
|
@ -75,7 +75,6 @@ Probleme cunoscute:
|
|||||||
<string name="revanced_ryd_compact_layout_summary">Ascunde separatorul butonului apreciez.</string>
|
<string name="revanced_ryd_compact_layout_summary">Ascunde separatorul butonului apreciez.</string>
|
||||||
<string name="revanced_ryd_about">Despre</string>
|
<string name="revanced_ryd_about">Despre</string>
|
||||||
<string name="revanced_ryd_attribution_summary">Datele sunt furnizate de API-ul Returnare YouTube Dislike. Atinge aici pentru a afla mai multe.</string>
|
<string name="revanced_ryd_attribution_summary">Datele sunt furnizate de API-ul Returnare YouTube Dislike. Atinge aici pentru a afla mai multe.</string>
|
||||||
<string name="revanced_ryd_video_likes_hidden_by_video_owner">Ascuns</string>
|
|
||||||
<!-- PreferenceScreen: SponsorBlock -->
|
<!-- PreferenceScreen: SponsorBlock -->
|
||||||
<!-- PreferenceScreen: Miscellaneous -->
|
<!-- PreferenceScreen: Miscellaneous -->
|
||||||
<string name="revanced_enable_debug_logging_title">Activează jurnalul de depanare</string>
|
<string name="revanced_enable_debug_logging_title">Activează jurnalul de depanare</string>
|
||||||
|
@ -137,6 +137,11 @@
|
|||||||
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
|
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
|
||||||
<string name="revanced_custom_filter_strings_summary">Настройте, какие компоненты фильтровать, обозначая конец каждого из них новой строкой.</string>
|
<string name="revanced_custom_filter_strings_summary">Настройте, какие компоненты фильтровать, обозначая конец каждого из них новой строкой.</string>
|
||||||
<string name="revanced_custom_filter_toast_invalid_syntax">Недопустимый пользовательский фильтр: %s.</string>
|
<string name="revanced_custom_filter_toast_invalid_syntax">Недопустимый пользовательский фильтр: %s.</string>
|
||||||
|
<string name="revanced_hide_settings_menu_title">Скрыть меню настроек</string>
|
||||||
|
<string name="revanced_hide_settings_menu_summary">"Скрывает элементы меню настроек.
|
||||||
|
При этом скрывается не только меню настроек YT Music, но и меню настроек ReVanced Extended."</string>
|
||||||
|
<string name="revanced_hide_settings_menu_filter_strings_title">Фильтр настроек меню</string>
|
||||||
|
<string name="revanced_hide_settings_menu_filter_strings_summary">Список названий меню настроек для фильтрации, разделенных новыми строками.</string>
|
||||||
<string name="revanced_hide_button_shelf_title">Скрыть ряд кнопок</string>
|
<string name="revanced_hide_button_shelf_title">Скрыть ряд кнопок</string>
|
||||||
<string name="revanced_hide_button_shelf_summary">Скрывает ряд кнопок с главной страницы и со вкладки \"Навигатор\".</string>
|
<string name="revanced_hide_button_shelf_summary">Скрывает ряд кнопок с главной страницы и со вкладки \"Навигатор\".</string>
|
||||||
<string name="revanced_hide_carousel_shelf_title">Скрыть карусель треков</string>
|
<string name="revanced_hide_carousel_shelf_title">Скрыть карусель треков</string>
|
||||||
@ -195,6 +200,10 @@
|
|||||||
<string name="revanced_hide_navigation_label_summary">Скрывает подписи под кнопками навигации.</string>
|
<string name="revanced_hide_navigation_label_summary">Скрывает подписи под кнопками навигации.</string>
|
||||||
<!-- PreferenceScreen: Player -->
|
<!-- PreferenceScreen: Player -->
|
||||||
<string name="revanced_preference_screen_player_title">Плеер</string>
|
<string name="revanced_preference_screen_player_title">Плеер</string>
|
||||||
|
<string name="revanced_disable_mini_player_gesture_title">Отключить жест мини плеера</string>
|
||||||
|
<string name="revanced_disable_mini_player_gesture_summary">Отключает свайп для переключения треков в миниплеере.</string>
|
||||||
|
<string name="revanced_disable_player_gesture_title">Отключить жест плеера</string>
|
||||||
|
<string name="revanced_disable_player_gesture_summary">Отключает свайп для переключения треков в плеере.</string>
|
||||||
<string name="revanced_enable_black_player_background_title">Включить черный фон плеера</string>
|
<string name="revanced_enable_black_player_background_title">Включить черный фон плеера</string>
|
||||||
<string name="revanced_enable_black_player_background_summary">Меняет адаптивный цвет фона плеера на черный.</string>
|
<string name="revanced_enable_black_player_background_summary">Меняет адаптивный цвет фона плеера на черный.</string>
|
||||||
<string name="revanced_enable_color_match_player_title">Цветовое соответствие проигрывателей</string>
|
<string name="revanced_enable_color_match_player_title">Цветовое соответствие проигрывателей</string>
|
||||||
@ -238,8 +247,12 @@
|
|||||||
<string name="revanced_custom_playback_speeds_summary">Настройте доступные скорости воспроизведения.</string>
|
<string name="revanced_custom_playback_speeds_summary">Настройте доступные скорости воспроизведения.</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_title">Запоминать изменения скорости</string>
|
<string name="revanced_remember_playback_speed_last_selected_title">Запоминать изменения скорости</string>
|
||||||
<string name="revanced_remember_playback_speed_last_selected_summary">Запоминает последнюю выбранную скорость воспроизведения.</string>
|
<string name="revanced_remember_playback_speed_last_selected_summary">Запоминает последнюю выбранную скорость воспроизведения.</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_title">Показывать всплывающее уведомление</string>
|
||||||
|
<string name="revanced_remember_playback_speed_last_selected_toast_summary">Показывать всплывающее уведомление при смене скорости воспроизведения по умолчанию.</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_title">Запоминать изменения качества видео</string>
|
<string name="revanced_remember_video_quality_last_selected_title">Запоминать изменения качества видео</string>
|
||||||
<string name="revanced_remember_video_quality_last_selected_summary">Запоминает последнее выбранное качество видео.</string>
|
<string name="revanced_remember_video_quality_last_selected_summary">Запоминает последнее выбранное качество видео.</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_title">Показывать всплывающее уведомление</string>
|
||||||
|
<string name="revanced_remember_video_quality_last_selected_toast_summary">Показывать всплывающее уведомление при смене качества видео по умолчанию.</string>
|
||||||
<string name="revanced_custom_playback_speeds_invalid">Недопустимые скорости. Значения сброшены к начальным.</string>
|
<string name="revanced_custom_playback_speeds_invalid">Недопустимые скорости. Значения сброшены к начальным.</string>
|
||||||
<string name="revanced_custom_playback_speeds_parse_exception">Недопустимые пользовательские скорости воспроизведения. Используются значения по умолчанию.</string>
|
<string name="revanced_custom_playback_speeds_parse_exception">Недопустимые пользовательские скорости воспроизведения. Используются значения по умолчанию.</string>
|
||||||
<string name="revanced_remember_playback_speed_toast">Скорость по умолчанию изменена на %s.</string>
|
<string name="revanced_remember_playback_speed_toast">Скорость по умолчанию изменена на %s.</string>
|
||||||
@ -263,7 +276,6 @@
|
|||||||
<string name="revanced_ryd_failure_connection_status_code">Отметки \"Не нравится\" недоступны (состояние %d).</string>
|
<string name="revanced_ryd_failure_connection_status_code">Отметки \"Не нравится\" недоступны (состояние %d).</string>
|
||||||
<string name="revanced_ryd_failure_client_rate_limit_requested">Отметки \"Не нравится\" недоступны (достигнут лимит клиентов сервера API).</string>
|
<string name="revanced_ryd_failure_client_rate_limit_requested">Отметки \"Не нравится\" недоступны (достигнут лимит клиентов сервера API).</string>
|
||||||
<string name="revanced_ryd_failure_generic">Отметки \"Не нравится\" недоступны (%s).</string>
|
<string name="revanced_ryd_failure_generic">Отметки \"Не нравится\" недоступны (%s).</string>
|
||||||
<string name="revanced_ryd_video_likes_hidden_by_video_owner">Скрыты</string>
|
|
||||||
<!-- PreferenceScreen: SponsorBlock -->
|
<!-- PreferenceScreen: SponsorBlock -->
|
||||||
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
<string name="revanced_preference_screen_sb_title">SponsorBlock</string>
|
||||||
<string name="revanced_sb_enabled">Включить SponsorBlock</string>
|
<string name="revanced_sb_enabled">Включить SponsorBlock</string>
|
||||||
@ -322,8 +334,10 @@
|
|||||||
<string name="revanced_sb_about_api">sponsor.ajay.app</string>
|
<string name="revanced_sb_about_api">sponsor.ajay.app</string>
|
||||||
<!-- PreferenceScreen: Miscellaneous -->
|
<!-- PreferenceScreen: Miscellaneous -->
|
||||||
<string name="revanced_preference_screen_misc_title">Разное</string>
|
<string name="revanced_preference_screen_misc_title">Разное</string>
|
||||||
<string name="revanced_enable_cairo_splash_animation_title">Анимация заставки Каир</string>
|
<string name="revanced_bypass_image_region_restrictions_title">Обойти ограничения изображений по региону</string>
|
||||||
<string name="revanced_enable_cairo_splash_animation_summary">Включает анимацию заставки Каир при запуске приложения.</string>
|
<string name="revanced_bypass_image_region_restrictions_summary">Заменяет заблокированный в некоторых регионах домен, чтобы можно было получать миниатюры плейлистов, аватары каналов и т. д.</string>
|
||||||
|
<string name="revanced_change_share_sheet_title">Изменить список \"Поделиться\"</string>
|
||||||
|
<string name="revanced_change_share_sheet_summary">Меняет встроенное диалоговое окно \"Поделиться\" на системное.</string>
|
||||||
<string name="revanced_enable_debug_logging_title">Ведение журнала отладки</string>
|
<string name="revanced_enable_debug_logging_title">Ведение журнала отладки</string>
|
||||||
<string name="revanced_enable_debug_logging_summary">Выводит журнал отладки.</string>
|
<string name="revanced_enable_debug_logging_summary">Выводит журнал отладки.</string>
|
||||||
<string name="revanced_enable_debug_buffer_logging_title">Ведение журналов отладки буфера</string>
|
<string name="revanced_enable_debug_buffer_logging_title">Ведение журналов отладки буфера</string>
|
||||||
|