diff --git a/CHANGELOG.md b/CHANGELOG.md index 64b8abf31..04eb14ff7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +# [5.46.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.8...v5.46.0-dev.9) (2025-11-09) + + +### Features + +* **YouTube Music:** Add `Change miniplayer color` patch ([#6259](https://github.com/ReVanced/revanced-patches/issues/6259)) ([ab808ae](https://github.com/ReVanced/revanced-patches/commit/ab808aeb773592cb26c848d8456478a346ec3bad)) + +# [5.46.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.7...v5.46.0-dev.8) (2025-11-09) + + +### Features + +* **YouTube Music:** Add `Hide buttons` patch ([#6255](https://github.com/ReVanced/revanced-patches/issues/6255)) ([7a18ebc](https://github.com/ReVanced/revanced-patches/commit/7a18ebc7ab74ba30c5d5284a4856c55cdfc31097)) + # [5.46.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v5.46.0-dev.6...v5.46.0-dev.7) (2025-11-08) diff --git a/extensions/music/src/main/java/app/revanced/extension/music/patches/ChangeMiniplayerColorPatch.java b/extensions/music/src/main/java/app/revanced/extension/music/patches/ChangeMiniplayerColorPatch.java new file mode 100644 index 000000000..ec941f7f3 --- /dev/null +++ b/extensions/music/src/main/java/app/revanced/extension/music/patches/ChangeMiniplayerColorPatch.java @@ -0,0 +1,14 @@ +package app.revanced.extension.music.patches; + +import app.revanced.extension.music.settings.Settings; + +@SuppressWarnings("unused") +public class ChangeMiniplayerColorPatch { + + /** + * Injection point + */ + public static boolean changeMiniplayerColor() { + return Settings.CHANGE_MINIPLAYER_COLOR.get(); + } +} diff --git a/extensions/music/src/main/java/app/revanced/extension/music/settings/Settings.java b/extensions/music/src/main/java/app/revanced/extension/music/settings/Settings.java index bebb3f86c..bd0c80402 100644 --- a/extensions/music/src/main/java/app/revanced/extension/music/settings/Settings.java +++ b/extensions/music/src/main/java/app/revanced/extension/music/settings/Settings.java @@ -30,6 +30,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting HIDE_NAVIGATION_BAR_LABEL = new BooleanSetting("revanced_music_hide_navigation_bar_labels", FALSE, true); // Player + public static final BooleanSetting CHANGE_MINIPLAYER_COLOR = new BooleanSetting("revanced_music_change_miniplayer_color", FALSE, true); public static final BooleanSetting PERMANENT_REPEAT = new BooleanSetting("revanced_music_play_permanent_repeat", FALSE, true); // Miscellaneous diff --git a/gradle.properties b/gradle.properties index 539c4f679..081ae8c1e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M org.gradle.parallel = true android.useAndroidX = true kotlin.code.style = official -version = 5.46.0-dev.7 +version = 5.46.0-dev.9 diff --git a/patches/api/patches.api b/patches/api/patches.api index dc1d7c1e0..29dafd744 100644 --- a/patches/api/patches.api +++ b/patches/api/patches.api @@ -380,6 +380,10 @@ public final class app/revanced/patches/music/layout/compactheader/HideCategoryB public static final fun getHideCategoryBar ()Lapp/revanced/patcher/patch/BytecodePatch; } +public final class app/revanced/patches/music/layout/miniplayercolor/ChangeMiniplayerColorKt { + public static final fun getChangeMiniplayerColor ()Lapp/revanced/patcher/patch/BytecodePatch; +} + public final class app/revanced/patches/music/layout/navigationbar/NavigationBarPatchKt { public static final fun getNavigationBarPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/buttons/HideButtons.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/buttons/HideButtons.kt index 331dae93d..bf2f8513f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/layout/buttons/HideButtons.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/buttons/HideButtons.kt @@ -55,7 +55,7 @@ val hideButtons = bytecodePatch( playerOverlayChip = getResourceId(ResourceType.ID, "player_overlay_chip") historyMenuItem = getResourceId(ResourceType.ID, "history_menu_item") offlineSettingsMenuItem = getResourceId(ResourceType.ID, "offline_settings_menu_item") - searchButton = getResourceId(ResourceType.ID, "search_button") + searchButton = getResourceId(ResourceType.LAYOUT, "search_button") topBarMenuItemImageView = getResourceId(ResourceType.ID, "top_bar_menu_item_image_view") addResources("music", "layout.buttons.hideButtons") diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/ChangeMiniplayerColor.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/ChangeMiniplayerColor.kt new file mode 100644 index 000000000..7a4d7d446 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/ChangeMiniplayerColor.kt @@ -0,0 +1,103 @@ +@file:Suppress("SpellCheckingInspection") + +package app.revanced.patches.music.layout.miniplayercolor + +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.patch.bytecodePatch +import app.revanced.patches.all.misc.resources.addResources +import app.revanced.patches.all.misc.resources.addResourcesPatch +import app.revanced.patches.music.misc.extension.sharedExtensionPatch +import app.revanced.patches.music.misc.settings.PreferenceScreen +import app.revanced.patches.music.misc.settings.settingsPatch +import app.revanced.patches.shared.misc.mapping.resourceMappingPatch +import app.revanced.patches.shared.misc.settings.preference.SwitchPreference +import app.revanced.util.addInstructionsAtControlFlowLabel +import app.revanced.util.findFreeRegister +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference + +private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/music/patches/ChangeMiniplayerColorPatch;" + +@Suppress("unused") +val changeMiniplayerColor = bytecodePatch( + name = "Change miniplayer color", + description = "Adds an option to change the miniplayer background color to match the fullscreen player." +) { + dependsOn( + sharedExtensionPatch, + settingsPatch, + addResourcesPatch, + resourceMappingPatch + ) + + compatibleWith( + "com.google.android.apps.youtube.music"( + "7.29.52", + "8.10.52" + ) + ) + + execute { + addResources("music", "layout.miniplayercolor.changeMiniplayerColor") + + PreferenceScreen.PLAYER.addPreferences( + SwitchPreference("revanced_music_change_miniplayer_color"), + ) + + switchToggleColorFingerprint.match(miniPlayerConstructorFingerprint.classDef).let { + val relativeIndex = it.patternMatch.endIndex + 1 + + val invokeVirtualIndex = it.method.indexOfFirstInstructionOrThrow( + relativeIndex, Opcode.INVOKE_VIRTUAL + ) + val colorMathPlayerInvokeVirtualReference = it.method + .getInstruction(invokeVirtualIndex).reference + + val iGetIndex = it.method.indexOfFirstInstructionOrThrow( + relativeIndex, Opcode.IGET + ) + val colorMathPlayerIGetReference = it.method + .getInstruction(iGetIndex).reference as FieldReference + + val colorGreyIndex = miniPlayerConstructorFingerprint.method.indexOfFirstInstructionReversedOrThrow { + getReference()?.name == "getColor" + } + val iPutIndex = miniPlayerConstructorFingerprint.method.indexOfFirstInstructionOrThrow( + colorGreyIndex, Opcode.IPUT + ) + val colorMathPlayerIPutReference = miniPlayerConstructorFingerprint.method + .getInstruction(iPutIndex).reference + + miniPlayerConstructorFingerprint.classDef.methods.single { method -> + method.accessFlags == AccessFlags.PUBLIC.value or AccessFlags.FINAL.value && + method.returnType == "V" && + method.parameters == it.originalMethod.parameters + }.apply { + val insertIndex = indexOfFirstInstructionReversedOrThrow(Opcode.INVOKE_DIRECT) + val freeRegister = findFreeRegister(insertIndex) + + addInstructionsAtControlFlowLabel( + insertIndex, + """ + invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->changeMiniplayerColor()Z + move-result v$freeRegister + if-eqz v$freeRegister, :off + invoke-virtual { p1 }, $colorMathPlayerInvokeVirtualReference + move-result-object v$freeRegister + check-cast v$freeRegister, ${colorMathPlayerIGetReference.definingClass} + iget v$freeRegister, v$freeRegister, $colorMathPlayerIGetReference + iput v$freeRegister, p0, $colorMathPlayerIPutReference + :off + nop + """ + ) + } + } + } +} diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/Fingerprints.kt new file mode 100644 index 000000000..c457f1000 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/Fingerprints.kt @@ -0,0 +1,30 @@ +package app.revanced.patches.music.layout.miniplayercolor + +import app.revanced.patcher.fingerprint +import app.revanced.patches.shared.misc.mapping.ResourceType +import app.revanced.patches.shared.misc.mapping.resourceLiteral +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode + +internal val miniPlayerConstructorFingerprint = fingerprint { + returns("V") + instructions( + resourceLiteral(ResourceType.ID, "mpp_player_bottom_sheet") + ) + strings("sharedToggleMenuItemMutations") +} + +/** + * Matches to the class found in [miniPlayerConstructorFingerprint]. + */ +internal val switchToggleColorFingerprint = fingerprint { + accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) + returns("V") + parameters("L", "J") + opcodes( + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CHECK_CAST, + Opcode.IGET + ) +} diff --git a/patches/src/main/resources/addresources/values-af-rZA/strings.xml b/patches/src/main/resources/addresources/values-af-rZA/strings.xml index 940171bf5..10b1bd7a2 100644 --- a/patches/src/main/resources/addresources/values-af-rZA/strings.xml +++ b/patches/src/main/resources/addresources/values-af-rZA/strings.xml @@ -1,5 +1,4 @@ -