diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/RestoreOldSeekbarThumbnailsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/RestoreOldSeekbarThumbnailsPatch.kt index 9d45b0ca8b..1e6f527672 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/RestoreOldSeekbarThumbnailsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/RestoreOldSeekbarThumbnailsPatch.kt @@ -2,9 +2,12 @@ package app.revanced.patches.youtube.layout.seekbar import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstructions +import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction +import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.all.misc.resources.AddResourcesPatch @@ -13,7 +16,14 @@ import app.revanced.patches.youtube.layout.seekbar.fingerprints.FullscreenSeekba import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.playservice.YouTubeVersionCheck import app.revanced.patches.youtube.misc.settings.SettingsPatch -import app.revanced.util.exception +import app.revanced.util.findOpcodeIndicesReversed +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow +import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Patch( name = "Restore old seekbar thumbnails", @@ -44,8 +54,8 @@ import app.revanced.util.exception "19.13.37", "19.14.43", "19.15.36", - "19.16.39" - // 19.17+ is not supported. + "19.16.39", + "19.34.42", ] ) ] @@ -58,24 +68,119 @@ object RestoreOldSeekbarThumbnailsPatch : BytecodePatch( "Lapp/revanced/integrations/youtube/patches/RestoreOldSeekbarThumbnailsPatch;" override fun execute(context: BytecodeContext) { - if (YouTubeVersionCheck.is_19_17_or_greater) { - // Give a more informative error, if the user has turned off version checks. - throw PatchException("'Restore old seekbar thumbnails' cannot be patched to any version after 19.16.39") - } - AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.SEEKBAR.addPreferences( SwitchPreference("revanced_restore_old_seekbar_thumbnails") ) - FullscreenSeekbarThumbnailsFingerprint.result?.mutableMethod?.apply { + if (false) FullscreenSeekbarThumbnailsFingerprint.resultOrThrow().mutableMethod.apply { val moveResultIndex = getInstructions().lastIndex - 1 addInstruction( moveResultIndex, "invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->useFullscreenSeekbarThumbnails()Z" ) - } ?: throw FullscreenSeekbarThumbnailsFingerprint.exception + } + + context.proxy(context.classes.first { it.type == "Laaxp;" }).mutableClass.methods + .find { it.name == "bX" }!!.apply { + val index = indexOfFirstWideLiteralInstructionValueOrThrow(45611695L) + val insertIndex = + indexOfFirstInstructionOrThrow(index) { opcode == Opcode.MOVE_RESULT } + + addInstruction( + insertIndex, + "invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->useFullscreenSeekbarThumbnails()Z" + ) + } + + + context.proxy(context.classes.first { it.type == "Lfwa;" }).mutableClass.methods + .find { it.name == "N" }!!.apply { + val index = indexOfFirstWideLiteralInstructionValueOrThrow(45367320L) + val insertIndex = + indexOfFirstInstructionOrThrow(index) { opcode == Opcode.MOVE_RESULT } + + addInstruction( + insertIndex, + "invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->useFullscreenSeekbarThumbnails()Z" + ) + } + + context.proxy(context.classes.first { it.type == "Lkrx;" }).mutableClass.methods + .find { it.name == "mF" }!!.apply { + val index = indexOfFirstInstructionOrThrow{ opcode == Opcode.INVOKE_VIRTUAL && getReference()?.name == "mF" } + + removeInstructions(index, getInstructions().size - index - 1) + } + + context.proxy(context.classes.first { it.type == "Lkvm;" }).mutableClass.methods + .find { it.name == "ab" }!!.apply { + val index = indexOfFirstInstructionOrThrow{ + val reference = getReference() + opcode == Opcode.INVOKE_VIRTUAL && reference?.definingClass == "Lkzh;" && reference.name == "l" + } + + removeInstruction(index) + } + + context.proxy(context.classes.first { it.type == "Lbbfq;" }).mutableClass.methods + .find { it.name == "dx" }!!.apply { + val insertIndex = + indexOfFirstInstructionOrThrow { opcode == Opcode.MOVE_RESULT } + + addInstruction( + insertIndex, + "invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->useFullscreenSeekbarThumbnails()Z" + ) + } + + context.proxy(context.classes.first { it.type == "Lkvk;" }).mutableClass.methods + .find { it.name == "mF" }!!.apply { + findOpcodeIndicesReversed { + val reference = getReference() + opcode == Opcode.INVOKE_VIRTUAL && reference?.definingClass == "Lkzh;" && reference.name == "mF" + }.forEach { index -> + val instruction = getInstruction(index) + val free = instruction.registerC + + addInstructionsWithLabels(index + 1, """ + move-object/from16 v$free, p0 + iget-object v$free, v$free, Lkvk;->b:Lkvm; + invoke-virtual { v$free }, Lkvm;->F()V # Inflate layout + iget-object v$free, v$free, Lkvm;->s:Lkvx; + iget-object v$free, v$free, Lgym;->d:Lahhj; + # + # FIXME: this field is always null. Something else needs to be set for this to work. + # + if-eqz v$free, :is_null + + invoke-virtual { v$free }, Lahhj;->j()Z + move-result v$free + if-eqz v$free, :do_not_show + + # This duplicate code can be fixed by using a second free register (or adding a helper method). + move-object/from16 v$free, p0 + iget-object v$free, v$free, Lkvk;->b:Lkvm; + iget-object v$free, v$free, Lkvm;->s:Lkvx; + iget-object v$free, v$free, Lgym;->d:Lahhj; + + invoke-virtual { v$free, v${instruction.registerD}, v${instruction.registerE}, v${instruction.registerF} }, Lahhj;->mF(IJ)V + + :is_null + :do_not_show + nop + """) + removeInstruction(index) + } + + findOpcodeIndicesReversed { + val reference = getReference() + opcode == Opcode.INVOKE_VIRTUAL && reference?.definingClass == "Lkov;" && reference.name == "j" + }.forEach { index -> + removeInstruction(index) + } + } } }