diff --git a/src/main/kotlin/app/revanced/patches/music/layout/floatingbutton/fingerprints/FloatingButtonFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/floatingbutton/fingerprints/FloatingButtonFingerprint.kt new file mode 100644 index 000000000..4bd0f162e --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/layout/floatingbutton/fingerprints/FloatingButtonFingerprint.kt @@ -0,0 +1,30 @@ +package app.revanced.patches.music.layout.floatingbutton.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch +import org.jf.dexlib2.iface.instruction.WideLiteralInstruction +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +object FloatingButtonFingerprint : MethodFingerprint( + returnType = "V", + access = AccessFlags.PRIVATE or AccessFlags.FINAL, + parameters = listOf("L"), + opcodes = listOf( + Opcode.CONST, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.MOVE_OBJECT, + Opcode.CHECK_CAST, + Opcode.CONST_4, + Opcode.INVOKE_VIRTUAL + ), + customFingerprint = { methodDef -> + methodDef.implementation?.instructions?.any { + it.opcode.ordinal == Opcode.CONST.ordinal && + (it as? WideLiteralInstruction)?.wideLiteral == SharedResourceIdPatch.floatingActionButtonLabelId + } == true + } +) + diff --git a/src/main/kotlin/app/revanced/patches/music/layout/floatingbutton/patch/NewPlaylistButtonPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/floatingbutton/patch/NewPlaylistButtonPatch.kt new file mode 100644 index 000000000..885a1e02d --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/layout/floatingbutton/patch/NewPlaylistButtonPatch.kt @@ -0,0 +1,63 @@ +package app.revanced.patches.music.layout.floatingbutton.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.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.music.layout.floatingbutton.fingerprints.FloatingButtonFingerprint +import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch +import app.revanced.patches.music.misc.settings.patch.MusicSettingsPatch +import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility +import app.revanced.util.integrations.Constants.MUSIC_SETTINGS_PATH +import org.jf.dexlib2.iface.instruction.formats.Instruction35c + +@Patch +@Name("hide-new-playlist") +@Description("Hide the New Playlist button in the Library tab.") +@DependsOn( + [ + MusicSettingsPatch::class, + SharedResourceIdPatch::class + ] +) +@YouTubeMusicCompatibility +@Version("0.0.1") +class NewPlaylistButtonPatch : BytecodePatch( + listOf( + FloatingButtonFingerprint + ) +) { + override fun execute(context: BytecodeContext): PatchResult { + + FloatingButtonFingerprint.result?.let { + with (it.mutableMethod) { + val targetIndex = it.scanResult.patternScanResult!!.endIndex + + val targetRegister = (instruction(targetIndex) as Instruction35c).registerC + val dummyRegister = (instruction(targetIndex) as Instruction35c).registerD + + addInstructions( + targetIndex + 1, """ + invoke-static {}, $MUSIC_SETTINGS_PATH->hideNewPlaylistButton()Z + move-result v$dummyRegister + if-eqz v$dummyRegister, :show + const/4 v$targetRegister, 0x0 + """, listOf(ExternalLabel("show", instruction(targetIndex + 1))) + ) + } + } ?: return FloatingButtonFingerprint.toErrorResult() + + MusicSettingsPatch.addMusicPreference("navigation", "revanced_hide_new_playlist_button", "false") + + return PatchResultSuccess() + } +} diff --git a/src/main/kotlin/app/revanced/patches/music/misc/resourceid/patch/SharedResourceIdPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/resourceid/patch/SharedResourceIdPatch.kt index 7c0ba3beb..5e5c4deb8 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/resourceid/patch/SharedResourceIdPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/resourceid/patch/SharedResourceIdPatch.kt @@ -19,6 +19,7 @@ class SharedResourceIdPatch : ResourcePatch { var colorGreyLabelId: Long = -1 var dialogSolidLabelId: Long = -1 var disabledIconLabelId: Long = -1 + var floatingActionButtonLabelId: Long = -1 var isTabletLabelId: Long = -1 } @@ -31,6 +32,7 @@ class SharedResourceIdPatch : ResourcePatch { colorGreyLabelId = findSharedResourceId("color", "ytm_color_grey_12") dialogSolidLabelId = findSharedResourceId("style", "Theme.YouTubeMusic.Dialog.Solid") disabledIconLabelId = findSharedResourceId("dimen", "disabled_icon_alpha") + floatingActionButtonLabelId = findSharedResourceId("id", "floating_action_button") isTabletLabelId = findSharedResourceId("bool", "is_tablet") return PatchResultSuccess() diff --git a/src/main/resources/music/settings/host/values/strings.xml b/src/main/resources/music/settings/host/values/strings.xml index 9b1c7ff20..84b42e609 100644 --- a/src/main/resources/music/settings/host/values/strings.xml +++ b/src/main/resources/music/settings/host/values/strings.xml @@ -36,6 +36,9 @@ "Hide ads before playing a track. (requires an app restart)" Hide music ads + "Hide the New Playlist button in the Library tab. +(requires an app restart)" + Hide new playlist button "Hides the playlist card from homepage. (requires an app restart)" Hide playlist card