Merge branch 'dev' into revanced-extended

This commit is contained in:
inotia00 2024-09-07 09:32:24 +09:00
commit c57de97576
238 changed files with 6120 additions and 4850 deletions

View File

@ -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.

View File

@ -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"
] ]
} }
], ],

View File

@ -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

View File

@ -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" }

Binary file not shown.

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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"
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -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"
)
} }
} }

View File

@ -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)

View File

@ -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,

View File

@ -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)

View File

@ -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.")
} }
} }

View File

@ -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
""" """

View File

@ -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;"
}
}

View File

@ -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.
) )
) )
) )

View File

@ -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

View File

@ -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
) )
} }

View File

@ -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.

View File

@ -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"
)
} }
} }

View File

@ -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
"""
)
}
}
}

View File

@ -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,
)
)

View File

@ -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

View File

@ -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

View File

@ -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,
) )

View File

@ -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
""" """
) )
} }

View File

@ -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;"
} }

View File

@ -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)

View File

@ -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
*/ */

View File

@ -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#")
) )

View File

@ -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))
) )
} }
} }

View File

@ -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)

View File

@ -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"
) )

View File

@ -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",

View File

@ -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,

View File

@ -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(

View File

@ -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"

View File

@ -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

View File

@ -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)
}
}

View File

@ -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"),
)

View File

@ -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",
),
)

View File

@ -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")
},
)

View File

@ -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"),
)

View File

@ -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")
}
}

View File

@ -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")
)

View File

@ -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
},
)

View File

@ -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,
),
)

View File

@ -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.
),
)

View File

@ -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 "),
)

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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

View File

@ -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;"
}
}

View File

@ -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

View File

@ -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;"
)
)

View File

@ -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
},
)

View File

@ -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

View File

@ -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" },
)

View File

@ -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
), ),

View File

@ -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
"""
)
}
}
}

View File

@ -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)
}
)

View File

@ -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)
}
)

View File

@ -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)
}
)

View File

@ -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#")
)

View File

@ -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("\\|"),
)

View File

@ -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.
),
)

View File

@ -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 - "),
)

View File

@ -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;"
) )
/** /**

View File

@ -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")

View File

@ -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(

View File

@ -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,

View File

@ -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,

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -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>

View File

@ -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">Скриване на менюто &amp; за помощ</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>

View File

@ -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>

View File

@ -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>

View File

@ -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 &amp; 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>

View File

@ -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>

View File

@ -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>

View File

@ -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 &amp; feedback menu</string> <string name="revanced_hide_flyout_menu_help_title">Sembunyikan menu bantuan &amp; 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>

View File

@ -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 &amp; feedback menu</string> <string name="revanced_hide_flyout_menu_help_title">Sembunyikan menu bantuan &amp; 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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

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