refactor(YouTube Music/Settings): reorganize settings menu

This commit is contained in:
inotia00 2024-05-05 00:22:51 +09:00
parent 1f59997e53
commit 01795e0fb4
157 changed files with 2834 additions and 3725 deletions

View File

@ -1,62 +0,0 @@
package app.revanced.patches.music.account.component
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patches.music.account.component.fingerprints.MenuEntryFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.ACCOUNT_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.util.getTargetIndexWithMethodReferenceName
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@Suppress("unused")
object MenuComponentPatch : BaseBytecodePatch(
name = "Hide account menu",
description = "Adds the ability to hide account menu elements using a custom filter.",
dependencies = setOf(
SettingsPatch::class,
SharedResourceIdPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(MenuEntryFingerprint)
) {
override fun execute(context: BytecodeContext) {
MenuEntryFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val textIndex = getTargetIndexWithMethodReferenceName("setText")
val viewIndex = getTargetIndexWithMethodReferenceName("addView")
val textRegister = getInstruction<FiveRegisterInstruction>(textIndex).registerD
val viewRegister = getInstruction<FiveRegisterInstruction>(viewIndex).registerD
addInstruction(
textIndex + 1,
"invoke-static {v$textRegister, v$viewRegister}, $ACCOUNT_CLASS_DESCRIPTOR->hideAccountMenu(Ljava/lang/CharSequence;Landroid/view/View;)V"
)
}
}
SettingsPatch.addSwitchPreference(
CategoryType.ACCOUNT,
"revanced_hide_account_menu",
"false"
)
SettingsPatch.addPreferenceWithIntent(
CategoryType.ACCOUNT,
"revanced_hide_account_menu_filter_strings",
"revanced_hide_account_menu"
)
SettingsPatch.addSwitchPreference(
CategoryType.ACCOUNT,
"revanced_hide_account_menu_empty_component",
"false",
"revanced_hide_account_menu"
)
}
}

View File

@ -0,0 +1,145 @@
package app.revanced.patches.music.account.components
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.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patches.music.account.components.fingerprints.AccountSwitcherAccessibilityLabelFingerprint
import app.revanced.patches.music.account.components.fingerprints.MenuEntryFingerprint
import app.revanced.patches.music.account.components.fingerprints.NamesInactiveAccountThumbnailSizeFingerprint
import app.revanced.patches.music.account.components.fingerprints.TermsOfServiceFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.ACCOUNT_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.util.getTargetIndexWithMethodReferenceName
import app.revanced.util.getTargetIndexWithReference
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Suppress("unused")
object AccountComponentsPatch : BaseBytecodePatch(
name = "Hide account components",
description = "Adds the options to hide components related to account menu.",
dependencies = setOf(
SettingsPatch::class,
SharedResourceIdPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(
AccountSwitcherAccessibilityLabelFingerprint,
MenuEntryFingerprint,
NamesInactiveAccountThumbnailSizeFingerprint,
TermsOfServiceFingerprint,
)
) {
override fun execute(context: BytecodeContext) {
// region patch for hide account menu
MenuEntryFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val textIndex = getTargetIndexWithMethodReferenceName("setText")
val viewIndex = getTargetIndexWithMethodReferenceName("addView")
val textRegister = getInstruction<FiveRegisterInstruction>(textIndex).registerD
val viewRegister = getInstruction<FiveRegisterInstruction>(viewIndex).registerD
addInstruction(
textIndex + 1,
"invoke-static {v$textRegister, v$viewRegister}, $ACCOUNT_CLASS_DESCRIPTOR->hideAccountMenu(Ljava/lang/CharSequence;Landroid/view/View;)V"
)
}
}
// endregion
// region patch for hide handle
// account menu
AccountSwitcherAccessibilityLabelFingerprint.resultOrThrow().let { result ->
result.mutableMethod.apply {
val textColorIndex = getTargetIndexWithMethodReferenceName("setTextColor")
val setVisibilityIndex = getTargetIndexWithMethodReferenceName(textColorIndex, "setVisibility")
val textViewInstruction = getInstruction<FiveRegisterInstruction>(setVisibilityIndex)
replaceInstruction(
setVisibilityIndex,
"invoke-static {v${textViewInstruction.registerC}, v${textViewInstruction.registerD}}, $ACCOUNT_CLASS_DESCRIPTOR->hideHandle(Landroid/widget/TextView;I)V"
)
}
}
// account switcher
NamesInactiveAccountThumbnailSizeFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val targetIndex = it.scanResult.patternScanResult!!.startIndex
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstructions(
targetIndex, """
invoke-static {v$targetRegister}, $ACCOUNT_CLASS_DESCRIPTOR->hideHandle(Z)Z
move-result v$targetRegister
"""
)
}
}
// endregion
// region patch for hide terms container
TermsOfServiceFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val insertIndex = getTargetIndexWithReference("/PrivacyTosFooter;->setVisibility(I)V")
val visibilityRegister =
getInstruction<FiveRegisterInstruction>(insertIndex).registerD
addInstruction(
insertIndex + 1,
"const/4 v$visibilityRegister, 0x0"
)
addInstructions(
insertIndex, """
invoke-static {}, $ACCOUNT_CLASS_DESCRIPTOR->hideTermsContainer()I
move-result v$visibilityRegister
"""
)
}
}
// endregion
SettingsPatch.addSwitchPreference(
CategoryType.ACCOUNT,
"revanced_hide_account_menu",
"false"
)
SettingsPatch.addPreferenceWithIntent(
CategoryType.ACCOUNT,
"revanced_hide_account_menu_filter_strings",
"revanced_hide_account_menu"
)
SettingsPatch.addSwitchPreference(
CategoryType.ACCOUNT,
"revanced_hide_account_menu_empty_component",
"false",
"revanced_hide_account_menu"
)
SettingsPatch.addSwitchPreference(
CategoryType.ACCOUNT,
"revanced_hide_handle",
"true"
)
SettingsPatch.addSwitchPreference(
CategoryType.ACCOUNT,
"revanced_hide_terms_container",
"false"
)
}
}

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.account.handle.fingerprints
package app.revanced.patches.music.account.components.fingerprints
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.AccountSwitcherAccessibility
import app.revanced.util.fingerprint.LiteralValueFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.account.component.fingerprints
package app.revanced.patches.music.account.components.fingerprints
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MenuEntry
import app.revanced.util.fingerprint.LiteralValueFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.account.handle.fingerprints
package app.revanced.patches.music.account.components.fingerprints
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.NamesInactiveAccountThumbnailSize
import app.revanced.util.fingerprint.LiteralValueFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.account.tos.fingerprints
package app.revanced.patches.music.account.components.fingerprints
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.TosFooter
import app.revanced.util.fingerprint.LiteralValueFingerprint

View File

@ -1,77 +0,0 @@
package app.revanced.patches.music.account.handle
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patches.music.account.handle.fingerprints.AccountSwitcherAccessibilityLabelFingerprint
import app.revanced.patches.music.account.handle.fingerprints.NamesInactiveAccountThumbnailSizeFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.ACCOUNT_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.util.getTargetIndexWithMethodReferenceName
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Suppress("unused")
object HandlePatch : BaseBytecodePatch(
name = "Hide handle",
description = "Adds an option to hide the handle in the account menu.",
dependencies = setOf(
SettingsPatch::class,
SharedResourceIdPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(
AccountSwitcherAccessibilityLabelFingerprint,
NamesInactiveAccountThumbnailSizeFingerprint
)
) {
override fun execute(context: BytecodeContext) {
/**
* Hide handle in account menu
*/
AccountSwitcherAccessibilityLabelFingerprint.resultOrThrow().let { result ->
result.mutableMethod.apply {
val textColorIndex = getTargetIndexWithMethodReferenceName("setTextColor")
val setVisibilityIndex = getTargetIndexWithMethodReferenceName(textColorIndex, "setVisibility")
val textViewInstruction = getInstruction<FiveRegisterInstruction>(setVisibilityIndex)
replaceInstruction(
setVisibilityIndex,
"invoke-static {v${textViewInstruction.registerC}, v${textViewInstruction.registerD}}, $ACCOUNT_CLASS_DESCRIPTOR->hideHandle(Landroid/widget/TextView;I)V"
)
}
}
/**
* Hide handle in account switcher
*/
NamesInactiveAccountThumbnailSizeFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val targetIndex = it.scanResult.patternScanResult!!.startIndex
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstructions(
targetIndex, """
invoke-static {v$targetRegister}, $ACCOUNT_CLASS_DESCRIPTOR->hideHandle(Z)Z
move-result v$targetRegister
"""
)
}
}
SettingsPatch.addSwitchPreference(
CategoryType.ACCOUNT,
"revanced_hide_handle",
"true"
)
}
}

View File

@ -1,57 +0,0 @@
package app.revanced.patches.music.account.tos
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.music.account.tos.fingerprints.TermsOfServiceFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.ACCOUNT_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.util.getTargetIndexWithReference
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@Suppress("unused")
object TermsContainerPatch : BaseBytecodePatch(
name = "Hide terms container",
description = "Adds an option to hide the terms of service container in the account menu.",
dependencies = setOf(
SettingsPatch::class,
SharedResourceIdPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(TermsOfServiceFingerprint)
) {
override fun execute(context: BytecodeContext) {
TermsOfServiceFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val insertIndex = getTargetIndexWithReference("/PrivacyTosFooter;->setVisibility(I)V")
val visibilityRegister =
getInstruction<FiveRegisterInstruction>(insertIndex).registerD
addInstruction(
insertIndex + 1,
"const/4 v$visibilityRegister, 0x0"
)
addInstructions(
insertIndex, """
invoke-static {}, $ACCOUNT_CLASS_DESCRIPTOR->hideTermsContainer()I
move-result v$visibilityRegister
"""
)
}
}
SettingsPatch.addSwitchPreference(
CategoryType.ACCOUNT,
"revanced_hide_terms_container",
"false"
)
}
}

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.actionbar.component
package app.revanced.patches.music.actionbar.components
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
@ -6,8 +6,8 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.music.actionbar.component.fingerprints.ActionBarComponentFingerprint
import app.revanced.patches.music.actionbar.component.fingerprints.LikeDislikeContainerFingerprint
import app.revanced.patches.music.actionbar.components.fingerprints.ActionBarComponentFingerprint
import app.revanced.patches.music.actionbar.components.fingerprints.LikeDislikeContainerFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.ACTIONBAR_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
@ -29,8 +29,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import kotlin.math.min
@Suppress("unused")
object ActionBarComponentPatch : BaseBytecodePatch(
name = "Hide action bar component",
object ActionBarComponentsPatch : BaseBytecodePatch(
name = "Hide action bar components",
description = "Adds options to hide action bar components and replace the offline download button with an external download button.",
dependencies = setOf(
SettingsPatch::class,
@ -53,7 +53,7 @@ object ActionBarComponentPatch : BaseBytecodePatch(
addInstruction(
addViewIndex + 1,
"invoke-static {v$addViewRegister}, $ACTIONBAR_CLASS_DESCRIPTOR->hookDownloadButton(Landroid/view/View;)V"
"invoke-static {v$addViewRegister}, $ACTIONBAR_CLASS_DESCRIPTOR->inAppDownloadButtonOnClick(Landroid/view/View;)V"
)
// hide action button label
@ -132,7 +132,7 @@ object ActionBarComponentPatch : BaseBytecodePatch(
SettingsPatch.addSwitchPreference(
CategoryType.ACTION_BAR,
"revanced_hide_action_button_add_to_playlist",
"revanced_hide_action_button_like_dislike",
"false"
)
SettingsPatch.addSwitchPreference(
@ -140,26 +140,16 @@ object ActionBarComponentPatch : BaseBytecodePatch(
"revanced_hide_action_button_comment",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.ACTION_BAR,
"revanced_hide_action_button_add_to_playlist",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.ACTION_BAR,
"revanced_hide_action_button_download",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.ACTION_BAR,
"revanced_hide_action_button_label",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.ACTION_BAR,
"revanced_hide_action_button_like_dislike",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.ACTION_BAR,
"revanced_hide_action_button_radio",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.ACTION_BAR,
"revanced_hide_action_button_share",
@ -167,13 +157,23 @@ object ActionBarComponentPatch : BaseBytecodePatch(
)
SettingsPatch.addSwitchPreference(
CategoryType.ACTION_BAR,
"revanced_hook_action_button_download",
"revanced_hide_action_button_radio",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.ACTION_BAR,
"revanced_hide_action_button_label",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.ACTION_BAR,
"revanced_external_downloader_action",
"false"
)
SettingsPatch.addPreferenceWithIntent(
CategoryType.ACTION_BAR,
"revanced_external_downloader_package_name",
"revanced_hook_action_button_download"
"revanced_external_downloader_action"
)
}

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.actionbar.component.fingerprints
package app.revanced.patches.music.actionbar.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.util.fingerprint.LiteralValueFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.actionbar.component.fingerprints
package app.revanced.patches.music.actionbar.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.LikeDislikeContainer

View File

@ -2,14 +2,19 @@ package app.revanced.patches.music.ads.general
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.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.music.ads.general.fingerprints.AccountMenuFooterFingerprint
import app.revanced.patches.music.ads.general.fingerprints.FloatingLayoutFingerprint
import app.revanced.patches.music.ads.general.fingerprints.GetPremiumTextViewFingerprint
import app.revanced.patches.music.ads.general.fingerprints.InterstitialsContainerFingerprint
import app.revanced.patches.music.ads.general.fingerprints.MembershipSettingsFingerprint
import app.revanced.patches.music.ads.general.fingerprints.MembershipSettingsParentFingerprint
import app.revanced.patches.music.ads.general.fingerprints.NotifierShelfFingerprint
import app.revanced.patches.music.ads.general.fingerprints.ShowDialogCommandFingerprint
import app.revanced.patches.music.ads.music.MusicAdsPatch
import app.revanced.patches.music.navigation.components.NavigationBarComponentsPatch
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.ADS_PATH
import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH
@ -20,25 +25,35 @@ import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.Interst
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.patches.shared.litho.LithoFilterPatch
import app.revanced.util.getTargetIndex
import app.revanced.util.getTargetIndexWithReference
import app.revanced.util.getWalkerMethod
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.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@Suppress("unused")
object GeneralAdsPatch : BaseBytecodePatch(
name = "Hide general ads",
description = "Adds options to hide general ads.",
object AdsPatch : BaseBytecodePatch(
name = "Hide ads",
description = "Adds options to hide ads.",
dependencies = setOf(
LithoFilterPatch::class,
MusicAdsPatch::class,
NavigationBarComponentsPatch::class, // for 'Hide upgrade button' setting
SettingsPatch::class,
SharedResourceIdPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(
AccountMenuFooterFingerprint,
FloatingLayoutFingerprint,
GetPremiumTextViewFingerprint,
InterstitialsContainerFingerprint,
MembershipSettingsParentFingerprint,
NotifierShelfFingerprint,
ShowDialogCommandFingerprint
)
@ -58,10 +73,9 @@ object GeneralAdsPatch : BaseBytecodePatch(
override fun execute(context: BytecodeContext) {
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
/**
* Hides fullscreen ads
* Non-litho view, used in some old clients.
*/
// region patch for hide fullscreen ads
// non-litho view, used in some old clients
InterstitialsContainerFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val targetIndex = getWideLiteralInstructionIndex(InterstitialsContainer) + 2
@ -74,10 +88,7 @@ object GeneralAdsPatch : BaseBytecodePatch(
}
}
/**
* Hides fullscreen ads
* Litho view, used in 'ShowDialogCommandOuterClass' in innertube
*/
// litho view, used in 'ShowDialogCommandOuterClass' in innertube
ShowDialogCommandFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
// In this method, custom dialog is created and shown.
@ -127,9 +138,10 @@ object GeneralAdsPatch : BaseBytecodePatch(
}
}
/**
* Hides premium promotion popup
*/
// endregion
// region patch for hide premium promotion popup
FloatingLayoutFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val targetIndex = getWideLiteralInstructionIndex(FloatingLayout) + 2
@ -142,9 +154,10 @@ object GeneralAdsPatch : BaseBytecodePatch(
}
}
/**
* Hides premium renewal banner
*/
// endregion
// region patch for hide premium renewal banner
NotifierShelfFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val linearLayoutIndex = getWideLiteralInstructionIndex(ButtonContainer) + 3
@ -158,6 +171,59 @@ object GeneralAdsPatch : BaseBytecodePatch(
}
}
// endregion
// region patch for hide get premium
// get premium button at the top of the account switching menu
GetPremiumTextViewFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.startIndex
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
addInstruction(
insertIndex + 1,
"const/4 v$register, 0x0"
)
}
}
// get premium button at the bottom of the account switching menu
AccountMenuFooterFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val constIndex = getWideLiteralInstructionIndex(SharedResourceIdPatch.PrivacyTosFooter)
val walkerIndex = getTargetIndex(constIndex + 2, Opcode.INVOKE_VIRTUAL)
val viewIndex = getTargetIndex(constIndex, Opcode.IGET_OBJECT)
val viewReference = getInstruction<ReferenceInstruction>(viewIndex).reference.toString()
val walkerMethod = getWalkerMethod(context, walkerIndex)
walkerMethod.apply {
val insertIndex = getTargetIndexWithReference(viewReference)
val nullCheckIndex = getTargetIndex(insertIndex - 1, Opcode.IF_NEZ)
val nullCheckRegister = getInstruction<OneRegisterInstruction>(nullCheckIndex).registerA
addInstruction(
nullCheckIndex,
"const/4 v$nullCheckRegister, 0x0"
)
}
}
}
// premium membership menu in settings
MembershipSettingsFingerprint.resolve(
context,
MembershipSettingsParentFingerprint.resultOrThrow().classDef
)
MembershipSettingsFingerprint.resultOrThrow().mutableMethod.addInstructions(
0, """
const/4 v0, 0x0
return-object v0
"""
)
// endregion
SettingsPatch.addSwitchPreference(
CategoryType.ADS,
"revanced_hide_fullscreen_ads",
@ -175,7 +241,7 @@ object GeneralAdsPatch : BaseBytecodePatch(
)
SettingsPatch.addSwitchPreference(
CategoryType.ADS,
"revanced_hide_paid_promotion",
"revanced_hide_paid_promotion_label",
"true"
)
SettingsPatch.addSwitchPreference(

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.ads.music
package app.revanced.patches.music.ads.general
import app.revanced.patches.music.utils.integrations.Constants.ADS_PATH
import app.revanced.patches.shared.ads.BaseAdsPatch

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.misc.premium.fingerprints
package app.revanced.patches.music.ads.general.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.PrivacyTosFooter

View File

@ -1,11 +1,11 @@
package app.revanced.patches.music.misc.premium.fingerprints
package app.revanced.patches.music.ads.general.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object HideGetPremiumFingerprint : MethodFingerprint(
internal object GetPremiumTextViewFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(),

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.misc.premium.fingerprints
package app.revanced.patches.music.ads.general.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.misc.premium.fingerprints
package app.revanced.patches.music.ads.general.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -0,0 +1,420 @@
package app.revanced.patches.music.flyoutmenu.components
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.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.music.flyoutmenu.components.fingerprints.DialogSolidFingerprint
import app.revanced.patches.music.flyoutmenu.components.fingerprints.EndButtonsContainerFingerprint
import app.revanced.patches.music.flyoutmenu.components.fingerprints.MenuItemFingerprint
import app.revanced.patches.music.flyoutmenu.components.fingerprints.SleepTimerFingerprint
import app.revanced.patches.music.flyoutmenu.components.fingerprints.TouchOutsideFingerprint
import app.revanced.patches.music.flyoutmenu.components.fingerprints.TrimSilenceConfigFingerprint
import app.revanced.patches.music.flyoutmenu.components.fingerprints.TrimSilenceSwitchFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.flyoutmenu.FlyoutMenuHookPatch
import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH
import app.revanced.patches.music.utils.integrations.Constants.FLYOUT_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.EndButtonsContainer
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.patches.music.utils.videotype.VideoTypeHookPatch
import app.revanced.patches.music.video.information.VideoInformationPatch
import app.revanced.patches.shared.litho.LithoFilterPatch
import app.revanced.util.getTargetIndex
import app.revanced.util.getTargetIndexWithMethodReferenceName
import app.revanced.util.getWalkerMethod
import app.revanced.util.getWideLiteralInstructionIndex
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.literalInstructionBooleanHook
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.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@Suppress("unused")
object FlyoutMenuComponentsPatch : BaseBytecodePatch(
name = "Flyout menu components",
description = "Adds options to hide or change flyout menu components.",
dependencies = setOf(
FlyoutMenuComponentsResourcePatch::class,
FlyoutMenuHookPatch::class,
LithoFilterPatch::class,
SettingsPatch::class,
SharedResourceIdPatch::class,
VideoInformationPatch::class,
VideoTypeHookPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(
DialogSolidFingerprint,
EndButtonsContainerFingerprint,
MenuItemFingerprint,
SleepTimerFingerprint,
TouchOutsideFingerprint,
TrimSilenceConfigFingerprint,
TrimSilenceSwitchFingerprint
)
) {
private const val FILTER_CLASS_DESCRIPTOR =
"$COMPONENTS_PATH/PlayerFlyoutMenuFilter;"
override fun execute(context: BytecodeContext) {
var trimSilenceIncluded = false
// region patch for enable compact dialog
DialogSolidFingerprint.resultOrThrow().let {
val walkerMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex)
walkerMethod.addInstructions(
2, """
invoke-static {p0}, $FLYOUT_CLASS_DESCRIPTOR->enableCompactDialog(I)I
move-result p0
"""
)
}
// endregion
// region patch for enable trim silence
TrimSilenceConfigFingerprint.result?.let {
TrimSilenceConfigFingerprint.literalInstructionBooleanHook(
45619123,
"$FLYOUT_CLASS_DESCRIPTOR->enableTrimSilence(Z)Z"
)
TrimSilenceSwitchFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val constIndex = getWideLiteralInstructionIndex(SharedResourceIdPatch.TrimSilenceSwitch)
val onCheckedChangedListenerIndex = getTargetIndex(constIndex, Opcode.INVOKE_DIRECT)
val onCheckedChangedListenerReference = getInstruction<ReferenceInstruction>(onCheckedChangedListenerIndex).reference
val onCheckedChangedListenerDefiningClass = (onCheckedChangedListenerReference as MethodReference).definingClass
val onCheckedChangedListenerClass =
context.findClass(onCheckedChangedListenerDefiningClass)!!.mutableClass
onCheckedChangedListenerClass.methods.find { method -> method.name == "onCheckedChanged" }
?.apply {
val walkerIndex = indexOfFirstInstruction {
val reference = ((this as? ReferenceInstruction)?.reference as? MethodReference)
opcode == Opcode.INVOKE_VIRTUAL
&& reference?.returnType == "V"
&& reference.parameterTypes.size == 1
&& reference.parameterTypes[0] == "Z"
}
getWalkerMethod(context, walkerIndex).apply {
val insertIndex = getTargetIndex(Opcode.MOVE_RESULT)
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstructions(
insertIndex + 1, """
invoke-static {v$insertRegister}, $FLYOUT_CLASS_DESCRIPTOR->enableTrimSilenceSwitch(Z)Z
move-result v$insertRegister
"""
)
}
} ?: throw PatchException("onClickClass not found!")
}
}
trimSilenceIncluded = true
}
// endregion
// region patch for hide flyout menu components and replace menu
MenuItemFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val freeIndex = getTargetIndex(Opcode.OR_INT_LIT16)
val textViewIndex = it.scanResult.patternScanResult!!.startIndex
val imageViewIndex = it.scanResult.patternScanResult!!.endIndex
val freeRegister =
getInstruction<TwoRegisterInstruction>(freeIndex).registerA
val textViewRegister =
getInstruction<OneRegisterInstruction>(textViewIndex).registerA
val imageViewRegister =
getInstruction<OneRegisterInstruction>(imageViewIndex).registerA
val enumIndex = indexOfFirstInstruction {
opcode == Opcode.INVOKE_STATIC
&& (this as? ReferenceInstruction)?.reference.toString().contains("(I)L")
} + 1
val enumRegister = getInstruction<OneRegisterInstruction>(enumIndex).registerA
addInstructionsWithLabels(
enumIndex + 1, """
invoke-static {v$enumRegister, v$textViewRegister, v$imageViewRegister}, $FLYOUT_CLASS_DESCRIPTOR->replaceComponents(Ljava/lang/Enum;Landroid/widget/TextView;Landroid/widget/ImageView;)V
invoke-static {v$enumRegister}, $FLYOUT_CLASS_DESCRIPTOR->hideComponents(Ljava/lang/Enum;)Z
move-result v$freeRegister
if-nez v$freeRegister, :hide
""", ExternalLabel("hide", getInstruction(implementation!!.instructions.size - 1))
)
}
}
TouchOutsideFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val setOnClickListenerIndex = getTargetIndexWithMethodReferenceName("setOnClickListener")
val setOnClickListenerRegister = getInstruction<FiveRegisterInstruction>(setOnClickListenerIndex).registerC
addInstruction(
setOnClickListenerIndex + 1,
"invoke-static {v$setOnClickListenerRegister}, $FLYOUT_CLASS_DESCRIPTOR->setTouchOutSideView(Landroid/view/View;)V"
)
}
}
EndButtonsContainerFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val startIndex = getWideLiteralInstructionIndex(EndButtonsContainer)
val targetIndex = getTargetIndex(startIndex, Opcode.MOVE_RESULT_OBJECT)
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstruction(
targetIndex + 1,
"invoke-static {v$targetRegister}, $FLYOUT_CLASS_DESCRIPTOR->hideLikeDislikeContainer(Landroid/view/View;)V"
)
}
}
// endregion
// region patch for enable sleep timer
/**
* Forces sleep timer menu to be enabled.
* This method may be desperate in the future.
*/
SleepTimerFingerprint.result?.let {
it.mutableMethod.apply {
val insertIndex = implementation!!.instructions.size - 1
val targetRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstruction(
insertIndex,
"const/4 v$targetRegister, 0x1"
)
}
}
// endregion
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_enable_compact_dialog",
"true"
)
if (trimSilenceIncluded) {
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_enable_trim_silence",
"true"
)
}
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_like_dislike",
"false",
false
)
if (SettingsPatch.upward0636) {
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_3_column_component",
"false",
false
)
}
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_add_to_queue",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_captions",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_delete_playlist",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_dismiss_queue",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_download",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_edit_playlist",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_go_to_album",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_go_to_artist",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_go_to_episode",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_go_to_podcast",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_help",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_play_next",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_quality",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_remove_from_library",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_remove_from_playlist",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_report",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_save_episode_for_later",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_save_to_library",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_save_to_playlist",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_share",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_shuffle_play",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_sleep_timer",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_start_radio",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_stats_for_nerds",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_subscribe",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_menu_view_song_credit",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_replace_flyout_menu_dismiss_queue",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_replace_flyout_menu_dismiss_queue_continue_watch",
"true",
"revanced_replace_flyout_menu_dismiss_queue"
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_replace_flyout_menu_report",
"true"
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_replace_flyout_menu_report_only_player",
"true",
"revanced_replace_flyout_menu_report"
)
}
}

View File

@ -1,11 +1,11 @@
package app.revanced.patches.music.flyoutpanel.replace
package app.revanced.patches.music.flyoutmenu.components
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.util.ResourceGroup
import app.revanced.util.copyResources
object ReplaceReportResourcePatch : ResourcePatch() {
object FlyoutMenuComponentsResourcePatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
fun copyResources(resourceGroups: List<ResourceGroup>) {

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.flyoutpanel.compactdialog.fingerprints
package app.revanced.patches.music.flyoutmenu.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.DialogSolid

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.flyoutpanel.component.fingerprints
package app.revanced.patches.music.flyoutmenu.components.fingerprints
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.EndButtonsContainer
import app.revanced.util.fingerprint.LiteralValueFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.flyoutpanel.shared.fingerprints
package app.revanced.patches.music.flyoutmenu.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.flyoutpanel.component.fingerprints
package app.revanced.patches.music.flyoutmenu.components.fingerprints
import app.revanced.util.fingerprint.LiteralValueFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.flyoutpanel.replace.fingerprints
package app.revanced.patches.music.flyoutmenu.components.fingerprints
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.TouchOutside
import app.revanced.util.fingerprint.LiteralValueFingerprint

View File

@ -0,0 +1,8 @@
package app.revanced.patches.music.flyoutmenu.components.fingerprints
import app.revanced.util.fingerprint.LiteralValueFingerprint
object TrimSilenceConfigFingerprint : LiteralValueFingerprint(
returnType = "Z",
literalSupplier = { 45619123 }
)

View File

@ -0,0 +1,13 @@
package app.revanced.patches.music.flyoutmenu.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.TrimSilenceSwitch
import app.revanced.util.fingerprint.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
object TrimSilenceSwitchFingerprint : LiteralValueFingerprint(
returnType = "Landroid/view/View;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
literalSupplier = { TrimSilenceSwitch }
)

View File

@ -1,44 +0,0 @@
package app.revanced.patches.music.flyoutpanel.compactdialog
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patches.music.flyoutpanel.compactdialog.fingerprints.DialogSolidFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.FLYOUT_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.util.getWalkerMethod
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
@Suppress("unused")
object CompactDialogPatch : BaseBytecodePatch(
name = "Enable compact dialog",
description = "Adds an option to enable the compact flyout menu on phones.",
dependencies = setOf(
SettingsPatch::class,
SharedResourceIdPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(DialogSolidFingerprint)
) {
override fun execute(context: BytecodeContext) {
DialogSolidFingerprint.resultOrThrow().let {
val walkerMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex)
walkerMethod.addInstructions(
2, """
invoke-static {p0}, $FLYOUT_CLASS_DESCRIPTOR->enableCompactDialog(I)I
move-result p0
"""
)
}
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_enable_compact_dialog",
"true"
)
}
}

View File

@ -1,248 +0,0 @@
package app.revanced.patches.music.flyoutpanel.component
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patches.music.flyoutpanel.component.fingerprints.EndButtonsContainerFingerprint
import app.revanced.patches.music.flyoutpanel.component.fingerprints.SleepTimerFingerprint
import app.revanced.patches.music.flyoutpanel.shared.FlyoutPanelMenuItemPatch
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH
import app.revanced.patches.music.utils.integrations.Constants.FLYOUT_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.EndButtonsContainer
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.patches.shared.litho.LithoFilterPatch
import app.revanced.util.getTargetIndex
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
@Suppress("unused")
object FlyoutPanelPatch : BaseBytecodePatch(
name = "Hide flyout panel",
description = "Adds options to hide flyout panel components.",
dependencies = setOf(
FlyoutPanelMenuItemPatch::class,
LithoFilterPatch::class,
SettingsPatch::class,
SharedResourceIdPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(
EndButtonsContainerFingerprint,
SleepTimerFingerprint
)
) {
private const val FILTER_CLASS_DESCRIPTOR =
"$COMPONENTS_PATH/PlayerFlyoutPanelsFilter;"
override fun execute(context: BytecodeContext) {
FlyoutPanelMenuItemPatch.hideComponents()
EndButtonsContainerFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val startIndex = getWideLiteralInstructionIndex(EndButtonsContainer)
val targetIndex = getTargetIndex(startIndex, Opcode.MOVE_RESULT_OBJECT)
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstruction(
targetIndex + 1,
"invoke-static {v$targetRegister}, $FLYOUT_CLASS_DESCRIPTOR->hideLikeDislikeContainer(Landroid/view/View;)V"
)
}
}
/**
* Forces sleep timer menu to be enabled.
* This method may be desperate in the future.
*/
SleepTimerFingerprint.result?.let {
it.mutableMethod.apply {
val insertIndex = implementation!!.instructions.size - 1
val targetRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstruction(
insertIndex,
"const/4 v$targetRegister, 0x1"
)
}
}
if (SettingsPatch.upward0636) {
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_3_column_component",
"false"
)
}
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_add_to_queue",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_captions",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_delete_playlist",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_dismiss_queue",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_download",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_edit_playlist",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_go_to_album",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_go_to_artist",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_go_to_episode",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_go_to_podcast",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_help",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_like_dislike",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_play_next",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_quality",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_remove_from_library",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_remove_from_playlist",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_report",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_save_episode_for_later",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_save_to_library",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_save_to_playlist",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_share",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_shuffle_play",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_sleep_timer",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_start_radio",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_stats_for_nerds",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_subscribe",
"false",
false
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_hide_flyout_panel_view_song_credit",
"false",
false
)
}
}

View File

@ -1,38 +0,0 @@
package app.revanced.patches.music.flyoutpanel.replace
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patches.music.flyoutpanel.shared.FlyoutPanelMenuItemPatch
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.patches.music.video.information.VideoInformationPatch
import app.revanced.util.patch.BaseBytecodePatch
@Suppress("unused")
object ReplaceDismissQueuePatch : BaseBytecodePatch(
name = "Replace dismiss queue",
description = "Adds an option to replace \"Dismiss queue\" with \"Watch on YouTube\" in the flyout menu.",
dependencies = setOf(
FlyoutPanelMenuItemPatch::class,
SettingsPatch::class,
VideoInformationPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE
) {
override fun execute(context: BytecodeContext) {
FlyoutPanelMenuItemPatch.replaceComponents()
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_replace_flyout_panel_dismiss_queue",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_replace_flyout_panel_dismiss_queue_continue_watch",
"true",
"revanced_replace_flyout_panel_dismiss_queue"
)
}
}

View File

@ -1,63 +0,0 @@
package app.revanced.patches.music.flyoutpanel.replace
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patches.music.flyoutpanel.replace.fingerprints.TouchOutsideFingerprint
import app.revanced.patches.music.flyoutpanel.shared.FlyoutPanelMenuItemPatch
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.flyoutpanel.PlaybackSpeedFlyoutPanelHookPatch
import app.revanced.patches.music.utils.integrations.Constants.FLYOUT_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.patches.music.video.information.VideoInformationPatch
import app.revanced.util.getTargetIndexWithMethodReferenceName
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@Suppress("unused")
object ReplaceReportPatch : BaseBytecodePatch(
name = "Replace report",
description = "Adds an option to replace \"Report\" with \"Playback speed\" in the flyout menu.",
dependencies = setOf(
FlyoutPanelMenuItemPatch::class,
PlaybackSpeedFlyoutPanelHookPatch::class,
ReplaceReportResourcePatch::class,
SettingsPatch::class,
SharedResourceIdPatch::class,
VideoInformationPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(TouchOutsideFingerprint)
) {
override fun execute(context: BytecodeContext) {
FlyoutPanelMenuItemPatch.replaceComponents()
TouchOutsideFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val setOnClickListenerIndex = getTargetIndexWithMethodReferenceName("setOnClickListener")
val setOnClickListenerRegister = getInstruction<FiveRegisterInstruction>(setOnClickListenerIndex).registerC
addInstruction(
setOnClickListenerIndex + 1,
"sput-object v$setOnClickListenerRegister, $FLYOUT_CLASS_DESCRIPTOR->touchOutSideView:Landroid/view/View;"
)
}
}
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_replace_flyout_panel_report",
"true"
)
SettingsPatch.addSwitchPreference(
CategoryType.FLYOUT,
"revanced_replace_flyout_panel_report_only_player",
"true",
"revanced_replace_flyout_panel_report"
)
}
}

View File

@ -1,83 +0,0 @@
package app.revanced.patches.music.flyoutpanel.shared
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.patch.BytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.music.flyoutpanel.shared.fingerprints.MenuItemFingerprint
import app.revanced.patches.music.utils.integrations.Constants.FLYOUT_CLASS_DESCRIPTOR
import app.revanced.util.getTargetIndex
import app.revanced.util.indexOfFirstInstruction
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.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import kotlin.properties.Delegates
object FlyoutPanelMenuItemPatch : BytecodePatch(
setOf(MenuItemFingerprint)
) {
private lateinit var menuItemMethod: MutableMethod
private var freeRegister by Delegates.notNull<Int>()
private var textViewRegister by Delegates.notNull<Int>()
private var imageViewRegister by Delegates.notNull<Int>()
private var instructionAdded = false
override fun execute(context: BytecodeContext) {
MenuItemFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val freeIndex = getTargetIndex(Opcode.OR_INT_LIT16)
val textViewIndex = it.scanResult.patternScanResult!!.startIndex
val imageViewIndex = it.scanResult.patternScanResult!!.endIndex
freeRegister =
getInstruction<TwoRegisterInstruction>(freeIndex).registerA
textViewRegister =
getInstruction<OneRegisterInstruction>(textViewIndex).registerA
imageViewRegister =
getInstruction<OneRegisterInstruction>(imageViewIndex).registerA
menuItemMethod = this
}
}
}
private fun MutableMethod.getEnumIndex() = indexOfFirstInstruction {
opcode == Opcode.INVOKE_STATIC
&& (this as? ReferenceInstruction)?.reference.toString().contains("(I)L")
} + 1
internal fun hideComponents() {
menuItemMethod.apply {
val enumIndex = getEnumIndex()
val enumRegister = getInstruction<OneRegisterInstruction>(enumIndex).registerA
addInstructionsWithLabels(
enumIndex + 1, """
invoke-static {v$enumRegister}, $FLYOUT_CLASS_DESCRIPTOR->hideComponents(Ljava/lang/Enum;)Z
move-result v$freeRegister
if-nez v$freeRegister, :hide
""", ExternalLabel("hide", getInstruction(implementation!!.instructions.size - 1))
)
}
}
internal fun replaceComponents() {
if (!instructionAdded) {
menuItemMethod.apply {
val enumIndex = getEnumIndex()
val enumRegister = getInstruction<OneRegisterInstruction>(enumIndex).registerA
addInstruction(
enumIndex + 1,
"invoke-static {v$enumRegister, v$textViewRegister, v$imageViewRegister}, $FLYOUT_CLASS_DESCRIPTOR->replaceComponents(Ljava/lang/Enum;Landroid/widget/TextView;Landroid/widget/ImageView;)V"
)
}
instructionAdded = true
}
}
}

View File

@ -21,7 +21,7 @@ object AutoCaptionsPatch : BaseResourcePatch(
) {
override fun execute(context: ResourceContext) {
VideoIdPatch.hookBackgroundPlayVideoId("$GENERAL_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;)V")
VideoIdPatch.hookVideoId("$GENERAL_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;)V")
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,

View File

@ -1,34 +0,0 @@
package app.revanced.patches.music.general.buttonshelf
import app.revanced.patcher.data.ResourceContext
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.patches.shared.litho.LithoFilterPatch
import app.revanced.util.patch.BaseResourcePatch
@Suppress("unused")
object ButtonShelfPatch : BaseResourcePatch(
name = "Hide button shelf",
description = "Adds an option to hide the button shelf from the homepage and explore tab.",
dependencies = setOf(
LithoFilterPatch::class,
SettingsPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE
) {
private const val FILTER_CLASS_DESCRIPTOR =
"$COMPONENTS_PATH/ButtonShelfFilter;"
override fun execute(context: ResourceContext) {
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_button_shelf",
"false"
)
}
}

View File

@ -1,34 +0,0 @@
package app.revanced.patches.music.general.carouselshelf
import app.revanced.patcher.data.ResourceContext
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.patches.shared.litho.LithoFilterPatch
import app.revanced.util.patch.BaseResourcePatch
@Suppress("unused")
object CarouselShelfPatch : BaseResourcePatch(
name = "Hide carousel shelf",
description = "Adds an option to hide the carousel shelf from the homepage and explore tab.",
dependencies = setOf(
LithoFilterPatch::class,
SettingsPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE
) {
private const val FILTER_CLASS_DESCRIPTOR =
"$COMPONENTS_PATH/CarouselShelfFilter;"
override fun execute(context: ResourceContext) {
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_carousel_shelf",
"false"
)
}
}

View File

@ -1,76 +0,0 @@
package app.revanced.patches.music.general.castbutton
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.patcher.patch.PatchException
import app.revanced.patches.music.general.castbutton.fingerprints.MediaRouteButtonFingerprint
import app.revanced.patches.music.general.castbutton.fingerprints.PlayerOverlayChipFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.PlayerOverlayChip
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.util.getWideLiteralInstructionIndex
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Suppress("unused")
object CastButtonPatch : BaseBytecodePatch(
name = "Hide cast button",
description = "Adds an option to hide the cast button.",
dependencies = setOf(
SettingsPatch::class,
SharedResourceIdPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(
MediaRouteButtonFingerprint,
PlayerOverlayChipFingerprint
)
) {
override fun execute(context: BytecodeContext) {
/**
* Hide cast button
*/
MediaRouteButtonFingerprint.resultOrThrow().let {
val setVisibilityMethod =
it.mutableClass.methods.find { method -> method.name == "setVisibility" }
setVisibilityMethod?.apply {
addInstructions(
0, """
invoke-static {p1}, $GENERAL_CLASS_DESCRIPTOR->hideCastButton(I)I
move-result p1
"""
)
} ?: throw PatchException("Failed to find setVisibility method")
}
/**
* Hide floating cast banner
*/
PlayerOverlayChipFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val targetIndex = getWideLiteralInstructionIndex(PlayerOverlayChip) + 2
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstruction(
targetIndex + 1,
"invoke-static {v$targetRegister}, $GENERAL_CLASS_DESCRIPTOR->hideCastButton(Landroid/view/View;)V"
)
}
}
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_cast_button",
"true"
)
}
}

View File

@ -1,47 +0,0 @@
package app.revanced.patches.music.general.categorybar
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patches.music.general.categorybar.fingerprints.ChipCloudFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Suppress("unused")
object CategoryBarPatch : BaseBytecodePatch(
name = "Hide category bar",
description = "Adds an option to hide the category bar.",
dependencies = setOf(
SettingsPatch::class,
SharedResourceIdPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(ChipCloudFingerprint)
) {
override fun execute(context: BytecodeContext) {
ChipCloudFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val targetIndex = it.scanResult.patternScanResult!!.endIndex
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstruction(
targetIndex + 1,
"invoke-static { v$targetRegister }, $GENERAL_CLASS_DESCRIPTOR->hideCategoryBar(Landroid/view/View;)V"
)
}
}
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_category_bar",
"false"
)
}
}

View File

@ -1,34 +0,0 @@
package app.revanced.patches.music.general.channelguidelines
import app.revanced.patcher.data.ResourceContext
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.patches.shared.litho.LithoFilterPatch
import app.revanced.util.patch.BaseResourcePatch
@Suppress("unused")
object ChannelGuidelinesPatch : BaseResourcePatch(
name = "Hide channel guidelines",
description = "Adds an option to hide the channel guidelines at the top of the comments section.",
dependencies = setOf(
LithoFilterPatch::class,
SettingsPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE
) {
private const val FILTER_CLASS_DESCRIPTOR =
"$COMPONENTS_PATH/ChannelGuidelinesFilter;"
override fun execute(context: ResourceContext) {
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_channel_guidelines",
"true"
)
}
}

View File

@ -0,0 +1,378 @@
package app.revanced.patches.music.general.components
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.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.booleanPatchOption
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.music.general.components.fingerprints.ChipCloudFingerprint
import app.revanced.patches.music.general.components.fingerprints.ContentPillInFingerprint
import app.revanced.patches.music.general.components.fingerprints.FloatingButtonFingerprint
import app.revanced.patches.music.general.components.fingerprints.FloatingButtonParentFingerprint
import app.revanced.patches.music.general.components.fingerprints.HistoryMenuItemFingerprint
import app.revanced.patches.music.general.components.fingerprints.HistoryMenuItemOfflineTabFingerprint
import app.revanced.patches.music.general.components.fingerprints.MediaRouteButtonFingerprint
import app.revanced.patches.music.general.components.fingerprints.PlayerOverlayChipFingerprint
import app.revanced.patches.music.general.components.fingerprints.SearchBarFingerprint
import app.revanced.patches.music.general.components.fingerprints.SearchBarParentFingerprint
import app.revanced.patches.music.general.components.fingerprints.SoundSearchFingerprint
import app.revanced.patches.music.general.components.fingerprints.TasteBuilderConstructorFingerprint
import app.revanced.patches.music.general.components.fingerprints.TasteBuilderSyntheticFingerprint
import app.revanced.patches.music.general.components.fingerprints.TooltipContentViewFingerprint
import app.revanced.patches.music.general.components.fingerprints.TopBarMenuItemImageViewFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH
import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.TopBarMenuItemImageView
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.patches.shared.litho.LithoFilterPatch
import app.revanced.patches.shared.voicesearch.VoiceSearchUtils.patchXml
import app.revanced.util.getTargetIndex
import app.revanced.util.getTargetIndexWithMethodReferenceName
import app.revanced.util.getWideLiteralInstructionIndex
import app.revanced.util.literalInstructionBooleanHook
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.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Suppress("unused")
object LayoutComponentsPatch : BaseBytecodePatch(
name = "Hide layout components",
description = "Adds options to hide general layout components.",
dependencies = setOf(
LithoFilterPatch::class,
SharedResourceIdPatch::class,
SettingsPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(
ChipCloudFingerprint,
ContentPillInFingerprint,
FloatingButtonParentFingerprint,
HistoryMenuItemFingerprint,
HistoryMenuItemOfflineTabFingerprint,
MediaRouteButtonFingerprint,
PlayerOverlayChipFingerprint,
SearchBarParentFingerprint,
SoundSearchFingerprint,
TasteBuilderConstructorFingerprint,
TooltipContentViewFingerprint,
TopBarMenuItemImageViewFingerprint
)
) {
private const val CUSTOM_FILTER_CLASS_DESCRIPTOR =
"$COMPONENTS_PATH/CustomFilter;"
private const val LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR =
"$COMPONENTS_PATH/LayoutComponentsFilter;"
private val ForceHideVoiceSearchButton by booleanPatchOption(
key = "ForceHideVoiceSearchButton",
default = false,
title = "Force hide voice search button",
description = "Hide voice search button with legacy method, button will always be hidden."
)
override fun execute(context: BytecodeContext) {
var notificationButtonIncluded = false
var soundSearchButtonIncluded = false
var voiceSearchButtonIncluded = false
// region patch for hide cast button
// hide cast button
MediaRouteButtonFingerprint.resultOrThrow().let {
val setVisibilityMethod =
it.mutableClass.methods.find { method -> method.name == "setVisibility" }
setVisibilityMethod?.apply {
addInstructions(
0, """
invoke-static {p1}, $GENERAL_CLASS_DESCRIPTOR->hideCastButton(I)I
move-result p1
"""
)
} ?: throw PatchException("Failed to find setVisibility method")
}
// hide floating cast banner
PlayerOverlayChipFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val targetIndex = getWideLiteralInstructionIndex(SharedResourceIdPatch.PlayerOverlayChip) + 2
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstruction(
targetIndex + 1,
"invoke-static {v$targetRegister}, $GENERAL_CLASS_DESCRIPTOR->hideCastButton(Landroid/view/View;)V"
)
}
}
// endregion
// region patch for hide category bar
ChipCloudFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val targetIndex = it.scanResult.patternScanResult!!.endIndex
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstruction(
targetIndex + 1,
"invoke-static { v$targetRegister }, $GENERAL_CLASS_DESCRIPTOR->hideCategoryBar(Landroid/view/View;)V"
)
}
}
// endregion
// region patch for hide floating button
FloatingButtonFingerprint.resolve(
context,
FloatingButtonParentFingerprint.resultOrThrow().classDef
)
FloatingButtonFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
addInstructionsWithLabels(
1, """
invoke-static {}, $GENERAL_CLASS_DESCRIPTOR->hideFloatingButton()Z
move-result v0
if-eqz v0, :show
return-void
""", ExternalLabel("show", getInstruction(1))
)
}
}
// endregion
// region patch for hide history button
arrayOf(
HistoryMenuItemFingerprint,
HistoryMenuItemOfflineTabFingerprint
).forEach { fingerprint ->
fingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.startIndex
val insertRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerD
addInstructions(
insertIndex, """
invoke-static {v$insertRegister}, $GENERAL_CLASS_DESCRIPTOR->hideHistoryButton(Z)Z
move-result v$insertRegister
"""
)
}
}
}
// endregion
// region patch for hide notification button
if (SettingsPatch.upward0642) {
TopBarMenuItemImageViewFingerprint.resultOrThrow().mutableMethod.apply {
val constIndex = getWideLiteralInstructionIndex(TopBarMenuItemImageView)
val targetIndex = getTargetIndex(constIndex, Opcode.MOVE_RESULT_OBJECT)
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstruction(
targetIndex + 1,
"invoke-static {v$targetRegister}, $GENERAL_CLASS_DESCRIPTOR->hideNotificationButton(Landroid/view/View;)V"
)
}
notificationButtonIncluded = true
}
// endregion
// region patch for hide sound search button
SoundSearchFingerprint.result?.let {
SoundSearchFingerprint.literalInstructionBooleanHook(
45625491,
"$GENERAL_CLASS_DESCRIPTOR->hideSoundSearchButton(Z)Z"
)
soundSearchButtonIncluded = true
}
// endregion
// region patch for hide tap to update button
ContentPillInFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
addInstructionsWithLabels(
0,
"""
invoke-static {}, $GENERAL_CLASS_DESCRIPTOR->hideTapToUpdateButton()Z
move-result v0
if-eqz v0, :show
return-void
""", ExternalLabel("show", getInstruction(0))
)
}
}
// endregion
// region patch for hide taste builder
TasteBuilderConstructorFingerprint.resultOrThrow().let { parentResult ->
TasteBuilderSyntheticFingerprint.resolve(context, parentResult.classDef)
parentResult.mutableMethod.apply {
val constIndex = getWideLiteralInstructionIndex(SharedResourceIdPatch.MusicTasteBuilderShelf)
val targetIndex = getTargetIndex(constIndex, Opcode.MOVE_RESULT_OBJECT)
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstruction(
targetIndex + 1,
"invoke-static {v$targetRegister}, $GENERAL_CLASS_DESCRIPTOR->hideTasteBuilder(Landroid/view/View;)V"
)
}
}
TasteBuilderSyntheticFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.startIndex
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstruction(
insertIndex,
"const/4 v$insertRegister, 0x0"
)
}
}
// endregion
// region patch for hide tooltip content
TooltipContentViewFingerprint.resultOrThrow().mutableMethod.addInstruction(
0,
"return-void"
)
// endregion
// region patch for hide voice search button
if (ForceHideVoiceSearchButton == true) {
SettingsPatch.contexts.patchXml(
arrayOf("search_toolbar_view.xml"),
arrayOf("height", "width")
)
} else {
SearchBarFingerprint.resolve(
context,
SearchBarParentFingerprint.resultOrThrow().classDef
)
SearchBarFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val setVisibilityIndex = getTargetIndexWithMethodReferenceName("setVisibility")
val setVisibilityInstruction = getInstruction<FiveRegisterInstruction>(setVisibilityIndex)
replaceInstruction(
setVisibilityIndex,
"invoke-static {v${setVisibilityInstruction.registerC}, v${setVisibilityInstruction.registerD}}, " +
"$GENERAL_CLASS_DESCRIPTOR->hideVoiceSearchButton(Landroid/widget/ImageView;I)V"
)
}
}
voiceSearchButtonIncluded = true
}
// endregion
LithoFilterPatch.addFilter(CUSTOM_FILTER_CLASS_DESCRIPTOR)
LithoFilterPatch.addFilter(LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR)
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_custom_filter",
"false"
)
SettingsPatch.addPreferenceWithIntent(
CategoryType.GENERAL,
"revanced_custom_filter_strings",
"revanced_custom_filter"
)
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_button_shelf",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_carousel_shelf",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_playlist_card_shelf",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_samples_shelf",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_cast_button",
"true"
)
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_category_bar",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_floating_button",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_tap_to_update_button",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_history_button",
"false"
)
if (notificationButtonIncluded) {
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_notification_button",
"false"
)
}
if (soundSearchButtonIncluded) {
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_sound_search_button",
"false"
)
}
if (voiceSearchButtonIncluded) {
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_voice_search_button",
"false"
)
}
}
}

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.general.categorybar.fingerprints
package app.revanced.patches.music.general.components.fingerprints
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.ChipCloud
import app.revanced.util.fingerprint.LiteralValueFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.general.taptoupdate.fingerprints
package app.revanced.patches.music.general.components.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.general.floatingbutton.fingerprints
package app.revanced.patches.music.general.components.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.general.floatingbutton.fingerprints
package app.revanced.patches.music.general.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.util.fingerprint.LiteralValueFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.general.historybutton.fingerprints
package app.revanced.patches.music.general.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.general.historybutton.fingerprints
package app.revanced.patches.music.general.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.general.castbutton.fingerprints
package app.revanced.patches.music.general.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.general.castbutton.fingerprints
package app.revanced.patches.music.general.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.PlayerOverlayChip

View File

@ -0,0 +1,8 @@
package app.revanced.patches.music.general.components.fingerprints
import app.revanced.util.fingerprint.MethodReferenceNameFingerprint
object SearchBarFingerprint : MethodReferenceNameFingerprint(
returnType = "V",
reference = { "setVisibility" }
)

View File

@ -0,0 +1,8 @@
package app.revanced.patches.music.general.components.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
object SearchBarParentFingerprint : MethodFingerprint(
returnType = "Landroid/content/Intent;",
strings = listOf("web_search")
)

View File

@ -0,0 +1,8 @@
package app.revanced.patches.music.general.components.fingerprints
import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object SoundSearchFingerprint : LiteralValueFingerprint(
parameters = emptyList(),
literalSupplier = { 45625491 }
)

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.misc.tastebuilder.fingerprints
package app.revanced.patches.music.general.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MusicTasteBuilderShelf

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.misc.tastebuilder.fingerprints
package app.revanced.patches.music.general.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.general.tooltip.fingerprints
package app.revanced.patches.music.general.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.ToolTipContentView

View File

@ -0,0 +1,14 @@
package app.revanced.patches.music.general.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.TopBarMenuItemImageView
import app.revanced.util.fingerprint.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object TopBarMenuItemImageViewFingerprint : LiteralValueFingerprint(
returnType = "Landroid/view/View;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(),
literalSupplier = { TopBarMenuItemImageView }
)

View File

@ -1,39 +0,0 @@
package app.revanced.patches.music.general.customfilter
import app.revanced.patcher.data.ResourceContext
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.patches.shared.litho.LithoFilterPatch
import app.revanced.util.patch.BaseResourcePatch
@Suppress("unused")
object CustomFilterPatch : BaseResourcePatch(
name = "Enable custom filter",
description = "Adds a custom filter which can be used to hide layout components.",
dependencies = setOf(
LithoFilterPatch::class,
SettingsPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE
) {
private const val FILTER_CLASS_DESCRIPTOR =
"$COMPONENTS_PATH/CustomFilter;"
override fun execute(context: ResourceContext) {
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_custom_filter",
"false"
)
SettingsPatch.addPreferenceWithIntent(
CategoryType.GENERAL,
"revanced_custom_filter_strings",
"revanced_custom_filter"
)
}
}

View File

@ -1,34 +0,0 @@
package app.revanced.patches.music.general.emojipicker
import app.revanced.patcher.data.ResourceContext
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.patches.shared.litho.LithoFilterPatch
import app.revanced.util.patch.BaseResourcePatch
@Suppress("unused")
object EmojiPickerPatch : BaseResourcePatch(
name = "Hide emoji picker and time stamp",
description = "Adds an option to hide the emoji picker and time stamp when typing comments.",
dependencies = setOf(
LithoFilterPatch::class,
SettingsPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE
) {
private const val FILTER_CLASS_DESCRIPTOR =
"$COMPONENTS_PATH/EmojiPickerFilter;"
override fun execute(context: ResourceContext) {
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_emoji_picker",
"false"
)
}
}

View File

@ -1,57 +0,0 @@
package app.revanced.patches.music.general.floatingbutton
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.music.general.floatingbutton.fingerprints.FloatingButtonFingerprint
import app.revanced.patches.music.general.floatingbutton.fingerprints.FloatingButtonParentFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
@Suppress("unused")
object FloatingButtonPatch : BaseBytecodePatch(
name = "Hide new playlist button",
description = "Adds an option to hide the \"New playlist\" button in the library.",
dependencies = setOf(
SettingsPatch::class,
SharedResourceIdPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(FloatingButtonParentFingerprint)
) {
override fun execute(context: BytecodeContext) {
FloatingButtonParentFingerprint.resultOrThrow().let { parentResult ->
FloatingButtonFingerprint.also {
it.resolve(
context,
parentResult.classDef
)
}.resultOrThrow().let {
it.mutableMethod.apply {
addInstructionsWithLabels(
1, """
invoke-static {}, $GENERAL_CLASS_DESCRIPTOR->hideNewPlaylistButton()Z
move-result v0
if-eqz v0, :show
return-void
""", ExternalLabel("show", getInstruction(1))
)
}
}
}
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_new_playlist_button",
"false"
)
}
}

View File

@ -1,59 +0,0 @@
package app.revanced.patches.music.general.historybutton
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patches.music.general.historybutton.fingerprints.HistoryMenuItemFingerprint
import app.revanced.patches.music.general.historybutton.fingerprints.HistoryMenuItemOfflineTabFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@Suppress("unused")
object HistoryButtonPatch : BaseBytecodePatch(
name = "Hide history button",
description = "Adds an option to hide the history button in the toolbar.",
dependencies = setOf(
SettingsPatch::class,
SharedResourceIdPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(
HistoryMenuItemFingerprint,
HistoryMenuItemOfflineTabFingerprint
)
) {
override fun execute(context: BytecodeContext) {
arrayOf(
HistoryMenuItemFingerprint,
HistoryMenuItemOfflineTabFingerprint
).forEach { fingerprint ->
fingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.startIndex
val insertRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerD
addInstructions(
insertIndex, """
invoke-static {v$insertRegister}, $GENERAL_CLASS_DESCRIPTOR->hideHistoryButton(Z)Z
move-result v$insertRegister
"""
)
}
}
}
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_history_button",
"false"
)
}
}

View File

@ -17,7 +17,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@Suppress("unused")
object OldStyleLibraryShelfPatch : BaseBytecodePatch(
name = "Enable old style library shelf",
name = "Restore old style library shelf",
description = "Adds an option to return the library tab to the old style.",
dependencies = setOf(SettingsPatch::class),
compatiblePackages = COMPATIBLE_PACKAGE,
@ -33,7 +33,7 @@ object OldStyleLibraryShelfPatch : BaseBytecodePatch(
addInstructions(
targetIndex + 1, """
invoke-static {v$targetRegister}, $GENERAL_CLASS_DESCRIPTOR->enableOldStyleLibraryShelf(Ljava/lang/String;)Ljava/lang/String;
invoke-static {v$targetRegister}, $GENERAL_CLASS_DESCRIPTOR->restoreOldStyleLibraryShelf(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$targetRegister
"""
)
@ -42,7 +42,7 @@ object OldStyleLibraryShelfPatch : BaseBytecodePatch(
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_enable_old_style_library_shelf",
"revanced_restore_old_style_library_shelf",
"false"
)

View File

@ -1,34 +0,0 @@
package app.revanced.patches.music.general.playlistcard
import app.revanced.patcher.data.ResourceContext
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.patches.shared.litho.LithoFilterPatch
import app.revanced.util.patch.BaseResourcePatch
@Suppress("unused")
object PlaylistCardPatch : BaseResourcePatch(
name = "Hide playlist card",
description = "Adds an option to hide the playlist card from the homepage.",
dependencies = setOf(
LithoFilterPatch::class,
SettingsPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE
) {
private const val FILTER_CLASS_DESCRIPTOR =
"$COMPONENTS_PATH/PlaylistCardFilter;"
override fun execute(context: ResourceContext) {
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_playlist_card",
"false"
)
}
}

View File

@ -1,34 +0,0 @@
package app.revanced.patches.music.general.sampleshelf
import app.revanced.patcher.data.ResourceContext
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.patches.shared.litho.LithoFilterPatch
import app.revanced.util.patch.BaseResourcePatch
@Suppress("unused")
object SampleShelfPatch : BaseResourcePatch(
name = "Hide sample shelf",
description = "Adds an option to hide the sample shelf from the homepage.",
dependencies = setOf(
LithoFilterPatch::class,
SettingsPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE
) {
private const val FILTER_CLASS_DESCRIPTOR =
"$COMPONENTS_PATH/SampleShelfFilter;"
override fun execute(context: ResourceContext) {
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_samples_shelf",
"false"
)
}
}

View File

@ -0,0 +1,8 @@
package app.revanced.patches.music.general.spoofappversion
import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
import app.revanced.patches.shared.spoofappversion.BaseSpoofAppVersionPatch
object SpoofAppVersionBytecodePatch : BaseSpoofAppVersionPatch(
"$GENERAL_CLASS_DESCRIPTOR->getVersionOverride(Ljava/lang/String;)Ljava/lang/String;"
)

View File

@ -1,10 +1,10 @@
package app.revanced.patches.music.misc.spoofappversion
package app.revanced.patches.music.general.spoofappversion
import app.revanced.patcher.data.ResourceContext
import app.revanced.patches.music.general.oldstylelibraryshelf.OldStyleLibraryShelfPatch
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.util.copyXmlNode
import app.revanced.util.patch.BaseResourcePatch
@Suppress("unused")
@ -13,6 +13,7 @@ object SpoofAppVersionPatch : BaseResourcePatch(
description = "Adds options to spoof the YouTube Music client version. " +
"This can remove the radio mode restriction in Canadian regions or disable real-time lyrics.",
dependencies = setOf(
OldStyleLibraryShelfPatch::class,
SettingsPatch::class,
SpoofAppVersionBytecodePatch::class
),
@ -20,18 +21,13 @@ object SpoofAppVersionPatch : BaseResourcePatch(
) {
override fun execute(context: ResourceContext) {
/**
* Copy arrays
*/
context.copyXmlNode("music/spoofappversion/host", "values/arrays.xml", "resources")
SettingsPatch.addSwitchPreference(
CategoryType.MISC,
CategoryType.GENERAL,
"revanced_spoof_app_version",
"false"
)
SettingsPatch.addPreferenceWithIntent(
CategoryType.MISC,
CategoryType.GENERAL,
"revanced_spoof_app_version_target",
"revanced_spoof_app_version"
)

View File

@ -9,8 +9,6 @@ import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKA
import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.patches.music.utils.settings.SettingsPatch.contexts
import app.revanced.util.copyXmlNode
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@ -41,11 +39,6 @@ object ChangeStartPagePatch : BaseBytecodePatch(
}
}
/**
* Copy arrays
*/
contexts.copyXmlNode("music/startpage/host", "values/arrays.xml", "resources")
SettingsPatch.addPreferenceWithIntent(
CategoryType.GENERAL,
"revanced_change_start_page"

View File

@ -1,46 +0,0 @@
package app.revanced.patches.music.general.taptoupdate
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.music.general.taptoupdate.fingerprints.ContentPillInFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
@Suppress("unused")
object TapToUpdateButtonPatch : BaseBytecodePatch(
name = "Hide tap to update button",
description = "Adds an option to hide the tap to update button.",
dependencies = setOf(SettingsPatch::class),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(ContentPillInFingerprint)
) {
override fun execute(context: BytecodeContext) {
ContentPillInFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
addInstructionsWithLabels(
0,
"""
invoke-static {}, $GENERAL_CLASS_DESCRIPTOR->hideTapToUpdateButton()Z
move-result v0
if-eqz v0, :show
return-void
""", ExternalLabel("show", getInstruction(0))
)
}
}
SettingsPatch.addSwitchPreference(
CategoryType.GENERAL,
"revanced_hide_tap_to_update_button",
"false"
)
}
}

View File

@ -1,27 +0,0 @@
package app.revanced.patches.music.general.tooltip
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patches.music.general.tooltip.fingerprints.TooltipContentViewFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
@Suppress("unused")
object TooltipContentViewPatch : BaseBytecodePatch(
name = "Hide tooltip content",
description = "Hides the tooltip box that appears when opening the app for the first time.",
dependencies = setOf(SharedResourceIdPatch::class),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(TooltipContentViewFingerprint)
) {
override fun execute(context: BytecodeContext) {
TooltipContentViewFingerprint.resultOrThrow().mutableMethod.addInstruction(
0,
"return-void"
)
}
}

View File

@ -1,23 +0,0 @@
package app.revanced.patches.music.general.voicesearch
import app.revanced.patcher.data.ResourceContext
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.shared.voicesearch.VoiceSearchUtils.patchXml
import app.revanced.util.patch.BaseResourcePatch
@Suppress("unused")
object VoiceSearchButtonPatch : BaseResourcePatch(
name = "Hide voice search button",
description = "Hides the voice search button in the search bar.",
compatiblePackages = COMPATIBLE_PACKAGE,
use = false
) {
override fun execute(context: ResourceContext) {
context.patchXml(
arrayOf("search_toolbar_view.xml"),
arrayOf("height", "width")
)
}
}

View File

@ -4,7 +4,6 @@ import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.LANGUAGE_LIST
import app.revanced.patches.shared.elements.StringsElementsUtils.removeStringsElements
import app.revanced.util.patch.BaseResourcePatch
@ -19,7 +18,7 @@ object CustomBrandingNamePatch : BaseResourcePatch(
private val AppNameNotification by stringPatchOption(
key = "AppNameNotification",
default = APP_NAME_NOTIFICATION,
default = APP_NAME_LAUNCHER,
values = mapOf(
"Full name" to APP_NAME_NOTIFICATION,
"Short name" to APP_NAME_LAUNCHER
@ -44,7 +43,6 @@ object CustomBrandingNamePatch : BaseResourcePatch(
override fun execute(context: ResourceContext) {
context.removeStringsElements(
LANGUAGE_LIST,
arrayOf("app_launcher_name", "app_name")
)

View File

@ -1,31 +0,0 @@
package app.revanced.patches.music.misc.backgroundplay
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patches.music.misc.backgroundplay.fingerprints.BackgroundPlaybackFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
@Suppress("unused")
object BackgroundPlayPatch : BaseBytecodePatch(
name = "Background play",
description = "Enables playing music in the background.",
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(BackgroundPlaybackFingerprint)
) {
override fun execute(context: BytecodeContext) {
BackgroundPlaybackFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
addInstructions(
0, """
const/4 v0, 0x1
return v0
"""
)
}
}
}
}

View File

@ -7,7 +7,7 @@ import app.revanced.util.patch.BaseResourcePatch
@Suppress("DEPRECATION", "unused")
object BitrateDefaultValuePatch : BaseResourcePatch(
name = "Bitrate default value",
description = "Sets the audio quality to \"Always High\" when you first install the app.",
description = "Sets the audio quality to 'Always High' when you first install the app.",
compatiblePackages = COMPATIBLE_PACKAGE
) {
private const val RESOURCE_FILE_PATH = "res/xml/data_saving_settings.xml"

View File

@ -1,88 +0,0 @@
package app.revanced.patches.music.misc.exclusiveaudio
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.music.misc.exclusiveaudio.fingerprints.DataSavingSettingsFragmentFingerprint
import app.revanced.patches.music.misc.exclusiveaudio.fingerprints.MusicBrowserServiceFingerprint
import app.revanced.patches.music.misc.exclusiveaudio.fingerprints.PodCastConfigFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.util.getStringInstructionIndex
import app.revanced.util.getWalkerMethod
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.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
@Suppress("unused")
object ExclusiveAudioPatch : BaseBytecodePatch(
name = "Exclusive audio playback",
description = "Unlocks the option to play music without video.",
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(
DataSavingSettingsFragmentFingerprint,
MusicBrowserServiceFingerprint,
PodCastConfigFingerprint
)
) {
override fun execute(context: BytecodeContext) {
/**
* Don't play music videos
*/
MusicBrowserServiceFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val targetIndex =
getStringInstructionIndex("MBS: Return empty root for client: %s, isFullMediaBrowserEnabled: %b, is client browsable: %b, isRedAccount: %b")
for (index in targetIndex downTo 0) {
if (getInstruction(index).opcode != Opcode.INVOKE_VIRTUAL) continue
val targetReference = getInstruction<ReferenceInstruction>(index).reference
if (!targetReference.toString().endsWith("()Z")) continue
val walkerMethod = getWalkerMethod(context, index)
walkerMethod.addInstructions(
0, """
const/4 v0, 0x1
return v0
"""
)
break
}
}
}
/**
* Don't play podcast videos
*/
PodCastConfigFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val insertIndex = implementation!!.instructions.size - 1
val targetRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstruction(
insertIndex,
"const/4 v$targetRegister, 0x1"
)
}
}
DataSavingSettingsFragmentFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val insertIndex = getStringInstructionIndex("pref_key_dont_play_nma_video") + 4
val targetRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerD
addInstruction(
insertIndex,
"const/4 v$targetRegister, 0x1"
)
}
}
}
}

View File

@ -2,23 +2,112 @@ package app.revanced.patches.music.misc.minimizedplayback
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.music.misc.minimizedplayback.fingerprints.BackgroundPlaybackFingerprint
import app.revanced.patches.music.misc.minimizedplayback.fingerprints.DataSavingSettingsFragmentFingerprint
import app.revanced.patches.music.misc.minimizedplayback.fingerprints.MinimizedPlaybackManagerFingerprint
import app.revanced.patches.music.misc.minimizedplayback.fingerprints.MusicBrowserServiceFingerprint
import app.revanced.patches.music.misc.minimizedplayback.fingerprints.PodCastConfigFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.util.getStringInstructionIndex
import app.revanced.util.getWalkerMethod
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.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
@Suppress("unused")
object MinimizedPlaybackPatch : BaseBytecodePatch(
name = "Enable minimized playback",
description = "Enables playback in miniplayer for Kids music.",
description = "Enables minimized and background playback.",
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(MinimizedPlaybackManagerFingerprint)
fingerprints = setOf(
BackgroundPlaybackFingerprint,
DataSavingSettingsFragmentFingerprint,
MinimizedPlaybackManagerFingerprint,
MusicBrowserServiceFingerprint,
PodCastConfigFingerprint,
)
) {
override fun execute(context: BytecodeContext) {
// region patch for background play
BackgroundPlaybackFingerprint.resultOrThrow().mutableMethod.addInstructions(
0, """
const/4 v0, 0x1
return v0
"""
)
// endregion
// region patch for exclusive audio playback
// don't play music video
MusicBrowserServiceFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val targetIndex =
getStringInstructionIndex("MBS: Return empty root for client: %s, isFullMediaBrowserEnabled: %b, is client browsable: %b, isRedAccount: %b")
for (index in targetIndex downTo 0) {
if (getInstruction(index).opcode != Opcode.INVOKE_VIRTUAL) continue
val targetReference = getInstruction<ReferenceInstruction>(index).reference
if (!targetReference.toString().endsWith("()Z")) continue
val walkerMethod = getWalkerMethod(context, index)
walkerMethod.addInstructions(
0, """
const/4 v0, 0x1
return v0
"""
)
break
}
}
}
// don't play podcast videos
PodCastConfigFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val insertIndex = implementation!!.instructions.size - 1
val targetRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstruction(
insertIndex,
"const/4 v$targetRegister, 0x1"
)
}
}
// don't play podcast videos
DataSavingSettingsFragmentFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val insertIndex = getStringInstructionIndex("pref_key_dont_play_nma_video") + 4
val targetRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerD
addInstruction(
insertIndex,
"const/4 v$targetRegister, 0x1"
)
}
}
// endregion
// region patch for minimized playback
MinimizedPlaybackManagerFingerprint.resultOrThrow().mutableMethod.addInstruction(
0, "return-void"
)
// endregion
}
}

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.misc.backgroundplay.fingerprints
package app.revanced.patches.music.misc.minimizedplayback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.util.fingerprint.LiteralValueFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.misc.exclusiveaudio.fingerprints
package app.revanced.patches.music.misc.minimizedplayback.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.misc.exclusiveaudio.fingerprints
package app.revanced.patches.music.misc.minimizedplayback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.misc.exclusiveaudio.fingerprints
package app.revanced.patches.music.misc.minimizedplayback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.util.fingerprint.LiteralValueFingerprint

View File

@ -1,90 +0,0 @@
package app.revanced.patches.music.misc.premium
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.music.misc.premium.fingerprints.AccountMenuFooterFingerprint
import app.revanced.patches.music.misc.premium.fingerprints.HideGetPremiumFingerprint
import app.revanced.patches.music.misc.premium.fingerprints.MembershipSettingsFingerprint
import app.revanced.patches.music.misc.premium.fingerprints.MembershipSettingsParentFingerprint
import app.revanced.patches.music.navigation.component.NavigationBarComponentPatch
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.PrivacyTosFooter
import app.revanced.util.getTargetIndex
import app.revanced.util.getTargetIndexWithReference
import app.revanced.util.getWalkerMethod
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.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
@Suppress("unused")
object GetPremiumPatch : BaseBytecodePatch(
name = "Hide get premium",
description = "Hides the \"Get Music Premium\" label from the account menu and settings.",
dependencies = setOf(
NavigationBarComponentPatch::class,
SharedResourceIdPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(
AccountMenuFooterFingerprint,
HideGetPremiumFingerprint,
MembershipSettingsParentFingerprint
)
) {
override fun execute(context: BytecodeContext) {
// Hides get premium button at the bottom of the account switching menu
HideGetPremiumFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.startIndex
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
addInstruction(
insertIndex + 1,
"const/4 v$register, 0x0"
)
}
}
// Hides get premium button at the top of the account switching menu
AccountMenuFooterFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val constIndex = getWideLiteralInstructionIndex(PrivacyTosFooter)
val walkerIndex = getTargetIndex(constIndex + 2, Opcode.INVOKE_VIRTUAL)
val viewIndex = getTargetIndex(constIndex, Opcode.IGET_OBJECT)
val viewReference = getInstruction<ReferenceInstruction>(viewIndex).reference.toString()
val walkerMethod = getWalkerMethod(context, walkerIndex)
walkerMethod.apply {
val insertIndex = getTargetIndexWithReference(viewReference)
val nullCheckIndex = getTargetIndex(insertIndex - 1, Opcode.IF_NEZ)
val nullCheckRegister = getInstruction<OneRegisterInstruction>(nullCheckIndex).registerA
addInstruction(
nullCheckIndex,
"const/4 v$nullCheckRegister, 0x0"
)
}
}
}
// Hides premium membership menu in settings
MembershipSettingsParentFingerprint.resultOrThrow().classDef.let { classDef ->
MembershipSettingsFingerprint.resolve(context, classDef)
MembershipSettingsFingerprint.resultOrThrow().mutableMethod.addInstructions(
0, """
const/4 v0, 0x0
return-object v0
"""
)
}
}
}

View File

@ -1,8 +0,0 @@
package app.revanced.patches.music.misc.spoofappversion
import app.revanced.patches.music.utils.integrations.Constants.MISC_PATH
import app.revanced.patches.shared.spoofappversion.BaseSpoofAppVersionPatch
object SpoofAppVersionBytecodePatch : BaseSpoofAppVersionPatch(
"$MISC_PATH/SpoofAppVersionPatch;->getVersionOverride(Ljava/lang/String;)Ljava/lang/String;"
)

View File

@ -1,58 +0,0 @@
package app.revanced.patches.music.misc.tastebuilder
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.music.misc.tastebuilder.fingerprints.TasteBuilderConstructorFingerprint
import app.revanced.patches.music.misc.tastebuilder.fingerprints.TasteBuilderSyntheticFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MusicTasteBuilderShelf
import app.revanced.util.getTargetIndex
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
@Suppress("unused")
object TasteBuilderPatch : BaseBytecodePatch(
name = "Hide taste builder",
description = "Hides the \"Tell us which artists you like\" card from the homepage.",
dependencies = setOf(SharedResourceIdPatch::class),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(TasteBuilderConstructorFingerprint)
) {
override fun execute(context: BytecodeContext) {
TasteBuilderConstructorFingerprint.resultOrThrow().let { parentResult ->
TasteBuilderSyntheticFingerprint.resolve(context, parentResult.classDef)
parentResult.mutableMethod.apply {
val freeRegister = implementation!!.registerCount - parameters.size - 2
val constIndex = getWideLiteralInstructionIndex(MusicTasteBuilderShelf)
val targetIndex = getTargetIndex(constIndex, Opcode.MOVE_RESULT_OBJECT)
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstructions(
targetIndex + 1, """
const/16 v$freeRegister, 0x8
invoke-virtual {v$targetRegister, v$freeRegister}, Landroid/view/View;->setVisibility(I)V
"""
)
}
}
TasteBuilderSyntheticFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.startIndex
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstruction(
insertIndex,
"const/4 v$insertRegister, 0x0"
)
}
}
}
}

View File

@ -1,50 +0,0 @@
package app.revanced.patches.music.navigation.black
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patches.music.navigation.black.fingerprints.TabLayoutFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.NAVIGATION_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Suppress("unused")
object BlackNavigationBarPatch : BaseBytecodePatch(
name = "Enable black navigation bar",
description = "Adds an option to set the navigation bar color to black.",
dependencies = setOf(
SettingsPatch::class,
SharedResourceIdPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(TabLayoutFingerprint)
) {
override fun execute(context: BytecodeContext) {
TabLayoutFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val targetIndex = it.scanResult.patternScanResult!!.endIndex
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstructions(
targetIndex + 1, """
invoke-static {}, $NAVIGATION_CLASS_DESCRIPTOR->enableBlackNavigationBar()I
move-result v$targetRegister
"""
)
}
}
SettingsPatch.addSwitchPreference(
CategoryType.NAVIGATION,
"revanced_enable_black_navigation_bar",
"true"
)
}
}

View File

@ -1,10 +1,12 @@
package app.revanced.patches.music.navigation.component
package app.revanced.patches.music.navigation.components
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.patcher.patch.PatchException
import app.revanced.patches.music.navigation.component.fingerprints.TabLayoutTextFingerprint
import app.revanced.patches.music.navigation.components.fingerprints.TabLayoutFingerprint
import app.revanced.patches.music.navigation.components.fingerprints.TabLayoutTextFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.integrations.Constants.NAVIGATION_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
@ -21,20 +23,41 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
@Suppress("DEPRECATION", "SpellCheckingInspection", "unused")
object NavigationBarComponentPatch : BaseBytecodePatch(
name = "Hide navigation bar component",
description = "Adds options to hide navigation bar components.",
object NavigationBarComponentsPatch : BaseBytecodePatch(
name = "Navigation bar components",
description = "Adds options to hide or change components related to navigation bar.",
dependencies = setOf(
SettingsPatch::class,
SharedResourceIdPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(TabLayoutTextFingerprint)
fingerprints = setOf(
TabLayoutFingerprint,
TabLayoutTextFingerprint
)
) {
private const val FLAG = "android:layout_weight"
private const val RESOURCE_FILE_PATH = "res/layout/image_with_text_tab.xml"
override fun execute(context: BytecodeContext) {
/**
* Enable black navigation bar
*/
TabLayoutFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val targetIndex = it.scanResult.patternScanResult!!.endIndex
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstructions(
targetIndex + 1, """
invoke-static {}, $NAVIGATION_CLASS_DESCRIPTOR->enableBlackNavigationBar()I
move-result v$targetRegister
"""
)
}
}
/**
* Hide navigation labels
*/
@ -94,19 +117,34 @@ object NavigationBarComponentPatch : BaseBytecodePatch(
SettingsPatch.addSwitchPreference(
CategoryType.NAVIGATION,
"revanced_hide_explore_button",
"revanced_enable_black_navigation_bar",
"true"
)
SettingsPatch.addSwitchPreference(
CategoryType.NAVIGATION,
"revanced_hide_navigation_home_button",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.NAVIGATION,
"revanced_hide_home_button",
"revanced_hide_navigation_samples_button",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.NAVIGATION,
"revanced_hide_library_button",
"revanced_hide_navigation_explore_button",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.NAVIGATION,
"revanced_hide_navigation_library_button",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.NAVIGATION,
"revanced_hide_navigation_upgrade_button",
"true"
)
SettingsPatch.addSwitchPreference(
CategoryType.NAVIGATION,
"revanced_hide_navigation_bar",
@ -117,15 +155,5 @@ object NavigationBarComponentPatch : BaseBytecodePatch(
"revanced_hide_navigation_label",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.NAVIGATION,
"revanced_hide_samples_button",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.NAVIGATION,
"revanced_hide_upgrade_button",
"true"
)
}
}

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.navigation.black.fingerprints
package app.revanced.patches.music.navigation.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.ColorGrey

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.navigation.component.fingerprints
package app.revanced.patches.music.navigation.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.Text1

View File

@ -1,107 +0,0 @@
package app.revanced.patches.music.player.colormatchplayer
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.extensions.or
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.fingerprints.MiniPlayerConstructorFingerprint
import app.revanced.patches.music.utils.fingerprints.SwitchToggleColorFingerprint
import app.revanced.patches.music.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.ColorGrey
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.util.getTargetIndex
import app.revanced.util.getTargetIndexReversed
import app.revanced.util.getWideLiteralInstructionIndex
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.MethodParameter
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.Reference
@Suppress("unused")
object ColorMatchPlayerPatch : BaseBytecodePatch(
name = "Enable color match player",
description = "Adds an option to match the color of the miniplayer to the fullscreen player.",
dependencies = setOf(
SettingsPatch::class,
SharedResourceIdPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(MiniPlayerConstructorFingerprint)
) {
private lateinit var invokeVirtualReference: Reference
private lateinit var iGetReference: Reference
private lateinit var iPutReference: Reference
private lateinit var methodParameter: List<MethodParameter>
override fun execute(context: BytecodeContext) {
MiniPlayerConstructorFingerprint.resultOrThrow().let { parentResult ->
// Resolves fingerprints
SwitchToggleColorFingerprint.resolve(context, parentResult.classDef)
SwitchToggleColorFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
methodParameter = parameters
val relativeIndex = it.scanResult.patternScanResult!!.endIndex + 1
val invokeVirtualIndex = getTargetIndex(relativeIndex, Opcode.INVOKE_VIRTUAL)
val iGetIndex = getTargetIndex(relativeIndex, Opcode.IGET)
invokeVirtualReference = getInstruction<ReferenceInstruction>(invokeVirtualIndex).reference
iGetReference = getInstruction<ReferenceInstruction>(iGetIndex).reference
}
parentResult.mutableMethod.apply {
val colorGreyIndex = getWideLiteralInstructionIndex(ColorGrey)
val iPutIndex = getTargetIndex(colorGreyIndex, Opcode.IPUT)
iPutReference = getInstruction<ReferenceInstruction>(iPutIndex).reference
}
parentResult.mutableClass.methods.filter { method ->
method.accessFlags == AccessFlags.PUBLIC or AccessFlags.FINAL
&& method.parameters == methodParameter
&& method.returnType == "V"
}.forEach { mutableMethod ->
mutableMethod.apply {
val freeRegister = implementation!!.registerCount - parameters.size - 3
val invokeDirectIndex = getTargetIndexReversed(implementation!!.instructions.size - 1, Opcode.INVOKE_DIRECT)
val invokeDirectReference = getInstruction<ReferenceInstruction>(invokeDirectIndex).reference
addInstructionsWithLabels(
invokeDirectIndex + 1, """
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->enableColorMatchPlayer()Z
move-result v$freeRegister
if-eqz v$freeRegister, :off
invoke-virtual {p1}, $invokeVirtualReference
move-result-object v$freeRegister
check-cast v$freeRegister, ${(iGetReference as FieldReference).definingClass}
iget v$freeRegister, v$freeRegister, $iGetReference
iput v$freeRegister, p0, $iPutReference
:off
invoke-direct {p0}, $invokeDirectReference
"""
)
removeInstruction(invokeDirectIndex)
}
}
}
}
SettingsPatch.addSwitchPreference(
CategoryType.PLAYER,
"revanced_enable_color_match_player",
"true"
)
}
}

View File

@ -0,0 +1,836 @@
package app.revanced.patches.music.player.components
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.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.music.player.components.fingerprints.HandleSearchRenderedFingerprint
import app.revanced.patches.music.player.components.fingerprints.HandleSignInEventFingerprint
import app.revanced.patches.music.player.components.fingerprints.InteractionLoggingEnumFingerprint
import app.revanced.patches.music.player.components.fingerprints.MiniPlayerConstructorFingerprint
import app.revanced.patches.music.player.components.fingerprints.MiniPlayerDefaultTextFingerprint
import app.revanced.patches.music.player.components.fingerprints.MiniPlayerDefaultViewVisibilityFingerprint
import app.revanced.patches.music.player.components.fingerprints.MiniPlayerParentFingerprint
import app.revanced.patches.music.player.components.fingerprints.MinimizedPlayerFingerprint
import app.revanced.patches.music.player.components.fingerprints.MppWatchWhileLayoutFingerprint
import app.revanced.patches.music.player.components.fingerprints.MusicActivityWidgetFingerprint
import app.revanced.patches.music.player.components.fingerprints.MusicPlaybackControlsFingerprint
import app.revanced.patches.music.player.components.fingerprints.NextButtonVisibilityFingerprint
import app.revanced.patches.music.player.components.fingerprints.OldEngagementPanelFingerprint
import app.revanced.patches.music.player.components.fingerprints.OldPlayerBackgroundFingerprint
import app.revanced.patches.music.player.components.fingerprints.OldPlayerLayoutFingerprint
import app.revanced.patches.music.player.components.fingerprints.PlayerPatchConstructorFingerprint
import app.revanced.patches.music.player.components.fingerprints.RemixGenericButtonFingerprint
import app.revanced.patches.music.player.components.fingerprints.RepeatTrackFingerprint
import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint
import app.revanced.patches.music.player.components.fingerprints.SwipeToCloseFingerprint
import app.revanced.patches.music.player.components.fingerprints.SwitchToggleColorFingerprint
import app.revanced.patches.music.player.components.fingerprints.ZenModeFingerprint
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.fingerprints.PendingIntentReceiverFingerprint
import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH
import app.revanced.patches.music.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.ColorGrey
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MiniPlayerPlayPauseReplayButton
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.TopEnd
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.TopStart
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.SettingsPatch
import app.revanced.patches.music.utils.videotype.VideoTypeHookPatch
import app.revanced.patches.shared.litho.LithoFilterPatch
import app.revanced.util.getReference
import app.revanced.util.getStringInstructionIndex
import app.revanced.util.getTargetIndex
import app.revanced.util.getTargetIndexReversed
import app.revanced.util.getTargetIndexWithFieldReferenceType
import app.revanced.util.getWalkerMethod
import app.revanced.util.getWideLiteralInstructionIndex
import app.revanced.util.literalInstructionBooleanHook
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow
import app.revanced.util.transformFields
import app.revanced.util.traverseClassHierarchy
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.iface.MethodParameter
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.iface.reference.Reference
import com.android.tools.smali.dexlib2.immutable.ImmutableField
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.util.MethodUtil
import kotlin.properties.Delegates
@Suppress("unused", "LocalVariableName")
object PlayerComponentsPatch : BaseBytecodePatch(
name = "Player components",
description = "Adds options to hide or change components related to player.",
dependencies = setOf(
LithoFilterPatch::class,
PlayerComponentsResourcePatch::class,
SettingsPatch::class,
SharedResourceIdPatch::class,
VideoTypeHookPatch::class
),
compatiblePackages = COMPATIBLE_PACKAGE,
fingerprints = setOf(
HandleSearchRenderedFingerprint,
InteractionLoggingEnumFingerprint,
MinimizedPlayerFingerprint,
MiniPlayerConstructorFingerprint,
MiniPlayerDefaultTextFingerprint,
MiniPlayerDefaultViewVisibilityFingerprint,
MiniPlayerParentFingerprint,
MppWatchWhileLayoutFingerprint,
MusicActivityWidgetFingerprint,
MusicPlaybackControlsFingerprint,
OldEngagementPanelFingerprint,
OldPlayerBackgroundFingerprint,
OldPlayerLayoutFingerprint,
PendingIntentReceiverFingerprint,
PlayerPatchConstructorFingerprint,
RemixGenericButtonFingerprint,
RepeatTrackFingerprint,
ShuffleClassReferenceFingerprint,
SwipeToCloseFingerprint,
)
) {
private const val FILTER_CLASS_DESCRIPTOR =
"$COMPONENTS_PATH/PlayerComponentsFilter;"
override fun execute(context: BytecodeContext) {
// region patch for enable color match player
lateinit var colorMathPlayerInvokeVirtualReference: Reference
lateinit var colorMathPlayerIGetReference: Reference
lateinit var colorMathPlayerIPutReference: Reference
lateinit var colorMathPlayerMethodParameter: List<MethodParameter>
MiniPlayerConstructorFingerprint.resultOrThrow().let { parentResult ->
// Resolves fingerprints
SwitchToggleColorFingerprint.resolve(context, parentResult.classDef)
SwitchToggleColorFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
colorMathPlayerMethodParameter = parameters
val relativeIndex = it.scanResult.patternScanResult!!.endIndex + 1
val invokeVirtualIndex = getTargetIndex(relativeIndex, Opcode.INVOKE_VIRTUAL)
val iGetIndex = getTargetIndex(relativeIndex, Opcode.IGET)
colorMathPlayerInvokeVirtualReference = getInstruction<ReferenceInstruction>(invokeVirtualIndex).reference
colorMathPlayerIGetReference = getInstruction<ReferenceInstruction>(iGetIndex).reference
}
parentResult.mutableMethod.apply {
val colorGreyIndex = getWideLiteralInstructionIndex(ColorGrey)
val iPutIndex = getTargetIndex(colorGreyIndex, Opcode.IPUT)
colorMathPlayerIPutReference = getInstruction<ReferenceInstruction>(iPutIndex).reference
}
parentResult.mutableClass.methods.filter { method ->
method.accessFlags == AccessFlags.PUBLIC or AccessFlags.FINAL
&& method.parameters == colorMathPlayerMethodParameter
&& method.returnType == "V"
}.forEach { mutableMethod ->
mutableMethod.apply {
val freeRegister = implementation!!.registerCount - parameters.size - 3
val invokeDirectIndex = getTargetIndexReversed(implementation!!.instructions.size - 1, Opcode.INVOKE_DIRECT)
val invokeDirectReference = getInstruction<ReferenceInstruction>(invokeDirectIndex).reference
addInstructionsWithLabels(
invokeDirectIndex + 1, """
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->enableColorMatchPlayer()Z
move-result v$freeRegister
if-eqz v$freeRegister, :off
invoke-virtual {p1}, $colorMathPlayerInvokeVirtualReference
move-result-object v$freeRegister
check-cast v$freeRegister, ${(colorMathPlayerIGetReference as FieldReference).definingClass}
iget v$freeRegister, v$freeRegister, $colorMathPlayerIGetReference
iput v$freeRegister, p0, $colorMathPlayerIPutReference
:off
invoke-direct {p0}, $invokeDirectReference
"""
)
removeInstruction(invokeDirectIndex)
}
}
}
}
SettingsPatch.addSwitchPreference(
CategoryType.PLAYER,
"revanced_enable_color_match_player",
"true"
)
// endregion
// region patch for enable force minimized player
MinimizedPlayerFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.endIndex
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstructions(
insertIndex, """
invoke-static {v$insertRegister}, $PLAYER_CLASS_DESCRIPTOR->enableForceMinimizedPlayer(Z)Z
move-result v$insertRegister
"""
)
}
}
SettingsPatch.addSwitchPreference(
CategoryType.PLAYER,
"revanced_enable_force_minimized_player",
"true"
)
// endregion
// region patch for enable next previous button
val NEXT_BUTTON_FIELD_NAME = "nextButton"
val PREVIOUS_BUTTON_FIELD_NAME = "previousButton"
val NEXT_BUTTON_CLASS_FIELD_NAME = "nextButtonClass"
val PREVIOUS_BUTTON_CLASS_FIELD_NAME = "previousButtonClass"
val NEXT_BUTTON_METHOD_NAME = "setNextButton"
val PREVIOUS_BUTTON_METHOD_NAME = "setPreviousButton"
val NEXT_BUTTON_ONCLICK_METHOD_NAME = "setNextButtonOnClickListener"
val PREVIOUS_BUTTON_ONCLICK_METHOD_NAME = "setPreviousButtonOnClickListener"
val NEXT_BUTTON_INTENT_STRING = "YTM Next"
val PREVIOUS_BUTTON_INTENT_STRING = "YTM Previous"
val miniPlayerConstructorMutableMethod =
MiniPlayerConstructorFingerprint.resultOrThrow().mutableMethod
val mppWatchWhileLayoutMutableMethod =
MppWatchWhileLayoutFingerprint.resultOrThrow().mutableMethod
val pendingIntentReceiverMutableMethod =
PendingIntentReceiverFingerprint.resultOrThrow().mutableMethod
if (!SettingsPatch.upward0642) {
MiniPlayerParentFingerprint.resultOrThrow().let { parentResult ->
// Resolves fingerprints
NextButtonVisibilityFingerprint.resolve(context, parentResult.classDef)
NextButtonVisibilityFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val targetIndex = it.scanResult.patternScanResult!!.startIndex + 1
val targetRegister =
getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstructions(
targetIndex + 1, """
invoke-static {v$targetRegister}, $PLAYER_CLASS_DESCRIPTOR->enableMiniPlayerNextButton(Z)Z
move-result v$targetRegister
"""
)
}
}
}
} else {
miniPlayerConstructorMutableMethod.setInstanceFieldValue(NEXT_BUTTON_METHOD_NAME, TopStart)
mppWatchWhileLayoutMutableMethod.setStaticFieldValue(NEXT_BUTTON_FIELD_NAME, TopStart)
pendingIntentReceiverMutableMethod.setOnClickListener(context, NEXT_BUTTON_INTENT_STRING, NEXT_BUTTON_ONCLICK_METHOD_NAME, NEXT_BUTTON_CLASS_FIELD_NAME)
}
miniPlayerConstructorMutableMethod.setInstanceFieldValue(PREVIOUS_BUTTON_METHOD_NAME, TopEnd)
mppWatchWhileLayoutMutableMethod.setStaticFieldValue(PREVIOUS_BUTTON_FIELD_NAME, TopEnd)
pendingIntentReceiverMutableMethod.setOnClickListener(context, PREVIOUS_BUTTON_INTENT_STRING, PREVIOUS_BUTTON_ONCLICK_METHOD_NAME, PREVIOUS_BUTTON_CLASS_FIELD_NAME)
mppWatchWhileLayoutMutableMethod.setViewArray()
SettingsPatch.addSwitchPreference(
CategoryType.PLAYER,
"revanced_enable_mini_player_next_button",
"true"
)
SettingsPatch.addSwitchPreference(
CategoryType.PLAYER,
"revanced_enable_mini_player_previous_button",
"true"
)
// endregion
// region patch for enable swipe to dismiss mini player
var swipeToDismissWidgetIndex by Delegates.notNull<Int>()
lateinit var swipeToDismissIGetObjectReference: Reference
lateinit var swipeToDismissInvokeInterfacePrimaryReference: Reference
lateinit var swipeToDismissCheckCastReference: Reference
lateinit var swipeToDismissSGetObjectReference: Reference
lateinit var swipeToDismissNewInstanceReference: Reference
lateinit var swipeToDismissInvokeStaticReference: Reference
lateinit var swipeToDismissInvokeDirectReference: Reference
lateinit var swipeToDismissInvokeInterfaceSecondaryReference: Reference
fun MutableMethod.getSwipeToDismissReference(
opcode: Opcode,
reversed: Boolean
): Reference {
val targetIndex = if (reversed)
getTargetIndexReversed(swipeToDismissWidgetIndex, opcode)
else
getTargetIndex(swipeToDismissWidgetIndex, opcode)
return getInstruction<ReferenceInstruction>(targetIndex).reference
}
if (!SettingsPatch.upward0642) {
SwipeToCloseFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val insertIndex = implementation!!.instructions.size - 1
val targetRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstructions(
insertIndex, """
invoke-static {v$targetRegister}, $PLAYER_CLASS_DESCRIPTOR->enableSwipeToDismissMiniPlayer(Z)Z
move-result v$targetRegister
"""
)
}
}
} else {
// region dismiss mini player by swiping down
InteractionLoggingEnumFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val stringIndex = getStringInstructionIndex("INTERACTION_LOGGING_GESTURE_TYPE_SWIPE")
val sPutObjectIndex = getTargetIndex(stringIndex, Opcode.SPUT_OBJECT)
swipeToDismissSGetObjectReference = getInstruction<ReferenceInstruction>(sPutObjectIndex).reference
}
}
MusicActivityWidgetFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
swipeToDismissWidgetIndex = getWideLiteralInstructionIndex(79500)
swipeToDismissIGetObjectReference = getSwipeToDismissReference(Opcode.IGET_OBJECT, true)
swipeToDismissInvokeInterfacePrimaryReference = getSwipeToDismissReference(Opcode.INVOKE_INTERFACE, true)
swipeToDismissCheckCastReference = getSwipeToDismissReference(Opcode.CHECK_CAST, true)
swipeToDismissNewInstanceReference = getSwipeToDismissReference(Opcode.NEW_INSTANCE, true)
swipeToDismissInvokeStaticReference = getSwipeToDismissReference(Opcode.INVOKE_STATIC, false)
swipeToDismissInvokeDirectReference = getSwipeToDismissReference(Opcode.INVOKE_DIRECT, false)
swipeToDismissInvokeInterfaceSecondaryReference = getSwipeToDismissReference(Opcode.INVOKE_INTERFACE, false)
}
}
HandleSearchRenderedFingerprint.resultOrThrow().let { parentResult ->
// resolves fingerprints
HandleSignInEventFingerprint.resolve(context, parentResult.classDef)
HandleSignInEventFingerprint.resultOrThrow().let {
val dismissBehaviorMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex)
dismissBehaviorMethod.apply {
val insertIndex = getTargetIndexWithFieldReferenceType("Ljava/util/concurrent/atomic/AtomicBoolean;")
val primaryRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerB
val secondaryRegister = primaryRegister + 1
val tertiaryRegister = secondaryRegister + 1
val freeRegister = implementation!!.registerCount - parameters.size - 2
addInstructionsWithLabels(
insertIndex, """
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->enableSwipeToDismissMiniPlayer()Z
move-result v$freeRegister
if-nez v$freeRegister, :dismiss
iget-object v$primaryRegister, v$primaryRegister, $swipeToDismissIGetObjectReference
invoke-interface {v$primaryRegister}, $swipeToDismissInvokeInterfacePrimaryReference
move-result-object v$primaryRegister
check-cast v$primaryRegister, $swipeToDismissCheckCastReference
sget-object v$secondaryRegister, $swipeToDismissSGetObjectReference
new-instance v$tertiaryRegister, $swipeToDismissNewInstanceReference
const p0, 0x878b
invoke-static {p0}, $swipeToDismissInvokeStaticReference
move-result-object p0
invoke-direct {v$tertiaryRegister, p0}, $swipeToDismissInvokeDirectReference
const/4 p0, 0x0
invoke-interface {v$primaryRegister, v$secondaryRegister, v$tertiaryRegister, p0}, $swipeToDismissInvokeInterfaceSecondaryReference
return-void
""", ExternalLabel("dismiss", getInstruction(insertIndex))
)
}
}
}
// endregion
// region hides default text display when the app is cold started
MiniPlayerDefaultTextFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.endIndex
val insertRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerB
addInstructions(
insertIndex, """
invoke-static {v$insertRegister}, $PLAYER_CLASS_DESCRIPTOR->enableSwipeToDismissMiniPlayer(Ljava/lang/Object;)Ljava/lang/Object;
move-result-object v$insertRegister
"""
)
}
}
// endregion
// region hides default text display after dismissing the mini player
MiniPlayerDefaultViewVisibilityFingerprint.resultOrThrow().let {
it.mutableClass.methods.find { method ->
method.parameters == listOf("Landroid/view/View;", "I")
}?.apply {
val bottomSheetBehaviorIndex = implementation!!.instructions.indexOfFirst { instruction ->
instruction.opcode == Opcode.INVOKE_VIRTUAL
&& instruction.getReference<MethodReference>()?.definingClass == "Lcom/google/android/material/bottomsheet/BottomSheetBehavior;"
&& instruction.getReference<MethodReference>()?.parameterTypes?.first() == "Z"
}
if (bottomSheetBehaviorIndex < 0)
throw PatchException("Could not find bottomSheetBehaviorIndex")
val freeRegister = getInstruction<FiveRegisterInstruction>(bottomSheetBehaviorIndex).registerD
addInstructionsWithLabels(
bottomSheetBehaviorIndex - 2, """
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->enableSwipeToDismissMiniPlayer()Z
move-result v$freeRegister
if-nez v$freeRegister, :dismiss
""", ExternalLabel("dismiss", getInstruction(bottomSheetBehaviorIndex + 1))
)
} ?: throw PatchException("Could not find targetMethod")
}
// endregion
}
SettingsPatch.addSwitchPreference(
CategoryType.PLAYER,
"revanced_enable_swipe_to_dismiss_mini_player",
"true"
)
// endregion
// region patch for enable zen mode
MiniPlayerConstructorFingerprint.resultOrThrow().let { parentResult ->
// resolves fingerprints
SwitchToggleColorFingerprint.resolve(context, parentResult.classDef)
ZenModeFingerprint.resolve(context, parentResult.classDef)
// this method is used for old player background (deprecated since YT Music v6.34.51)
ZenModeFingerprint.result?.let {
it.mutableMethod.apply {
val startIndex = it.scanResult.patternScanResult!!.startIndex
val targetRegister = getInstruction<OneRegisterInstruction>(startIndex).registerA
val insertIndex = it.scanResult.patternScanResult!!.endIndex + 1
addInstructions(
insertIndex, """
invoke-static {v$targetRegister}, $PLAYER_CLASS_DESCRIPTOR->enableZenMode(I)I
move-result v$targetRegister
"""
)
}
} // no exception
SwitchToggleColorFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val invokeDirectIndex = getTargetIndex(Opcode.INVOKE_DIRECT)
val walkerMethod = getWalkerMethod(context, invokeDirectIndex)
walkerMethod.addInstructions(
0, """
invoke-static {p1}, $PLAYER_CLASS_DESCRIPTOR->enableZenMode(I)I
move-result p1
invoke-static {p2}, $PLAYER_CLASS_DESCRIPTOR->enableZenMode(I)I
move-result p2
"""
)
}
}
}
SettingsPatch.addSwitchPreference(
CategoryType.PLAYER,
"revanced_enable_zen_mode",
"false"
)
SettingsPatch.addSwitchPreference(
CategoryType.PLAYER,
"revanced_enable_zen_mode_podcast",
"false",
"revanced_enable_zen_mode"
)
// endregion
// region patch for hide channel guideline, timestamps & emoji picker buttons
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
SettingsPatch.addSwitchPreference(
CategoryType.PLAYER,
"revanced_hide_comment_channel_guidelines",
"true"
)
SettingsPatch.addSwitchPreference(
CategoryType.PLAYER,
"revanced_hide_comment_timestamp_and_emoji_buttons",
"false"
)
// region patch for hide fullscreen share button
RemixGenericButtonFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val targetIndex = it.scanResult.patternScanResult!!.endIndex
val targetRegister = getInstruction<TwoRegisterInstruction>(targetIndex).registerA
addInstructions(
targetIndex + 1, """
invoke-static {v$targetRegister}, $PLAYER_CLASS_DESCRIPTOR->hideFullscreenShareButton(I)I
move-result v$targetRegister
"""
)
}
}
SettingsPatch.addSwitchPreference(
CategoryType.PLAYER,
"revanced_hide_fullscreen_share_button",
"false"
)
// endregion
// region patch for remember repeat state
RepeatTrackFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
val targetIndex = it.scanResult.patternScanResult!!.endIndex
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstructions(
targetIndex, """
invoke-static {v$targetRegister}, $PLAYER_CLASS_DESCRIPTOR->rememberRepeatState(Z)Z
move-result v$targetRegister
"""
)
}
}
SettingsPatch.addSwitchPreference(
CategoryType.PLAYER,
"revanced_remember_repeat_state",
"true"
)
// endregion
// region patch for remember shuffle state
val MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR =
"Lcom/google/android/apps/youtube/music/watchpage/MusicPlaybackControls;"
lateinit var rememberShuffleStateObjectClass: String
lateinit var rememberShuffleStateImageViewReference: Reference
lateinit var rememberShuffleStateShuffleStateLabel: String
ShuffleClassReferenceFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
rememberShuffleStateObjectClass = definingClass
val startIndex = it.scanResult.patternScanResult!!.startIndex
val endIndex = it.scanResult.patternScanResult!!.endIndex
val imageViewIndex = getTargetIndexWithFieldReferenceType("Landroid/widget/ImageView;")
val shuffleReference1 = getInstruction<ReferenceInstruction>(startIndex).reference
val shuffleReference2 = getInstruction<ReferenceInstruction>(startIndex + 1).reference
val shuffleReference3 = getInstruction<ReferenceInstruction>(endIndex).reference
val shuffleFieldReference = shuffleReference3 as FieldReference
rememberShuffleStateImageViewReference = getInstruction<ReferenceInstruction>(imageViewIndex).reference
rememberShuffleStateShuffleStateLabel = """
iget-object v1, v0, $shuffleReference1
invoke-interface {v1}, $shuffleReference2
move-result-object v1
check-cast v1, ${shuffleFieldReference.definingClass}
iget-object v1, v1, $shuffleReference3
invoke-virtual {v1}, ${shuffleFieldReference.type}->ordinal()I
move-result v1
"""
}
val constructorMethod =
it.mutableClass.methods.first { method -> MethodUtil.isConstructor(method) }
val onClickMethod = it.mutableClass.methods.first { method -> method.name == "onClick" }
constructorMethod.apply {
addInstruction(
implementation!!.instructions.size - 1,
"sput-object p0, $MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR->shuffleClass:$rememberShuffleStateObjectClass"
)
}
onClickMethod.apply {
addInstructions(
0, """
move-object v0, p0
""" + rememberShuffleStateShuffleStateLabel + """
invoke-static {v1}, $PLAYER_CLASS_DESCRIPTOR->setShuffleState(I)V
"""
)
}
context.traverseClassHierarchy(it.mutableClass) {
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL
transformFields {
ImmutableField(
definingClass,
name,
type,
AccessFlags.PUBLIC or AccessFlags.PUBLIC,
null,
annotations,
null
).toMutable()
}
}
}
MusicPlaybackControlsFingerprint.resultOrThrow().let {
it.mutableMethod.apply {
addInstruction(
0,
"invoke-virtual {v0}, $MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR->rememberShuffleState()V"
)
val shuffleField = ImmutableField(
definingClass,
"shuffleClass",
rememberShuffleStateObjectClass,
AccessFlags.PUBLIC or AccessFlags.STATIC,
null,
annotations,
null
).toMutable()
val shuffleMethod = ImmutableMethod(
definingClass,
"rememberShuffleState",
emptyList(),
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL,
annotations, null,
MutableMethodImplementation(5)
).toMutable()
shuffleMethod.addInstructionsWithLabels(
0, """
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->getShuffleState()I
move-result v2
if-nez v2, :dont_shuffle
sget-object v0, $MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR->shuffleClass:$rememberShuffleStateObjectClass
""" + rememberShuffleStateShuffleStateLabel + """
iget-object v3, v0, $rememberShuffleStateImageViewReference
invoke-virtual {v3}, Landroid/widget/ImageView;->performClick()Z
if-eqz v1, :dont_shuffle
invoke-virtual {v3}, Landroid/widget/ImageView;->performClick()Z
:dont_shuffle
return-void
"""
)
it.mutableClass.methods.add(shuffleMethod)
it.mutableClass.staticFields.add(shuffleField)
}
}
SettingsPatch.addSwitchPreference(
CategoryType.PLAYER,
"revanced_remember_shuffle_state",
"true"
)
// endregion
// region patch for restore old comments popup panels
OldEngagementPanelFingerprint.literalInstructionBooleanHook(
45427672,
"$PLAYER_CLASS_DESCRIPTOR->restoreOldCommentsPopUpPanels(Z)Z"
)
SettingsPatch.addSwitchPreference(
CategoryType.PLAYER,
"revanced_restore_old_comments_popup_panels",
"false"
)
// endregion
// region patch for restore old player background
OldPlayerBackgroundFingerprint.result?.let {
OldPlayerBackgroundFingerprint.literalInstructionBooleanHook(
45415319,
"$PLAYER_CLASS_DESCRIPTOR->restoreOldPlayerBackground(Z)Z"
)
SettingsPatch.addSwitchPreference(
CategoryType.PLAYER,
"revanced_restore_old_player_background",
"false"
)
}
// endregion
// region patch for restore old player layout
OldPlayerLayoutFingerprint.result?.let {
OldPlayerLayoutFingerprint.literalInstructionBooleanHook(
45399578,
"$PLAYER_CLASS_DESCRIPTOR->restoreOldPlayerLayout(Z)Z"
)
SettingsPatch.addSwitchPreference(
CategoryType.PLAYER,
"revanced_restore_old_player_layout",
"false"
)
}
// endregion
}
private fun MutableMethod.setInstanceFieldValue(
methodName: String,
viewId: Long
) {
val miniPlayerPlayPauseReplayButtonIndex = getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton)
val miniPlayerPlayPauseReplayButtonRegister = getInstruction<OneRegisterInstruction>(miniPlayerPlayPauseReplayButtonIndex).registerA
val findViewByIdIndex = getTargetIndex(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_VIRTUAL)
val parentViewRegister = getInstruction<FiveRegisterInstruction>(findViewByIdIndex).registerC
addInstructions(
miniPlayerPlayPauseReplayButtonIndex, """
const v$miniPlayerPlayPauseReplayButtonRegister, $viewId
invoke-virtual {v$parentViewRegister, v$miniPlayerPlayPauseReplayButtonRegister}, Landroid/view/View;->findViewById(I)Landroid/view/View;
move-result-object v$miniPlayerPlayPauseReplayButtonRegister
invoke-static {v$miniPlayerPlayPauseReplayButtonRegister}, $PLAYER_CLASS_DESCRIPTOR->$methodName(Landroid/view/View;)V
"""
)
}
private fun MutableMethod.setStaticFieldValue(
fieldName: String,
viewId: Long
) {
val miniPlayerPlayPauseReplayButtonIndex = getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton)
val constRegister = getInstruction<OneRegisterInstruction>(miniPlayerPlayPauseReplayButtonIndex).registerA
val findViewByIdIndex = getTargetIndex(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_VIRTUAL)
val findViewByIdRegister = getInstruction<FiveRegisterInstruction>(findViewByIdIndex).registerC
addInstructions(
miniPlayerPlayPauseReplayButtonIndex, """
const v$constRegister, $viewId
invoke-virtual {v$findViewByIdRegister, v$constRegister}, $definingClass->findViewById(I)Landroid/view/View;
move-result-object v$constRegister
sput-object v$constRegister, $PLAYER_CLASS_DESCRIPTOR->$fieldName:Landroid/view/View;
"""
)
}
private fun MutableMethod.setViewArray() {
val miniPlayerPlayPauseReplayButtonIndex = getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton)
val invokeStaticIndex = getTargetIndex(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_STATIC)
val viewArrayRegister = getInstruction<FiveRegisterInstruction>(invokeStaticIndex).registerC
addInstructions(
invokeStaticIndex, """
invoke-static {v$viewArrayRegister}, $PLAYER_CLASS_DESCRIPTOR->getViewArray([Landroid/view/View;)[Landroid/view/View;
move-result-object v$viewArrayRegister
"""
)
}
private fun MutableMethod.setOnClickListener(
context: BytecodeContext,
intentString: String,
methodName: String,
fieldName: String
) {
val startIndex = getStringInstructionIndex(intentString)
val onClickIndex = getTargetIndexReversed(startIndex, Opcode.INVOKE_VIRTUAL)
val onClickReference = getInstruction<ReferenceInstruction>(onClickIndex).reference
val onClickReferenceDefiningClass = (onClickReference as MethodReference).definingClass
val onClickClass =
context.findClass(onClickReferenceDefiningClass)!!.mutableClass
onClickClass.methods.find { method -> method.name == "<init>" }
?.apply {
addInstruction(
implementation!!.instructions.size - 1,
"sput-object p0, $PLAYER_CLASS_DESCRIPTOR->$fieldName:$onClickReferenceDefiningClass"
)
} ?: throw PatchException("onClickClass not found!")
PlayerPatchConstructorFingerprint.resultOrThrow().let {
val mutableClass = it.mutableClass
mutableClass.methods.find { method -> method.name == methodName }
?.apply {
mutableClass.staticFields.add(
ImmutableField(
definingClass,
fieldName,
onClickReferenceDefiningClass,
AccessFlags.PUBLIC or AccessFlags.STATIC,
null,
annotations,
null
).toMutable()
)
addInstructionsWithLabels(
0, """
sget-object v0, $PLAYER_CLASS_DESCRIPTOR->$fieldName:$onClickReferenceDefiningClass
if-eqz v0, :ignore
invoke-virtual {v0}, $onClickReference
:ignore
return-void
"""
)
}
}
}
}

View File

@ -1,6 +1,6 @@
@file:Suppress("DEPRECATION")
package app.revanced.patches.music.player.nextprevious
package app.revanced.patches.music.player.components
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
@ -14,7 +14,7 @@ import org.w3c.dom.Element
import java.io.Closeable
@Patch(dependencies = [SettingsPatch::class])
object MiniPlayerButtonResourcePatch : ResourcePatch(), Closeable {
object PlayerComponentsResourcePatch : ResourcePatch(), Closeable {
private const val IMAGE_VIEW_TAG_NAME =
"com.google.android.libraries.youtube.common.ui.TouchImageView"
private const val NEXT_BUTTON_VIEW_ID =

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.player.swipetodismiss.fingerprints
package app.revanced.patches.music.player.components.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.player.swipetodismiss.fingerprints
package app.revanced.patches.music.player.components.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.player.swipetodismiss.fingerprints
package app.revanced.patches.music.player.components.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.utils.fingerprints
package app.revanced.patches.music.player.components.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.ColorGrey

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.player.swipetodismiss.fingerprints
package app.revanced.patches.music.player.components.fingerprints
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MiniPlayerDefaultText
import app.revanced.util.fingerprint.LiteralValueFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.player.swipetodismiss.fingerprints
package app.revanced.patches.music.player.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.player.nextprevious.fingerprints
package app.revanced.patches.music.player.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MiniPlayerMdxPlaying

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.player.minimizedplayer.fingerprints
package app.revanced.patches.music.player.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.player.nextprevious.fingerprints
package app.revanced.patches.music.player.components.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MiniPlayerPlayPauseReplayButton

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.player.swipetodismiss.fingerprints
package app.revanced.patches.music.player.components.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.util.containsWideLiteralInstructionIndex

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.player.shuffle.fingerprints
package app.revanced.patches.music.player.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.player.nextprevious.fingerprints
package app.revanced.patches.music.player.components.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -0,0 +1,9 @@
package app.revanced.patches.music.player.components.fingerprints
import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object OldEngagementPanelFingerprint : LiteralValueFingerprint(
returnType = "Z",
parameters = emptyList(),
literalSupplier = { 45427672 }
)

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.player.oldplayerbackground.fingerprints
package app.revanced.patches.music.player.components.fingerprints
import app.revanced.util.fingerprint.LiteralValueFingerprint

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.player.oldplayerlayout.fingerprints
package app.revanced.patches.music.player.components.fingerprints
import app.revanced.util.fingerprint.LiteralValueFingerprint

Some files were not shown because too many files have changed in this diff Show More