1+ package io.github.chsbuffer.revancedxposed.spotify
2+
3+ import app.revanced.extension.spotify.layout.hide.createbutton.HideCreateButtonPatch
4+ import de.robv.android.xposed.XC_MethodHook
5+ import io.github.chsbuffer.revancedxposed.AccessFlags
6+ import io.github.chsbuffer.revancedxposed.Opcode
7+ import io.github.chsbuffer.revancedxposed.fingerprint
8+
9+ fun SpotifyHook.HideCreateButton () {
10+ val oldNavigationBarAddItemMethod = runCatching {
11+ getDexMethod(" oldNavigationBarAddItemFingerprint" ) {
12+ fingerprint {
13+ strings(" Bottom navigation tabs exceeds maximum of 5 tabs" )
14+ }
15+ }
16+ }.getOrNull()
17+
18+ val navigationBarItemSetClassDef = runCatching {
19+ getDexClass(" navigationBarItemSetClassFingerprint" ) {
20+ fingerprint {
21+ strings(" NavigationBarItemSet(" )
22+ }.declaredClass!!
23+ }
24+ }.getOrNull()
25+
26+ if (navigationBarItemSetClassDef != null ) {
27+ // Main patch for newest and most versions.
28+ // The NavigationBarItemSet constructor accepts multiple parameters which represent each navigation bar item.
29+ // Each item is manually checked whether it is not null and then added to a LinkedHashSet.
30+ // Since the order of the items can differ, we are required to check every parameter to see whether it is the
31+ // Create button. So, for every parameter passed to the method, invoke our extension method and overwrite it
32+ // to null in case it is the Create button.
33+ getDexMethod(" navigationBarItemSetConstructorFingerprint" ) {
34+ fingerprint {
35+ accessFlags(AccessFlags .PUBLIC , AccessFlags .CONSTRUCTOR )
36+ // Make sure the method checks whether navigation bar items are null before adding them.
37+ // If this is not true, then we cannot patch the method and potentially transform the parameters into null.
38+ opcodes(Opcode .IF_EQZ , Opcode .INVOKE_VIRTUAL )
39+ classMatcher {
40+ className = navigationBarItemSetClassDef.className
41+ }
42+ methodMatcher {
43+ addInvoke { name = " add" }
44+ }
45+ }
46+ }.hookMethod(object : XC_MethodHook () {
47+ override fun beforeHookedMethod (param : MethodHookParam ) {
48+ for ((i, arg) in param.args.withIndex()) {
49+ param.args[i] = HideCreateButtonPatch .returnNullIfIsCreateButton(arg)
50+ }
51+ }
52+ })
53+ }
54+
55+ @Suppress(" IfThenToSafeAccess" )
56+ if (oldNavigationBarAddItemMethod != null ) {
57+ // In case an older version of the app is being patched, hook the old method which adds navigation bar items.
58+ // Return early if the navigation bar item title resource id is the old Create button title resource id.
59+ oldNavigationBarAddItemMethod.hookMethod(object : XC_MethodHook () {
60+ override fun beforeHookedMethod (param : MethodHookParam ) {
61+ for (arg in param.args) {
62+ if (arg !is Int ) continue
63+ if (HideCreateButtonPatch .isOldCreateButton(arg)) {
64+ param.result = null
65+ return
66+ }
67+ }
68+ }
69+ })
70+ }
71+ }
0 commit comments