fix(YouTube Music - Hide ads): Renewal banner or update banner disappears too late

This commit is contained in:
inotia00 2025-01-31 20:28:54 +09:00
parent 9b56cb6c0d
commit a50eed6466
5 changed files with 125 additions and 15 deletions

View File

@ -8,32 +8,43 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import app.revanced.extension.music.settings.Settings;
import app.revanced.extension.shared.utils.Logger;
import app.revanced.extension.music.shared.NavigationBar;
import app.revanced.extension.shared.utils.Utils;
@SuppressWarnings("unused")
public class PremiumRenewalPatch {
private static final String dialogGotItText =
str("dialog_got_it_text");
public static void hidePremiumRenewal(LinearLayout buttonContainerView) {
if (!Settings.HIDE_PREMIUM_RENEWAL.get())
return;
buttonContainerView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
try {
Utils.runOnMainThreadDelayed(() -> {
if (!(buttonContainerView.getChildAt(0) instanceof ViewGroup closeButtonParentView))
return;
if (!(closeButtonParentView.getChildAt(0) instanceof TextView closeButtonView))
return;
if (closeButtonView.getText().toString().equals(str("dialog_got_it_text")))
Utils.clickView(closeButtonView);
else
Utils.hideViewByLayoutParams((View) buttonContainerView.getParent());
}, 0
);
} catch (Exception ex) {
Logger.printException(() -> "hidePremiumRenewal failure", ex);
if (NavigationBar.getNavigationTabIndex() == 0) {
// Always hide the banner when the navigation bar index is 0.
hideParentViewByLayoutParams(buttonContainerView);
} else {
// This banner is exposed to the library as well as the home.
// In this case, it is necessary to check whether the text of the button is 'Got it' or not.
if (!(buttonContainerView.getChildAt(0) instanceof ViewGroup closeButtonParentView))
return;
if (!(closeButtonParentView.getChildAt(0) instanceof TextView closeButtonView))
return;
// If the text of the button is 'Got it', just click the button.
// If not, tab sometimes becomes freezing.
if (closeButtonView.getText().toString().equals(dialogGotItText)) {
Utils.clickView(closeButtonView);
} else {
hideParentViewByLayoutParams(buttonContainerView);
}
}
});
}
private static void hideParentViewByLayoutParams(View view) {
if (view.getParent() instanceof View parentView) {
Utils.hideViewByLayoutParams(parentView);
}
}
}

View File

@ -0,0 +1,19 @@
package app.revanced.extension.music.shared;
@SuppressWarnings("unused")
public final class NavigationBar {
private static volatile int lastIndex = 0;
/**
* Injection point.
*/
public static void navigationTabSelected(int index, boolean isSelected) {
if (isSelected) {
lastIndex = index;
}
}
public static int getNavigationTabIndex() {
return lastIndex;
}
}

View File

@ -7,6 +7,7 @@ import app.revanced.patches.music.navigation.components.navigationBarComponentsP
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.extension.Constants.ADS_PATH
import app.revanced.patches.music.utils.extension.Constants.COMPONENTS_PATH
import app.revanced.patches.music.utils.navigation.navigationBarHookPatch
import app.revanced.patches.music.utils.patch.PatchList.HIDE_ADS
import app.revanced.patches.music.utils.resourceid.buttonContainer
import app.revanced.patches.music.utils.resourceid.floatingLayout
@ -55,6 +56,7 @@ val adsPatch = bytecodePatch(
baseAdsPatch("$ADS_PATH/MusicAdsPatch;", "hideMusicAds"),
lithoFilterPatch,
navigationBarComponentsPatch, // for 'Hide upgrade button' setting
navigationBarHookPatch,
sharedResourceIdPatch,
)

View File

@ -0,0 +1,30 @@
package app.revanced.patches.music.utils.navigation
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 tabLayoutViewSetSelectedFingerprint = legacyFingerprint(
name = "tabLayoutViewSetSelectedFingerprint",
returnType = "V",
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
parameters = listOf("I"),
customFingerprint = { method, classDef ->
classDef.type == "Lcom/google/android/material/tabs/TabLayout;" &&
indexOfChildAtInstruction(method) >= 0 &&
indexOfSetViewActivatedInstruction(method) >= 0
}
)
internal fun indexOfChildAtInstruction(method: Method) = method.indexOfFirstInstruction {
opcode == Opcode.INVOKE_VIRTUAL && getReference<MethodReference>()?.name == "getChildAt"
}
private fun indexOfSetViewActivatedInstruction(method: Method) = method.indexOfFirstInstruction {
opcode == Opcode.INVOKE_VIRTUAL && getReference<MethodReference>()?.name == "setActivated"
}

View File

@ -0,0 +1,48 @@
package app.revanced.patches.music.utils.navigation
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.music.utils.extension.Constants.SHARED_PATH
import app.revanced.patches.music.utils.extension.sharedExtensionPatch
import app.revanced.util.fingerprint.methodOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal const val EXTENSION_CLASS_DESCRIPTOR =
"$SHARED_PATH/NavigationBar;"
val navigationBarHookPatch = bytecodePatch(
description = "navigationBarHookPatch",
) {
dependsOn(sharedExtensionPatch)
execute {
tabLayoutViewSetSelectedFingerprint.methodOrThrow().apply {
val childAtIndex = indexOfChildAtInstruction(this)
val tabIndexRegister =
getInstruction<FiveRegisterInstruction>(childAtIndex).registerD
implementation!!.instructions
.withIndex()
.filter { (_, instruction) ->
val reference = (instruction as? ReferenceInstruction)?.reference
reference is MethodReference &&
reference.name == "setActivated"
}
.map { (index, _) -> index }
.reversed()
.forEach { index ->
val isSelectedRegister =
getInstruction<FiveRegisterInstruction>(childAtIndex).registerD
addInstruction(
index,
"invoke-static {v$tabIndexRegister, v$isSelectedRegister}, " +
"$EXTENSION_CLASS_DESCRIPTOR->navigationTabSelected(IZ)V"
)
}
}
}
}