feat(youtube): support version 18.19.35
This commit is contained in:
+1
-1
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.interaction.copyvideourl.annotation
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class CopyVideoUrlCompatibility
|
||||
+1
-1
@@ -3,7 +3,7 @@ package app.revanced.patches.youtube.interaction.downloads.annotation
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class DownloadsCompatibility
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ package app.revanced.patches.youtube.interaction.seekbar.annotation
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class SeekbarTappingCompatibility
|
||||
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package app.revanced.patches.youtube.interaction.seekbar.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patches.youtube.interaction.seekbar.patch.EnableSeekbarTappingResourcePatch
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
||||
|
||||
|
||||
object AccessibilityPlayerProgressTimeFingerprint : MethodFingerprint(
|
||||
returnType = "L",
|
||||
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.implementation?.instructions?.any { instruction ->
|
||||
if (instruction.opcode != Opcode.CONST) return@any false
|
||||
|
||||
val wideLiteral = (instruction as WideLiteralInstruction).wideLiteral
|
||||
|
||||
EnableSeekbarTappingResourcePatch.accessibilityPlayerProgressTime == wideLiteral
|
||||
} ?: false
|
||||
}
|
||||
)
|
||||
+23
-23
@@ -1,34 +1,34 @@
|
||||
package app.revanced.patches.youtube.interaction.seekbar.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
|
||||
|
||||
|
||||
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||
object SeekbarTappingFingerprint : MethodFingerprint(
|
||||
"Z", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L"), listOf(
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_WIDE,
|
||||
Opcode.IGET,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IGET,
|
||||
Opcode.DIV_INT_2ADDR,
|
||||
Opcode.ADD_INT,
|
||||
Opcode.SUB_INT_2ADDR,
|
||||
Opcode.INT_TO_FLOAT,
|
||||
Opcode.CMPG_FLOAT,
|
||||
Opcode.IF_GTZ,
|
||||
Opcode.INT_TO_FLOAT,
|
||||
Opcode.CMPG_FLOAT,
|
||||
Opcode.IF_GTZ,
|
||||
Opcode.CONST_4,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.NEW_INSTANCE,
|
||||
Opcode.INVOKE_DIRECT,
|
||||
returnType = "Z",
|
||||
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("L"),
|
||||
opcodes = listOf(
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL
|
||||
)
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
// Insert seekbar tapping instructions here.
|
||||
Opcode.RETURN,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
),
|
||||
customFingerprint = custom@{ methodDef, _ ->
|
||||
if (methodDef.name != "onTouchEvent") return@custom false
|
||||
|
||||
methodDef.implementation!!.instructions.any { instruction ->
|
||||
if (instruction.opcode != Opcode.CONST) return@any false
|
||||
|
||||
val literal = (instruction as NarrowLiteralInstruction).narrowLiteral
|
||||
|
||||
// onTouchEvent method contains a CONST instruction
|
||||
// with this literal making it unique with the rest of the properties of this fingerprint.
|
||||
literal == Integer.MAX_VALUE
|
||||
}
|
||||
}
|
||||
)
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
package app.revanced.patches.youtube.interaction.seekbar.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
|
||||
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||
object SeekbarTappingParentFingerprint : MethodFingerprint(
|
||||
"L", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf(
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CONST_4,
|
||||
Opcode.NEW_ARRAY,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_WIDE,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CONST_4,
|
||||
Opcode.APUT_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_WIDE,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CONST_4,
|
||||
Opcode.APUT_OBJECT,
|
||||
Opcode.CONST,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.RETURN_OBJECT
|
||||
)
|
||||
)
|
||||
+53
-67
@@ -1,109 +1,95 @@
|
||||
package app.revanced.patches.youtube.interaction.seekbar.patch
|
||||
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.instruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.interaction.seekbar.annotation.SeekbarTappingCompatibility
|
||||
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.AccessibilityPlayerProgressTimeFingerprint
|
||||
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.SeekbarTappingFingerprint
|
||||
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.SeekbarTappingParentFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
|
||||
import org.jf.dexlib2.iface.Method
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction11n
|
||||
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
||||
|
||||
@Patch
|
||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, EnableSeekbarTappingResourcePatch::class])
|
||||
@Name("seekbar-tapping")
|
||||
@Description("Enables tap-to-seek on the seekbar of the video player.")
|
||||
@SeekbarTappingCompatibility
|
||||
@Version("0.0.1")
|
||||
class EnableSeekbarTappingPatch : BytecodePatch(
|
||||
listOf(
|
||||
SeekbarTappingParentFingerprint, SeekbarTappingFingerprint
|
||||
)
|
||||
listOf(AccessibilityPlayerProgressTimeFingerprint, SeekbarTappingFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_tap_seeking",
|
||||
StringResource("revanced_tap_seeking_title", "Enable seekbar tapping"),
|
||||
StringResource("revanced_tap_seeking_summary_on", "Seekbar tapping is enabled"),
|
||||
StringResource("revanced_tap_seeking_summary_off", "Seekbar tapping is disabled")
|
||||
)
|
||||
)
|
||||
// Find the required methods to tap the seekbar.
|
||||
val seekbarTappingMethods =
|
||||
AccessibilityPlayerProgressTimeFingerprint.result?.classDef?.methods?.let { methods ->
|
||||
buildMap {
|
||||
// find the methods which tap the seekbar
|
||||
methods.forEach { method ->
|
||||
if (method.implementation == null) return@forEach
|
||||
|
||||
var result = SeekbarTappingParentFingerprint.result!!
|
||||
val instructions = method.implementation!!.instructions
|
||||
|
||||
val tapSeekMethods = mutableMapOf<String, Method>()
|
||||
// The method has more than 7 instructions.
|
||||
if (instructions.count() < 7) return@forEach
|
||||
|
||||
// find the methods which tap the seekbar
|
||||
for (it in result.classDef.methods) {
|
||||
if (it.implementation == null) continue
|
||||
// The 7th instruction has the opcode CONST_4.
|
||||
val instruction = instructions.elementAt(6)
|
||||
if (instruction.opcode != Opcode.CONST_4) return@forEach
|
||||
|
||||
val instructions = it.implementation!!.instructions
|
||||
// here we make sure we actually find the method because it has more than 7 instructions
|
||||
if (instructions.count() < 7) continue
|
||||
// the literal for this instruction has to be either 1 or 2.
|
||||
val literal = (instruction as NarrowLiteralInstruction).narrowLiteral
|
||||
|
||||
// we know that the 7th instruction has the opcode CONST_4
|
||||
val instruction = instructions.elementAt(6)
|
||||
if (instruction.opcode != Opcode.CONST_4) continue
|
||||
// Based on the literal, determine which method is which.
|
||||
if (literal == 1) this["P"] = method
|
||||
if (literal == 2) this["O"] = method
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the literal for this instruction has to be either 1 or 2
|
||||
val literal = (instruction as Instruction11n).narrowLiteral
|
||||
seekbarTappingMethods ?: return AccessibilityPlayerProgressTimeFingerprint.toErrorResult()
|
||||
|
||||
// method founds
|
||||
if (literal == 1) tapSeekMethods["P"] = it
|
||||
if (literal == 2) tapSeekMethods["O"] = it
|
||||
}
|
||||
SeekbarTappingFingerprint.result?.let {
|
||||
val insertIndex = it.scanResult.patternScanResult!!.endIndex - 1
|
||||
|
||||
// replace map because we don't need the upper one anymore
|
||||
result = SeekbarTappingFingerprint.result!!
|
||||
it.mutableMethod.apply {
|
||||
val thisInstanceRegister = instruction<Instruction35c>(insertIndex - 1).registerC
|
||||
|
||||
val implementation = result.mutableMethod.implementation!!
|
||||
val freeRegister = 0
|
||||
val xAxisRegister = 2
|
||||
|
||||
// if tap-seeking is enabled, do not invoke the two methods below
|
||||
val pMethod = tapSeekMethods["P"]!!
|
||||
val oMethod = tapSeekMethods["O"]!!
|
||||
val pMethod = seekbarTappingMethods["P"]!!
|
||||
val oMethod = seekbarTappingMethods["O"]!!
|
||||
|
||||
val insertIndex = result.scanResult.patternScanResult!!.endIndex + 1
|
||||
fun Method.toInvokeInstructionString() =
|
||||
"invoke-virtual { v$thisInstanceRegister, v$xAxisRegister }, $definingClass->$name(I)V"
|
||||
|
||||
// get the required register
|
||||
val instruction = implementation.instructions[insertIndex - 1]
|
||||
if (instruction.opcode != Opcode.INVOKE_VIRTUAL) return PatchResultError("Could not find the correct register")
|
||||
val register = (instruction as Instruction35c).registerC
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static { }, Lapp/revanced/integrations/patches/SeekbarTappingPatch;->seekbarTappingEnabled()Z
|
||||
move-result v$freeRegister
|
||||
if-eqz v$freeRegister, :disabled
|
||||
${oMethod.toInvokeInstructionString()}
|
||||
${pMethod.toInvokeInstructionString()}
|
||||
""",
|
||||
listOf(ExternalLabel("disabled", instruction(insertIndex)))
|
||||
)
|
||||
}
|
||||
} ?: return SeekbarTappingFingerprint.toErrorResult()
|
||||
|
||||
val elseLabel = implementation.newLabelForIndex(insertIndex)
|
||||
// the instructions are written in reverse order.
|
||||
result.mutableMethod.addInstructions(
|
||||
insertIndex, """
|
||||
invoke-virtual { v$register, v2 }, ${oMethod.definingClass}->${oMethod.name}(I)V
|
||||
invoke-virtual { v$register, v2 }, ${pMethod.definingClass}->${pMethod.name}(I)V
|
||||
"""
|
||||
)
|
||||
|
||||
// if tap-seeking is disabled, do not invoke the two methods above by jumping to the else label
|
||||
implementation.addInstruction(
|
||||
insertIndex, BuilderInstruction21t(Opcode.IF_EQZ, 0, elseLabel)
|
||||
)
|
||||
result.mutableMethod.addInstructions(
|
||||
insertIndex, """
|
||||
invoke-static { }, Lapp/revanced/integrations/patches/SeekbarTappingPatch;->isTapSeekingEnabled()Z
|
||||
move-result v0
|
||||
"""
|
||||
)
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package app.revanced.patches.youtube.interaction.seekbar.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultError
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
|
||||
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
|
||||
@Version("0.0.1")
|
||||
class EnableSeekbarTappingResourcePatch : ResourcePatch {
|
||||
override fun execute(context: ResourceContext): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_seekbar_tapping",
|
||||
StringResource("revanced_seekbar_tapping_title", "Enable seekbar tapping"),
|
||||
StringResource("revanced_seekbar_tapping_summary_on", "Seekbar tapping is enabled"),
|
||||
StringResource("revanced_seekbar_tapping_summary_off", "Seekbar tapping is disabled")
|
||||
)
|
||||
)
|
||||
|
||||
accessibilityPlayerProgressTime = ResourceMappingPatch.resourceMappings.find {
|
||||
it.name == "accessibility_player_progress_time"
|
||||
}?.id ?: return PatchResultError("Failed to find required resource")
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
internal companion object {
|
||||
var accessibilityPlayerProgressTime = -1L
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3,6 +3,6 @@ package app.revanced.patches.youtube.interaction.swipecontrols.annotation
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37"))])
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class SwipeControlsCompatibility
|
||||
|
||||
Reference in New Issue
Block a user