chore: Merge branch dev to main (#4781)

This commit is contained in:
oSumAtrIX 2025-04-15 12:59:44 +02:00 committed by GitHub
commit 42230b0291
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
75 changed files with 815 additions and 342 deletions

View File

@ -1,3 +1,52 @@
# [5.20.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.20.0-dev.6...v5.20.0-dev.7) (2025-04-15)
### Bug Fixes
* **Spotify:** Fix login by replacing `Spoof signature` patch with new `Spoof package info` patch ([#4794](https://github.com/ReVanced/revanced-patches/issues/4794)) ([d639151](https://github.com/ReVanced/revanced-patches/commit/d639151641352ce651037b17fb65bd58953cd51c))
# [5.20.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v5.20.0-dev.5...v5.20.0-dev.6) (2025-04-15)
### Bug Fixes
* **Duolingo - Hide ads:** Support lastest app release ([#4790](https://github.com/ReVanced/revanced-patches/issues/4790)) ([215fccb](https://github.com/ReVanced/revanced-patches/commit/215fccbaf2fdd54251c46cbda106029eb304996b))
# [5.20.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.20.0-dev.4...v5.20.0-dev.5) (2025-04-14)
### Features
* **YouTube - Swipe controls:** Add option to change volume swipe sensitivity (step size) ([#4557](https://github.com/ReVanced/revanced-patches/issues/4557)) ([8957325](https://github.com/ReVanced/revanced-patches/commit/8957325d78eb42e087c4c1ff0abedb2146aa4423))
# [5.20.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.20.0-dev.3...v5.20.0-dev.4) (2025-04-14)
### Bug Fixes
* **Spotify - Unlock Spotify Premium:** Remove premium restriction for 'Spotify Connect' ([#4782](https://github.com/ReVanced/revanced-patches/issues/4782)) ([50f5b1a](https://github.com/ReVanced/revanced-patches/commit/50f5b1ac54372542d76e87626f00ddefb54da125))
# [5.20.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.20.0-dev.2...v5.20.0-dev.3) (2025-04-13)
### Bug Fixes
* **YouTube - Remove background playback restrictions:** Restore PiP button functionality after screen is unlocked ([6837348](https://github.com/ReVanced/revanced-patches/commit/6837348c45156d6743a63fef8b6e045087afbda8))
# [5.20.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.20.0-dev.1...v5.20.0-dev.2) (2025-04-13)
### Features
* **Spotify - Custom theme:** Add option to use unmodified player background gradient ([#4741](https://github.com/ReVanced/revanced-patches/issues/4741)) ([0ee3693](https://github.com/ReVanced/revanced-patches/commit/0ee36939f43f325afca37119db1cf1af3b63be27))
# [5.20.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.19.1...v5.20.0-dev.1) (2025-04-13)
### Features
* Add `Set target SDK version 34` patch (Disable edge-to-edge display) ([#4780](https://github.com/ReVanced/revanced-patches/issues/4780)) ([dcf6178](https://github.com/ReVanced/revanced-patches/commit/dcf6178f19f86dd1b57d54c855b8c47b086dd33a))
## [5.19.1](https://github.com/ReVanced/revanced-patches/compare/v5.19.0...v5.19.1) (2025-04-12)

View File

@ -80,6 +80,9 @@ public final class UnlockPremiumPatch {
new OverrideAttribute("streaming-rules", ""),
// Enables premium UI in settings and removes the premium button in the nav-bar.
new OverrideAttribute("nft-disabled", "1"),
// Enable Spotify Connect and disable other premium related UI, like buying premium.
// It also removes the download button.
new OverrideAttribute("type", "premium"),
// Enable Spotify Car Thing hardware device.
// Device is discontinued and no longer works with the latest releases,
// but it might still work with older app targets.

View File

@ -319,6 +319,7 @@ public class Settings extends BaseSettings {
parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME));
public static final IntegerSetting SWIPE_MAGNITUDE_THRESHOLD = new IntegerSetting("revanced_swipe_threshold", 30, true,
parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME));
public static final IntegerSetting SWIPE_VOLUME_SENSITIVITY = new IntegerSetting("revanced_swipe_volume_sensitivity", 1, true, parent(SWIPE_VOLUME));
public static final BooleanSetting SWIPE_SHOW_CIRCULAR_OVERLAY = new BooleanSetting("revanced_swipe_show_circular_overlay", FALSE, true,
parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME));
public static final BooleanSetting SWIPE_OVERLAY_MINIMAL_STYLE = new BooleanSetting("revanced_swipe_overlay_minimal_style", FALSE, true,

View File

@ -1,6 +1,5 @@
package app.revanced.extension.youtube.swipecontrols
import android.content.Context
import android.graphics.Color
import app.revanced.extension.shared.StringRef.str
import app.revanced.extension.shared.Utils
@ -9,12 +8,8 @@ import app.revanced.extension.youtube.shared.PlayerType
/**
* provider for configuration for volume and brightness swipe controls
*
* @param context the context to create in
*/
class SwipeControlsConfigurationProvider(
private val context: Context,
) {
class SwipeControlsConfigurationProvider {
//region swipe enable
/**
* should swipe controls be enabled? (global setting)
@ -60,6 +55,23 @@ class SwipeControlsConfigurationProvider(
*/
val swipeMagnitudeThreshold: Int
get() = Settings.SWIPE_MAGNITUDE_THRESHOLD.get()
/**
* How much volume will change by single swipe.
* If it is set to 0, it will reset to the default value because 0 would disable swiping.
* */
val volumeSwipeSensitivity: Int
get() {
val sensitivity = Settings.SWIPE_VOLUME_SENSITIVITY.get()
if (sensitivity < 1) {
Settings.SWIPE_VOLUME_SENSITIVITY.resetToDefault()
return Settings.SWIPE_VOLUME_SENSITIVITY.get()
}
return sensitivity
}
//endregion
//region overlay adjustments

View File

@ -127,7 +127,7 @@ class SwipeControlsHostActivity : Activity() {
private fun initialize() {
// create controllers
printDebug { "initializing swipe controls controllers" }
config = SwipeControlsConfigurationProvider(this)
config = SwipeControlsConfigurationProvider()
keys = VolumeKeysController(this)
audio = createAudioController()
screen = createScreenController()

View File

@ -41,7 +41,7 @@ class VolumeKeysController(
private fun handleVolumeKeyEvent(event: KeyEvent, volumeUp: Boolean): Boolean {
if (event.action == KeyEvent.ACTION_DOWN) {
controller.audio?.apply {
volume += if (volumeUp) 1 else -1
volume += controller.config.volumeSwipeSensitivity * if (volumeUp) 1 else -1
controller.overlay.onVolumeChanged(volume, maxVolume)
}
}

View File

@ -24,6 +24,7 @@ abstract class BaseGestureController(
controller.overlay,
10,
1,
controller.config.volumeSwipeSensitivity,
) {
/**

View File

@ -41,6 +41,7 @@ interface VolumeAndBrightnessScroller {
* @param overlayController overlay controller instance
* @param volumeDistance unit distance for volume scrolling, in dp
* @param brightnessDistance unit distance for brightness scrolling, in dp
* @param volumeSwipeSensitivity how much volume will change by single swipe
*/
class VolumeAndBrightnessScrollerImpl(
context: Context,
@ -49,6 +50,7 @@ class VolumeAndBrightnessScrollerImpl(
private val overlayController: SwipeControlsOverlay,
volumeDistance: Int = 10,
brightnessDistance: Int = 1,
private val volumeSwipeSensitivity: Int,
) : VolumeAndBrightnessScroller {
// region volume
@ -60,7 +62,7 @@ class VolumeAndBrightnessScrollerImpl(
),
) { _, _, direction ->
volumeController?.run {
volume += direction
volume += direction * volumeSwipeSensitivity
overlayController.onVolumeChanged(volume, maxVolume)
}
}

View File

@ -25,7 +25,7 @@ class SwipeControlsOverlayLayout(
private val config: SwipeControlsConfigurationProvider,
) : RelativeLayout(context), SwipeControlsOverlay {
constructor(context: Context) : this(context, SwipeControlsConfigurationProvider(context))
constructor(context: Context) : this(context, SwipeControlsConfigurationProvider())
// Drawable icons for brightness and volume
private val autoBrightnessIcon: Drawable = getDrawable("revanced_ic_sc_brightness_auto")

View File

@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
org.gradle.parallel = true
android.useAndroidX = true
kotlin.code.style = official
version = 5.19.1
version = 5.20.0-dev.7

View File

@ -108,6 +108,10 @@ public final class app/revanced/patches/all/misc/shortcut/sharetargets/RemoveSha
public static final fun getRemoveShareTargetsPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
}
public final class app/revanced/patches/all/misc/targetSdk/SetTargetSdkVersion34Kt {
public static final fun getSetTargetSdkVersion34 ()Lapp/revanced/patcher/patch/ResourcePatch;
}
public abstract interface class app/revanced/patches/all/misc/transformation/IMethodCall {
public abstract fun getDefinedClassName ()Ljava/lang/String;
public abstract fun getMethodName ()Ljava/lang/String;
@ -838,6 +842,10 @@ public final class app/revanced/patches/spotify/misc/extension/ExtensionPatchKt
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/spotify/misc/fix/SpoofPackageInfoPatchKt {
public static final fun getSpoofPackageInfoPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/spotify/misc/fix/SpoofSignaturePatchKt {
public static final fun getSpoofSignaturePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
@ -1521,7 +1529,11 @@ public final class app/revanced/patches/yuka/misc/unlockpremium/UnlockPremiumPat
}
public final class app/revanced/util/BytecodeUtilsKt {
public static final fun addInstructionsAtControlFlowLabel (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)V
public static final fun containsLiteralInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;D)Z
public static final fun containsLiteralInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;F)Z
public static final fun containsLiteralInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;J)Z
public static final fun findFreeRegister (Lcom/android/tools/smali/dexlib2/iface/Method;I[I)I
public static final fun findInstructionIndicesReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/Opcode;)Ljava/util/List;
public static final fun findInstructionIndicesReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
public static final fun findInstructionIndicesReversedOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/Opcode;)Ljava/util/List;
@ -1548,9 +1560,17 @@ public final class app/revanced/util/BytecodeUtilsKt {
public static final fun indexOfFirstInstructionReversedOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;)I
public static synthetic fun indexOfFirstInstructionReversedOrThrow$default (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lcom/android/tools/smali/dexlib2/Opcode;ILjava/lang/Object;)I
public static synthetic fun indexOfFirstInstructionReversedOrThrow$default (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)I
public static final fun indexOfFirstLiteralInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;D)I
public static final fun indexOfFirstLiteralInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;F)I
public static final fun indexOfFirstLiteralInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;J)I
public static final fun indexOfFirstLiteralInstructionOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;D)I
public static final fun indexOfFirstLiteralInstructionOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;F)I
public static final fun indexOfFirstLiteralInstructionOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;J)I
public static final fun indexOfFirstLiteralInstructionReversed (Lcom/android/tools/smali/dexlib2/iface/Method;D)I
public static final fun indexOfFirstLiteralInstructionReversed (Lcom/android/tools/smali/dexlib2/iface/Method;F)I
public static final fun indexOfFirstLiteralInstructionReversed (Lcom/android/tools/smali/dexlib2/iface/Method;J)I
public static final fun indexOfFirstLiteralInstructionReversedOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;D)I
public static final fun indexOfFirstLiteralInstructionReversedOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;F)I
public static final fun indexOfFirstLiteralInstructionReversedOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;J)I
public static final fun indexOfFirstResourceId (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I
public static final fun indexOfFirstResourceIdOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I

View File

@ -0,0 +1,48 @@
package app.revanced.patches.all.misc.targetSdk
import app.revanced.patcher.patch.resourcePatch
import app.revanced.util.getNode
import org.w3c.dom.Element
import java.util.logging.Logger
@Suppress("unused")
val setTargetSdkVersion34 = resourcePatch(
name = "Set target SDK version 34",
description = "Changes the target SDK to version 34 (Android 14). " +
"For devices running Android 15+, this will disable edge-to-edge display.",
use = false,
) {
execute {
val targetSdkOverride = 34 // Android 14.
document("AndroidManifest.xml").use { document ->
fun getLogger() = Logger.getLogger(this::class.java.name)
// Ideally, the override should only be applied if the existing target is higher.
// But since ApkTool does not add targetSdkVersion to the decompiled AndroidManifest,
// there is no way to check targetSdkVersion. Instead, check compileSdkVersion and print a warning.
try {
val manifestElement = document.getNode("manifest") as Element
val compileSdkVersion = Integer.parseInt(
manifestElement.getAttribute("android:compileSdkVersion")
)
if (compileSdkVersion <= targetSdkOverride) {
getLogger().warning(
"This app does not appear to use a target SDK above $targetSdkOverride: " +
"(compileSdkVersion: $compileSdkVersion)"
)
}
} catch (_: Exception) {
getLogger().warning("Could not check compileSdkVersion")
}
// Change targetSdkVersion to override value.
document.getElementsByTagName("manifest").item(0).let {
var element = it.ownerDocument.createElement("uses-sdk")
element.setAttribute("android:targetSdkVersion", targetSdkOverride.toString())
it.appendChild(element)
}
}
}
}

View File

@ -12,7 +12,8 @@ internal val initializeMonetizationDebugSettingsFingerprint = fingerprint {
"Z", // useDebugBilling
"Z", // showManageSubscriptions
"Z", // alwaysShowSuperAds
"Lcom/duolingo/debug/FamilyQuestOverride;",
// matches "Lcom/duolingo/debug/FamilyQuestOverride;" or "Lcom/duolingo/data/debug/monetization/FamilyQuestOverride;"
"Lcom/duolingo/",
)
opcodes(Opcode.IPUT_BOOLEAN)
}

View File

@ -14,7 +14,7 @@ import app.revanced.util.findFreeRegister
import app.revanced.util.findInstructionIndicesReversedOrThrow
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.insertFeatureFlagBooleanOverride
import app.revanced.util.insertLiteralOverride
import app.revanced.util.returnEarly
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@ -235,7 +235,7 @@ fun spoofVideoStreamsPatch(
// region Fix iOS livestream current time.
hlsCurrentTimeFingerprint.method.insertFeatureFlagBooleanOverride(
hlsCurrentTimeFingerprint.method.insertLiteralOverride(
HLS_CURRENT_TIME_FEATURE_FLAG,
"$EXTENSION_CLASS_DESCRIPTOR->fixHLSCurrentTime(Z)Z"
)
@ -245,21 +245,21 @@ fun spoofVideoStreamsPatch(
// region turn off stream config replacement feature flag.
if (fixMediaFetchHotConfigChanges()) {
mediaFetchHotConfigFingerprint.method.insertFeatureFlagBooleanOverride(
mediaFetchHotConfigFingerprint.method.insertLiteralOverride(
MEDIA_FETCH_HOT_CONFIG_FEATURE_FLAG,
"$EXTENSION_CLASS_DESCRIPTOR->useMediaFetchHotConfigReplacement(Z)Z"
)
}
if (fixMediaFetchHotConfigAlternativeChanges()) {
mediaFetchHotConfigAlternativeFingerprint.method.insertFeatureFlagBooleanOverride(
mediaFetchHotConfigAlternativeFingerprint.method.insertLiteralOverride(
MEDIA_FETCH_HOT_CONFIG_ALTERNATIVE_FEATURE_FLAG,
"$EXTENSION_CLASS_DESCRIPTOR->useMediaFetchHotConfigReplacement(Z)Z"
)
}
if (fixParsePlaybackResponseFeatureFlag()) {
playbackStartDescriptorFeatureFlagFingerprint.method.insertFeatureFlagBooleanOverride(
playbackStartDescriptorFeatureFlagFingerprint.method.insertLiteralOverride(
PLAYBACK_START_CHECK_ENDPOINT_USED_FEATURE_FLAG,
"$EXTENSION_CLASS_DESCRIPTOR->usePlaybackStartFeatureFlag(Z)Z"
)

View File

@ -1,82 +0,0 @@
package app.revanced.patches.spotify.layout.theme
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.fingerprint
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.spotify.misc.extension.IS_SPOTIFY_LEGACY_APP_TARGET
import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch
import app.revanced.util.*
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/spotify/layout/theme/CustomThemePatch;"
internal val customThemeByteCodePatch = bytecodePatch {
dependsOn(sharedExtensionPatch)
val backgroundColor by spotifyBackgroundColor
val backgroundColorSecondary by spotifyBackgroundColorSecondary
execute {
if (IS_SPOTIFY_LEGACY_APP_TARGET) {
// Bytecode changes are not needed for legacy app target.
// Player background color is changed with existing resource patch.
return@execute
}
fun MutableMethod.addColorChangeInstructions(literal: Long, colorString: String) {
val index = indexOfFirstLiteralInstructionOrThrow(literal)
val register = getInstruction<OneRegisterInstruction>(index).registerA
addInstructions(
index + 1,
"""
const-string v$register, "$colorString"
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getThemeColor(Ljava/lang/String;)J
move-result-wide v$register
"""
)
}
val encoreColorsClassName = with(encoreThemeFingerprint) {
// Find index of the first static get found after the string constant.
val encoreColorsFieldReferenceIndex = originalMethod.indexOfFirstInstructionOrThrow(
stringMatches!!.first().index,
Opcode.SGET_OBJECT
)
originalMethod.getInstruction(encoreColorsFieldReferenceIndex)
.getReference<FieldReference>()!!.definingClass
}
val encoreColorsConstructorFingerprint = fingerprint {
accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR)
custom { method, classDef ->
classDef.type == encoreColorsClassName &&
method.containsLiteralInstruction(PLAYLIST_BACKGROUND_COLOR_LITERAL)
}
}
encoreColorsConstructorFingerprint.method.apply {
// Playlist song list background color.
addColorChangeInstructions(PLAYLIST_BACKGROUND_COLOR_LITERAL, backgroundColor!!)
// Share menu background color.
addColorChangeInstructions(SHARE_MENU_BACKGROUND_COLOR_LITERAL, backgroundColorSecondary!!)
}
homeCategoryPillColorsFingerprint.method.apply {
// Home category pills background color.
addColorChangeInstructions(HOME_CATEGORY_PILL_COLOR_LITERAL, backgroundColorSecondary!!)
}
settingsHeaderColorFingerprint.method.apply {
// Settings header background color.
addColorChangeInstructions(SETTINGS_HEADER_COLOR_LITERAL, backgroundColorSecondary!!)
}
}
}

View File

@ -1,8 +1,133 @@
package app.revanced.patches.spotify.layout.theme
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.fingerprint
import app.revanced.patcher.patch.booleanOption
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.resourcePatch
import app.revanced.patcher.patch.stringOption
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.spotify.misc.extension.IS_SPOTIFY_LEGACY_APP_TARGET
import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch
import app.revanced.util.*
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import org.w3c.dom.Element
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/spotify/layout/theme/CustomThemePatch;"
internal val spotifyBackgroundColor = stringOption(
key = "backgroundColor",
default = "@android:color/black",
title = "Primary background color",
description = "The background color. Can be a hex color or a resource reference.",
required = true,
)
internal val overridePlayerGradientColor = booleanOption(
key = "overridePlayerGradientColor",
default = false,
title = "Override player gradient color",
description = "Apply primary background color to the player gradient color, which changes dynamically with the song.",
required = false
)
internal val spotifyBackgroundColorSecondary = stringOption(
key = "backgroundColorSecondary",
default = "#FF121212",
title = "Secondary background color",
description =
"The secondary background color. (e.g. playlist list in home, player artist, song credits). Can be a hex color or a resource reference.",
required = true,
)
internal val spotifyAccentColor = stringOption(
key = "accentColor",
default = "#FF1ED760",
title = "Accent color",
description = "The accent color ('Spotify green' by default). Can be a hex color or a resource reference.",
required = true,
)
internal val spotifyAccentColorPressed = stringOption(
key = "accentColorPressed",
default = "#FF169C46",
title = "Pressed dark theme accent color",
description =
"The color when accented buttons are pressed, by default slightly darker than accent. Can be a hex color or a resource reference.",
required = true,
)
private val customThemeBytecodePatch = bytecodePatch {
dependsOn(sharedExtensionPatch)
execute {
if (IS_SPOTIFY_LEGACY_APP_TARGET) {
// Bytecode changes are not needed for legacy app target.
// Player background color is changed with existing resource patch.
return@execute
}
fun MutableMethod.addColorChangeInstructions(literal: Long, colorString: String) {
val index = indexOfFirstLiteralInstructionOrThrow(literal)
val register = getInstruction<OneRegisterInstruction>(index).registerA
addInstructions(
index + 1,
"""
const-string v$register, "$colorString"
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getThemeColor(Ljava/lang/String;)J
move-result-wide v$register
"""
)
}
val encoreColorsClassName = with(encoreThemeFingerprint.originalMethod) {
// "Encore" colors are referenced right before the value of POSITIVE_INFINITY is returned.
// Begin the instruction find using the index of where POSITIVE_INFINITY is set into the register.
val positiveInfinityIndex = indexOfFirstLiteralInstructionOrThrow(
Float.POSITIVE_INFINITY
)
val encoreColorsFieldReferenceIndex = indexOfFirstInstructionReversedOrThrow(
positiveInfinityIndex,
Opcode.SGET_OBJECT
)
getInstruction(encoreColorsFieldReferenceIndex)
.getReference<FieldReference>()!!.definingClass
}
val encoreColorsConstructorFingerprint = fingerprint {
accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR)
custom { method, classDef ->
classDef.type == encoreColorsClassName &&
method.containsLiteralInstruction(PLAYLIST_BACKGROUND_COLOR_LITERAL)
}
}
val backgroundColor by spotifyBackgroundColor
val backgroundColorSecondary by spotifyBackgroundColorSecondary
encoreColorsConstructorFingerprint.method.apply {
addColorChangeInstructions(PLAYLIST_BACKGROUND_COLOR_LITERAL, backgroundColor!!)
addColorChangeInstructions(SHARE_MENU_BACKGROUND_COLOR_LITERAL, backgroundColorSecondary!!)
}
homeCategoryPillColorsFingerprint.method.addColorChangeInstructions(
HOME_CATEGORY_PILL_COLOR_LITERAL,
backgroundColorSecondary!!
)
settingsHeaderColorFingerprint.method.addColorChangeInstructions(
SETTINGS_HEADER_COLOR_LITERAL,
backgroundColorSecondary!!
)
}
}
@Suppress("unused")
val customThemePatch = resourcePatch(
name = "Custom theme",
@ -11,9 +136,10 @@ val customThemePatch = resourcePatch(
) {
compatibleWith("com.spotify.music")
dependsOn(customThemeByteCodePatch)
dependsOn(customThemeBytecodePatch)
val backgroundColor by spotifyBackgroundColor()
val overridePlayerGradientColor by overridePlayerGradientColor()
val backgroundColorSecondary by spotifyBackgroundColorSecondary()
val accentColor by spotifyAccentColor()
val accentColorPressed by spotifyAccentColorPressed()
@ -25,31 +151,39 @@ val customThemePatch = resourcePatch(
val childNodes = resourcesNode.childNodes
for (i in 0 until childNodes.length) {
val node = childNodes.item(i) as? Element ?: continue
val name = node.getAttribute("name")
node.textContent = when (node.getAttribute("name")) {
// Gradient next to user photo and "All" in home page
// Skip overriding song/player gradient start color if the option is disabled.
// Gradient end color should be themed regardless to allow the gradient to connect with
// our primary background color.
if (name == "bg_gradient_start_color" && !overridePlayerGradientColor!!) {
continue
}
node.textContent = when (name) {
// Gradient next to user photo and "All" in home page.
"dark_base_background_base",
// Main background
// Main background.
"gray_7",
// Left sidebar background in tablet mode
// Left sidebar background in tablet mode.
"gray_10",
// Add account, Settings and privacy, View Profile left sidebar background
// "Add account", "Settings and privacy", "View Profile" left sidebar background.
"dark_base_background_elevated_base",
// Song/player background
// Song/player gradient start/end color.
"bg_gradient_start_color", "bg_gradient_end_color",
// Login screen
"sthlm_blk", "sthlm_blk_grad_start", "stockholm_black",
// Misc
// Login screen background and gradient start.
"sthlm_blk", "sthlm_blk_grad_start",
// Misc.
"image_placeholder_color",
-> backgroundColor
// Track credits, merch in song player
// Track credits, merch background in song player.
"track_credits_card_bg", "benefit_list_default_color", "merch_card_background",
// Playlist list background in home page
// Playlist list background in home page.
"opacity_white_10",
// About artist background in song player
// "About the artist" background in song player.
"gray_15",
// What's New pills background
// "What's New" pills background.
"dark_base_background_tinted_highlight"
-> backgroundColorSecondary
@ -59,5 +193,13 @@ val customThemePatch = resourcePatch(
}
}
}
// Login screen gradient.
document("res/drawable/start_screen_gradient.xml").use { document ->
val gradientNode = document.getElementsByTagName("gradient").item(0) as Element
gradientNode.setAttribute("android:startColor", backgroundColor)
gradientNode.setAttribute("android:endColor", backgroundColor)
}
}
}

View File

@ -5,13 +5,13 @@ import app.revanced.util.containsLiteralInstruction
import com.android.tools.smali.dexlib2.AccessFlags
internal val encoreThemeFingerprint = fingerprint {
strings("Encore theme was not provided.") // Partial string match.
strings("No EncoreLayoutTheme provided")
}
internal const val SETTINGS_HEADER_COLOR_LITERAL = 0xFF282828
internal const val HOME_CATEGORY_PILL_COLOR_LITERAL = 0xFF333333
internal const val PLAYLIST_BACKGROUND_COLOR_LITERAL = 0xFF121212
internal const val SHARE_MENU_BACKGROUND_COLOR_LITERAL = 0xFF1F1F1F
internal const val HOME_CATEGORY_PILL_COLOR_LITERAL = 0xFF333333
internal const val SETTINGS_HEADER_COLOR_LITERAL = 0xFF282828
internal val homeCategoryPillColorsFingerprint = fingerprint{
accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR)

View File

@ -1,36 +0,0 @@
package app.revanced.patches.spotify.layout.theme
import app.revanced.patcher.patch.stringOption
internal val spotifyBackgroundColor = stringOption(
key = "backgroundColor",
default = "@android:color/black",
title = "Primary background color",
description = "The background color. Can be a hex color or a resource reference.",
required = true,
)
internal val spotifyBackgroundColorSecondary = stringOption(
key = "backgroundColorSecondary",
default = "#FF121212",
title = "Secondary background color",
description = "The secondary background color. (e.g. playlist list, player arist, credits). Can be a hex color or a resource reference.",
required = true,
)
internal val spotifyAccentColor = stringOption(
key = "accentColor",
default = "#FF1ED760",
title = "Accent color",
description = "The accent color ('Spotify green' by default). Can be a hex color or a resource reference.",
required = true,
)
internal val spotifyAccentColorPressed = stringOption(
key = "accentColorPressed",
default = "#FF169C46",
title = "Pressed dark theme accent color",
description =
"The color when accented buttons are pressed, by default slightly darker than accent. Can be a hex color or a resource reference.",
required = true,
)

View File

@ -49,7 +49,7 @@ val unlockPremiumPatch = bytecodePatch(
}
// Override the attributes map in the getter method.
with(productStateProtoFingerprint.method) {
productStateProtoFingerprint.method.apply {
val getAttributesMapIndex = indexOfFirstInstructionOrThrow(Opcode.IGET_OBJECT)
val attributesMapRegister = getInstruction<TwoRegisterInstruction>(getAttributesMapIndex).registerA
@ -62,10 +62,11 @@ val unlockPremiumPatch = bytecodePatch(
// Add the query parameter trackRows to show popular tracks in the artist page.
with(buildQueryParametersFingerprint) {
buildQueryParametersFingerprint.apply {
val addQueryParameterConditionIndex = method.indexOfFirstInstructionReversedOrThrow(
stringMatches!!.first().index, Opcode.IF_EQZ
)
method.replaceInstruction(addQueryParameterConditionIndex, "nop")
}
@ -114,17 +115,19 @@ val unlockPremiumPatch = bytecodePatch(
// Disable the "Spotify Premium" upsell experiment in context menus.
with(contextMenuExperimentsFingerprint) {
contextMenuExperimentsFingerprint.apply {
val moveIsEnabledIndex = method.indexOfFirstInstructionOrThrow(
stringMatches!!.first().index, Opcode.MOVE_RESULT
)
val isUpsellEnabledRegister = method.getInstruction<OneRegisterInstruction>(moveIsEnabledIndex).registerA
method.replaceInstruction(moveIsEnabledIndex, "const/4 v$isUpsellEnabledRegister, 0")
}
// Make featureTypeCase_ accessible so we can check the home section type in the extension.
homeSectionFingerprint.classDef.fields.first { it.name == "featureTypeCase_" }.apply {
// Add public flag and remove private.
accessFlags = accessFlags.or(AccessFlags.PUBLIC.value).and(AccessFlags.PRIVATE.value.inv())
}
@ -143,7 +146,7 @@ val unlockPremiumPatch = bytecodePatch(
// Protobuffer list has an 'isMutable' boolean parameter that sets the mutability.
// Forcing that always on breaks unrelated code in strange ways.
// Instead, remove the method call that checks if the list is unmodifiable.
with(protobufListRemoveFingerprint.method) {
protobufListRemoveFingerprint.method.apply {
val invokeThrowUnmodifiableIndex = indexOfFirstInstructionOrThrow {
val reference = getReference<MethodReference>()
opcode == Opcode.INVOKE_VIRTUAL &&
@ -155,7 +158,7 @@ val unlockPremiumPatch = bytecodePatch(
}
// Remove ads sections from home.
with(homeStructureFingerprint.method) {
homeStructureFingerprint.method.apply {
val getSectionsIndex = indexOfFirstInstructionOrThrow(Opcode.IGET_OBJECT)
val sectionsRegister = getInstruction<TwoRegisterInstruction>(getSectionsIndex).registerA

View File

@ -2,4 +2,16 @@ package app.revanced.patches.spotify.misc.fix
import app.revanced.patcher.fingerprint
internal val getAppSignatureFingerprint = fingerprint { strings("Failed to get the application signatures") }
internal val getPackageInfoFingerprint = fingerprint {
strings(
"Failed to get the application signatures",
"Failed to get installer package"
)
}
internal val getPackageInfoLegacyFingerprint = fingerprint {
strings(
"Failed to get the application signatures"
)
}

View File

@ -0,0 +1,72 @@
package app.revanced.patches.spotify.misc.fix
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.spotify.misc.extension.IS_SPOTIFY_LEGACY_APP_TARGET
import app.revanced.util.addInstructionsAtControlFlowLabel
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Suppress("unused")
val spoofPackageInfoPatch = bytecodePatch(
name = "Spoof package info",
description = "Spoofs the package info of the app to fix various functions of the app.",
) {
compatibleWith("com.spotify.music")
execute {
val getPackageInfoFingerprint = if (IS_SPOTIFY_LEGACY_APP_TARGET) {
getPackageInfoLegacyFingerprint
} else {
getPackageInfoFingerprint
}
getPackageInfoFingerprint.method.apply {
val stringMatches = getPackageInfoFingerprint.stringMatches!!
// region Spoof signature.
val failedToGetSignaturesStringIndex = stringMatches.first().index
val concatSignaturesIndex = indexOfFirstInstructionReversedOrThrow(
failedToGetSignaturesStringIndex,
Opcode.MOVE_RESULT_OBJECT,
)
val signatureRegister = getInstruction<OneRegisterInstruction>(concatSignaturesIndex).registerA
val expectedSignature = "d6a6dced4a85f24204bf9505ccc1fce114cadb32"
replaceInstruction(concatSignaturesIndex, "const-string v$signatureRegister, \"$expectedSignature\"")
// endregion
// region Spoof installer name.
if (IS_SPOTIFY_LEGACY_APP_TARGET) {
// Installer name is not used in the legacy app target.
return@execute
}
val expectedInstallerName = "com.android.vending"
val returnInstallerNameIndex = indexOfFirstInstructionOrThrow(
stringMatches.last().index,
Opcode.RETURN_OBJECT
)
val installerNameRegister = getInstruction<OneRegisterInstruction>(
returnInstallerNameIndex
).registerA
addInstructionsAtControlFlowLabel(
returnInstallerNameIndex,
"const-string v$installerNameRegister, \"$expectedInstallerName\""
)
// endregion
}
}
}

View File

@ -1,33 +1,13 @@
package app.revanced.patches.spotify.misc.fix
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Deprecated("Superseded by spoofPackageInfoPatch", ReplaceWith("spoofPackageInfoPatch"))
@Suppress("unused")
val spoofSignaturePatch = bytecodePatch(
name = "Spoof signature",
description = "Spoofs the signature of the app to fix various functions of the app.",
description = "Spoofs the signature of the app fix various functions of the app.",
) {
compatibleWith("com.spotify.music")
execute {
getAppSignatureFingerprint.method.apply {
val failedToGetSignaturesStringMatch = getAppSignatureFingerprint.stringMatches!!.first()
val concatSignaturesIndex = indexOfFirstInstructionReversedOrThrow(
failedToGetSignaturesStringMatch.index,
Opcode.MOVE_RESULT_OBJECT,
)
val register = getInstruction<OneRegisterInstruction>(concatSignaturesIndex).registerA
val expectedSignature = "d6a6dced4a85f24204bf9505ccc1fce114cadb32"
replaceInstruction(concatSignaturesIndex, "const-string v$register, \"$expectedSignature\"")
}
}
dependsOn(spoofPackageInfoPatch)
}

View File

@ -47,6 +47,7 @@ private val swipeControlsResourcePatch = resourcePatch {
TextPreference("revanced_swipe_overlay_background_opacity", inputType = InputType.NUMBER),
TextPreference("revanced_swipe_overlay_timeout", inputType = InputType.NUMBER),
TextPreference("revanced_swipe_threshold", inputType = InputType.NUMBER),
TextPreference("revanced_swipe_volume_sensitivity", inputType = InputType.NUMBER),
)
copyResources(
@ -117,7 +118,7 @@ val swipeControlsPatch = bytecodePatch(
// region patch to enable/disable swipe to change video.
if (is_19_43_or_greater) {
swipeChangeVideoFingerprint.method.insertFeatureFlagBooleanOverride(
swipeChangeVideoFingerprint.method.insertLiteralOverride(
SWIPE_CHANGE_VIDEO_FEATURE_FLAG,
"$EXTENSION_CLASS_DESCRIPTOR->allowSwipeChangeVideo(Z)Z"
)

View File

@ -18,7 +18,7 @@ import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.insertFeatureFlagBooleanOverride
import app.revanced.util.insertLiteralOverride
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@ -119,17 +119,17 @@ val navigationButtonsPatch = bytecodePatch(
// Force on/off translucent effect on status bar and navigation buttons.
if (is_19_25_or_greater) {
translucentNavigationStatusBarFeatureFlagFingerprint.method.insertFeatureFlagBooleanOverride(
translucentNavigationStatusBarFeatureFlagFingerprint.method.insertLiteralOverride(
TRANSLUCENT_NAVIGATION_STATUS_BAR_FEATURE_FLAG,
"$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationStatusBar(Z)Z",
)
translucentNavigationButtonsFeatureFlagFingerprint.method.insertFeatureFlagBooleanOverride(
translucentNavigationButtonsFeatureFlagFingerprint.method.insertLiteralOverride(
TRANSLUCENT_NAVIGATION_BUTTONS_FEATURE_FLAG,
"$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationButtons(Z)Z",
)
translucentNavigationButtonsSystemFeatureFlagFingerprint.method.insertFeatureFlagBooleanOverride(
translucentNavigationButtonsSystemFeatureFlagFingerprint.method.insertLiteralOverride(
TRANSLUCENT_NAVIGATION_BUTTONS_SYSTEM_FEATURE_FLAG,
"$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationButtons(Z)Z",
)

View File

@ -278,7 +278,7 @@ val miniplayerPatch = bytecodePatch(
fun Fingerprint.insertMiniplayerFeatureFlagBooleanOverride(
literal: Long,
extensionMethod: String,
) = method.insertFeatureFlagBooleanOverride(
) = method.insertLiteralOverride(
literal,
"$EXTENSION_CLASS_DESCRIPTOR->$extensionMethod(Z)Z"
)

View File

@ -5,7 +5,7 @@ import app.revanced.patches.youtube.layout.shortsplayer.openShortsInRegularPlaye
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.playservice.is_19_46_or_greater
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.util.insertFeatureFlagBooleanOverride
import app.revanced.util.insertLiteralOverride
internal const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/OpenVideosFullscreenHookPatch;"
@ -24,7 +24,7 @@ internal val openVideosFullscreenHookPatch = bytecodePatch {
return@execute
}
openVideosFullscreenPortraitFingerprint.method.insertFeatureFlagBooleanOverride(
openVideosFullscreenPortraitFingerprint.method.insertLiteralOverride(
OPEN_VIDEOS_FULLSCREEN_PORTRAIT_FEATURE_FLAG,
"$EXTENSION_CLASS_DESCRIPTOR->openVideoFullscreenPortrait(Z)Z"
)

View File

@ -28,9 +28,8 @@ import app.revanced.util.findElementByAttributeValueOrThrow
import app.revanced.util.findInstructionIndicesReversedOrThrow
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
import app.revanced.util.inputStreamFromBundledResource
import app.revanced.util.insertFeatureFlagBooleanOverride
import app.revanced.util.insertLiteralOverride
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
@ -229,16 +228,9 @@ val seekbarColorPatch = bytecodePatch(
execute {
fun MutableMethod.addColorChangeInstructions(resourceId: Long) {
val index = indexOfFirstLiteralInstructionOrThrow(resourceId)
val insertIndex = indexOfFirstInstructionOrThrow(index, Opcode.MOVE_RESULT)
val register = getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstructions(
insertIndex + 1,
"""
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getVideoPlayerSeekbarColor(I)I
move-result v$register
"""
insertLiteralOverride(
resourceId,
"$EXTENSION_CLASS_DESCRIPTOR->getVideoPlayerSeekbarColor(I)I"
)
}
@ -354,7 +346,7 @@ val seekbarColorPatch = bytecodePatch(
launchScreenLayoutTypeFingerprint,
mainActivityOnCreateFingerprint
).forEach { fingerprint ->
fingerprint.method.insertFeatureFlagBooleanOverride(
fingerprint.method.insertLiteralOverride(
launchScreenLayoutTypeLotteFeatureFlag,
"$EXTENSION_CLASS_DESCRIPTOR->useLotteLaunchSplashScreen(Z)Z"
)

View File

@ -21,7 +21,7 @@ import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.util.forEachChildElement
import app.revanced.util.insertFeatureFlagBooleanOverride
import app.revanced.util.insertLiteralOverride
import org.w3c.dom.Element
private const val EXTENSION_CLASS_DESCRIPTOR =
@ -233,7 +233,7 @@ val themePatch = bytecodePatch(
SwitchPreference("revanced_gradient_loading_screen"),
)
useGradientLoadingScreenFingerprint.method.insertFeatureFlagBooleanOverride(
useGradientLoadingScreenFingerprint.method.insertLiteralOverride(
GRADIENT_LOADING_SCREEN_AB_CONSTANT,
"$EXTENSION_CLASS_DESCRIPTOR->gradientLoadingScreenEnabled(Z)Z"
)

View File

@ -12,6 +12,8 @@ import app.revanced.patches.shared.misc.mapping.resourceMappings
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.patches.youtube.video.information.videoInformationPatch
@ -44,6 +46,7 @@ val backgroundPlaybackPatch = bytecodePatch(
playerTypeHookPatch,
videoInformationPatch,
settingsPatch,
versionCheckPatch
)
compatibleWith(
@ -100,5 +103,13 @@ val backgroundPlaybackPatch = bytecodePatch(
// Force allowing background play for videos labeled for kids.
kidsBackgroundPlaybackPolicyControllerFingerprint.method.returnEarly()
// Fix PiP buttons not working after locking/unlocking device screen.
if (is_19_34_or_greater) {
pipInputConsumerFeatureFlagFingerprint.method.insertLiteralOverride(
PIP_INPUT_CONSUMER_FEATURE_FLAG,
false
)
}
}
}

View File

@ -84,3 +84,10 @@ internal val shortsBackgroundPlaybackFeatureFlagFingerprint = fingerprint {
parameters()
literal { 45415425 }
}
internal const val PIP_INPUT_CONSUMER_FEATURE_FLAG = 45638483L
// Fix 'E/InputDispatcher: Window handle pip_input_consumer has no registered input channel'
internal val pipInputConsumerFeatureFlagFingerprint = fingerprint {
literal { PIP_INPUT_CONSUMER_FEATURE_FLAG}
}

View File

@ -269,7 +269,7 @@ val settingsPatch = bytecodePatch(
}
// Add setting to force cairo settings fragment on/off.
cairoFragmentConfigFingerprint.method.insertFeatureFlagBooleanOverride(
cairoFragmentConfigFingerprint.method.insertLiteralOverride(
CAIRO_CONFIG_LITERAL_VALUE,
"$activityHookClassDescriptor->useCairoSettingsFragment(Z)Z"
)

View File

@ -121,11 +121,11 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
// Override the min/max speeds that can be used.
speedLimiterFingerprint.method.apply {
val limitMinIndex = indexOfFirstLiteralInstructionOrThrow(0.25f.toRawBits().toLong())
var limitMaxIndex = indexOfFirstLiteralInstruction(2.0f.toRawBits().toLong())
val limitMinIndex = indexOfFirstLiteralInstructionOrThrow(0.25f)
var limitMaxIndex = indexOfFirstLiteralInstruction(2.0f)
// Newer targets have 4x max speed.
if (limitMaxIndex < 0) {
limitMaxIndex = indexOfFirstLiteralInstructionOrThrow(4.0f.toRawBits().toLong())
limitMaxIndex = indexOfFirstLiteralInstructionOrThrow(4.0f)
}
val limitMinRegister = getInstruction<OneRegisterInstruction>(limitMinIndex).registerA

View File

@ -14,6 +14,9 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.misc.mapping.get
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
import app.revanced.patches.shared.misc.mapping.resourceMappings
import app.revanced.util.InstructionUtils.Companion.branchOpcodes
import app.revanced.util.InstructionUtils.Companion.returnOpcodes
import app.revanced.util.InstructionUtils.Companion.writeOpcodes
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.Opcode.*
import com.android.tools.smali.dexlib2.iface.Method
@ -43,7 +46,7 @@ import java.util.EnumSet
* @throws IllegalArgumentException If a branch or conditional statement is encountered
* before a suitable register is found.
*/
internal fun Method.findFreeRegister(startIndex: Int, vararg registersToExclude: Int): Int {
fun Method.findFreeRegister(startIndex: Int, vararg registersToExclude: Int): Int {
if (implementation == null) {
throw IllegalArgumentException("Method has no implementation: $this")
}
@ -51,82 +54,6 @@ internal fun Method.findFreeRegister(startIndex: Int, vararg registersToExclude:
throw IllegalArgumentException("startIndex out of bounds: $startIndex")
}
// All registers used by an instruction.
fun Instruction.getRegistersUsed() = when (this) {
is FiveRegisterInstruction -> {
when (registerCount) {
1 -> listOf(registerC)
2 -> listOf(registerC, registerD)
3 -> listOf(registerC, registerD, registerE)
4 -> listOf(registerC, registerD, registerE, registerF)
else -> listOf(registerC, registerD, registerE, registerF, registerG)
}
}
is ThreeRegisterInstruction -> listOf(registerA, registerB, registerC)
is TwoRegisterInstruction -> listOf(registerA, registerB)
is OneRegisterInstruction -> listOf(registerA)
is RegisterRangeInstruction -> (startRegister until (startRegister + registerCount)).toList()
else -> emptyList()
}
// Register that is written to by an instruction.
fun Instruction.getWriteRegister() : Int {
// Two and three register instructions extend OneRegisterInstruction.
if (this is OneRegisterInstruction) return registerA
throw IllegalStateException("Not a write instruction: $this")
}
val writeOpcodes = EnumSet.of(
ARRAY_LENGTH,
INSTANCE_OF,
NEW_INSTANCE, NEW_ARRAY,
MOVE, MOVE_FROM16, MOVE_16, MOVE_WIDE, MOVE_WIDE_FROM16, MOVE_WIDE_16, MOVE_OBJECT,
MOVE_OBJECT_FROM16, MOVE_OBJECT_16, MOVE_RESULT, MOVE_RESULT_WIDE, MOVE_RESULT_OBJECT, MOVE_EXCEPTION,
CONST, CONST_4, CONST_16, CONST_HIGH16, CONST_WIDE_16, CONST_WIDE_32,
CONST_WIDE, CONST_WIDE_HIGH16, CONST_STRING, CONST_STRING_JUMBO,
IGET, IGET_WIDE, IGET_OBJECT, IGET_BOOLEAN, IGET_BYTE, IGET_CHAR, IGET_SHORT,
IGET_VOLATILE, IGET_WIDE_VOLATILE, IGET_OBJECT_VOLATILE,
SGET, SGET_WIDE, SGET_OBJECT, SGET_BOOLEAN, SGET_BYTE, SGET_CHAR, SGET_SHORT,
SGET_VOLATILE, SGET_WIDE_VOLATILE, SGET_OBJECT_VOLATILE,
AGET, AGET_WIDE, AGET_OBJECT, AGET_BOOLEAN, AGET_BYTE, AGET_CHAR, AGET_SHORT,
// Arithmetic and logical operations.
ADD_DOUBLE_2ADDR, ADD_DOUBLE, ADD_FLOAT_2ADDR, ADD_FLOAT, ADD_INT_2ADDR,
ADD_INT_LIT8, ADD_INT, ADD_LONG_2ADDR, ADD_LONG, ADD_INT_LIT16,
AND_INT_2ADDR, AND_INT_LIT8, AND_INT_LIT16, AND_INT, AND_LONG_2ADDR, AND_LONG,
DIV_DOUBLE_2ADDR, DIV_DOUBLE, DIV_FLOAT_2ADDR, DIV_FLOAT, DIV_INT_2ADDR,
DIV_INT_LIT16, DIV_INT_LIT8, DIV_INT, DIV_LONG_2ADDR, DIV_LONG,
DOUBLE_TO_FLOAT, DOUBLE_TO_INT, DOUBLE_TO_LONG,
FLOAT_TO_DOUBLE, FLOAT_TO_INT, FLOAT_TO_LONG,
INT_TO_BYTE, INT_TO_CHAR, INT_TO_DOUBLE, INT_TO_FLOAT, INT_TO_LONG, INT_TO_SHORT,
LONG_TO_DOUBLE, LONG_TO_FLOAT, LONG_TO_INT,
MUL_DOUBLE_2ADDR, MUL_DOUBLE, MUL_FLOAT_2ADDR, MUL_FLOAT, MUL_INT_2ADDR,
MUL_INT_LIT16, MUL_INT_LIT8, MUL_INT, MUL_LONG_2ADDR, MUL_LONG,
NEG_DOUBLE, NEG_FLOAT, NEG_INT, NEG_LONG,
NOT_INT, NOT_LONG,
OR_INT_2ADDR, OR_INT_LIT16, OR_INT_LIT8, OR_INT, OR_LONG_2ADDR, OR_LONG,
REM_DOUBLE_2ADDR, REM_DOUBLE, REM_FLOAT_2ADDR, REM_FLOAT, REM_INT_2ADDR,
REM_INT_LIT16, REM_INT_LIT8, REM_INT, REM_LONG_2ADDR, REM_LONG,
RSUB_INT_LIT8, RSUB_INT,
SHL_INT_2ADDR, SHL_INT_LIT8, SHL_INT, SHL_LONG_2ADDR, SHL_LONG,
SHR_INT_2ADDR, SHR_INT_LIT8, SHR_INT, SHR_LONG_2ADDR, SHR_LONG,
SUB_DOUBLE_2ADDR, SUB_DOUBLE, SUB_FLOAT_2ADDR, SUB_FLOAT, SUB_INT_2ADDR,
SUB_INT, SUB_LONG_2ADDR, SUB_LONG,
USHR_INT_2ADDR, USHR_INT_LIT8, USHR_INT, USHR_LONG_2ADDR, USHR_LONG,
XOR_INT_2ADDR, XOR_INT_LIT16, XOR_INT_LIT8, XOR_INT, XOR_LONG_2ADDR, XOR_LONG,
)
val branchOpcodes = EnumSet.of(
GOTO, GOTO_16, GOTO_32,
IF_EQ, IF_NE, IF_LT, IF_GE, IF_GT, IF_LE,
IF_EQZ, IF_NEZ, IF_LTZ, IF_GEZ, IF_GTZ, IF_LEZ,
PACKED_SWITCH_PAYLOAD, SPARSE_SWITCH_PAYLOAD
)
val returnOpcodes = EnumSet.of(
RETURN_VOID, RETURN, RETURN_WIDE, RETURN_OBJECT, RETURN_VOID_NO_BARRIER,
THROW
)
// Highest 4-bit register available, exclusive. Ideally return a free register less than this.
val maxRegister4Bits = 16
var bestFreeRegisterFound: Int? = null
@ -134,10 +61,9 @@ internal fun Method.findFreeRegister(startIndex: Int, vararg registersToExclude:
for (i in startIndex until instructions.count()) {
val instruction = getInstruction(i)
val instructionRegisters = instruction.getRegistersUsed()
val instructionRegisters = instruction.registersUsed
if (instruction.opcode in returnOpcodes) {
// Method returns.
if (instruction.isReturnInstruction) {
usedRegisters.addAll(instructionRegisters)
// Use lowest register that hasn't been encountered.
@ -157,7 +83,7 @@ internal fun Method.findFreeRegister(startIndex: Int, vararg registersToExclude:
"$startIndex excluding: $registersToExclude")
}
if (instruction.opcode in branchOpcodes) {
if (instruction.isBranchInstruction) {
if (bestFreeRegisterFound != null) {
return bestFreeRegisterFound
}
@ -165,9 +91,9 @@ internal fun Method.findFreeRegister(startIndex: Int, vararg registersToExclude:
throw IllegalArgumentException("Encountered a branch statement before a free register could be found")
}
if (instruction.opcode in writeOpcodes) {
val writeRegister = instruction.getWriteRegister()
val writeRegister = instruction.writeRegister
if (writeRegister != null) {
if (writeRegister !in usedRegisters) {
// Verify the register is only used for write and not also as a parameter.
// If the instruction uses the write register once then it's not also a read register.
@ -194,6 +120,53 @@ internal fun Method.findFreeRegister(startIndex: Int, vararg registersToExclude:
throw IllegalArgumentException("Start index is outside the range of normal control flow: $startIndex")
}
/**
* @return The registers used by this instruction.
*/
internal val Instruction.registersUsed: List<Int>
get() = when (this) {
is FiveRegisterInstruction -> {
when (registerCount) {
1 -> listOf(registerC)
2 -> listOf(registerC, registerD)
3 -> listOf(registerC, registerD, registerE)
4 -> listOf(registerC, registerD, registerE, registerF)
else -> listOf(registerC, registerD, registerE, registerF, registerG)
}
}
is ThreeRegisterInstruction -> listOf(registerA, registerB, registerC)
is TwoRegisterInstruction -> listOf(registerA, registerB)
is OneRegisterInstruction -> listOf(registerA)
is RegisterRangeInstruction -> (startRegister until (startRegister + registerCount)).toList()
else -> emptyList()
}
/**
* @return The register that is written to by this instruction,
* or NULL if this is not a write opcode.
*/
internal val Instruction.writeRegister: Int?
get() {
if (this.opcode !in writeOpcodes) {
return null
}
if (this !is OneRegisterInstruction) {
throw IllegalStateException("Not a write instruction: $this")
}
return registerA
}
/**
* @return If this instruction is an unconditional or conditional branch opcode.
*/
internal val Instruction.isBranchInstruction: Boolean
get() = this.opcode in branchOpcodes
/**
* @return If this instruction returns or throws.
*/
internal val Instruction.isReturnInstruction: Boolean
get() = this.opcode in returnOpcodes
/**
* Find the [MutableMethod] from a given [Method] in a [MutableClass].
@ -247,7 +220,7 @@ fun MutableMethod.injectHideViewCall(
* (patch code)
* (original code)
*/
internal fun MutableMethod.addInstructionsAtControlFlowLabel(
fun MutableMethod.addInstructionsAtControlFlowLabel(
insertIndex: Int,
instructions: String,
) {
@ -298,7 +271,7 @@ fun Method.indexOfFirstResourceIdOrThrow(resourceName: String): Int {
}
/**
* Find the index of the first literal instruction with the given value.
* Find the index of the first literal instruction with the given long value.
*
* @return the first literal instruction with the value, or -1 if not found.
* @see indexOfFirstLiteralInstructionOrThrow
@ -310,14 +283,56 @@ fun Method.indexOfFirstLiteralInstruction(literal: Long) = implementation?.let {
} ?: -1
/**
* Find the index of the first literal instruction with the given value,
* Find the index of the first literal instruction with the given long value,
* or throw an exception if not found.
*
* @return the first literal instruction with the value, or throws [PatchException] if not found.
*/
fun Method.indexOfFirstLiteralInstructionOrThrow(literal: Long): Int {
val index = indexOfFirstLiteralInstruction(literal)
if (index < 0) throw PatchException("Could not find literal value: $literal")
if (index < 0) throw PatchException("Could not find long literal: $literal")
return index
}
/**
* Find the index of the first literal instruction with the given float value.
*
* @return the first literal instruction with the value, or -1 if not found.
* @see indexOfFirstLiteralInstructionOrThrow
*/
fun Method.indexOfFirstLiteralInstruction(literal: Float) =
indexOfFirstLiteralInstruction(literal.toRawBits().toLong())
/**
* Find the index of the first literal instruction with the given float value,
* or throw an exception if not found.
*
* @return the first literal instruction with the value, or throws [PatchException] if not found.
*/
fun Method.indexOfFirstLiteralInstructionOrThrow(literal: Float): Int {
val index = indexOfFirstLiteralInstruction(literal)
if (index < 0) throw PatchException("Could not find float literal: $literal")
return index
}
/**
* Find the index of the first literal instruction with the given double value.
*
* @return the first literal instruction with the value, or -1 if not found.
* @see indexOfFirstLiteralInstructionOrThrow
*/
fun Method.indexOfFirstLiteralInstruction(literal: Double) =
indexOfFirstLiteralInstruction(literal.toRawBits().toLong())
/**
* Find the index of the first literal instruction with the given double value,
* or throw an exception if not found.
*
* @return the first literal instruction with the value, or throws [PatchException] if not found.
*/
fun Method.indexOfFirstLiteralInstructionOrThrow(literal: Double): Int {
val index = indexOfFirstLiteralInstruction(literal)
if (index < 0) throw PatchException("Could not find double literal: $literal")
return index
}
@ -334,24 +349,80 @@ fun Method.indexOfFirstLiteralInstructionReversed(literal: Long) = implementatio
} ?: -1
/**
* Find the index of the last wide literal instruction with the given value,
* Find the index of the last wide literal instruction with the given long value,
* or throw an exception if not found.
*
* @return the last literal instruction with the value, or throws [PatchException] if not found.
*/
fun Method.indexOfFirstLiteralInstructionReversedOrThrow(literal: Long): Int {
val index = indexOfFirstLiteralInstructionReversed(literal)
if (index < 0) throw PatchException("Could not find literal value: $literal")
if (index < 0) throw PatchException("Could not find long literal: $literal")
return index
}
/**
* Check if the method contains a literal with the given value.
* Find the index of the last literal instruction with the given float value.
*
* @return the last literal instruction with the value, or -1 if not found.
* @see indexOfFirstLiteralInstructionOrThrow
*/
fun Method.indexOfFirstLiteralInstructionReversed(literal: Float) =
indexOfFirstLiteralInstructionReversed(literal.toRawBits().toLong())
/**
* Find the index of the last wide literal instruction with the given float value,
* or throw an exception if not found.
*
* @return the last literal instruction with the value, or throws [PatchException] if not found.
*/
fun Method.indexOfFirstLiteralInstructionReversedOrThrow(literal: Float): Int {
val index = indexOfFirstLiteralInstructionReversed(literal)
if (index < 0) throw PatchException("Could not find float literal: $literal")
return index
}
/**
* Find the index of the last literal instruction with the given double value.
*
* @return the last literal instruction with the value, or -1 if not found.
* @see indexOfFirstLiteralInstructionOrThrow
*/
fun Method.indexOfFirstLiteralInstructionReversed(literal: Double) =
indexOfFirstLiteralInstructionReversed(literal.toRawBits().toLong())
/**
* Find the index of the last wide literal instruction with the given double value,
* or throw an exception if not found.
*
* @return the last literal instruction with the value, or throws [PatchException] if not found.
*/
fun Method.indexOfFirstLiteralInstructionReversedOrThrow(literal: Double): Int {
val index = indexOfFirstLiteralInstructionReversed(literal)
if (index < 0) throw PatchException("Could not find double literal: $literal")
return index
}
/**
* Check if the method contains a literal with the given long value.
*
* @return if the method contains a literal with the given value.
*/
fun Method.containsLiteralInstruction(literal: Long) = indexOfFirstLiteralInstruction(literal) >= 0
/**
* Check if the method contains a literal with the given float value.
*
* @return if the method contains a literal with the given value.
*/
fun Method.containsLiteralInstruction(literal: Float) = indexOfFirstLiteralInstruction(literal) >= 0
/**
* Check if the method contains a literal with the given double value.
*
* @return if the method contains a literal with the given value.
*/
fun Method.containsLiteralInstruction(literal: Double) = indexOfFirstLiteralInstruction(literal) >= 0
/**
* Traverse the class hierarchy starting from the given root class.
*
@ -565,7 +636,12 @@ fun Method.findInstructionIndicesReversedOrThrow(opcode: Opcode): List<Int> {
return instructions
}
internal fun MutableMethod.insertFeatureFlagBooleanOverride(literal: Long, extensionsMethod: String) {
/**
* Overrides the first move result with an extension call.
* Suitable for calls to extension code to override boolean and integer values.
*/
internal fun MutableMethod.insertLiteralOverride(literal: Long, extensionMethodDescriptor: String) {
// TODO: make this work with objects and wide values.
val literalIndex = indexOfFirstLiteralInstructionOrThrow(literal)
val index = indexOfFirstInstructionOrThrow(literalIndex, MOVE_RESULT)
val register = getInstruction<OneRegisterInstruction>(index).registerA
@ -579,9 +655,24 @@ internal fun MutableMethod.insertFeatureFlagBooleanOverride(literal: Long, exten
addInstructions(
index + 1,
"""
$operation, $extensionsMethod
$operation, $extensionMethodDescriptor
move-result v$register
""",
"""
)
}
/**
* Overrides a literal value result with a constant value.
*/
internal fun MutableMethod.insertLiteralOverride(literal: Long, override: Boolean) {
val literalIndex = indexOfFirstLiteralInstructionOrThrow(literal)
val index = indexOfFirstInstructionOrThrow(literalIndex, MOVE_RESULT)
val register = getInstruction<OneRegisterInstruction>(index).registerA
val overrideValue = if (override) "0x1" else "0x0"
addInstruction(
index + 1,
"const v$register, $overrideValue"
)
}
@ -643,3 +734,58 @@ fun FingerprintBuilder.literal(literalSupplier: () -> Long) {
method.containsLiteralInstruction(literalSupplier())
}
}
private class InstructionUtils {
companion object {
val branchOpcodes: EnumSet<Opcode> = EnumSet.of(
GOTO, GOTO_16, GOTO_32,
IF_EQ, IF_NE, IF_LT, IF_GE, IF_GT, IF_LE,
IF_EQZ, IF_NEZ, IF_LTZ, IF_GEZ, IF_GTZ, IF_LEZ,
PACKED_SWITCH_PAYLOAD, SPARSE_SWITCH_PAYLOAD
)
val returnOpcodes: EnumSet<Opcode> = EnumSet.of(
RETURN_VOID, RETURN, RETURN_WIDE, RETURN_OBJECT, RETURN_VOID_NO_BARRIER,
THROW
)
val writeOpcodes: EnumSet<Opcode> = EnumSet.of(
ARRAY_LENGTH,
INSTANCE_OF,
NEW_INSTANCE, NEW_ARRAY,
MOVE, MOVE_FROM16, MOVE_16, MOVE_WIDE, MOVE_WIDE_FROM16, MOVE_WIDE_16, MOVE_OBJECT,
MOVE_OBJECT_FROM16, MOVE_OBJECT_16, MOVE_RESULT, MOVE_RESULT_WIDE, MOVE_RESULT_OBJECT, MOVE_EXCEPTION,
CONST, CONST_4, CONST_16, CONST_HIGH16, CONST_WIDE_16, CONST_WIDE_32,
CONST_WIDE, CONST_WIDE_HIGH16, CONST_STRING, CONST_STRING_JUMBO,
IGET, IGET_WIDE, IGET_OBJECT, IGET_BOOLEAN, IGET_BYTE, IGET_CHAR, IGET_SHORT,
IGET_VOLATILE, IGET_WIDE_VOLATILE, IGET_OBJECT_VOLATILE,
SGET, SGET_WIDE, SGET_OBJECT, SGET_BOOLEAN, SGET_BYTE, SGET_CHAR, SGET_SHORT,
SGET_VOLATILE, SGET_WIDE_VOLATILE, SGET_OBJECT_VOLATILE,
AGET, AGET_WIDE, AGET_OBJECT, AGET_BOOLEAN, AGET_BYTE, AGET_CHAR, AGET_SHORT,
// Arithmetic and logical operations.
ADD_DOUBLE_2ADDR, ADD_DOUBLE, ADD_FLOAT_2ADDR, ADD_FLOAT, ADD_INT_2ADDR,
ADD_INT_LIT8, ADD_INT, ADD_LONG_2ADDR, ADD_LONG, ADD_INT_LIT16,
AND_INT_2ADDR, AND_INT_LIT8, AND_INT_LIT16, AND_INT, AND_LONG_2ADDR, AND_LONG,
DIV_DOUBLE_2ADDR, DIV_DOUBLE, DIV_FLOAT_2ADDR, DIV_FLOAT, DIV_INT_2ADDR,
DIV_INT_LIT16, DIV_INT_LIT8, DIV_INT, DIV_LONG_2ADDR, DIV_LONG,
DOUBLE_TO_FLOAT, DOUBLE_TO_INT, DOUBLE_TO_LONG,
FLOAT_TO_DOUBLE, FLOAT_TO_INT, FLOAT_TO_LONG,
INT_TO_BYTE, INT_TO_CHAR, INT_TO_DOUBLE, INT_TO_FLOAT, INT_TO_LONG, INT_TO_SHORT,
LONG_TO_DOUBLE, LONG_TO_FLOAT, LONG_TO_INT,
MUL_DOUBLE_2ADDR, MUL_DOUBLE, MUL_FLOAT_2ADDR, MUL_FLOAT, MUL_INT_2ADDR,
MUL_INT_LIT16, MUL_INT_LIT8, MUL_INT, MUL_LONG_2ADDR, MUL_LONG,
NEG_DOUBLE, NEG_FLOAT, NEG_INT, NEG_LONG,
NOT_INT, NOT_LONG,
OR_INT_2ADDR, OR_INT_LIT16, OR_INT_LIT8, OR_INT, OR_LONG_2ADDR, OR_LONG,
REM_DOUBLE_2ADDR, REM_DOUBLE, REM_FLOAT_2ADDR, REM_FLOAT, REM_INT_2ADDR,
REM_INT_LIT16, REM_INT_LIT8, REM_INT, REM_LONG_2ADDR, REM_LONG,
RSUB_INT_LIT8, RSUB_INT,
SHL_INT_2ADDR, SHL_INT_LIT8, SHL_INT, SHL_LONG_2ADDR, SHL_LONG,
SHR_INT_2ADDR, SHR_INT_LIT8, SHR_INT, SHR_LONG_2ADDR, SHR_LONG,
SUB_DOUBLE_2ADDR, SUB_DOUBLE, SUB_FLOAT_2ADDR, SUB_FLOAT, SUB_INT_2ADDR,
SUB_INT, SUB_LONG_2ADDR, SUB_LONG,
USHR_INT_2ADDR, USHR_INT_LIT8, USHR_INT, USHR_LONG_2ADDR, USHR_LONG,
XOR_INT_2ADDR, XOR_INT_LIT16, XOR_INT_LIT8, XOR_INT, XOR_LONG_2ADDR, XOR_LONG,
)
}
}

View File

@ -466,6 +466,8 @@ Second \"item\" text"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">يجب أن يكون تعتيم التمرير السريع بين 0-100</string>
<string name="revanced_swipe_threshold_title">مقدار حد التمرير</string>
<string name="revanced_swipe_threshold_summary">الحد الأدنى من التمرير قبل اكتشاف الإيماءة</string>
<string name="revanced_swipe_volume_sensitivity_title">حساسية إيماءة تمرير مستوى الصوت</string>
<string name="revanced_swipe_volume_sensitivity_summary">مقدار تغير مستوى الصوت لكل تمريرة</string>
<string name="revanced_swipe_show_circular_overlay_title">عرض الواجهة الدائرية</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">يتم عرض التراكب الدائري</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">يتم عرض التراكب الأفقي</string>

View File

@ -613,6 +613,9 @@ Bu seçimi dəyişdirmə işə düşmürsə, Gizli rejimə keçməyə çalışı
<string name="revanced_hide_player_flyout_audio_track_summary_on">Səs axını menyusu gizlidir</string>
<string name="revanced_hide_player_flyout_audio_track_summary_off">Səs axını menyusu göstərilir</string>
<!-- 'Spoof video streams' should be the same translation used for revanced_spoof_video_streams_screen_title -->
<string name="revanced_hide_player_flyout_audio_track_not_available">"Audio trek seçimi gizlədilib
Audio trek seçimin göstərmək üçün \"Video axınları saxtalaşdır\"ı iOS TV-yə dəyiş"</string>
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_watch_in_vr_title">\"VR-da İzləni\" gizlət</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">VR menyusunda izləmə gizlidir</string>

View File

@ -466,6 +466,8 @@ Second \"item\" text"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Непразрыстасць пракруткі павінна быць паміж 0-100</string>
<string name="revanced_swipe_threshold_title">Парог велічыні пальцам</string>
<string name="revanced_swipe_threshold_summary">Велічыня парогавага значэння для правядзення пальцам</string>
<string name="revanced_swipe_volume_sensitivity_title">Адчувальнасць правядзення для гучнасці</string>
<string name="revanced_swipe_volume_sensitivity_summary">Наколькі змяняецца гучнасць пры кожным правядзенні</string>
<string name="revanced_swipe_show_circular_overlay_title">Паказваць кругавое накладанне</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Кругавое накладанне паказваецца</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Гарызантальнае накладанне паказваецца</string>

View File

@ -466,6 +466,8 @@ Second \"item\" text"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Непрозрачността на плъзгането трябва да е между 0-100</string>
<string name="revanced_swipe_threshold_title">Праг на величината на плъзгане</string>
<string name="revanced_swipe_threshold_summary">Праг преди да се осъществи плъзгането</string>
<string name="revanced_swipe_volume_sensitivity_title">Чувствителност при плъзгане за сила на звука</string>
<string name="revanced_swipe_volume_sensitivity_summary">Колко се променя силата на звука при всяко плъзгане</string>
<string name="revanced_swipe_show_circular_overlay_title">Показване на кръгъл овърлей</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Показва се кръгъл овърлей</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Показва се хоризонтален овърлей</string>

View File

@ -466,6 +466,8 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">সোয়াইপের অস্বচ্ছতা অবশ্যই 0-100 এর মধ্যে হতে হবে</string>
<string name="revanced_swipe_threshold_title">সোয়াইপ থ্রেশহোল্ড এর মাত্রা</string>
<string name="revanced_swipe_threshold_summary">সোয়াইপ করার থ্রেশহোল্ডের পরিমাণ</string>
<string name="revanced_swipe_volume_sensitivity_title">ভলিউম সোয়াইপ সংবেদনশীলতা</string>
<string name="revanced_swipe_volume_sensitivity_summary">প্রতি সোয়াইপে ভলিউম কতটা পরিবর্তিত হয়</string>
<string name="revanced_swipe_show_circular_overlay_title">বৃত্তাকার ওভারলে দেখান</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">বৃত্তাকার ওভারলে দেখানো হয়েছে</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">অনুভূমিক ওভারলে দেখানো হয়েছে</string>

View File

@ -466,6 +466,8 @@ Ajusteu el volum lliscant verticalment a la part dreta de la pantalla"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">L\'opacitat de lliscament ha d\'estar entre 0 i 100</string>
<string name="revanced_swipe_threshold_title">Llindar de magnitud de lliscament</string>
<string name="revanced_swipe_threshold_summary">La quantitat de llindar per a què es produeixi el desplaçament</string>
<string name="revanced_swipe_volume_sensitivity_title">Sensibilitat del lliscament de volum</string>
<string name="revanced_swipe_volume_sensitivity_summary">Quant canvia el volum per lliscament</string>
<string name="revanced_swipe_show_circular_overlay_title">Mostra la superposició circular</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Es mostra la superposició circular</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Es mostra la superposició horitzontal</string>

View File

@ -466,6 +466,8 @@ Hlasitost se upravuje svislým přejetím po pravé straně obrazovky"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Průsvitnost tažení musí být mezi 0-100</string>
<string name="revanced_swipe_threshold_title">Práh vynucení gesta</string>
<string name="revanced_swipe_threshold_summary">Velikost prahu pro provedení gesta</string>
<string name="revanced_swipe_volume_sensitivity_title">Citlivost přejetí hlasitosti</string>
<string name="revanced_swipe_volume_sensitivity_summary">O kolik se změní hlasitost na jedno přejetí</string>
<string name="revanced_swipe_show_circular_overlay_title">Zobrazit kruhovou překryvnou vrstvu</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Zobrazuje se kruhová překryvná vrstva</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Zobrazuje se vodorovná překryvná vrstva</string>

View File

@ -430,6 +430,8 @@ Juster lydstyrken ved at swipe lodret i højre side af skærmen"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Gennemsigtighed for swipe skal være mellem 0-100</string>
<string name="revanced_swipe_threshold_title">Stryg størrelse tærskel</string>
<string name="revanced_swipe_threshold_summary">Beløbet for tærskelværdi for stryg der skal ske</string>
<string name="revanced_swipe_volume_sensitivity_title">Volumen strygefølsomhed</string>
<string name="revanced_swipe_volume_sensitivity_summary">Hvor meget lydstyrken ændres pr. strygning</string>
<string name="revanced_swipe_show_circular_overlay_title">Vis cirkulært overlejring</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Cirkulært overlejring vises</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Horisontalt overlejring vises</string>

View File

@ -459,6 +459,8 @@ Passen Sie die Helligkeit an, indem Sie auf der linken Seite des Bildschirms ver
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Die Wischdeckkraft muss zwischen 0 und 100 liegen</string>
<string name="revanced_swipe_threshold_title">Wischgrößenschwelle</string>
<string name="revanced_swipe_threshold_summary">Der Schwellenwert für Wischen</string>
<string name="revanced_swipe_volume_sensitivity_title">Lautstärke-Wischgestenempfindlichkeit</string>
<string name="revanced_swipe_volume_sensitivity_summary">Wie stark sich die Lautstärke pro Wisch ändert</string>
<string name="revanced_swipe_show_circular_overlay_title">Kreisförmiges Overlay anzeigen</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Kreisförmiges Overlay wird angezeigt</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Horizontales Overlay wird angezeigt</string>

View File

@ -468,6 +468,8 @@ Second \"item\" text"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Η αδιαφάνεια σάρωσης πρέπει να είναι μεταξύ 0-100</string>
<string name="revanced_swipe_threshold_title">Κατώτατο όριο μεγέθους σάρωσης</string>
<string name="revanced_swipe_threshold_summary">Η ελάχιστη απόσταση που θα διανύσετε με το δάκτυλο σας για να είναι αναγνωρίσιμη η χειρονομία σάρωσης</string>
<string name="revanced_swipe_volume_sensitivity_title">Ευαισθησία σάρωσης έντασης ήχου</string>
<string name="revanced_swipe_volume_sensitivity_summary">Πόσο αλλάζει η ένταση ήχου ανά σάρωση</string>
<string name="revanced_swipe_show_circular_overlay_title">Εμφάνιση κυκλικής διάταξης</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Η διάταξη των ελέγχων σάρωσης είναι κυκλική</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Η διάταξη των ελέγχων σάρωσης είναι οριζόντια</string>

View File

@ -463,6 +463,8 @@ Ajusta el volumen deslizando verticalmente en el lado derecho de la pantalla"</s
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">La opacidad de la superposición de deslizamiento debe estar entre 0 y 100</string>
<string name="revanced_swipe_threshold_title">Umbral de magnitud del deslizamiento</string>
<string name="revanced_swipe_threshold_summary">La cantidad de umbral para que se desliza</string>
<string name="revanced_swipe_volume_sensitivity_title">Sensibilidad del deslizamiento de volumen</string>
<string name="revanced_swipe_volume_sensitivity_summary">Cuánto cambia el volumen por deslizamiento</string>
<string name="revanced_swipe_show_circular_overlay_title">Mostrar superposición circular</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Se muestra la superposición circular</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Se muestra la superposición horizontal</string>

View File

@ -466,6 +466,8 @@ Helitugevuse reguleerimiseks pühkige ekraani paremal küljel vertikaalselt"</st
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Pühkiva katte läbipaistvus peab olema vahemikus 0-100</string>
<string name="revanced_swipe_threshold_title">Pühkimise suuruse lävi</string>
<string name="revanced_swipe_threshold_summary">Lävi väärtus pühkimise toimimiseks</string>
<string name="revanced_swipe_volume_sensitivity_title">Helitugevuse libistamise tundlikkus</string>
<string name="revanced_swipe_volume_sensitivity_summary">Kui palju helitugevus ühe libistusega muutub</string>
<string name="revanced_swipe_show_circular_overlay_title">Kuva ümmargune ülekattekiht</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Ümmargune ülekattekiht on nähtav</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Horisontaalne ülekattekiht on nähtav</string>

View File

@ -466,6 +466,8 @@ Säädä äänenvoimakkuutta pyyhkäisemällä pystysuoraan näytön oikealta pu
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Pyyhkäisyn läpinäkymättömyyden on oltava välillä 0100</string>
<string name="revanced_swipe_threshold_title">Pyyhkäisyn kynnysraja</string>
<string name="revanced_swipe_threshold_summary">Pyyhkäisyä varten tarvittavan kynnyksen määrä</string>
<string name="revanced_swipe_volume_sensitivity_title">Äänenvoimakkuuden pyyhkäisyn herkkyys</string>
<string name="revanced_swipe_volume_sensitivity_summary">Kuinka paljon äänenvoimakkuus muuttuu pyyhkäisyä kohden</string>
<string name="revanced_swipe_show_circular_overlay_title">Näytä pyöreä peittokuva</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Pyöreä peittokuva näytetään</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Vaakasuora peittokuva näytetään</string>
@ -613,6 +615,9 @@ Jos tämän asetuksen muuttaminen ei tule voimaan, kokeile vaihtaa Incognito-til
<string name="revanced_hide_player_flyout_audio_track_summary_on">Ääniraitavalikko on piilotettu</string>
<string name="revanced_hide_player_flyout_audio_track_summary_off">Ääniraitavalikko näytetään</string>
<!-- 'Spoof video streams' should be the same translation used for revanced_spoof_video_streams_screen_title -->
<string name="revanced_hide_player_flyout_audio_track_not_available">"Ääniraitavalikko on piilotettu
Jos haluat nähdä sen, aseta \"Naamioi videovirrat\" iOS TV:ksi"</string>
<!-- 'Watch in VR' should be translated using the same localized wording YouTube displays for the menu item. -->
<string name="revanced_hide_player_flyout_watch_in_vr_title">Piilota Katso VR-tilassa</string>
<string name="revanced_hide_player_flyout_watch_in_vr_summary_on">Katso VR-tilassa -valinta on piilotettu</string>

View File

@ -466,6 +466,8 @@ Ayusin ang volume sa pamamagitan ng pag-swipe nang patayo sa kanang bahagi ng sc
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Ang opacity ng swipe ay dapat nasa pagitan ng 0-100</string>
<string name="revanced_swipe_threshold_title">I-swipe ang magnitude threshold</string>
<string name="revanced_swipe_threshold_summary">Ang halaga ng threshold para sa pag-swipe na magaganap</string>
<string name="revanced_swipe_volume_sensitivity_title">Pagkasensitibo sa pag-swipe ng volume</string>
<string name="revanced_swipe_volume_sensitivity_summary">Gaano karami ang pagbabago ng volume sa bawat swipe</string>
<string name="revanced_swipe_show_circular_overlay_title">Ipakita ang pabilog na overlay</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Ipinapakita ang pabilog na overlay</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Ipinapakita ang pahalang na overlay</string>

View File

@ -466,6 +466,8 @@ Réglez le volume en balayant verticalement sur le côté droit de l'écran"</st
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">L\'opacité doit être comprise entre 0 et 100 pour les gestes</string>
<string name="revanced_swipe_threshold_title">Seuil d\'intensité des balayages</string>
<string name="revanced_swipe_threshold_summary">L\'intensité du mouvement à effectuer pour qu\'un balayage soit pris en compte</string>
<string name="revanced_swipe_volume_sensitivity_title">Sensibilité du geste de contrôle du volume</string>
<string name="revanced_swipe_volume_sensitivity_summary">Quantité de modification du volume à chaque balayage</string>
<string name="revanced_swipe_show_circular_overlay_title">Afficher l\'overlay circulaire</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">L\'overlay circulaire est affiché</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">L\'overlay horizontal est affiché</string>

View File

@ -466,6 +466,8 @@ Coigeartaigh an toirt trí haisceartán go hingearach ar thaobh deas an scáile
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Caithfidh léaráidí traslaithe a bheith idir 0-100</string>
<string name="revanced_swipe_threshold_title">Tairseach méid swipe</string>
<string name="revanced_swipe_threshold_summary">Méid an tairseach le haghaidh sruthú tarlú</string>
<string name="revanced_swipe_volume_sensitivity_title">Íogaireacht swipe toirte</string>
<string name="revanced_swipe_volume_sensitivity_summary">An méid a athraíonn an toirt in aghaidh gach swipe</string>
<string name="revanced_swipe_show_circular_overlay_title">Taispeáin forleagan ciorclach</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Léirítear forleagan ciorclach</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Taispeántar forleagan cothrománach</string>

View File

@ -466,6 +466,8 @@ A hangerő a képernyő jobb oldalán függőlegesen húzva állítható be"</st
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">A csúsztatás átlátszóságának 0 és 100 között kell lennie</string>
<string name="revanced_swipe_threshold_title">A csúsztatás küszöbértéke</string>
<string name="revanced_swipe_threshold_summary">A csúsztatáshoz szükséges küszöbérték</string>
<string name="revanced_swipe_volume_sensitivity_title">Hangerő-görgetés érzékenysége</string>
<string name="revanced_swipe_volume_sensitivity_summary">Mennyit változzon a hangerő görgetésenként</string>
<string name="revanced_swipe_show_circular_overlay_title">Kör alakú fedvény megjelenítése</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Kör alakú fedvény megjelenik</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Vízszintes fedvény megjelenik</string>

View File

@ -466,6 +466,8 @@ MicroG-ի համար մարտկոցի օպտիմալացումը անջատել
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Սողալու անթափանցությունը պետք է լինի 0-100 միջակայքում</string>
<string name="revanced_swipe_threshold_title">Սահմանման վերածման չափը</string>
<string name="revanced_swipe_threshold_summary">Սահմանման վերածման չափը</string>
<string name="revanced_swipe_volume_sensitivity_title">Ձայնի սահեցման զգայունություն</string>
<string name="revanced_swipe_volume_sensitivity_summary">Թե որքան է ձայնի բարձրությունը փոխվում մեկ սահեցմամբ</string>
<string name="revanced_swipe_show_circular_overlay_title">Ցույց տալ շրջանաձև ծածկույթը</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Ցուցադրված է շրջանաձև ծածկույթ</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Հորիզոնական ծածկույթը ցուցադրվում է</string>

View File

@ -466,6 +466,8 @@ Menyesuaikan volume dengan mengusap secara vertikal di sisi kanan layar"</string
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Opasitas geser harus antara 0-100</string>
<string name="revanced_swipe_threshold_title">Ambang batas magnitudo usap</string>
<string name="revanced_swipe_threshold_summary">Jumlah ambang batas untuk terjadinya usapan</string>
<string name="revanced_swipe_volume_sensitivity_title">Sensitivitas gesek volume</string>
<string name="revanced_swipe_volume_sensitivity_summary">Seberapa besar perubahan volume per gesekan</string>
<string name="revanced_swipe_show_circular_overlay_title">Tampilkan hamparan melingkar</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Hamparan melingkar ditampilkan</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Hamparan horizontal ditampilkan</string>

View File

@ -466,6 +466,8 @@ Regola il volume scorrendo verticalmente sul lato destro dello schermo"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">L\'opacità di scorrimento deve essere tra 0-100</string>
<string name="revanced_swipe_threshold_title">Ampiezza limite della soglia di scorrimento</string>
<string name="revanced_swipe_threshold_summary">Il limite di ampiezza entro cui deve avvenire lo scorrimento</string>
<string name="revanced_swipe_volume_sensitivity_title">Sensibilità allo scorrimento del volume</string>
<string name="revanced_swipe_volume_sensitivity_summary">La quantità di volume che cambia per scorrimento</string>
<string name="revanced_swipe_show_circular_overlay_title">Mostra sovrapposizione circolare</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">La sovrapposizione circolare viene mostrata</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">La sovrapposizione orizzontale viene mostrata</string>

View File

@ -340,7 +340,7 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
<string name="revanced_hide_keyword_content_about_whole_words_summary">キーワードを二重引用符で囲むことで、動画のタイトルやチャンネル名の単語の一部とキーワードが合致しないようにできます&lt;br&gt;&lt;br&gt;例えば、&lt;br&gt;&lt;b&gt;\"ai\"&lt;/b&gt;は、次の動画を除外します:&lt;b&gt;How does AI work?&lt;/b&gt;&lt;br&gt;しかし、次の動画は除外しません:&lt;b&gt;What does fair use mean?&lt;/b&gt;</string>
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
<string name="revanced_hide_keyword_toast_invalid_common">キーワードを使用できません: %s</string>
<string name="revanced_hide_keyword_toast_invalid_common_whole_word_required">キーワード %sを使用する引用符を追加</string>
<string name="revanced_hide_keyword_toast_invalid_common_whole_word_required">キーワードを二重引用符で囲む必要があります: %s</string>
<string name="revanced_hide_keyword_toast_invalid_conflicting">キーワードに矛盾する宣言があります: %s</string>
<string name="revanced_hide_keyword_toast_invalid_length">キーワードが短すぎるため二重引用符で囲む必要があります: %s</string>
<string name="revanced_hide_keyword_toast_invalid_broad">キーワードはすべての動画を除外します: %s</string>
@ -402,11 +402,11 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
<string name="revanced_share_copy_url_success">URL をクリップボードにコピーしました</string>
<string name="revanced_share_copy_url_timestamp_success">タイムスタンプ付きの URL がコピーされました</string>
<string name="revanced_copy_video_url_title">「動画の URL をコピー」ボタンを表示</string>
<string name="revanced_copy_video_url_summary_on">オーバーレイにボタンが表示されます。タップすると動画の URL を、長押しするとタイムスタンプ付きの URL をそれぞれコピーできます</string>
<string name="revanced_copy_video_url_summary_off">オーバーレイにボタンは表示されません</string>
<string name="revanced_copy_video_url_summary_on">オーバーレイにボタンが表示されます。タップすると動画の URL を、長押しするとタイムスタンプ付きの URL をそれぞれコピーできます</string>
<string name="revanced_copy_video_url_summary_off">オーバーレイにボタンは表示されません</string>
<string name="revanced_copy_video_url_timestamp_title">「動画のタイムスタンプ付き URL をコピー」ボタンを表示</string>
<string name="revanced_copy_video_url_timestamp_summary_on">オーバーレイにボタンが表示されます。タップするとタイムスタンプ付きの URL を、長押しするとタイムスタンプなしの URL をそれぞれコピーできます</string>
<string name="revanced_copy_video_url_timestamp_summary_off">オーバーレイにボタンは表示されません</string>
<string name="revanced_copy_video_url_timestamp_summary_on">オーバーレイにボタンが表示されます。タップするとタイムスタンプ付きの URL を、長押しするとタイムスタンプなしの URL をそれぞれコピーできます</string>
<string name="revanced_copy_video_url_timestamp_summary_off">オーバーレイにボタンは表示されません</string>
</patch>
<patch id="interaction.dialog.removeViewerDiscretionDialogPatch">
<string name="revanced_remove_viewer_discretion_dialog_title">「ご自身の責任」ダイアログを削除</string>
@ -418,8 +418,8 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
<string name="revanced_external_downloader_screen_title">外部ダウンロード</string>
<string name="revanced_external_downloader_screen_summary">外部ダウンローダーの設定</string>
<string name="revanced_external_downloader_title">外部ダウンロード ボタンを表示</string>
<string name="revanced_external_downloader_summary_on">オーバーレイに外部ダウンロード ボタンが表示されます</string>
<string name="revanced_external_downloader_summary_off">オーバーレイに外部ダウンロード ボタンは表示されません</string>
<string name="revanced_external_downloader_summary_on">オーバーレイに外部ダウンロード ボタンが表示されます</string>
<string name="revanced_external_downloader_summary_off">オーバーレイに外部ダウンロード ボタンは表示されません</string>
<!-- 'download action button' should be translated using the same wording as the translation of 'revanced_hide_download_button_title' -->
<string name="revanced_external_downloader_action_button_title">オフライン ボタンの動作を上書きする</string>
<string name="revanced_external_downloader_action_button_summary_on">オフライン ボタンは外部ダウンローダーを呼び出します</string>
@ -465,10 +465,12 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
<string name="revanced_swipe_overlay_timeout_summary">オーバーレイが表示される時間(ミリ秒)</string>
<string name="revanced_swipe_overlay_background_opacity_title">オーバーレイの背景の透明度</string>
<string name="revanced_swipe_overlay_background_opacity_summary">透明度の値は 0-100 の範囲で、0 が透明です</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">透明度の値は 0-100 の間でなければなりません</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">スワイプ: 透明度の値は 0-100 でなければなりません</string>
<string name="revanced_swipe_threshold_title">スワイプのしきい値</string>
<string name="revanced_swipe_threshold_summary">スワイプと判定される最小の距離</string>
<string name="revanced_swipe_show_circular_overlay_title">オーバーレイを円形にする</string>
<string name="revanced_swipe_volume_sensitivity_title">音量ジェスチャーのスワイプ感度</string>
<string name="revanced_swipe_volume_sensitivity_summary">スワイプによる音量の変化量</string>
<string name="revanced_swipe_show_circular_overlay_title">円形のオーバーレイを使用する</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">円形のオーバーレイが表示されます</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">横長のオーバーレイが表示されます</string>
<string name="revanced_swipe_overlay_minimal_style_title">オーバーレイを最小限化する</string>
@ -631,15 +633,15 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
<string name="revanced_hide_player_previous_next_buttons_summary_on">前の動画ボタンと次の動画ボタンは表示されません</string>
<string name="revanced_hide_player_previous_next_buttons_summary_off">前の動画ボタンと次の動画ボタンは表示されます</string>
<string name="revanced_hide_cast_button_title">キャスト ボタンを非表示</string>
<string name="revanced_hide_cast_button_summary_on">オーバーレイにキャスト ボタンは表示されません</string>
<string name="revanced_hide_cast_button_summary_off">オーバーレイにキャスト ボタンが表示されます</string>
<string name="revanced_hide_cast_button_summary_on">オーバーレイにキャスト ボタンは表示されません</string>
<string name="revanced_hide_cast_button_summary_off">オーバーレイにキャスト ボタンが表示されます</string>
<!-- This button does not display any text, but 'captions' should be translated using the same wording used as the translation of 'revanced_hide_player_flyout_captions_title' -->
<string name="revanced_hide_captions_button_title">字幕ボタンを非表示</string>
<string name="revanced_hide_captions_button_summary_on">オーバーレイに字幕ボタンは表示されません</string>
<string name="revanced_hide_captions_button_summary_off">オーバーレイに字幕ボタンが表示されます</string>
<string name="revanced_hide_captions_button_summary_on">オーバーレイに字幕ボタンは表示されません</string>
<string name="revanced_hide_captions_button_summary_off">オーバーレイに字幕ボタンが表示されます</string>
<string name="revanced_hide_autoplay_button_title">自動再生ボタンを非表示</string>
<string name="revanced_hide_autoplay_button_summary_on">オーバーレイに自動再生ボタンは表示されません</string>
<string name="revanced_hide_autoplay_button_summary_off">オーバーレイに自動再生ボタンが表示されます</string>
<string name="revanced_hide_autoplay_button_summary_on">オーバーレイに自動再生ボタンは表示されません</string>
<string name="revanced_hide_autoplay_button_summary_off">オーバーレイに自動再生ボタンが表示されます</string>
</patch>
<patch id="layout.hide.endscreencards.hideEndscreenCardsResourcePatch">
<string name="revanced_hide_endscreen_cards_title">動画の終了画面を非表示</string>
@ -695,8 +697,8 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
<string name="revanced_hide_shorts_subscribe_button_summary_on">チャンネル登録ボタンは表示されません</string>
<string name="revanced_hide_shorts_subscribe_button_summary_off">チャンネル登録ボタンは表示されます</string>
<string name="revanced_hide_shorts_paused_overlay_buttons_title">一時停止中のオーバーレイ上のボタンを非表示</string>
<string name="revanced_hide_shorts_paused_overlay_buttons_summary_on">一時停止中のオーバーレイ上のボタンは表示されません</string>
<string name="revanced_hide_shorts_paused_overlay_buttons_summary_off">一時停止中のオーバーレイ上のボタンは表示されます</string>
<string name="revanced_hide_shorts_paused_overlay_buttons_summary_on">一時停止中のオーバーレイボタンは表示されません</string>
<string name="revanced_hide_shorts_paused_overlay_buttons_summary_off">一時停止中のオーバーレイにボタンが表示されます</string>
<string name="revanced_hide_shorts_shop_button_title">ショップ ボタンを非表示</string>
<string name="revanced_hide_shorts_shop_button_summary_on">ショップ ボタンは表示されません</string>
<string name="revanced_hide_shorts_shop_button_summary_off">ショップ ボタンは表示されます</string>
@ -805,7 +807,7 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
<patch id="layout.player.overlay.customPlayerOverlayOpacityResourcePatch">
<string name="revanced_player_overlay_opacity_title">オーバーレイの透明度</string>
<string name="revanced_player_overlay_opacity_summary">透明度の値は 0-100 の範囲で、0 が透明です</string>
<string name="revanced_player_overlay_opacity_invalid_toast">オーバーレイの透明度は 0-100 の間でなければなりません</string>
<string name="revanced_player_overlay_opacity_invalid_toast">プレーヤー: オーバーレイの透明度は 0-100 でなければなりません</string>
</patch>
<patch id="layout.returnyoutubedislike.returnYouTubeDislikePatch">
<!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. -->
@ -1201,7 +1203,7 @@ Automotive レイアウト
<string name="revanced_miniplayer_width_dip_invalid_toast">ピクセル サイズの値は %1$s と %2$s の間でなければなりません</string>
<string name="revanced_miniplayer_opacity_title">オーバーレイの透明度</string>
<string name="revanced_miniplayer_opacity_summary">透明度の値は 0-100 の範囲で、0 が透明です</string>
<string name="revanced_miniplayer_opacity_invalid_toast">オーバーレイの透明度の値は 0-100 の間でなければなりません</string>
<string name="revanced_miniplayer_opacity_invalid_toast">ミニプレーヤー: オーバーレイの透明度は 0-100 でなければなりません</string>
</patch>
<patch id="layout.theme.themePatch">
<string name="revanced_gradient_loading_screen_title">グラデーション読み込み画面を有効にする</string>
@ -1324,21 +1326,21 @@ Automotive レイアウト
<string name="revanced_remember_video_quality_last_selected_summary_on">画質の変更はすべての動画に適用されます</string>
<string name="revanced_remember_video_quality_last_selected_summary_off">画質の変更は現在の動画にのみ適用されます</string>
<string name="revanced_video_quality_default_wifi_title">デフォルトの画質Wi-Fi</string>
<string name="revanced_video_quality_default_mobile_title">デフォルトの画質(モバイル ネットワーク</string>
<string name="revanced_remember_shorts_quality_last_selected_title">ショート動画の画質の変更を保存する</string>
<string name="revanced_video_quality_default_mobile_title">デフォルトの画質(携帯回線</string>
<string name="revanced_remember_shorts_quality_last_selected_title">ショートの画質の変更を保存する</string>
<string name="revanced_remember_shorts_quality_last_selected_summary_on">画質の変更はすべてのショート動画に適用されます</string>
<string name="revanced_remember_shorts_quality_last_selected_summary_off">画質の変更は現在のショート動画にのみ適用されます</string>
<string name="revanced_shorts_quality_default_wifi_title">デフォルトのショート動画の画質Wi-Fi</string>
<string name="revanced_shorts_quality_default_mobile_title">デフォルトのショート動画の画質(モバイル ネットワーク</string>
<string name="revanced_remember_video_quality_mobile">モバイル ネットワーク</string>
<string name="revanced_shorts_quality_default_wifi_title">デフォルトのショートの画質Wi-Fi</string>
<string name="revanced_shorts_quality_default_mobile_title">デフォルトのショートの画質(携帯回線</string>
<string name="revanced_remember_video_quality_mobile">携帯回線</string>
<string name="revanced_remember_video_quality_wifi">Wi-Fi</string>
<string name="revanced_remember_video_quality_toast">デフォルトの画質 (%1$s) を %2$s に変更しました</string>
<string name="revanced_remember_video_quality_toast_shorts">ショート動画の画質 (%1$s) を %2$s に変更しました</string>
<string name="revanced_remember_video_quality_toast">デフォルトの画質 (%1$s): %2$s</string>
<string name="revanced_remember_video_quality_toast_shorts">ショートの画質 (%1$s): %2$s</string>
</patch>
<patch id="video.speed.button.playbackSpeedButtonPatch">
<string name="revanced_playback_speed_dialog_button_title">再生速度設定ボタンを非表示</string>
<string name="revanced_playback_speed_dialog_button_summary_on">オーバーレイに再生速度設定ボタンが表示されます</string>
<string name="revanced_playback_speed_dialog_button_summary_off">オーバーレイに再生速度設定ボタンは表示されません</string>
<string name="revanced_playback_speed_dialog_button_summary_on">オーバーレイに再生速度設定ボタンが表示されます</string>
<string name="revanced_playback_speed_dialog_button_summary_off">オーバーレイに再生速度設定ボタンは表示されません</string>
</patch>
<patch id="video.speed.custom.customPlaybackSpeedPatch">
<string name="revanced_custom_speed_menu_title">カスタムした再生速度リストを使用する</string>
@ -1357,7 +1359,7 @@ Automotive レイアウト
<string name="revanced_remember_playback_speed_last_selected_summary_on">再生速度の変更はすべての動画に適用されます</string>
<string name="revanced_remember_playback_speed_last_selected_summary_off">再生速度の変更は現在の動画にのみ適用されます</string>
<string name="revanced_playback_speed_default_title">デフォルトの再生速度</string>
<string name="revanced_remember_playback_speed_toast">デフォルトの再生速度を %s に変更しました</string>
<string name="revanced_remember_playback_speed_toast">デフォルトの再生速度: %s</string>
</patch>
<patch id="video.hdr.disableHdrPatch">
<string name="revanced_disable_hdr_video_title">HDR 動画を無効にする</string>

View File

@ -465,6 +465,8 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">스와이프 불투명도 값은 0-100 사이여야 합니다</string>
<string name="revanced_swipe_threshold_title">스와이프 한계치</string>
<string name="revanced_swipe_threshold_summary">제스처 인식을 위해 얼마나 스와이프를 해야 할지를 지정할 수 있으며, 원하지 않은 제스처 인식을 방지할 수 있습니다</string>
<string name="revanced_swipe_volume_sensitivity_title">볼륨 스와이프 민감도</string>
<string name="revanced_swipe_volume_sensitivity_summary">스와이프할 때마다 볼륨이 얼마나 변경되는지를 지정할 수 있습니다</string>
<string name="revanced_swipe_show_circular_overlay_title">원형 오버레이 표시하기</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">원형 오버레이를 표시합니다</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">바형 오버레이를 표시합니다</string>

View File

@ -466,6 +466,8 @@ Reguliuokite garsumą braukdami vertikaliai dešinėje ekrano pusėje"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Slinkties permatnumas turi būti nuo 0 iki 100</string>
<string name="revanced_swipe_threshold_title">Slinkties dydžio slenkstis</string>
<string name="revanced_swipe_threshold_summary">Slenkstis, reikalingas slinkčiai</string>
<string name="revanced_swipe_volume_sensitivity_title">Slinkimo garsumo jautrumas</string>
<string name="revanced_swipe_volume_sensitivity_summary">Kiek garsumas pasikeičia per braukimą</string>
<string name="revanced_swipe_show_circular_overlay_title">Rodyti apskritą perdangą</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Rodoma apskrita perdanga</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Rodoma horizontali perdanga</string>

View File

@ -466,6 +466,8 @@ Regulējiet skaļumu, velkot vertikāli ekrāna labajā pusē"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Pārvilkšanas necaurredzamībai jābūt no 0 līdz 100</string>
<string name="revanced_swipe_threshold_title">Slīdēšanas lieluma slieksnis</string>
<string name="revanced_swipe_threshold_summary">Slieksnis, lai slīdēšana varētu notikt</string>
<string name="revanced_swipe_volume_sensitivity_title">Svilpes jutīgums skaļuma regulēšanai</string>
<string name="revanced_swipe_volume_sensitivity_summary">Cik daudz skaļums mainās ar katru vilkšanu</string>
<string name="revanced_swipe_show_circular_overlay_title">Rādīt apļveida pārklājumu</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Apļveida pārklājums tiek rādīts</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Horizontālais pārklājums tiek rādīts</string>

View File

@ -466,6 +466,8 @@ Pas het volume aan door verticaal over de rechterkant van het scherm te vegen"</
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Dekking moet tussen 0-100 zijn</string>
<string name="revanced_swipe_threshold_title">Drempelwaarde swipe-sterkte</string>
<string name="revanced_swipe_threshold_summary">De hoeveelheid drempelwaarde voor swipe om te gebeuren</string>
<string name="revanced_swipe_volume_sensitivity_title">Gevoeligheid volumegest</string>
<string name="revanced_swipe_volume_sensitivity_summary">Hoeveel het volume verandert per swipe</string>
<string name="revanced_swipe_show_circular_overlay_title">Circulaire overlay weergeven</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Circulaire overlay wordt weergegeven</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Horizontale overlay wordt weergegeven</string>

View File

@ -466,6 +466,8 @@ Dostosuj głośność, przesuwając pionowo po prawej stronie ekranu"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Przezroczystość przesuwania musi być między 0 a 100</string>
<string name="revanced_swipe_threshold_title">Minimalna długość przesunięcia</string>
<string name="revanced_swipe_threshold_summary">Wartość wymagana do wykonania gestu przesunięcia</string>
<string name="revanced_swipe_volume_sensitivity_title">Czułość przesunięcia głośności</string>
<string name="revanced_swipe_volume_sensitivity_summary">O ile zmienia się głośność na przesunięcie</string>
<string name="revanced_swipe_show_circular_overlay_title">Pokaż okrągłą nakładkę</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Wyświetlana jest okrągła nakładka</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Wyświetlana jest pozioma nakładka</string>

View File

@ -464,6 +464,8 @@ Ajuste o volume deslizando verticalmente no lado direito da tela"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">A opacidade do deslizar deve estar entre 0-100</string>
<string name="revanced_swipe_threshold_title">Limiar distância no gesto</string>
<string name="revanced_swipe_threshold_summary">Quantidade limite que o gesto irá ocorrer</string>
<string name="revanced_swipe_volume_sensitivity_title">Sensibilidade ao deslizar o volume</string>
<string name="revanced_swipe_volume_sensitivity_summary">O quanto o volume muda por deslize</string>
<string name="revanced_swipe_show_circular_overlay_title">Mostrar sobreposição circular</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">A sobreposição circular é mostrada</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">A sobreposição horizontal é mostrada</string>

View File

@ -466,6 +466,8 @@ Ajuste o volume deslizando verticalmente no lado direito da tela"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">A opacidade do deslizar deve estar entre 0-100</string>
<string name="revanced_swipe_threshold_title">Limite de magnitude</string>
<string name="revanced_swipe_threshold_summary">A quantidade limite para deslizar irá ocorrer</string>
<string name="revanced_swipe_volume_sensitivity_title">Sensibilidade ao deslizar o volume</string>
<string name="revanced_swipe_volume_sensitivity_summary">O quanto o volume muda por deslize</string>
<string name="revanced_swipe_show_circular_overlay_title">Mostrar sobreposição circular</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">A sobreposição circular é mostrada</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">A sobreposição horizontal é mostrada</string>

View File

@ -466,6 +466,8 @@ Reglați volumul glisând vertical pe partea dreaptă a ecranului"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Opacitatea glisării trebuie să fie între 0-100</string>
<string name="revanced_swipe_threshold_title">Pragul mărimii glisării</string>
<string name="revanced_swipe_threshold_summary">Cantitatea de prag pentru a glisa</string>
<string name="revanced_swipe_volume_sensitivity_title">Sensibilitate glisare volum</string>
<string name="revanced_swipe_volume_sensitivity_summary">Cât de mult se modifică volumul per glisare</string>
<string name="revanced_swipe_show_circular_overlay_title">Afișează suprapunerea circulară</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Suprapunerea circulară este afișată</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Suprapunerea orizontală este afișată</string>

View File

@ -466,6 +466,8 @@ Second \"item\" text"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Значение затемнения панели жестов должно быть от 0 до 100</string>
<string name="revanced_swipe_threshold_title">Порог величины жеста</string>
<string name="revanced_swipe_threshold_summary">Минимальная амплитуда движения, распознаваемого как жест</string>
<string name="revanced_swipe_volume_sensitivity_title">Чувствительность свайпа для регулировки громкости</string>
<string name="revanced_swipe_volume_sensitivity_summary">На сколько изменяется громкость при каждом свайпе</string>
<string name="revanced_swipe_show_circular_overlay_title">Показать круговой индикатор</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Круговой индикатор показан</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Горизонтальный индикатор показан</string>

View File

@ -459,6 +459,8 @@ Upravte hlasitosť posúvaním vertikálne na pravej strane obrazovky"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Priehľadnosť prekrytia potiahnutia musí byť medzi 0-100</string>
<string name="revanced_swipe_threshold_title">Prahová hodnota potiahnutia</string>
<string name="revanced_swipe_threshold_summary">Hodnota prahu, ktorý sa má vykonať potiahnutím prstom</string>
<string name="revanced_swipe_volume_sensitivity_title">Citlivosť posúvania hlasitosti</string>
<string name="revanced_swipe_volume_sensitivity_summary">Ako veľmi sa mení hlasitosť na jedno posunutie</string>
<string name="revanced_swipe_show_circular_overlay_title">Zobraziť kruhovú vrstvu</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Kruhová vrstva sa zobrazuje</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Zobrazuje sa vodorovná vrstva</string>

View File

@ -466,6 +466,8 @@ Prilagodite glasnost s potegom navpično na desni strani zaslona"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Prosojnost drsenja mora biti med 0 in 100</string>
<string name="revanced_swipe_threshold_title">Prazg prag za pomikanje</string>
<string name="revanced_swipe_threshold_summary">Vrednost praga za pomikanje</string>
<string name="revanced_swipe_volume_sensitivity_title">Občutljivost drsenja za glasnost</string>
<string name="revanced_swipe_volume_sensitivity_summary">Koliko se spremeni glasnost na poteg</string>
<string name="revanced_swipe_show_circular_overlay_title">Pokaži krožni prekrivni element</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Krožni prekrivni element je prikazan</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Prikazan je vodoravni prekrivni element</string>

View File

@ -466,6 +466,8 @@ Përshtate shkëlqimin duke rrëshqitur vertikalisht në anën e majtë të ekra
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Opaciteti i shtypjes duhet të jetë midis 0-100</string>
<string name="revanced_swipe_threshold_title">Pragu i madhësisë së shërbimit</string>
<string name="revanced_swipe_threshold_summary">Sasia e pragut për të ndodhur shërbimi</string>
<string name="revanced_swipe_volume_sensitivity_title">Ndjeshmëria e rrëshqitjes së volumit</string>
<string name="revanced_swipe_volume_sensitivity_summary">Sa ndryshon volumi për rrëshqitje</string>
<string name="revanced_swipe_show_circular_overlay_title">Shfaq mbivendosjen rrethore</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Mbivendosja rrethore është shfaqur</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Mbivendosja horizontale është shfaqur</string>

View File

@ -466,6 +466,8 @@ Podesite jačinu zvuka prevlačenjem vertikalno na desnoj strani ekrana"</string
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Neprozirnost pokreta prevlačenja mora biti između 0 i 100</string>
<string name="revanced_swipe_threshold_title">Prag trajanja prevlačenja</string>
<string name="revanced_swipe_threshold_summary">Iznos praga trajanja prevlačenja</string>
<string name="revanced_swipe_volume_sensitivity_title">Osetljivost prevlačenja za jačinu zvuka</string>
<string name="revanced_swipe_volume_sensitivity_summary">Koliko se jačina zvuka menja po prevlačenju</string>
<string name="revanced_swipe_show_circular_overlay_title">Prikaži kružni preklop</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Prikazan je kružni preklop</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Prikazan je horizontalni preklop</string>

View File

@ -466,6 +466,8 @@ Second \"item\" text"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Непрозирност покрета превлачења мора бити између 0 и 100</string>
<string name="revanced_swipe_threshold_title">Праг трајања превлачења</string>
<string name="revanced_swipe_threshold_summary">Износ прага трајања превлачења</string>
<string name="revanced_swipe_volume_sensitivity_title">Осетљивост покрета за јачину звука</string>
<string name="revanced_swipe_volume_sensitivity_summary">Колико се јачина звука мења по покрету</string>
<string name="revanced_swipe_show_circular_overlay_title">Прикажи кружни преклоп</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Приказан је кружни преклоп</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Приказан је хоризонтални преклоп</string>

View File

@ -466,6 +466,8 @@ Justera volymen genom att svepa vertikalt på höger sida av skärmen"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Överlagrad svepopacitet måste vara mellan 0-100</string>
<string name="revanced_swipe_threshold_title">Svep magnitud tröskel</string>
<string name="revanced_swipe_threshold_summary">Mängden tröskel för att svepa ska uppstå</string>
<string name="revanced_swipe_volume_sensitivity_title">Volym svepkänslighet</string>
<string name="revanced_swipe_volume_sensitivity_summary">Hur mycket volymen ändras per svep</string>
<string name="revanced_swipe_show_circular_overlay_title">Visa cirkelformad overlay</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Cirkelformad overlay visas</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Horisontell overlay visas</string>

View File

@ -464,6 +464,8 @@ Second \"item\" text"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">ค่าความทึบแสงของสไลด์ต้องอยู่ระหว่าง 0-100</string>
<string name="revanced_swipe_threshold_title">เกณฑ์ขนาดของการปัด</string>
<string name="revanced_swipe_threshold_summary">จำนวนเกณฑ์สำหรับการปัดที่จะเกิดขึ้น</string>
<string name="revanced_swipe_volume_sensitivity_title">ความไวในการปัดปรับระดับเสียง</string>
<string name="revanced_swipe_volume_sensitivity_summary">ปริมาณการเปลี่ยนแปลงระดับเสียงต่อการปัดแต่ละครั้ง</string>
<string name="revanced_swipe_show_circular_overlay_title">แสดงภาพซ้อนทับแบบวงกลม</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">แสดงภาพซ้อนทับแบบวงกลม</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">แสดงภาพซ้อนทับแนวนอน</string>

View File

@ -466,6 +466,8 @@ Ekranın sağ tarafında dikey olarak kaydırarak sesi ayarlayın"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Kaydırma opaklığı 0-100 arasında olmalıdır</string>
<string name="revanced_swipe_threshold_title">Kaydırma büyüklük eşiği</string>
<string name="revanced_swipe_threshold_summary">Kaydırma işleminin gerçekleşmesi için eşik miktarı</string>
<string name="revanced_swipe_volume_sensitivity_title">Ses kaydırma hassasiyeti</string>
<string name="revanced_swipe_volume_sensitivity_summary">Kaydırma başına sesin ne kadar değişeceği</string>
<string name="revanced_swipe_show_circular_overlay_title">Dairesel katmanı göster</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Dairesel katman gösteriliyor</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Yatay katman gösteriliyor</string>

View File

@ -466,6 +466,8 @@ Second \"item\" text"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Значення затемнення панелі жесту має бути в межах від 0 до 100</string>
<string name="revanced_swipe_threshold_title">Поріг величини жесту</string>
<string name="revanced_swipe_threshold_summary">Мінімальна амплітуда руху, що розпізнається як жест</string>
<string name="revanced_swipe_volume_sensitivity_title">Чутливість гортання гучності</string>
<string name="revanced_swipe_volume_sensitivity_summary">На скільки змінюється гучність за одне гортання</string>
<string name="revanced_swipe_show_circular_overlay_title">Показувати круговий індикатор</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Показується круговий індикатор</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Показується горизонтальний індикатор</string>

View File

@ -466,6 +466,8 @@ Tính năng này chỉ khả dụng cho các thiết bị cũ hơn"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Độ mờ vuốt phải nằm trong khoảng từ 0-100</string>
<string name="revanced_swipe_threshold_title">Độ rộng ngưỡng vuốt</string>
<string name="revanced_swipe_threshold_summary">Độ rộng của ngưỡng vuốt để thực hiện cử chỉ vuốt</string>
<string name="revanced_swipe_volume_sensitivity_title">Độ nhạy vuốt âm lượng</string>
<string name="revanced_swipe_volume_sensitivity_summary">Mức âm lượng thay đổi trên mỗi lần vuốt</string>
<string name="revanced_swipe_show_circular_overlay_title">Hiện lớp phủ hình tròn</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Lớp phủ tròn được hiện</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Lớp phủ ngang được hiện</string>

View File

@ -459,19 +459,21 @@ Second \"item\" text"</string>
<string name="revanced_swipe_lowest_value_enable_auto_brightness_title">启用自动亮度手势</string>
<string name="revanced_swipe_lowest_value_enable_auto_brightness_summary_on">滑动到最低亮度手势将启用自动亮度</string>
<string name="revanced_swipe_lowest_value_enable_auto_brightness_summary_off">滑动到最低亮度手势不启用自动亮度</string>
<string name="revanced_swipe_overlay_timeout_title">滑动覆盖超时</string>
<string name="revanced_swipe_overlay_timeout_summary">滑动叠加层显示的时长(毫秒)</string>
<string name="revanced_swipe_overlay_background_opacity_title">滑动叠加层背景的不透明度</string>
<string name="revanced_swipe_overlay_timeout_title">滑动提示层显示时长</string>
<string name="revanced_swipe_overlay_timeout_summary">滑动提示的显示时长(毫秒)</string>
<string name="revanced_swipe_overlay_background_opacity_title">滑动提示层背景的不透明度</string>
<string name="revanced_swipe_overlay_background_opacity_summary">不透明度值介于 0-100 之间</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">滑动不透明度必须介于 0-100 之间</string>
<string name="revanced_swipe_threshold_title">滑动幅度阈值</string>
<string name="revanced_swipe_threshold_summary">防误触的滑动幅度阈值</string>
<string name="revanced_swipe_show_circular_overlay_title">显示圆形叠加层</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">圆形叠加层已显示</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">水平叠加层已显示</string>
<string name="revanced_swipe_overlay_minimal_style_title">启用极简样式</string>
<string name="revanced_swipe_overlay_minimal_style_summary_on">已启用极简叠加样式</string>
<string name="revanced_swipe_overlay_minimal_style_summary_off">已停用最小叠加层样式</string>
<string name="revanced_swipe_volume_sensitivity_title">音量滑动灵敏度</string>
<string name="revanced_swipe_volume_sensitivity_summary">每次滑动音量变化的幅度</string>
<string name="revanced_swipe_show_circular_overlay_title">圆形的叠加层样式</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">提示层显示为圆形样式</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">提示层显示为水平样式</string>
<string name="revanced_swipe_overlay_minimal_style_title">极简提示样式</string>
<string name="revanced_swipe_overlay_minimal_style_summary_on">极简样式已启用</string>
<string name="revanced_swipe_overlay_minimal_style_summary_off">极简样式已禁用</string>
<string name="revanced_swipe_change_video_title">启用滑动切换视频</string>
<string name="revanced_swipe_change_video_summary_on">在全屏模式下滑动将切换到下一个/上一个视频</string>
<string name="revanced_swipe_change_video_summary_off">在全屏模式下滑动将不会切换到下一个/上一个视频</string>
@ -882,9 +884,9 @@ Second \"item\" text"</string>
<string name="revanced_sb_enable_voting">显示投票按钮</string>
<string name="revanced_sb_enable_voting_sum_on">显示片段投票按钮</string>
<string name="revanced_sb_enable_voting_sum_off">不显示片段投票按钮</string>
<string name="revanced_sb_square_layout">使用方形布局</string>
<string name="revanced_sb_square_layout_sum_on">使用方形的按钮和控件</string>
<string name="revanced_sb_square_layout_sum_off">使用圆角的按钮和控件</string>
<string name="revanced_sb_square_layout">使用方形控件</string>
<string name="revanced_sb_square_layout_sum_on">使用方形样式的按钮和控件</string>
<string name="revanced_sb_square_layout_sum_off">使用圆角样式的按钮和控件</string>
<!-- Translations should use language similar to 'revanced_ryd_compact_layout_title' -->
<string name="revanced_sb_enable_compact_skip_button">使用紧凑的跳过按钮</string>
<string name="revanced_sb_enable_compact_skip_button_sum_on">跳过按钮样式为最小宽度</string>

View File

@ -527,6 +527,8 @@ Adjust volume by swiping vertically on the right side of the screen"</string>
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Swipe opacity must be between 0-100</string>
<string name="revanced_swipe_threshold_title">Swipe magnitude threshold</string>
<string name="revanced_swipe_threshold_summary">The amount of threshold for swipe to occur</string>
<string name="revanced_swipe_volume_sensitivity_title">Volume swipe sensitivity</string>
<string name="revanced_swipe_volume_sensitivity_summary">How much the volume changes per swipe</string>
<string name="revanced_swipe_show_circular_overlay_title">Show circular overlay</string>
<string name="revanced_swipe_show_circular_overlay_summary_on">Circular overlay is shown</string>
<string name="revanced_swipe_show_circular_overlay_summary_off">Horizontal overlay is shown</string>