mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-10 11:23:57 +01:00
Compare commits
16 Commits
v5.20.1-de
...
v5.21.0-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cce21c4d4a | ||
|
|
5e069bde90 | ||
|
|
6a49208982 | ||
|
|
404bb2e86e | ||
|
|
bc869fe359 | ||
|
|
7d166cf82c | ||
|
|
8efbaae65c | ||
|
|
e27ab23279 | ||
|
|
ce42604083 | ||
|
|
fc6282d0cb | ||
|
|
0559fc7fd0 | ||
|
|
7cc6995682 | ||
|
|
476f13bf98 | ||
|
|
f216e16c0b | ||
|
|
f2a8789649 | ||
|
|
5973b64f52 |
42
CHANGELOG.md
42
CHANGELOG.md
@@ -1,3 +1,45 @@
|
||||
# [5.21.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.21.0-dev.4...v5.21.0-dev.5) (2025-04-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* `Hide ADB status` patch ([#4814](https://github.com/ReVanced/revanced-patches/issues/4814)) ([dc89be0](https://github.com/ReVanced/revanced-patches/commit/dc89be0e94880733f862b250d95d4848f02c594d))
|
||||
|
||||
# [5.21.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.21.0-dev.3...v5.21.0-dev.4) (2025-04-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Disable auto captions:** Correctly hide captions with YT 20.12 ([5ecbe82](https://github.com/ReVanced/revanced-patches/commit/5ecbe823ed5197533328cc37f1de5cd1f048a217))
|
||||
|
||||
# [5.21.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.21.0-dev.2...v5.21.0-dev.3) (2025-04-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **X / Twitter:** Support version `10.86.0-release.0` ([#4805](https://github.com/ReVanced/revanced-patches/issues/4805)) ([655b390](https://github.com/ReVanced/revanced-patches/commit/655b39043ad77efcb4380de67c3f603666e7bc49))
|
||||
|
||||
# [5.21.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.21.0-dev.1...v5.21.0-dev.2) (2025-04-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add `Hide ADB status` patch ([#4585](https://github.com/ReVanced/revanced-patches/issues/4585)) ([1ea8047](https://github.com/ReVanced/revanced-patches/commit/1ea8047aefdaa358e9af8038923ac54d68a39176))
|
||||
|
||||
# [5.21.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.20.1...v5.21.0-dev.1) (2025-04-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Support version `20.12.46` ([#4779](https://github.com/ReVanced/revanced-patches/issues/4779)) ([703359f](https://github.com/ReVanced/revanced-patches/commit/703359f0c16b613c204cf16cf42227b628f664fa))
|
||||
|
||||
## [5.20.1](https://github.com/ReVanced/revanced-patches/compare/v5.20.0...v5.20.1) (2025-04-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Spotify - Custom theme:** Support latest app target ([#4800](https://github.com/ReVanced/revanced-patches/issues/4800)) ([03d0eb2](https://github.com/ReVanced/revanced-patches/commit/03d0eb2f8c0f3e48d53bdab38d34057f2020bb65))
|
||||
|
||||
## [5.20.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.20.0...v5.20.1-dev.1) (2025-04-15)
|
||||
|
||||
|
||||
|
||||
16
extensions/all/misc/adb/hide-adb/build.gradle.kts
Normal file
16
extensions/all/misc/adb/hide-adb/build.gradle.kts
Normal file
@@ -0,0 +1,16 @@
|
||||
android {
|
||||
namespace = "app.revanced.extension"
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 21
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.annotation)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<manifest/>
|
||||
@@ -0,0 +1,28 @@
|
||||
package app.revanced.extension.all.misc.hide.adb;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.provider.Settings;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class HideAdbPatch {
|
||||
private static final List<String> SPOOF_SETTINGS = Arrays.asList("adb_enabled", "adb_wifi_enabled", "development_settings_enabled");
|
||||
|
||||
public static int getInt(ContentResolver cr, String name) throws Settings.SettingNotFoundException {
|
||||
if (SPOOF_SETTINGS.contains(name)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Settings.Global.getInt(cr, name);
|
||||
}
|
||||
|
||||
public static int getInt(ContentResolver cr, String name, int def) {
|
||||
if (SPOOF_SETTINGS.contains(name)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Settings.Global.getInt(cr, name, def);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.extension.all.connectivity.wifi.spoof;
|
||||
package app.revanced.extension.all.misc.connectivity.wifi.spoof;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.extension.all.screencapture.removerestriction;
|
||||
package app.revanced.extension.all.misc.screencapture.removerestriction;
|
||||
|
||||
import android.media.AudioAttributes;
|
||||
import android.os.Build;
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.extension.all.screenshot.removerestriction;
|
||||
package app.revanced.extension.all.misc.screenshot.removerestriction;
|
||||
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
@@ -204,7 +204,7 @@ public class StreamingDataRequest {
|
||||
// but empty response body does.
|
||||
if (connection.getContentLength() == 0) {
|
||||
if (BaseSettings.DEBUG.get() && BaseSettings.DEBUG_TOAST_ON_ERROR.get()) {
|
||||
Utils.showToastShort("Ignoring empty spoof stream client: " + clientType);
|
||||
Utils.showToastShort("Debug: Ignoring empty spoof stream client " + clientType);
|
||||
}
|
||||
} else {
|
||||
try (InputStream inputStream = new BufferedInputStream(connection.getInputStream());
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
package app.revanced.extension.youtube.patches;
|
||||
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.shared.ShortsPlayerState;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class DisableAutoCaptionsPatch {
|
||||
|
||||
/**
|
||||
* Used by injected code. Do not delete.
|
||||
*/
|
||||
public static boolean captionsButtonDisabled;
|
||||
private static volatile boolean captionsButtonStatus;
|
||||
|
||||
public static boolean autoCaptionsEnabled() {
|
||||
return Settings.AUTO_CAPTIONS.get()
|
||||
// Do not use auto captions for Shorts.
|
||||
&& ShortsPlayerState.isOpen();
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean disableAutoCaptions() {
|
||||
return Settings.DISABLE_AUTO_CAPTIONS.get() && !captionsButtonStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void setCaptionsButtonStatus(boolean status) {
|
||||
captionsButtonStatus = status;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +124,7 @@ public class Settings extends BaseSettings {
|
||||
// Player
|
||||
public static final BooleanSetting COPY_VIDEO_URL = new BooleanSetting("revanced_copy_video_url", FALSE);
|
||||
public static final BooleanSetting COPY_VIDEO_URL_TIMESTAMP = new BooleanSetting("revanced_copy_video_url_timestamp", TRUE);
|
||||
public static final BooleanSetting DISABLE_AUTO_CAPTIONS = new BooleanSetting("revanced_disable_auto_captions", FALSE, true);
|
||||
public static final BooleanSetting DISABLE_FULLSCREEN_AMBIENT_MODE = new BooleanSetting("revanced_disable_fullscreen_ambient_mode", TRUE, true);
|
||||
public static final BooleanSetting DISABLE_ROLLING_NUMBER_ANIMATIONS = new BooleanSetting("revanced_disable_rolling_number_animations", FALSE);
|
||||
public static final EnumSetting<FullscreenMode> EXIT_FULLSCREEN = new EnumSetting<>("revanced_exit_fullscreen", FullscreenMode.DISABLED);
|
||||
@@ -294,7 +295,6 @@ public class Settings extends BaseSettings {
|
||||
// Misc
|
||||
public static final BooleanSetting ANNOUNCEMENTS = new BooleanSetting("revanced_announcements", TRUE);
|
||||
public static final IntegerSetting ANNOUNCEMENT_LAST_ID = new IntegerSetting("revanced_announcement_last_id", -1, false, false);
|
||||
public static final BooleanSetting AUTO_CAPTIONS = new BooleanSetting("revanced_auto_captions", FALSE);
|
||||
public static final BooleanSetting AUTO_REPEAT = new BooleanSetting("revanced_auto_repeat", FALSE);
|
||||
public static final BooleanSetting BYPASS_URL_REDIRECTS = new BooleanSetting("revanced_bypass_url_redirects", TRUE);
|
||||
public static final BooleanSetting CHECK_WATCH_HISTORY_DOMAIN_NAME = new BooleanSetting("revanced_check_watch_history_domain_name", TRUE, false, false);
|
||||
@@ -403,6 +403,7 @@ public class Settings extends BaseSettings {
|
||||
private static final StringSetting DEPRECATED_SEEKBAR_CUSTOM_COLOR_PRIMARY = new StringSetting("revanced_seekbar_custom_color_value", "#FF0033");
|
||||
private static final BooleanSetting DEPRECATED_DISABLE_SUGGESTED_VIDEO_END_SCREEN = new BooleanSetting("revanced_disable_suggested_video_end_screen", FALSE);
|
||||
private static final BooleanSetting DEPRECATED_RESTORE_OLD_VIDEO_QUALITY_MENU = new BooleanSetting("revanced_restore_old_video_quality_menu", TRUE);
|
||||
private static final BooleanSetting DEPRECATED_AUTO_CAPTIONS = new BooleanSetting("revanced_auto_captions", FALSE);
|
||||
|
||||
static {
|
||||
// region Migration
|
||||
@@ -456,6 +457,11 @@ public class Settings extends BaseSettings {
|
||||
SPOOF_APP_VERSION_TARGET.resetToDefault();
|
||||
}
|
||||
|
||||
if (!DEPRECATED_AUTO_CAPTIONS.isSetToDefault()) {
|
||||
DISABLE_AUTO_CAPTIONS.save(true);
|
||||
DEPRECATED_AUTO_CAPTIONS.resetToDefault();
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region SB import/export callbacks
|
||||
|
||||
@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
|
||||
org.gradle.parallel = true
|
||||
android.useAndroidX = true
|
||||
kotlin.code.style = official
|
||||
version = 5.20.1-dev.1
|
||||
version = 5.21.0-dev.5
|
||||
|
||||
@@ -2,6 +2,10 @@ public final class app/revanced/patches/all/misc/activity/exportall/ExportAllAct
|
||||
public static final fun getExportAllActivitiesPatch ()Lapp/revanced/patcher/patch/ResourcePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/all/misc/adb/HideAdbPatchKt {
|
||||
public static final fun getHideAdbStatusPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/all/misc/build/BaseSpoofBuildInfoPatchKt {
|
||||
public static final fun baseSpoofBuildInfoPatch (Lkotlin/jvm/functions/Function0;)Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -1416,6 +1420,8 @@ public final class app/revanced/patches/youtube/misc/playservice/VersionCheckPat
|
||||
public static final fun is_20_07_or_greater ()Z
|
||||
public static final fun is_20_09_or_greater ()Z
|
||||
public static final fun is_20_10_or_greater ()Z
|
||||
public static final fun is_20_14_or_greater ()Z
|
||||
public static final fun is_20_15_or_greater ()Z
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/privacy/RemoveTrackingQueryParameterPatchKt {
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package app.revanced.patches.all.misc.adb
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
|
||||
import app.revanced.util.getReference
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference
|
||||
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/all/misc/hide/adb/HideAdbPatch;"
|
||||
|
||||
private val SETTINGS_GLOBAL_GET_INT_OR_THROW_METHOD_REFERENCE = ImmutableMethodReference(
|
||||
"Landroid/provider/Settings\$Global;",
|
||||
"getInt",
|
||||
listOf("Landroid/content/ContentResolver;", "Ljava/lang/String;"),
|
||||
"I"
|
||||
)
|
||||
|
||||
private val SETTINGS_GLOBAL_GET_INT_OR_DEFAULT_METHOD_REFERENCE = ImmutableMethodReference(
|
||||
"Landroid/provider/Settings\$Global;",
|
||||
"getInt",
|
||||
listOf("Landroid/content/ContentResolver;", "Ljava/lang/String;", "I"),
|
||||
"I"
|
||||
)
|
||||
|
||||
private fun MethodReference.anyMethodSignatureMatches(vararg anyOf: MethodReference): Boolean {
|
||||
return anyOf.any {
|
||||
MethodUtil.methodSignaturesMatch(it, this)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
val hideAdbStatusPatch = bytecodePatch(
|
||||
name = "Hide ADB status",
|
||||
description = "Hides enabled development settings and/or ADB.",
|
||||
use = false,
|
||||
) {
|
||||
extendWith("extensions/all/misc/adb/hide-adb.rve")
|
||||
|
||||
dependsOn(
|
||||
transformInstructionsPatch(
|
||||
filterMap = filterMap@{ classDef, method, instruction, instructionIndex ->
|
||||
val reference = instruction
|
||||
.takeIf { it.opcode == Opcode.INVOKE_STATIC }
|
||||
?.getReference<MethodReference>()
|
||||
?.takeIf {
|
||||
it.anyMethodSignatureMatches(it,
|
||||
SETTINGS_GLOBAL_GET_INT_OR_THROW_METHOD_REFERENCE,
|
||||
SETTINGS_GLOBAL_GET_INT_OR_DEFAULT_METHOD_REFERENCE
|
||||
)
|
||||
}
|
||||
?: return@filterMap null
|
||||
|
||||
Triple(instruction as Instruction35c, instructionIndex, reference.parameterTypes)
|
||||
},
|
||||
transform = { method, entry ->
|
||||
val (instruction, index, parameterTypes) = entry
|
||||
val parameterString = parameterTypes.joinToString(separator = "")
|
||||
|
||||
val registerString = when (parameterTypes.size) {
|
||||
2 -> "v${instruction.registerC}, v${instruction.registerD}"
|
||||
else -> "v${instruction.registerC}, v${instruction.registerD}, v${instruction.registerE}"
|
||||
}
|
||||
|
||||
method.replaceInstruction(
|
||||
index,
|
||||
"invoke-static { $registerString }, $EXTENSION_CLASS_DESCRIPTOR->getInt($parameterString)I"
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import app.revanced.patches.all.misc.transformation.filterMapInstruction35c
|
||||
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR_PREFIX =
|
||||
"Lapp/revanced/extension/all/connectivity/wifi/spoof/SpoofWifiPatch"
|
||||
"Lapp/revanced/extension/all/misc/connectivity/wifi/spoof/SpoofWifiPatch"
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "$EXTENSION_CLASS_DESCRIPTOR_PREFIX;"
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ private val removeCaptureRestrictionResourcePatch = resourcePatch(
|
||||
}
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR_PREFIX =
|
||||
"Lapp/revanced/extension/all/screencapture/removerestriction/RemoveScreenCaptureRestrictionPatch"
|
||||
"Lapp/revanced/extension/all/misc/screencapture/removerestriction/RemoveScreenCaptureRestrictionPatch"
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "$EXTENSION_CLASS_DESCRIPTOR_PREFIX;"
|
||||
|
||||
@Suppress("unused")
|
||||
|
||||
@@ -10,7 +10,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction22c
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR_PREFIX =
|
||||
"Lapp/revanced/extension/all/screenshot/removerestriction/RemoveScreenshotRestrictionPatch"
|
||||
"Lapp/revanced/extension/all/misc/screenshot/removerestriction/RemoveScreenshotRestrictionPatch"
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "$EXTENSION_CLASS_DESCRIPTOR_PREFIX;"
|
||||
|
||||
@Suppress("unused")
|
||||
|
||||
@@ -12,7 +12,7 @@ val dynamicColorPatch = resourcePatch(
|
||||
) {
|
||||
compatibleWith(
|
||||
"com.twitter.android"(
|
||||
"10.84.0-release.0",
|
||||
"10.86.0-release.0",
|
||||
"10.60.0-release.0",
|
||||
"10.48.0-release.0"
|
||||
)
|
||||
|
||||
@@ -13,8 +13,8 @@ fun hookPatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.twitter.android"(
|
||||
// 10.85+ uses Pairip and requires additional changes to work.
|
||||
"10.84.0-release.0",
|
||||
// Only v10.85 uses Pairip and requires additional changes to work.
|
||||
"10.86.0-release.0",
|
||||
// Confirmed to not show reply ads. Slightly newer versions may also work.
|
||||
"10.60.0-release.0",
|
||||
"10.48.0-release.0"
|
||||
|
||||
@@ -39,7 +39,7 @@ val changeLinkSharingDomainPatch = bytecodePatch(
|
||||
|
||||
compatibleWith(
|
||||
"com.twitter.android"(
|
||||
"10.84.0-release.0",
|
||||
"10.86.0-release.0",
|
||||
"10.60.0-release.0",
|
||||
"10.48.0-release.0"
|
||||
)
|
||||
|
||||
@@ -10,7 +10,7 @@ val sanitizeSharingLinksPatch = bytecodePatch(
|
||||
) {
|
||||
compatibleWith(
|
||||
"com.twitter.android"(
|
||||
"10.84.0-release.0",
|
||||
"10.86.0-release.0",
|
||||
"10.60.0-release.0",
|
||||
"10.48.0-release.0"
|
||||
)
|
||||
|
||||
@@ -84,7 +84,8 @@ val hideAdsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -31,7 +31,8 @@ val hideGetPremiumPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -29,7 +29,8 @@ val videoAdsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -59,7 +59,8 @@ val copyVideoUrlPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -30,7 +30,8 @@ val removeViewerDiscretionDialogPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
val extensionMethodDescriptor =
|
||||
|
||||
@@ -74,7 +74,8 @@ val downloadsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -10,10 +10,15 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.util.findFreeRegister
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/SeekbarTappingPatch;"
|
||||
|
||||
val enableSeekbarTappingPatch = bytecodePatch(
|
||||
description = "Adds an option to enable tap to seek on the seekbar of the video player.",
|
||||
) {
|
||||
@@ -31,38 +36,36 @@ val enableSeekbarTappingPatch = bytecodePatch(
|
||||
)
|
||||
|
||||
// Find the required methods to tap the seekbar.
|
||||
val patternMatch = onTouchEventHandlerFingerprint.patternMatch!!
|
||||
|
||||
fun getReference(index: Int) = onTouchEventHandlerFingerprint.method.getInstruction<ReferenceInstruction>(index)
|
||||
val seekbarTappingMethods = onTouchEventHandlerFingerprint.let {
|
||||
fun getMethodReference(index: Int) = it.method.getInstruction<ReferenceInstruction>(index)
|
||||
.reference as MethodReference
|
||||
|
||||
val seekbarTappingMethods = buildMap {
|
||||
put("N", getReference(patternMatch.startIndex))
|
||||
put("O", getReference(patternMatch.endIndex))
|
||||
listOf(
|
||||
getMethodReference(it.patternMatch!!.startIndex),
|
||||
getMethodReference(it.patternMatch!!.endIndex)
|
||||
)
|
||||
}
|
||||
|
||||
val insertIndex = seekbarTappingFingerprint.patternMatch!!.endIndex - 1
|
||||
|
||||
seekbarTappingFingerprint.method.apply {
|
||||
val thisInstanceRegister = getInstruction<Instruction35c>(insertIndex - 1).registerC
|
||||
val pointIndex = indexOfNewPointInstruction(this)
|
||||
val invokeIndex = indexOfFirstInstructionOrThrow(pointIndex, Opcode.INVOKE_VIRTUAL)
|
||||
val insertIndex = invokeIndex + 1
|
||||
|
||||
val freeRegister = 0
|
||||
val xAxisRegister = 2
|
||||
val thisInstanceRegister = getInstruction<FiveRegisterInstruction>(invokeIndex).registerC
|
||||
val xAxisRegister = this.getInstruction<FiveRegisterInstruction>(pointIndex).registerD
|
||||
val freeRegister = findFreeRegister(insertIndex, thisInstanceRegister, xAxisRegister)
|
||||
|
||||
val oMethod = seekbarTappingMethods["O"]!!
|
||||
val nMethod = seekbarTappingMethods["N"]!!
|
||||
|
||||
fun MethodReference.toInvokeInstructionString() =
|
||||
"invoke-virtual { v$thisInstanceRegister, v$xAxisRegister }, $this"
|
||||
val oMethod = seekbarTappingMethods[0]
|
||||
val nMethod = seekbarTappingMethods[1]
|
||||
|
||||
addInstructionsWithLabels(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static { }, Lapp/revanced/extension/youtube/patches/SeekbarTappingPatch;->seekbarTappingEnabled()Z
|
||||
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->seekbarTappingEnabled()Z
|
||||
move-result v$freeRegister
|
||||
if-eqz v$freeRegister, :disabled
|
||||
${oMethod.toInvokeInstructionString()}
|
||||
${nMethod.toInvokeInstructionString()}
|
||||
invoke-virtual { v$thisInstanceRegister, v$xAxisRegister }, $oMethod
|
||||
invoke-virtual { v$thisInstanceRegister, v$xAxisRegister }, $nMethod
|
||||
""",
|
||||
ExternalLabel("disabled", getInstruction(insertIndex)),
|
||||
)
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package app.revanced.patches.youtube.interaction.seekbar
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.containsLiteralInstruction
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.indexOfFirstInstructionReversed
|
||||
import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.StringReference
|
||||
|
||||
internal val swipingUpGestureParentFingerprint = fingerprint {
|
||||
@@ -101,14 +105,17 @@ internal val seekbarTappingFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("Z")
|
||||
parameters("L")
|
||||
opcodes(
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
// Insert seekbar tapping instructions here.
|
||||
Opcode.RETURN,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
)
|
||||
literal { Integer.MAX_VALUE.toLong() }
|
||||
custom { method, _ ->
|
||||
method.name == "onTouchEvent"
|
||||
&& method.containsLiteralInstruction(Integer.MAX_VALUE.toLong())
|
||||
&& indexOfNewPointInstruction(method) >= 0
|
||||
}
|
||||
}
|
||||
|
||||
internal fun indexOfNewPointInstruction(method: Method) = method.indexOfFirstInstructionReversed {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.definingClass == "Landroid/graphics/Point;"
|
||||
&& reference.name == "<init>"
|
||||
}
|
||||
|
||||
internal val slideToSeekFingerprint = fingerprint {
|
||||
|
||||
@@ -26,6 +26,7 @@ val seekbarPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -87,7 +87,8 @@ val swipeControlsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -8,7 +8,9 @@ import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.shared.subtitleButtonControllerFingerprint
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/DisableAutoCaptionsPatch;"
|
||||
|
||||
val autoCaptionsPatch = bytecodePatch(
|
||||
name = "Disable auto captions",
|
||||
@@ -28,42 +30,41 @@ val autoCaptionsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("youtube", "layout.autocaptions.autoCaptionsPatch")
|
||||
|
||||
PreferenceScreen.PLAYER.addPreferences(
|
||||
SwitchPreference("revanced_auto_captions"),
|
||||
SwitchPreference("revanced_disable_auto_captions"),
|
||||
)
|
||||
|
||||
subtitleTrackFingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->disableAutoCaptions()Z
|
||||
move-result v0
|
||||
if-eqz v0, :auto_captions_enabled
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
:auto_captions_enabled
|
||||
nop
|
||||
"""
|
||||
)
|
||||
|
||||
mapOf(
|
||||
startVideoInformerFingerprint to 0,
|
||||
subtitleButtonControllerFingerprint to 1,
|
||||
storyboardRendererDecoderRecommendedLevelFingerprint to 1
|
||||
).forEach { (fingerprint, enabled) ->
|
||||
fingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x$enabled
|
||||
sput-boolean v0, Lapp/revanced/extension/youtube/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
|
||||
""",
|
||||
invoke-static { v0 }, $EXTENSION_CLASS_DESCRIPTOR->setCaptionsButtonStatus(Z)V
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
subtitleTrackFingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static {}, Lapp/revanced/extension/youtube/patches/DisableAutoCaptionsPatch;->autoCaptionsEnabled()Z
|
||||
move-result v0
|
||||
if-eqz v0, :auto_captions_enabled
|
||||
sget-boolean v0, Lapp/revanced/extension/youtube/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
|
||||
if-nez v0, :auto_captions_enabled
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
:auto_captions_enabled
|
||||
nop
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,13 @@ internal val startVideoInformerFingerprint = fingerprint {
|
||||
strings("pc")
|
||||
}
|
||||
|
||||
internal val storyboardRendererDecoderRecommendedLevelFingerprint = fingerprint {
|
||||
returns("V")
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
parameters("L")
|
||||
strings("#-1#")
|
||||
}
|
||||
|
||||
internal val subtitleTrackFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("Z")
|
||||
@@ -28,6 +35,6 @@ internal val subtitleTrackFingerprint = fingerprint {
|
||||
)
|
||||
strings("DISABLE_CAPTIONS_OPTION")
|
||||
custom { _, classDef ->
|
||||
classDef.endsWith("SubtitleTrack;")
|
||||
classDef.endsWith("/SubtitleTrack;")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,8 @@ val customBrandingPatch = resourcePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
val appName by stringOption(
|
||||
|
||||
@@ -47,6 +47,7 @@ val changeHeaderPatch = resourcePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -28,7 +28,8 @@ val hideButtonsPatch = resourcePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -46,7 +46,8 @@ val navigationButtonsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -60,7 +60,8 @@ val hidePlayerOverlayButtonsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -39,7 +39,8 @@ val changeFormFactorPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -65,7 +65,8 @@ val hideEndscreenCardsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -37,7 +37,8 @@ val hideEndScreenSuggestedVideoPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -35,7 +35,8 @@ val disableFullscreenAmbientModePatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -16,9 +16,22 @@ internal val hideShowMoreButtonFingerprint = fingerprint {
|
||||
}
|
||||
|
||||
/**
|
||||
* 20.07+
|
||||
* 20.12+
|
||||
*/
|
||||
internal val parseElementFromBufferFingerprint = fingerprint {
|
||||
parameters("L", "L", "[B", "L", "L")
|
||||
opcodes(
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
)
|
||||
strings("Failed to parse Element") // String is a partial match.
|
||||
}
|
||||
|
||||
/**
|
||||
* 20.07+
|
||||
*/
|
||||
internal val parseElementFromBufferLegacy2007Fingerprint = fingerprint {
|
||||
parameters("L", "L", "[B", "L", "L")
|
||||
opcodes(
|
||||
Opcode.IGET_OBJECT,
|
||||
@@ -29,7 +42,10 @@ internal val parseElementFromBufferFingerprint = fingerprint {
|
||||
strings("Failed to parse Element") // String is a partial match.
|
||||
}
|
||||
|
||||
internal val parseElementFromBufferLegacyFingerprint = fingerprint {
|
||||
/**
|
||||
* 19.01 - 20.06
|
||||
*/
|
||||
internal val parseElementFromBufferLegacy1901Fingerprint = fingerprint {
|
||||
parameters("L", "L", "[B", "L", "L")
|
||||
opcodes(
|
||||
Opcode.IGET_OBJECT,
|
||||
|
||||
@@ -21,6 +21,7 @@ import app.revanced.patches.youtube.misc.litho.filter.addLithoFilter
|
||||
import app.revanced.patches.youtube.misc.litho.filter.lithoFilterPatch
|
||||
import app.revanced.patches.youtube.misc.navigation.navigationBarHookPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_07_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_09_or_greater
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.util.findFreeRegister
|
||||
@@ -132,7 +133,8 @@ val hideLayoutComponentsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
@@ -247,8 +249,9 @@ val hideLayoutComponentsPatch = bytecodePatch(
|
||||
|
||||
// region Mix playlists
|
||||
|
||||
(if (is_20_07_or_greater) parseElementFromBufferFingerprint
|
||||
else parseElementFromBufferLegacyFingerprint).let {
|
||||
(if (is_20_09_or_greater) parseElementFromBufferFingerprint
|
||||
else if (is_20_07_or_greater) parseElementFromBufferLegacy2007Fingerprint
|
||||
else parseElementFromBufferLegacy1901Fingerprint).let {
|
||||
it.method.apply {
|
||||
val byteArrayParameter = "p3"
|
||||
val startIndex = it.patternMatch!!.startIndex
|
||||
|
||||
@@ -63,7 +63,8 @@ val hideInfoCardsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -30,7 +30,8 @@ val hidePlayerFlyoutMenuPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -35,7 +35,8 @@ val disableRollingNumberAnimationPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -178,7 +178,8 @@ val hideShortsComponentsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
hideShortsAppShortcutOption()
|
||||
|
||||
@@ -1,24 +1,16 @@
|
||||
package app.revanced.patches.youtube.layout.hide.time
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal val timeCounterFingerprint = fingerprint(
|
||||
fuzzyPatternScanThreshold = 1,
|
||||
) {
|
||||
returns("V")
|
||||
internal val timeCounterFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
parameters()
|
||||
opcodes(
|
||||
Opcode.SUB_LONG_2ADDR,
|
||||
Opcode.IGET_WIDE,
|
||||
Opcode.SUB_LONG_2ADDR,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.IGET_WIDE,
|
||||
Opcode.IGET_WIDE,
|
||||
Opcode.SUB_LONG_2ADDR
|
||||
)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@ val hideTimestampPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstructio
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||
@@ -172,7 +173,8 @@ val miniplayerPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
@@ -346,7 +348,12 @@ val miniplayerPatch = bytecodePatch(
|
||||
// endregion
|
||||
|
||||
// region Legacy tablet miniplayer hooks.
|
||||
val appNameStringIndex = miniplayerOverrideFingerprint.stringMatches!!.first().index + 2
|
||||
val appNameStringIndex = miniplayerOverrideFingerprint.let {
|
||||
it.method.indexOfFirstInstructionOrThrow(it.stringMatches!!.first().index) {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.parameterTypes?.firstOrNull() == "Landroid/content/Context;"
|
||||
}
|
||||
}
|
||||
navigate(miniplayerOverrideFingerprint.originalMethod).to(appNameStringIndex).stop().apply {
|
||||
findReturnIndicesReversed().forEach { index -> insertLegacyTabletMiniplayerOverride(index) }
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@ val playerPopupPanelsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -18,7 +18,8 @@ val playerControlsBackgroundPatch = resourcePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -27,6 +27,7 @@ internal val exitFullscreenPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ val openVideosFullscreenPatch = bytecodePatch(
|
||||
"com.google.android.youtube"(
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -58,7 +58,8 @@ val customPlayerOverlayOpacityPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.revanced.patches.youtube.layout.returnyoutubedislike
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
@@ -121,3 +122,12 @@ internal val textComponentLookupFingerprint = fingerprint {
|
||||
parameters("L")
|
||||
strings("…")
|
||||
}
|
||||
|
||||
internal const val LITHO_NEW_TEXT_COMPONENT_FEATURE_FLAG = 45675738L
|
||||
|
||||
internal val textComponentFeatureFlagFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.FINAL)
|
||||
returns("Z")
|
||||
parameters()
|
||||
literal { LITHO_NEW_TEXT_COMPONENT_FEATURE_FLAG }
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import app.revanced.patches.youtube.misc.litho.filter.addLithoFilter
|
||||
import app.revanced.patches.youtube.misc.litho.filter.lithoFilterPatch
|
||||
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_33_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_07_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_10_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.addSettingPreference
|
||||
@@ -59,7 +60,8 @@ val returnYouTubeDislikePatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
@@ -174,6 +176,14 @@ val returnYouTubeDislikePatch = bytecodePatch(
|
||||
// Filter that parses the video id from the UI
|
||||
addLithoFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
if (is_20_07_or_greater) {
|
||||
// Turn off a/b flag that enables new code for creating litho spans.
|
||||
// If enabled then the litho text span hook is never called.
|
||||
// Target code is very obfuscated and exactly what the code does is not clear.
|
||||
// Return late so debug patch logs if the flag is enabled.
|
||||
textComponentFeatureFlagFingerprint.method.returnLate(false)
|
||||
}
|
||||
|
||||
// Player response video id is needed to search for the video ids in Shorts litho components.
|
||||
hookPlayerResponseVideoId("$FILTER_CLASS_DESCRIPTOR->newPlayerResponseVideoId(Ljava/lang/String;Z)V")
|
||||
|
||||
|
||||
@@ -35,7 +35,8 @@ val wideSearchbarPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -39,7 +39,8 @@ val shortsAutoplayPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -47,7 +47,8 @@ val openShortsInRegularPlayerPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -20,12 +20,6 @@ internal val appendTimeFingerprint = fingerprint {
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_NEZ,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.CHECK_CAST,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.RETURN_VOID,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,8 @@ val sponsorBlockPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -64,7 +64,8 @@ val spoofAppVersionPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -35,7 +35,8 @@ val changeStartPagePatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -40,7 +40,8 @@ val disableResumingShortsOnStartupPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -10,13 +10,6 @@ internal val lithoThemeFingerprint = fingerprint {
|
||||
returns("V")
|
||||
parameters("Landroid/graphics/Rect;")
|
||||
opcodes(
|
||||
Opcode.APUT,
|
||||
Opcode.NEW_INSTANCE,
|
||||
Opcode.INVOKE_DIRECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.IGET,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
|
||||
@@ -223,7 +223,8 @@ val themePatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -39,7 +39,8 @@ val alternativeThumbnailsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -33,7 +33,8 @@ val bypassImageRegionRestrictionsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -29,7 +29,8 @@ val announcementsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -30,7 +30,8 @@ val autoRepeatPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -57,7 +57,8 @@ val backgroundPlaybackPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -40,7 +40,8 @@ val enableDebuggingPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -30,7 +30,8 @@ val spoofDeviceDimensionsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -27,7 +27,8 @@ val checkWatchHistoryDomainNameResolutionPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -9,9 +9,7 @@ internal val onBackPressedFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
opcodes(Opcode.RETURN_VOID)
|
||||
custom { method, classDef ->
|
||||
method.name == "onBackPressed" &&
|
||||
// Old versions of YouTube called this class "WatchWhileActivity" instead.
|
||||
(classDef.endsWith("MainActivity;") || classDef.endsWith("WatchWhileActivity;"))
|
||||
method.name == "onBackPressed" && classDef.endsWith("MainActivity;")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +25,9 @@ internal val scrollPositionFingerprint = fingerprint {
|
||||
strings("scroll_position")
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves using class found in [recyclerViewTopScrollingParentFingerprint].
|
||||
*/
|
||||
internal val recyclerViewTopScrollingFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
|
||||
@@ -41,7 +41,8 @@ val gmsCoreSupportPatch = gmsCoreSupportPatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,8 @@ val bypassURLRedirectsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -47,7 +47,8 @@ val openLinksExternallyPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -47,11 +47,7 @@ internal val mainActivityOnBackPressedFingerprint = fingerprint {
|
||||
returns("V")
|
||||
parameters()
|
||||
custom { method, classDef ->
|
||||
val matchesClass = classDef.endsWith("MainActivity;") ||
|
||||
// Old versions of YouTube called this class "WatchWhileActivity" instead.
|
||||
classDef.endsWith("WatchWhileActivity;")
|
||||
|
||||
matchesClass && method.name == "onBackPressed"
|
||||
method.name == "onBackPressed" && classDef.endsWith("MainActivity;")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,10 @@ var is_20_09_or_greater = false
|
||||
private set
|
||||
var is_20_10_or_greater = false
|
||||
private set
|
||||
var is_20_14_or_greater = false
|
||||
private set
|
||||
var is_20_15_or_greater = false
|
||||
private set
|
||||
|
||||
val versionCheckPatch = resourcePatch(
|
||||
description = "Uses the Play Store service version to find the major/minor version of the YouTube target app.",
|
||||
@@ -98,5 +102,7 @@ val versionCheckPatch = resourcePatch(
|
||||
is_20_07_or_greater = 250805000 <= playStoreServicesVersion
|
||||
is_20_09_or_greater = 251006000 <= playStoreServicesVersion
|
||||
is_20_10_or_greater = 251105000 <= playStoreServicesVersion
|
||||
is_20_14_or_greater = 251505000 <= playStoreServicesVersion
|
||||
is_20_15_or_greater = 251605000 <= playStoreServicesVersion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,8 @@ val removeTrackingQueryParameterPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -9,6 +9,7 @@ import app.revanced.patches.shared.misc.spoof.spoofVideoStreamsPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_03_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_10_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_14_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
@@ -22,7 +23,8 @@ val spoofVideoStreamsPatch = spoofVideoStreamsPatch({
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
dependsOn(
|
||||
@@ -33,7 +35,8 @@ val spoofVideoStreamsPatch = spoofVideoStreamsPatch({
|
||||
}, {
|
||||
is_19_34_or_greater
|
||||
}, {
|
||||
is_20_10_or_greater
|
||||
// In 20.14 the flag was merged with 20.03 start playback flag.
|
||||
is_20_10_or_greater && !is_20_14_or_greater
|
||||
}, {
|
||||
is_20_03_or_greater
|
||||
}, {
|
||||
|
||||
@@ -27,7 +27,8 @@ val zoomHapticsPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -33,8 +33,7 @@ internal val mainActivityFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
parameters()
|
||||
custom { _, classDef ->
|
||||
// Old versions of YouTube called this class "WatchWhileActivity" instead.
|
||||
classDef.endsWith("MainActivity;") || classDef.endsWith("WatchWhileActivity;")
|
||||
classDef.endsWith("MainActivity;")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,12 +41,7 @@ internal val mainActivityOnCreateFingerprint = fingerprint {
|
||||
returns("V")
|
||||
parameters("Landroid/os/Bundle;")
|
||||
custom { method, classDef ->
|
||||
method.name == "onCreate" &&
|
||||
(
|
||||
classDef.endsWith("MainActivity;") ||
|
||||
// Old versions of YouTube called this class "WatchWhileActivity" instead.
|
||||
classDef.endsWith("WatchWhileActivity;")
|
||||
)
|
||||
method.name == "onCreate" && classDef.endsWith("MainActivity;")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,8 @@ val forceOriginalAudioPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -34,7 +34,8 @@ val disableHdrPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
),
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -117,13 +117,6 @@ internal val playbackSpeedMenuSpeedChangedFingerprint = fingerprint {
|
||||
returns("L")
|
||||
parameters("L")
|
||||
opcodes(
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.IGET,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.SGET_OBJECT,
|
||||
|
||||
@@ -5,9 +5,35 @@ import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import org.stringtemplate.v4.compiler.Bytecode.instructions
|
||||
|
||||
/**
|
||||
* For targets 20.10 and later.
|
||||
* For targets 20.15 and later.
|
||||
*/
|
||||
internal val playerParameterBuilderFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("L")
|
||||
parameters(
|
||||
"Ljava/lang/String;", // VideoId.
|
||||
"[B",
|
||||
"Ljava/lang/String;", // Player parameters proto buffer.
|
||||
"Ljava/lang/String;",
|
||||
"I",
|
||||
"Z",
|
||||
"I",
|
||||
"L",
|
||||
"Ljava/util/Set;",
|
||||
"Ljava/lang/String;",
|
||||
"Ljava/lang/String;",
|
||||
"L",
|
||||
"Z", // Appears to indicate if the video id is being opened or is currently playing.
|
||||
"Z",
|
||||
"Z"
|
||||
)
|
||||
strings("psps")
|
||||
}
|
||||
|
||||
/**
|
||||
* For targets 20.10 to 20.14.
|
||||
*/
|
||||
internal val playerParameterBuilder2010Fingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("L")
|
||||
parameters(
|
||||
|
||||
@@ -9,6 +9,7 @@ import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_23_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_02_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_10_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_15_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
|
||||
private val hooks = mutableSetOf<Hook>()
|
||||
@@ -39,9 +40,12 @@ val playerResponseMethodHookPatch = bytecodePatch {
|
||||
|
||||
execute {
|
||||
val fingerprint : Fingerprint
|
||||
if (is_20_10_or_greater) {
|
||||
if (is_20_15_or_greater) {
|
||||
parameterIsShortAndOpeningOrPlaying = 13
|
||||
fingerprint = playerParameterBuilderFingerprint
|
||||
} else if (is_20_10_or_greater) {
|
||||
parameterIsShortAndOpeningOrPlaying = 13
|
||||
fingerprint = playerParameterBuilder2010Fingerprint
|
||||
} else if (is_20_02_or_greater) {
|
||||
parameterIsShortAndOpeningOrPlaying = 12
|
||||
fingerprint = playerParameterBuilder2002Fingerprint
|
||||
|
||||
@@ -29,6 +29,7 @@ val videoQualityPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ val playbackSpeedPatch = bytecodePatch(
|
||||
"19.43.41",
|
||||
"19.47.53",
|
||||
"20.07.39",
|
||||
"20.12.46",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -698,29 +698,54 @@ fun BytecodePatchContext.forEachLiteralValueInstruction(
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the method early.
|
||||
* Overrides the first instruction of a method with a constant return value.
|
||||
* None of the method code will ever execute.
|
||||
*/
|
||||
fun MutableMethod.returnEarly(bool: Boolean = false) {
|
||||
fun MutableMethod.returnEarly(overrideValue: Boolean = false) = overrideReturnValue(overrideValue, false)
|
||||
|
||||
/**
|
||||
* Overrides all return statements with a constant value.
|
||||
* All method code is executed the same as unpatched.
|
||||
*
|
||||
* @see returnEarly
|
||||
*/
|
||||
internal fun MutableMethod.returnLate(overrideValue: Boolean = false) = overrideReturnValue(overrideValue, true)
|
||||
|
||||
private fun MutableMethod.overrideReturnValue(bool: Boolean, returnLate: Boolean) {
|
||||
val const = if (bool) "0x1" else "0x0"
|
||||
|
||||
val stringInstructions = when (returnType.first()) {
|
||||
'L' ->
|
||||
val instructions = when (returnType.first()) {
|
||||
'L' -> {
|
||||
"""
|
||||
const/4 v0, $const
|
||||
return-object v0
|
||||
"""
|
||||
}
|
||||
|
||||
'V' -> "return-void"
|
||||
'I', 'Z' ->
|
||||
'V' -> {
|
||||
if (returnLate) throw IllegalArgumentException("Cannot return late for method of void type")
|
||||
"return-void"
|
||||
}
|
||||
|
||||
'I', 'Z' -> {
|
||||
"""
|
||||
const/4 v0, $const
|
||||
return v0
|
||||
"""
|
||||
}
|
||||
|
||||
else -> throw Exception("Return type is not supported: $this")
|
||||
}
|
||||
|
||||
addInstructions(0, stringInstructions)
|
||||
if (returnLate) {
|
||||
findInstructionIndicesReversed {
|
||||
opcode == RETURN || opcode == RETURN_OBJECT
|
||||
}.forEach { index ->
|
||||
addInstructionsAtControlFlowLabel(index, instructions)
|
||||
}
|
||||
} else {
|
||||
addInstructions(0, instructions)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -479,9 +479,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_swipe_change_video_summary_off">لن يؤدي التمرير في وضع ملء الشاشة إلى التغيير للفيديو التالي/السابق</string>
|
||||
</patch>
|
||||
<patch id="layout.autocaptions.autoCaptionsPatch">
|
||||
<string name="revanced_auto_captions_title">تعطيل التَّرْجَمَة التلقائية</string>
|
||||
<string name="revanced_auto_captions_summary_on">تم تعطيل التَّرْجَمَة التلقائية</string>
|
||||
<string name="revanced_auto_captions_summary_off">تم تمكين التَّرْجَمَة التلقائية</string>
|
||||
<string name="revanced_disable_auto_captions_title">تعطيل التَّرْجَمَة التلقائية</string>
|
||||
<string name="revanced_disable_auto_captions_summary_on">تم تعطيل التَّرْجَمَة التلقائية</string>
|
||||
<string name="revanced_disable_auto_captions_summary_off">تم تمكين التَّرْجَمَة التلقائية</string>
|
||||
</patch>
|
||||
<patch id="layout.buttons.action.hideButtonsPatch">
|
||||
<string name="revanced_hide_buttons_screen_title">أزرار الإجراء</string>
|
||||
@@ -832,8 +832,8 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_ryd_compact_layout_summary_on">زر أعجبني مصمم لأدنى عرض</string>
|
||||
<string name="revanced_ryd_compact_layout_summary_off">زر أعجبني مصمم لأفضل مظهر</string>
|
||||
<string name="revanced_ryd_estimated_like_title">عرض الإعجابات المقدرة</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_on">يتم عرض الإعجابات المقدرة</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_off">تم إخفاء الإعجابات المقدرة</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_on">يتم عرض عدد تقديري للإعجابات في مقاطع الفيديو التي تم تعطيل الإعجابات فيها</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_off">لا يتم عرض عدد الإعجابات المقدرة</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_title">عرض ملاحظة إذا كان API غير متاح</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_summary_on">يتم عرض الملاحظة في حالة عدم توفر Return YouTube Dislike</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_summary_off">لا يتم عرض الملاحظة في حالة عدم توفر Return YouTube Dislike</string>
|
||||
|
||||
@@ -466,6 +466,8 @@ Ekranın sağ tərəfində düzünə sürüşdürərək səs səviyyəsini tənz
|
||||
<string name="revanced_swipe_overlay_background_opacity_invalid_toast">Sürüşmə qeyri-şəffaflığı 0-100 arası olmalıdır</string>
|
||||
<string name="revanced_swipe_threshold_title">Sürüşdürmə böyüklük həddi</string>
|
||||
<string name="revanced_swipe_threshold_summary">Sürüşdürmənin icra edilməsi üçün son dəyər</string>
|
||||
<string name="revanced_swipe_volume_sensitivity_title">Səs səviyyəsin sürüşdürmə təzyiqi</string>
|
||||
<string name="revanced_swipe_volume_sensitivity_summary">Hər sürüşdürmədə səs səviyyəsi nə qədər dəyişir</string>
|
||||
<string name="revanced_swipe_show_circular_overlay_title">Dairəvi örtüyü göstər</string>
|
||||
<string name="revanced_swipe_show_circular_overlay_summary_on">Dairəvi örtük göstərilir</string>
|
||||
<string name="revanced_swipe_show_circular_overlay_summary_off">Düzünə örtük göstərilir</string>
|
||||
@@ -477,9 +479,7 @@ Ekranın sağ tərəfində düzünə sürüşdürərək səs səviyyəsini tənz
|
||||
<string name="revanced_swipe_change_video_summary_off">Tam ekran rejimində sürüşdürmə növbəti/əvvəlki videoya ötürməyəcək</string>
|
||||
</patch>
|
||||
<patch id="layout.autocaptions.autoCaptionsPatch">
|
||||
<string name="revanced_auto_captions_title">Avtomatik titrləri qeyri-aktiv et</string>
|
||||
<string name="revanced_auto_captions_summary_on">Avtomatik titrlər qeyri-aktivdir</string>
|
||||
<string name="revanced_auto_captions_summary_off">Avtomatik titrlər aktivdir</string>
|
||||
<string name="revanced_disable_auto_captions_title">Avtomatik titrləri qeyri-aktiv et</string>
|
||||
</patch>
|
||||
<patch id="layout.buttons.action.hideButtonsPatch">
|
||||
<string name="revanced_hide_buttons_screen_title">Fəaliyyət düymələri</string>
|
||||
@@ -829,8 +829,6 @@ Məhdudiyyət: Bəyənməmələr gizli rejimdə görünməyə bilər"</string>
|
||||
<string name="revanced_ryd_compact_layout_summary_on">Daha kiçik en üçün hazırlanmış Bəyən düyməsi</string>
|
||||
<string name="revanced_ryd_compact_layout_summary_off">Ən yaxşı görünüş üçün tərtib edilmiş Bəyən düyməsi</string>
|
||||
<string name="revanced_ryd_estimated_like_title">Təxmini bəyənmələri göstər</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_on">Təxmini bəyənmələr göstərilir</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_off">Təxmini bəyənmələr gizlədilir</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_title">API əlçatan deyilsə ani bildiriş göstər</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_summary_on">Return YouTube Dislike əlçatan deyilsə ani bildiriş göstər</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_summary_off">Return YouTube Dislike əlçatan deyilsə ani bildiriş göstərmə</string>
|
||||
|
||||
@@ -479,9 +479,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_swipe_change_video_summary_off">Правядзенне пальцам у рэжыме поўнага экрана не зьменіць відэа на наступнае/папярэдняе</string>
|
||||
</patch>
|
||||
<patch id="layout.autocaptions.autoCaptionsPatch">
|
||||
<string name="revanced_auto_captions_title">Адключыць аўтаматычныя цітры</string>
|
||||
<string name="revanced_auto_captions_summary_on">Аўтаматычныя цітры адключаны</string>
|
||||
<string name="revanced_auto_captions_summary_off">Аўтаматычныя цітры ўключаны</string>
|
||||
<string name="revanced_disable_auto_captions_title">Адключыць аўтаматычныя цітры</string>
|
||||
<string name="revanced_disable_auto_captions_summary_on">Аўтаматычныя субцітры адключаны</string>
|
||||
<string name="revanced_disable_auto_captions_summary_off">Аўтаматычныя субцітры ўключаны</string>
|
||||
</patch>
|
||||
<patch id="layout.buttons.action.hideButtonsPatch">
|
||||
<string name="revanced_hide_buttons_screen_title">Кнопкі дзеянняў</string>
|
||||
@@ -832,8 +832,8 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_ryd_compact_layout_summary_on">Кнопка \"Падабаецца\" ў стылі мінімальнай шырыні</string>
|
||||
<string name="revanced_ryd_compact_layout_summary_off">Кнопка \"Падабаецца\", аформленая для лепшага выгляду</string>
|
||||
<string name="revanced_ryd_estimated_like_title">Паказваць прыблізную колькасць падабаек</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_on">Паказана прыблізная колькасць падабаек</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_off">Прыблізная колькасць падабаек схавана</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_on">У відэа з адключанымі лайкамі паказваецца прыблізная колькасць лайкаў</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_off">Прыблізныя лайкі не паказваюцца</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_title">Паказаць тост, калі API недаступны</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_summary_on">Тост паказваецца, калі функцыя \"Вярнуць не падабаецца YouTube\" недаступная</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_summary_off">Тост не паказваецца, калі функцыя \"Вярнуць не падабаецца YouTube\" недаступная</string>
|
||||
|
||||
@@ -479,9 +479,9 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_swipe_change_video_summary_off">Плъзването в режим на цял екран няма да превключи към следващото/предишно видео</string>
|
||||
</patch>
|
||||
<patch id="layout.autocaptions.autoCaptionsPatch">
|
||||
<string name="revanced_auto_captions_title">Автоматични Субтитри</string>
|
||||
<string name="revanced_auto_captions_summary_on">Автоматичните Субтитри са деактивирани</string>
|
||||
<string name="revanced_auto_captions_summary_off">Автоматичните Субтитри са активирани</string>
|
||||
<string name="revanced_disable_auto_captions_title">Автоматични Субтитри</string>
|
||||
<string name="revanced_disable_auto_captions_summary_on">Автоматичните надписи са деактивирани</string>
|
||||
<string name="revanced_disable_auto_captions_summary_off">Автоматичните надписи са активирани</string>
|
||||
</patch>
|
||||
<patch id="layout.buttons.action.hideButtonsPatch">
|
||||
<string name="revanced_hide_buttons_screen_title">Бутони за действия</string>
|
||||
@@ -832,8 +832,8 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_ryd_compact_layout_summary_on">Включен компактен бутон \"Харесва ми\"</string>
|
||||
<string name="revanced_ryd_compact_layout_summary_off">Най-добър изглед на бутона за харесване</string>
|
||||
<string name="revanced_ryd_estimated_like_title">Показване на прогнозни харесвания</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_on">Показват се прогнозни харесвания</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_off">Прогнозните харесвания са скрити</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_on">Видеата с деактивирани харесвания показват прогнозен брой харесвания</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_off">Прогнозните харесвания не се показват</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_title">Показване на известие, ако API не е наличен</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_summary_on">Показва известие, ако Return YouTube Dislike не е наличен</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_summary_off">Не се показва известие, ако ReturnYouTube Dislike не е наличен</string>
|
||||
|
||||
@@ -479,9 +479,9 @@ MicroG-এর জন্য ব্যাটারি অপ্টিমাইজ
|
||||
<string name="revanced_swipe_change_video_summary_off">ফুলস্ক্রিন মোডে সোয়াইপ করলে পরবর্তী /পূর্ববর্তী ভিডিওতে পরিবর্তন হবে না</string>
|
||||
</patch>
|
||||
<patch id="layout.autocaptions.autoCaptionsPatch">
|
||||
<string name="revanced_auto_captions_title">স্বয়ংক্রিয় ক্যাপশন বন্ধ করুন</string>
|
||||
<string name="revanced_auto_captions_summary_on">অটো ক্যাপশন বন্ধ করা হয়েছে</string>
|
||||
<string name="revanced_auto_captions_summary_off">অটো ক্যাপশন চালু করা হয়েছে</string>
|
||||
<string name="revanced_disable_auto_captions_title">স্বয়ংক্রিয় ক্যাপশন বন্ধ করুন</string>
|
||||
<string name="revanced_disable_auto_captions_summary_on">অটো ক্যাপশনগুলি নিষ্ক্রিয় করা হয়েছে</string>
|
||||
<string name="revanced_disable_auto_captions_summary_off">অটো ক্যাপশনগুলি সক্রিয় করা হয়েছে</string>
|
||||
</patch>
|
||||
<patch id="layout.buttons.action.hideButtonsPatch">
|
||||
<string name="revanced_hide_buttons_screen_title">অ্যাকশন বোতাম</string>
|
||||
@@ -832,8 +832,8 @@ YouTube সেটিংসে অটো প্লে পরিবর্তন
|
||||
<string name="revanced_ryd_compact_layout_summary_on">পছন্দ বোতামটি ন্যূনতম প্রস্থের জন্য সাজানো হয়েছে</string>
|
||||
<string name="revanced_ryd_compact_layout_summary_off">পছন্দ বোতামটি সেরা চেহারার জন্য সাজানো হয়েছে</string>
|
||||
<string name="revanced_ryd_estimated_like_title">অনুমানিত লাইক দেখান</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_on">অনুমানিত লাইক দেখানো হয়েছে</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_off">অনুমানিত লাইক লুকানো হয়েছে</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_on">পছন্দগুলি অক্ষম করা ভিডিওগুলি একটি আনুমানিক পছন্দের সংখ্যা দেখায়</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_off">আনুমানিক পছন্দগুলি দেখানো হয় না</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_title">API উপলভ্য না থাকলে একটি টোস্ট দেখান</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_summary_on">Return YouTube Dislike উপলভ্য না থাকলে টোস্ট দেখানো হবে</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_summary_off">Return YouTube Dislike উপলভ্য না থাকলে টোস্ট দেখানো হবে না</string>
|
||||
|
||||
@@ -479,9 +479,9 @@ Ajusteu el volum lliscant verticalment a la part dreta de la pantalla"</string>
|
||||
<string name="revanced_swipe_change_video_summary_off">Lliscar en mode de pantalla completa no canviarà al vídeo següent/anterior</string>
|
||||
</patch>
|
||||
<patch id="layout.autocaptions.autoCaptionsPatch">
|
||||
<string name="revanced_auto_captions_title">Desactiva els subtítols automàtics</string>
|
||||
<string name="revanced_auto_captions_summary_on">Els subtítols automàtics estan desactivats</string>
|
||||
<string name="revanced_auto_captions_summary_off">Els subtítols automàtics estan activats</string>
|
||||
<string name="revanced_disable_auto_captions_title">Desactiva els subtítols automàtics</string>
|
||||
<string name="revanced_disable_auto_captions_summary_on">Les subtítols Auto estan desactivats</string>
|
||||
<string name="revanced_disable_auto_captions_summary_off">Els subtítols Auto estan habilitats</string>
|
||||
</patch>
|
||||
<patch id="layout.buttons.action.hideButtonsPatch">
|
||||
<string name="revanced_hide_buttons_screen_title">Botons d\'acció</string>
|
||||
@@ -832,8 +832,8 @@ Limitació: és possible que els \"no m'agrada\" no apareguin en mode d'incògni
|
||||
<string name="revanced_ryd_compact_layout_summary_on">Botó \"m\'agrada\" estilitzat per a l\'amplada mínima</string>
|
||||
<string name="revanced_ryd_compact_layout_summary_off">Botó \"m\'agrada\" estilitzat per a la millor aparença</string>
|
||||
<string name="revanced_ryd_estimated_like_title">Mostra els \"m\'agrada\" estimats</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_on">Es mostren els \"m\'agrada\" estimats</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_off">S\'han amagat els \"m\'agrada\" estimats</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_on">Els vídeos amb els \"m\'agrada\" desactivats mostren un recompte de \"m\'agrada\" estimat</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_off">No es mostren els \"m\'agrada\" estimats</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_title">Mostrar una \"toast\" si l\'API no està disponible</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_summary_on">La \"toast\" es mostra si Return YouTube Dislike no està disponible</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_summary_off">La \"toast\" no es mostra si Return YouTube Dislike no està disponible</string>
|
||||
|
||||
@@ -479,9 +479,9 @@ Hlasitost se upravuje svislým přejetím po pravé straně obrazovky"</string>
|
||||
<string name="revanced_swipe_change_video_summary_off">Přejetí prstem v režimu celé obrazovky nebude video měnit na další/předchozí</string>
|
||||
</patch>
|
||||
<patch id="layout.autocaptions.autoCaptionsPatch">
|
||||
<string name="revanced_auto_captions_title">Zakázat automatické titulky</string>
|
||||
<string name="revanced_auto_captions_summary_on">Automatické titulky jsou zakázány</string>
|
||||
<string name="revanced_auto_captions_summary_off">Automatické titulky jsou povoleny</string>
|
||||
<string name="revanced_disable_auto_captions_title">Zakázat automatické titulky</string>
|
||||
<string name="revanced_disable_auto_captions_summary_on">Automatické titulky jsou zakázány</string>
|
||||
<string name="revanced_disable_auto_captions_summary_off">Automatické titulky jsou povoleny</string>
|
||||
</patch>
|
||||
<patch id="layout.buttons.action.hideButtonsPatch">
|
||||
<string name="revanced_hide_buttons_screen_title">Akční tlačítka</string>
|
||||
@@ -832,8 +832,8 @@ Omezení: Počty „Nelíbí se mi“ se nemusí zobrazit v anonymním režimu"<
|
||||
<string name="revanced_ryd_compact_layout_summary_on">Tlačítko lajku stylizované pro minimální šířku</string>
|
||||
<string name="revanced_ryd_compact_layout_summary_off">Tlačítko lajku stylizované pro nejlepší vzhled</string>
|
||||
<string name="revanced_ryd_estimated_like_title">Zobrazit odhadované počty To se mi líbí</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_on">Zobrazují se odhadované počty To se mi líbí</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_off">Odhadované počty To se mi líbí jsou skryté</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_on">U videí s vypnutými hodnoceními se zobrazuje odhadovaný počet hodnocení</string>
|
||||
<string name="revanced_ryd_estimated_like_summary_off">Odhadovaná hodnocení se nezobrazují</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_title">Zobrazit toast, pokud API není dostupné</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_summary_on">Toast se zobrazí, pokud Return YouTube Dislike není dostupný</string>
|
||||
<string name="revanced_ryd_toast_on_connection_error_summary_off">Toast se nezobrazí, pokud Return YouTube Dislike není dostupný</string>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user