From 7339479fd1bd1c48a0240415f8667975462fdc83 Mon Sep 17 00:00:00 2001 From: inotia00 <108592928+inotia00@users.noreply.github.com> Date: Sun, 11 Aug 2024 17:42:02 +0900 Subject: [PATCH] feat(YouTube): add `Change share sheet` patch --- .../youtube/misc/share/ShareSheetPatch.kt | 86 +++++++++++++++++++ .../BottomSheetRecyclerViewFingerprint.kt | 13 +++ .../UpdateShareSheetCommandFingerprint.kt | 28 ++++++ .../utils/resourceid/SharedResourceIdPatch.kt | 2 + .../youtube/settings/host/values/strings.xml | 3 + .../youtube/settings/xml/revanced_prefs.xml | 4 + 6 files changed, 136 insertions(+) create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/share/ShareSheetPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/share/fingerprints/BottomSheetRecyclerViewFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/share/fingerprints/UpdateShareSheetCommandFingerprint.kt diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/share/ShareSheetPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/share/ShareSheetPatch.kt new file mode 100644 index 0000000000..58ec1dfb5e --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/share/ShareSheetPatch.kt @@ -0,0 +1,86 @@ +package app.revanced.patches.youtube.misc.share + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patches.shared.litho.LithoFilterPatch +import app.revanced.patches.youtube.misc.share.fingerprints.BottomSheetRecyclerViewFingerprint +import app.revanced.patches.youtube.misc.share.fingerprints.UpdateShareSheetCommandFingerprint +import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE +import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH +import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH +import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch +import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.BottomSheetRecyclerView +import app.revanced.patches.youtube.utils.settings.SettingsPatch +import app.revanced.util.getTargetIndexOrThrow +import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.patch.BaseBytecodePatch +import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction + +@Suppress("unused") +object ShareSheetPatch : BaseBytecodePatch( + name = "Change share sheet", + description = "Add option to change from in-app share sheet to system share sheet.", + dependencies = setOf( + LithoFilterPatch::class, + SettingsPatch::class, + SharedResourceIdPatch::class + ), + compatiblePackages = COMPATIBLE_PACKAGE, + fingerprints = setOf( + BottomSheetRecyclerViewFingerprint, + UpdateShareSheetCommandFingerprint, + ) +) { + private const val INTEGRATIONS_CLASS_DESCRIPTOR = + "$MISC_PATH/ShareSheetPatch;" + + private const val FILTER_CLASS_DESCRIPTOR = + "$COMPONENTS_PATH/ShareSheetMenuFilter;" + + override fun execute(context: BytecodeContext) { + + // Detects that the Share sheet panel has been invoked. + BottomSheetRecyclerViewFingerprint.resultOrThrow().mutableMethod.apply { + val constIndex = getWideLiteralInstructionIndex(BottomSheetRecyclerView) + val targetIndex = getTargetIndexOrThrow(constIndex, Opcode.CHECK_CAST) + val targetRegister = getInstruction(targetIndex).registerA + + addInstruction( + targetIndex + 1, + "invoke-static {v$targetRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onShareSheetMenuCreate(Landroid/support/v7/widget/RecyclerView;)V" + ) + } + + // Remove the app list from the Share sheet panel on YouTube. + UpdateShareSheetCommandFingerprint.resultOrThrow().let { + it.mutableMethod.apply { + val targetIndex = it.scanResult.patternScanResult!!.endIndex + val targetRegister = getInstruction(targetIndex).registerA + + addInstructions( + targetIndex + 1, """ + invoke-static {v$targetRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->overridePackageName(Ljava/lang/String;)Ljava/lang/String; + move-result-object v$targetRegister + """ + ) + } + } + + LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR) + + /** + * Add settings + */ + SettingsPatch.addPreference( + arrayOf( + "PREFERENCE_CATEGORY: MISC_EXPERIMENTAL_FLAGS", + "SETTINGS: CHANGE_SHARE_SHEET" + ) + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/share/fingerprints/BottomSheetRecyclerViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/share/fingerprints/BottomSheetRecyclerViewFingerprint.kt new file mode 100644 index 0000000000..6f32beb8c4 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/share/fingerprints/BottomSheetRecyclerViewFingerprint.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.youtube.misc.share.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.BottomSheetRecyclerView +import app.revanced.util.fingerprint.LiteralValueFingerprint +import com.android.tools.smali.dexlib2.AccessFlags + +internal object BottomSheetRecyclerViewFingerprint : LiteralValueFingerprint( + returnType = "Lj${'$'}/util/Optional;", + accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL, + parameters = emptyList(), + literalSupplier = { BottomSheetRecyclerView } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/share/fingerprints/UpdateShareSheetCommandFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/share/fingerprints/UpdateShareSheetCommandFingerprint.kt new file mode 100644 index 0000000000..b303a42182 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/share/fingerprints/UpdateShareSheetCommandFingerprint.kt @@ -0,0 +1,28 @@ +package app.revanced.patches.youtube.misc.share.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.reference.FieldReference + +internal object UpdateShareSheetCommandFingerprint : MethodFingerprint( + returnType = "V", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + parameters = listOf("L", "Ljava/util/Map;"), + opcodes = listOf( + Opcode.IF_EQZ, + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CHECK_CAST, + Opcode.IGET_OBJECT + ), + customFingerprint = custom@{ methodDef, _ -> + methodDef.indexOfFirstInstruction { + opcode == Opcode.SGET_OBJECT && + getReference()?.name == "updateShareSheetCommand" + } >= 0 + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt index 0faac59cb5..82361b9f6d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt @@ -32,6 +32,7 @@ object SharedResourceIdPatch : ResourcePatch() { var Bar = -1L var BarContainerHeight = -1L var BottomSheetFooterText = -1L + var BottomSheetRecyclerView = -1L var BottomUiContainerStub = -1L var CaptionToggleContainer = -1L var CastMediaRouteButton = -1L @@ -136,6 +137,7 @@ object SharedResourceIdPatch : ResourcePatch() { Bar = getId(LAYOUT, "bar") BarContainerHeight = getId(DIMEN, "bar_container_height") BottomSheetFooterText = getId(ID, "bottom_sheet_footer_text") + BottomSheetRecyclerView = getId(LAYOUT, "bottom_sheet_recycler_view") BottomUiContainerStub = getId(ID, "bottom_ui_container_stub") CaptionToggleContainer = getId(ID, "caption_toggle_container") CastMediaRouteButton = getId(LAYOUT, "castmediaroutebutton") diff --git a/src/main/resources/youtube/settings/host/values/strings.xml b/src/main/resources/youtube/settings/host/values/strings.xml index b21ad10045..27d5644a50 100644 --- a/src/main/resources/youtube/settings/host/values/strings.xml +++ b/src/main/resources/youtube/settings/host/values/strings.xml @@ -1538,6 +1538,9 @@ Tap on the continue button and disable battery optimizations." Disable QUIC protocol "Disable CronetEngine's QUIC protocol." + Change share sheet + System share sheet is used. + In-app share sheet is used. Enable OPUS codec Enable the OPUS codec if the player response includes the OPUS codec. diff --git a/src/main/resources/youtube/settings/xml/revanced_prefs.xml b/src/main/resources/youtube/settings/xml/revanced_prefs.xml index 5a6a0229a1..4eb8bfd75f 100644 --- a/src/main/resources/youtube/settings/xml/revanced_prefs.xml +++ b/src/main/resources/youtube/settings/xml/revanced_prefs.xml @@ -668,6 +668,9 @@ + + @@ -742,6 +745,7 @@ +