feat(YouTube Music - Navigation bar components): Add Replace Samples button and Replace Upgrade button settings

This commit is contained in:
inotia00
2025-03-14 18:42:59 +09:00
parent f81581cbb3
commit 9f762e8bd0
14 changed files with 363 additions and 93 deletions

View File

@ -3,9 +3,13 @@ package app.revanced.patches.music.navigation.components
import app.revanced.patches.music.utils.resourceid.colorGrey
import app.revanced.patches.music.utils.resourceid.text1
import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal val tabLayoutFingerprint = legacyFingerprint(
name = "tabLayoutFingerprint",
@ -30,5 +34,22 @@ internal val tabLayoutTextFingerprint = legacyFingerprint(
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT
),
literals = listOf(text1)
strings = listOf("FEmusic_search"),
literals = listOf(text1),
customFingerprint = { method, _ ->
indexOfGetVisibilityInstruction(method) >= 0 &&
indexOfSetTextInstruction(method) >= 0
}
)
internal fun indexOfGetVisibilityInstruction(method: Method) =
method.indexOfFirstInstruction {
opcode == Opcode.INVOKE_VIRTUAL &&
getReference<MethodReference>()?.name == "getVisibility"
}
internal fun indexOfSetTextInstruction(method: Method) =
method.indexOfFirstInstruction {
opcode == Opcode.INVOKE_VIRTUAL &&
getReference<MethodReference>()?.name == "setText"
}

View File

@ -6,26 +6,36 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.resourcePatch
import app.revanced.patches.music.general.startpage.changeStartPagePatch
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.extension.Constants.NAVIGATION_CLASS_DESCRIPTOR
import app.revanced.patches.music.utils.patch.PatchList.NAVIGATION_BAR_COMPONENTS
import app.revanced.patches.music.utils.resourceid.colorGrey
import app.revanced.patches.music.utils.resourceid.sharedResourceIdPatch
import app.revanced.patches.music.utils.resourceid.text1
import app.revanced.patches.music.utils.resourceid.ytFillSamples
import app.revanced.patches.music.utils.resourceid.ytFillYouTubeMusic
import app.revanced.patches.music.utils.resourceid.ytOutlineSamples
import app.revanced.patches.music.utils.resourceid.ytOutlineYouTubeMusic
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.ResourceUtils.updatePatchStatus
import app.revanced.patches.music.utils.settings.addPreferenceWithIntent
import app.revanced.patches.music.utils.settings.addSwitchPreference
import app.revanced.patches.music.utils.settings.settingsPatch
import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT
import app.revanced.util.fingerprint.matchOrThrow
import app.revanced.util.fingerprint.methodOrThrow
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
import app.revanced.util.replaceLiteralInstructionCall
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.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
private const val FLAG = "android:layout_weight"
@ -56,6 +66,7 @@ val navigationBarComponentsPatch = bytecodePatch(
compatibleWith(COMPATIBLE_PACKAGE)
dependsOn(
changeStartPagePatch,
navigationBarComponentsResourcePatch,
sharedResourceIdPatch,
settingsPatch,
@ -105,29 +116,73 @@ val navigationBarComponentsPatch = bytecodePatch(
*/
tabLayoutTextFingerprint.matchOrThrow().let {
it.method.apply {
val stringIndex = it.stringMatches!!.first().index
val browseIdIndex = indexOfFirstInstructionReversedOrThrow(stringIndex) {
opcode == Opcode.IGET_OBJECT &&
getReference<FieldReference>()?.type == "Ljava/lang/String;"
}
val browseIdReference = getInstruction<ReferenceInstruction>(browseIdIndex).reference as FieldReference
val fieldName = browseIdReference.name
val componentIndex = indexOfFirstInstructionOrThrow(stringIndex) {
opcode == Opcode.IGET_OBJECT &&
getReference<FieldReference>()?.toString() == browseIdReference.toString()
}
val browseIdRegister = getInstruction<TwoRegisterInstruction>(componentIndex).registerA
val componentRegister = getInstruction<TwoRegisterInstruction>(componentIndex).registerB
val enumIndex = it.patternMatch!!.startIndex + 3
val enumRegister = getInstruction<OneRegisterInstruction>(enumIndex).registerA
val insertEnumIndex = indexOfFirstInstructionOrThrow(Opcode.AND_INT_LIT8) - 2
val pivotTabIndex = indexOfFirstInstructionOrThrow {
opcode == Opcode.INVOKE_VIRTUAL &&
getReference<MethodReference>()?.name == "getVisibility"
}
val pivotTabIndex = indexOfGetVisibilityInstruction(this)
val pivotTabRegister =
getInstruction<FiveRegisterInstruction>(pivotTabIndex).registerC
val spannedIndex = indexOfSetTextInstruction(this)
val spannedRegister =
getInstruction<FiveRegisterInstruction>(spannedIndex).registerD
addInstruction(
pivotTabIndex,
"invoke-static {v$pivotTabRegister}, $NAVIGATION_CLASS_DESCRIPTOR->hideNavigationButton(Landroid/view/View;)V"
)
addInstructions(
componentIndex + 1, """
const-string v$enumRegister, "$fieldName"
invoke-static {v$componentRegister, v$browseIdRegister, v$enumRegister}, $NAVIGATION_CLASS_DESCRIPTOR->replaceBrowseId(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
move-result-object v$browseIdRegister
"""
)
addInstructions(
spannedIndex, """
invoke-static {v$spannedRegister}, $NAVIGATION_CLASS_DESCRIPTOR->replaceNavigationLabel(Landroid/text/Spanned;)Landroid/text/Spanned;
move-result-object v$spannedRegister
"""
)
addInstruction(
insertEnumIndex,
"sput-object v$enumRegister, $NAVIGATION_CLASS_DESCRIPTOR->lastPivotTab:Ljava/lang/Enum;"
"invoke-static {v$enumRegister}, $NAVIGATION_CLASS_DESCRIPTOR->setLastAppNavigationEnum(Ljava/lang/Enum;)V"
)
}
}
val smaliInstruction = """
invoke-static {v$REGISTER_TEMPLATE_REPLACEMENT}, $NAVIGATION_CLASS_DESCRIPTOR->replaceNavigationIcon(I)I
move-result v$REGISTER_TEMPLATE_REPLACEMENT
"""
arrayOf(
ytFillSamples,
ytFillYouTubeMusic,
ytOutlineSamples,
ytOutlineYouTubeMusic,
).forEach { literal ->
replaceLiteralInstructionCall(literal, smaliInstruction)
}
addSwitchPreference(
CategoryType.NAVIGATION,
"revanced_enable_custom_navigation_bar_color",
@ -173,6 +228,20 @@ val navigationBarComponentsPatch = bytecodePatch(
"revanced_hide_navigation_label",
"false"
)
addSwitchPreference(
CategoryType.NAVIGATION,
"revanced_replace_navigation_samples_button",
"false"
)
addSwitchPreference(
CategoryType.NAVIGATION,
"revanced_replace_navigation_upgrade_button",
"false"
)
addPreferenceWithIntent(
CategoryType.NAVIGATION,
"revanced_replace_navigation_button_about"
)
updatePatchStatus(NAVIGATION_BAR_COMPONENTS)

View File

@ -105,6 +105,14 @@ var trimSilenceSwitch = -1L
private set
var varispeedUnavailableTitle = -1L
private set
var ytFillSamples = -1L
private set
var ytFillYouTubeMusic = -1L
private set
var ytOutlineSamples = -1L
private set
var ytOutlineYouTubeMusic = -1L
private set
var ytmLogo = -1L
private set
var ytmLogoRingo2 = -1L
@ -300,6 +308,22 @@ internal val sharedResourceIdPatch = resourcePatch(
STRING,
"varispeed_unavailable_title"
]
ytFillSamples = resourceMappings[
DRAWABLE,
"yt_fill_samples_vd_theme_24",
]
ytFillYouTubeMusic = resourceMappings[
DRAWABLE,
"yt_fill_youtube_music_vd_theme_24",
]
ytOutlineSamples = resourceMappings[
DRAWABLE,
"yt_outline_samples_vd_theme_24",
]
ytOutlineYouTubeMusic = resourceMappings[
DRAWABLE,
"yt_outline_youtube_music_vd_theme_24",
]
ytmLogo = resourceMappings[
DRAWABLE,
"ytm_logo",