mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-04-30 14:44:33 +02:00
chore: Merge branch dev
to main
(#3899)
This commit is contained in:
commit
4d8ff41143
15
CHANGELOG.md
15
CHANGELOG.md
@ -1,3 +1,18 @@
|
|||||||
|
## [5.0.2-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.0.2-dev.1...v5.0.2-dev.2) (2024-11-12)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **YouTube - Player controls:** Show player control buttons with A/B layout ([#3901](https://github.com/ReVanced/revanced-patches/issues/3901)) ([bb526bc](https://github.com/ReVanced/revanced-patches/commit/bb526bc00a384eb808f46267e5802c8e5beaa7d5))
|
||||||
|
|
||||||
|
## [5.0.2-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.0.1...v5.0.2-dev.1) (2024-11-11)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **Sync for Reddit - Fix /s/ links:** Fix patch by using correct fingerprints ([a0ad07e](https://github.com/ReVanced/revanced-patches/commit/a0ad07ef3170dbe1d91ebd40f11d97b63d1c63d0))
|
||||||
|
* **Sync for Reddit - Spoof client:** Fix patch by using correct fingerprints ([5776de3](https://github.com/ReVanced/revanced-patches/commit/5776de3cfbfa62360267eb6026525d2da8c45654))
|
||||||
|
|
||||||
## [5.0.1](https://github.com/ReVanced/revanced-patches/compare/v5.0.0...v5.0.1) (2024-11-11)
|
## [5.0.1](https://github.com/ReVanced/revanced-patches/compare/v5.0.0...v5.0.1) (2024-11-11)
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,4 +53,18 @@ public final class EnableDebuggingPatch {
|
|||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point.
|
||||||
|
*/
|
||||||
|
public static String isStringFeatureFlagEnabled(String value, long flag, String defaultValue) {
|
||||||
|
if (BaseSettings.DEBUG.get() && !defaultValue.equals(value)) {
|
||||||
|
if (featureFlags.putIfAbsent(flag, true) == null) {
|
||||||
|
Logger.printDebug(() -> " string feature is enabled: " + flag
|
||||||
|
+ " value: " + value + (defaultValue.isEmpty() ? "" : " default: " + defaultValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import app.revanced.extension.shared.Logger;
|
|||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class PlayerControlsPatch {
|
public class PlayerControlsPatch {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injection point.
|
* Injection point.
|
||||||
*/
|
*/
|
||||||
@ -41,4 +42,11 @@ public class PlayerControlsPatch {
|
|||||||
public static void fullscreenButtonVisibilityChanged(boolean isVisible) {
|
public static void fullscreenButtonVisibilityChanged(boolean isVisible) {
|
||||||
// Code added during patching.
|
// Code added during patching.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point.
|
||||||
|
*/
|
||||||
|
public static String getPlayerTopControlsLayoutResourceName(String original) {
|
||||||
|
return "default";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
|
|||||||
org.gradle.parallel = true
|
org.gradle.parallel = true
|
||||||
android.useAndroidX = true
|
android.useAndroidX = true
|
||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
version = 5.0.1
|
version = 5.0.2-dev.2
|
||||||
|
@ -1444,10 +1444,12 @@ public final class app/revanced/util/BytecodeUtilsKt {
|
|||||||
public static final fun indexOfFirstInstructionOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/Opcode;)I
|
public static final fun indexOfFirstInstructionOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/Opcode;)I
|
||||||
public static synthetic fun indexOfFirstInstructionOrThrow$default (Lcom/android/tools/smali/dexlib2/iface/Method;ILcom/android/tools/smali/dexlib2/Opcode;ILjava/lang/Object;)I
|
public static synthetic fun indexOfFirstInstructionOrThrow$default (Lcom/android/tools/smali/dexlib2/iface/Method;ILcom/android/tools/smali/dexlib2/Opcode;ILjava/lang/Object;)I
|
||||||
public static synthetic fun indexOfFirstInstructionOrThrow$default (Lcom/android/tools/smali/dexlib2/iface/Method;ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)I
|
public static synthetic fun indexOfFirstInstructionOrThrow$default (Lcom/android/tools/smali/dexlib2/iface/Method;ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)I
|
||||||
|
public static final fun indexOfFirstInstructionReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/Opcode;)I
|
||||||
public static final fun indexOfFirstInstructionReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lcom/android/tools/smali/dexlib2/Opcode;)I
|
public static final fun indexOfFirstInstructionReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lcom/android/tools/smali/dexlib2/Opcode;)I
|
||||||
public static final fun indexOfFirstInstructionReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;)I
|
public static final fun indexOfFirstInstructionReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;)I
|
||||||
public static synthetic fun indexOfFirstInstructionReversed$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 indexOfFirstInstructionReversed$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 indexOfFirstInstructionReversed$default (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)I
|
public static synthetic fun indexOfFirstInstructionReversed$default (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)I
|
||||||
|
public static final fun indexOfFirstInstructionReversedOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/Opcode;)I
|
||||||
public static final fun indexOfFirstInstructionReversedOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lcom/android/tools/smali/dexlib2/Opcode;)I
|
public static final fun indexOfFirstInstructionReversedOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lcom/android/tools/smali/dexlib2/Opcode;)I
|
||||||
public static final fun indexOfFirstInstructionReversedOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;)I
|
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;Lcom/android/tools/smali/dexlib2/Opcode;ILjava/lang/Object;)I
|
||||||
|
@ -63,7 +63,7 @@ val spoofClientPatch = spoofClientPatch(
|
|||||||
val randomName = (0..100000).random()
|
val randomName = (0..100000).random()
|
||||||
val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)"
|
val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)"
|
||||||
|
|
||||||
imgurImageAPIFingerprint.method.replaceInstruction(
|
getUserAgentFingerprint.method.replaceInstruction(
|
||||||
0,
|
0,
|
||||||
"""
|
"""
|
||||||
const-string v0, "$userAgent"
|
const-string v0, "$userAgent"
|
||||||
@ -75,8 +75,8 @@ val spoofClientPatch = spoofClientPatch(
|
|||||||
|
|
||||||
// region Patch Imgur API URL.
|
// region Patch Imgur API URL.
|
||||||
|
|
||||||
val apiUrlIndex = getUserAgentFingerprint.stringMatches!!.first().index
|
val apiUrlIndex = imgurImageAPIFingerprint.stringMatches!!.first().index
|
||||||
getUserAgentFingerprint.method.replaceInstruction(
|
imgurImageAPIFingerprint.method.replaceInstruction(
|
||||||
apiUrlIndex,
|
apiUrlIndex,
|
||||||
"const-string v1, \"https://api.imgur.com/3/image\"",
|
"const-string v1, \"https://api.imgur.com/3/image\"",
|
||||||
)
|
)
|
||||||
|
@ -6,8 +6,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
|||||||
import app.revanced.patcher.util.smali.ExternalLabel
|
import app.revanced.patcher.util.smali.ExternalLabel
|
||||||
import app.revanced.patches.reddit.customclients.RESOLVE_S_LINK_METHOD
|
import app.revanced.patches.reddit.customclients.RESOLVE_S_LINK_METHOD
|
||||||
import app.revanced.patches.reddit.customclients.SET_ACCESS_TOKEN_METHOD
|
import app.revanced.patches.reddit.customclients.SET_ACCESS_TOKEN_METHOD
|
||||||
import app.revanced.patches.reddit.customclients.boostforreddit.fix.slink.getOAuthAccessTokenFingerprint
|
|
||||||
import app.revanced.patches.reddit.customclients.boostforreddit.fix.slink.handleNavigationFingerprint
|
|
||||||
import app.revanced.patches.reddit.customclients.fixSLinksPatch
|
import app.revanced.patches.reddit.customclients.fixSLinksPatch
|
||||||
import app.revanced.patches.reddit.customclients.sync.syncforreddit.extension.sharedExtensionPatch
|
import app.revanced.patches.reddit.customclients.sync.syncforreddit.extension.sharedExtensionPatch
|
||||||
|
|
||||||
@ -26,7 +24,7 @@ val fixSLinksPatch = fixSLinksPatch(
|
|||||||
execute {
|
execute {
|
||||||
// region Patch navigation handler.
|
// region Patch navigation handler.
|
||||||
|
|
||||||
handleNavigationFingerprint.method.apply {
|
linkHelperOpenLinkFingerprint.method.apply {
|
||||||
val urlRegister = "p3"
|
val urlRegister = "p3"
|
||||||
val tempRegister = "v2"
|
val tempRegister = "v2"
|
||||||
|
|
||||||
@ -46,7 +44,7 @@ val fixSLinksPatch = fixSLinksPatch(
|
|||||||
|
|
||||||
// region Patch set access token.
|
// region Patch set access token.
|
||||||
|
|
||||||
getOAuthAccessTokenFingerprint.method.addInstruction(
|
setAuthorizationHeaderFingerprint.method.addInstruction(
|
||||||
0,
|
0,
|
||||||
"invoke-static { p0 }, $EXTENSION_CLASS_DESCRIPTOR->$SET_ACCESS_TOKEN_METHOD",
|
"invoke-static { p0 }, $EXTENSION_CLASS_DESCRIPTOR->$SET_ACCESS_TOKEN_METHOD",
|
||||||
)
|
)
|
||||||
|
@ -11,6 +11,7 @@ import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
|||||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
|
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||||
@ -105,7 +106,23 @@ val enableDebuggingPatch = bytecodePatch(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// There exists other experimental accessor methods for String, byte[], and wrappers for obfuscated classes,
|
experimentalStringFeatureFlagFingerprint.match(
|
||||||
// but currently none of those are hooked.
|
experimentalFeatureFlagParentFingerprint.originalClassDef
|
||||||
|
).method.apply {
|
||||||
|
val insertIndex = indexOfFirstInstructionReversedOrThrow(Opcode.MOVE_RESULT_OBJECT)
|
||||||
|
|
||||||
|
addInstructions(
|
||||||
|
insertIndex,
|
||||||
|
"""
|
||||||
|
move-result-object v0
|
||||||
|
invoke-static { v0, p1, p2, p3 }, $EXTENSION_CLASS_DESCRIPTOR->isStringFeatureFlagEnabled(Ljava/lang/String;JLjava/lang/String;)Ljava/lang/String;
|
||||||
|
move-result-object v0
|
||||||
|
return-object v0
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// There exists other experimental accessor methods for byte[]
|
||||||
|
// and wrappers for obfuscated classes, but currently none of those are hooked.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,3 +28,9 @@ internal val experimentalLongFeatureFlagFingerprint = fingerprint {
|
|||||||
parameters("J", "J")
|
parameters("J", "J")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal val experimentalStringFeatureFlagFingerprint = fingerprint {
|
||||||
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
|
returns("Ljava/lang/String;")
|
||||||
|
parameters("J", "Ljava/lang/String;")
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -47,10 +47,17 @@ internal val controlsOverlayVisibilityFingerprint = fingerprint {
|
|||||||
parameters("Z", "Z")
|
parameters("Z", "Z")
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val playerControlsExploderFeatureFlagFingerprint = fingerprint {
|
internal val playerBottomControlsExploderFeatureFlagFingerprint = fingerprint {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returns("Z")
|
returns("Z")
|
||||||
parameters()
|
parameters()
|
||||||
literal { 45643739L }
|
literal { 45643739L }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal val playerTopControlsExperimentalLayoutFeatureFlagFingerprint = fingerprint {
|
||||||
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
|
returns("I")
|
||||||
|
parameters()
|
||||||
|
literal { 45629424L }
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package app.revanced.patches.youtube.misc.playercontrols
|
package app.revanced.patches.youtube.misc.playercontrols
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
import app.revanced.patcher.patch.PatchException
|
import app.revanced.patcher.patch.PatchException
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
@ -10,6 +11,7 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
|||||||
import app.revanced.patches.shared.misc.mapping.get
|
import app.revanced.patches.shared.misc.mapping.get
|
||||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||||
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||||
|
import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater
|
||||||
import app.revanced.patches.youtube.misc.playservice.is_19_35_or_greater
|
import app.revanced.patches.youtube.misc.playservice.is_19_35_or_greater
|
||||||
import app.revanced.util.*
|
import app.revanced.util.*
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
@ -263,12 +265,36 @@ val playerControlsPatch = bytecodePatch(
|
|||||||
|
|
||||||
visibilityImmediateMethod = playerControlsExtensionHookFingerprint.method
|
visibilityImmediateMethod = playerControlsExtensionHookFingerprint.method
|
||||||
|
|
||||||
// A/B test for a slightly different overlay controls,
|
// A/B test for a slightly different bottom overlay controls,
|
||||||
// that uses layout file youtube_video_exploder_controls_bottom_ui_container.xml
|
// that uses layout file youtube_video_exploder_controls_bottom_ui_container.xml
|
||||||
// The change to support this is simple and only requires adding buttons to both layout files,
|
// The change to support this is simple and only requires adding buttons to both layout files,
|
||||||
// but for now force this different layout off since it's still an experimental test.
|
// but for now force this different layout off since it's still an experimental test.
|
||||||
if (is_19_35_or_greater) {
|
if (is_19_35_or_greater) {
|
||||||
playerControlsExploderFeatureFlagFingerprint.method.returnEarly()
|
playerBottomControlsExploderFeatureFlagFingerprint.method.returnEarly()
|
||||||
|
}
|
||||||
|
|
||||||
|
// A/B test of new top overlay controls. Two different layouts can be used:
|
||||||
|
// youtube_cf_navigation_improvement_controls_layout.xml
|
||||||
|
// youtube_cf_minimal_impact_controls_layout.xml
|
||||||
|
//
|
||||||
|
// Visually there is no noticeable difference between either of these compared to the default.
|
||||||
|
// There is additional logic that is active when youtube_cf_navigation_improvement_controls_layout
|
||||||
|
// is active, but what it does is not entirely clear.
|
||||||
|
//
|
||||||
|
// For now force this a/b feature off as it breaks the top player buttons.
|
||||||
|
if (is_19_25_or_greater) {
|
||||||
|
playerTopControlsExperimentalLayoutFeatureFlagFingerprint.method.apply {
|
||||||
|
val index = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT_OBJECT)
|
||||||
|
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||||
|
|
||||||
|
addInstructions(
|
||||||
|
index + 1,
|
||||||
|
"""
|
||||||
|
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getPlayerTopControlsLayoutResourceName(Ljava/lang/String;)Ljava/lang/String;
|
||||||
|
move-result-object v$register
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -309,6 +309,17 @@ fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, filter: Inst
|
|||||||
return instructions.indexOfLast(filter)
|
return instructions.indexOfLast(filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the index of matching instruction,
|
||||||
|
* starting from the end of the method and searching down.
|
||||||
|
*
|
||||||
|
* @return -1 if the instruction is not found.
|
||||||
|
*/
|
||||||
|
fun Method.indexOfFirstInstructionReversed(targetOpcode: Opcode): Int =
|
||||||
|
indexOfFirstInstructionReversed {
|
||||||
|
opcode == targetOpcode
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the index of matching instruction,
|
* Get the index of matching instruction,
|
||||||
* starting from and [startIndex] and searching down.
|
* starting from and [startIndex] and searching down.
|
||||||
@ -322,6 +333,16 @@ fun Method.indexOfFirstInstructionReversedOrThrow(startIndex: Int? = null, targe
|
|||||||
opcode == targetOpcode
|
opcode == targetOpcode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the index of matching instruction,
|
||||||
|
* starting from the end of the method and searching down.
|
||||||
|
*
|
||||||
|
* @return -1 if the instruction is not found.
|
||||||
|
*/
|
||||||
|
fun Method.indexOfFirstInstructionReversedOrThrow(targetOpcode: Opcode): Int =
|
||||||
|
indexOfFirstInstructionReversedOrThrow {
|
||||||
|
opcode == targetOpcode
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Get the index of matching instruction,
|
* Get the index of matching instruction,
|
||||||
* starting from and [startIndex] and searching down.
|
* starting from and [startIndex] and searching down.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user