From 4e9eff5de2aaf1b8b8314c0da2b8a600b641a595 Mon Sep 17 00:00:00 2001 From: inotia00 Date: Thu, 23 Feb 2023 16:54:40 +0900 Subject: [PATCH] refactor(hide-floating-microphone): use more dynamic fingerprint --- .../FloatingMicrophoneFingerprint.kt | 20 ++++ .../patch/FloatingMicrophonePatch.kt | 96 +++++++------------ .../resourceid/patch/SharedResourceIdPatch.kt | 2 + 3 files changed, 55 insertions(+), 63 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/general/floatingmicrophone/fingerprints/FloatingMicrophoneFingerprint.kt diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/general/floatingmicrophone/fingerprints/FloatingMicrophoneFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/general/floatingmicrophone/fingerprints/FloatingMicrophoneFingerprint.kt new file mode 100644 index 000000000..e774809f3 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/general/floatingmicrophone/fingerprints/FloatingMicrophoneFingerprint.kt @@ -0,0 +1,20 @@ +package app.revanced.patches.youtube.layout.general.floatingmicrophone.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourcdIdPatch +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.iface.instruction.WideLiteralInstruction + +object FloatingMicrophoneFingerprint : MethodFingerprint( + opcodes = listOf( + Opcode.IGET_BOOLEAN, + Opcode.IF_EQZ, + Opcode.RETURN_VOID + ), + customFingerprint = { methodDef -> + methodDef.implementation?.instructions?.any { + it.opcode.ordinal == Opcode.CONST.ordinal && + (it as? WideLiteralInstruction)?.wideLiteral == SharedResourcdIdPatch.fabLabelId + } == true + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/general/floatingmicrophone/patch/FloatingMicrophonePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/general/floatingmicrophone/patch/FloatingMicrophonePatch.kt index a85d8f77d..f9062b655 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/general/floatingmicrophone/patch/FloatingMicrophonePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/general/floatingmicrophone/patch/FloatingMicrophonePatch.kt @@ -1,98 +1,68 @@ package app.revanced.patches.youtube.layout.general.floatingmicrophone.patch -import app.revanced.extensions.findMutableMethodOf +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.patches.shared.annotation.YouTubeCompatibility -import app.revanced.patches.shared.patch.mapping.ResourceMappingPatch +import app.revanced.patches.youtube.layout.general.floatingmicrophone.fingerprints.FloatingMicrophoneFingerprint +import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourcdIdPatch import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch import app.revanced.util.integrations.Constants.GENERAL_LAYOUT -import org.jf.dexlib2.Opcode import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction -import org.jf.dexlib2.iface.instruction.formats.Instruction31i @Patch @Name("hide-floating-microphone") @Description("Hide the floating microphone button above the keyboard.") @DependsOn( [ - ResourceMappingPatch::class, - SettingsPatch::class + SettingsPatch::class, + SharedResourcdIdPatch::class ] ) @YouTubeCompatibility @Version("0.0.1") -class FloatingMicrophonePatch : BytecodePatch() { - - // list of resource names to get the id of - private val resourceIds = arrayOf( - "fab" - ).map { name -> - ResourceMappingPatch.resourceMappings.single { it.name == name }.id - } - private var patchSuccessArray = Array(resourceIds.size) {false} - +class FloatingMicrophonePatch : BytecodePatch( + listOf( + FloatingMicrophoneFingerprint + ) +) { override fun execute(context: BytecodeContext): PatchResult { - context.classes.forEach { classDef -> - classDef.methods.forEach { method -> - with(method.implementation) { - this?.instructions?.forEachIndexed { index, instruction -> - when (instruction.opcode) { - Opcode.CONST -> { - when ((instruction as Instruction31i).wideLiteral) { - resourceIds[0] -> { // FloatingActionButton - val insertIndex = index + 4 - val invokeInstruction = instructions.elementAt(insertIndex) - if (invokeInstruction.opcode != Opcode.IGET_BOOLEAN) return@forEachIndexed - val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method) + FloatingMicrophoneFingerprint.result?.let { + with (it.mutableMethod) { + val insertIndex = it.scanResult.patternScanResult!!.startIndex + val register = (instruction(insertIndex) as TwoRegisterInstruction).registerA - val viewRegister = (invokeInstruction as TwoRegisterInstruction).registerA - - mutableMethod.addInstructions( - insertIndex + 1, """ - invoke-static {v$viewRegister}, $GENERAL_LAYOUT->hideFloatingMicrophone(Z)Z - move-result v$viewRegister - """ - ) - - patchSuccessArray[0] = true; - } - } - } - else -> return@forEachIndexed - } - } - } - } - } - - val errorIndex: Int = patchSuccessArray.indexOf(false) - - if (errorIndex == -1) { - /* - * Add settings - */ - SettingsPatch.addPreference( - arrayOf( - "PREFERENCE: GENERAL_LAYOUT_SETTINGS", - "SETTINGS: HIDE_FLOATING_MICROPHONE" + addInstructions( + insertIndex + 1, """ + invoke-static {v$register}, $GENERAL_LAYOUT->hideFloatingMicrophone(Z)Z + move-result v$register + """ ) + } + } ?: return FloatingMicrophoneFingerprint.toErrorResult() + + /* + * Add settings + */ + SettingsPatch.addPreference( + arrayOf( + "PREFERENCE: GENERAL_LAYOUT_SETTINGS", + "SETTINGS: HIDE_FLOATING_MICROPHONE" ) + ) - SettingsPatch.updatePatchStatus("hide-floating-microphone") + SettingsPatch.updatePatchStatus("hide-floating-microphone") - return PatchResultSuccess() - } else - return PatchResultError("Instruction not found: $errorIndex") + return PatchResultSuccess() } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/resourceid/patch/SharedResourceIdPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/resourceid/patch/SharedResourceIdPatch.kt index 591932017..a3f48ff64 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/resourceid/patch/SharedResourceIdPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/resourceid/patch/SharedResourceIdPatch.kt @@ -27,6 +27,7 @@ class SharedResourcdIdPatch : ResourcePatch { var donationCompanionResourceId: Long = -1 var educationTextViewResourceId: Long = -1 var emptycolorLabelId: Long = -1 + var fabLabelId: Long = -1 var floatybarQueueLabelId: Long = -1 var imageOnlyTabId: Long = -1 var imageWithTextTabId: Long = -1 @@ -57,6 +58,7 @@ class SharedResourcdIdPatch : ResourcePatch { donationCompanionResourceId = findSharedResourceId("layout", "donation_companion") educationTextViewResourceId = findSharedResourceId("id", "user_education_text_view") emptycolorLabelId = findSharedResourceId("color", "inline_time_bar_colorized_bar_empty_color_dark") + fabLabelId = findSharedResourceId("id", "fab") floatybarQueueLabelId = findSharedResourceId("string", "floaty_bar_queue_status") imageOnlyTabId = findSharedResourceId("layout", "image_only_tab") imageWithTextTabId = findSharedResourceId("layout", "image_with_text_tab")