feat(YouTube - Hide ads): Add Hide player popup ads setting

Close https://github.com/anddea/revanced-patches/issues/1405
Close https://github.com/anddea/revanced-patches/issues/1420
This commit is contained in:
Aaron Veil 2026-03-25 11:19:13 +03:00
parent 5247736538
commit 06275f4cf4
7 changed files with 49 additions and 6 deletions

View file

@ -1,6 +1,7 @@
package app.morphe.extension.shared.utils;
import static android.text.Html.FROM_HTML_MODE_COMPACT;
import static app.morphe.extension.shared.Utils.isNotEmpty;
import static app.morphe.extension.shared.utils.BaseThemeUtils.getCancelOrNeutralButtonBackgroundColor;
import static app.morphe.extension.shared.utils.BaseThemeUtils.getOkButtonBackgroundColor;
import static app.morphe.extension.shared.utils.BaseThemeUtils.isDarkModeEnabled;
@ -219,10 +220,12 @@ public class Utils {
}
public static int indexOfFirstFound(@NonNull String value, @NonNull String... targets) {
for (String string : targets) {
if (!string.isEmpty()) {
final int indexOf = value.indexOf(string);
if (indexOf >= 0) return indexOf;
if (isNotEmpty(value)) {
for (String string : targets) {
if (!string.isEmpty()) {
final int indexOf = value.indexOf(string);
if (indexOf >= 0) return indexOf;
}
}
}
return -1;

View file

@ -9,6 +9,7 @@ import android.widget.TextView;
import java.util.List;
import app.morphe.extension.shared.utils.Logger;
import app.morphe.extension.shared.utils.Utils;
import app.morphe.extension.youtube.settings.Settings;
import app.morphe.extension.youtube.utils.ExtendedUtils;
@ -23,6 +24,10 @@ public class AdsPatch {
Settings.HIDE_YOUTUBE_PREMIUM_PROMOTION.get();
private static final boolean HIDE_VIDEO_ADS =
Settings.HIDE_VIDEO_ADS.get();
private static final String[] PLAYER_POPUP_AD_PANEL_IDS = {
"PAproduct", // Shopping.
"jumpahead" // Premium promotion.
};
// https://encrypted-tbn0.gstatic.com/shopping?q=tbn
private static final String STORE_BANNER_DOMAIN =
@ -75,6 +80,14 @@ public class AdsPatch {
return Settings.HIDE_PAID_PROMOTION_LABEL.get();
}
/**
* Injection point.
*/
public static boolean hidePlayerPopupAds(String panelId) {
return Settings.HIDE_PLAYER_POPUP_ADS.get()
&& Utils.containsAny(panelId, PLAYER_POPUP_AD_PANEL_IDS);
}
/**
* Injection point.
*/

View file

@ -85,6 +85,7 @@ public class Settings extends SharedYouTubeSettings {
public static final BooleanSetting HIDE_GENERAL_ADS = new BooleanSetting("revanced_hide_general_ads", TRUE);
public static final BooleanSetting HIDE_MERCHANDISE_SHELF = new BooleanSetting("revanced_hide_merchandise_shelf", TRUE);
public static final BooleanSetting HIDE_PAID_PROMOTION_LABEL = new BooleanSetting("revanced_hide_paid_promotion_label", TRUE);
public static final BooleanSetting HIDE_PLAYER_POPUP_ADS = new BooleanSetting("revanced_hide_player_popup_ads", TRUE);
public static final BooleanSetting HIDE_SELF_SPONSOR_CARDS = new BooleanSetting("revanced_hide_self_sponsor_cards", TRUE);
public static final BooleanSetting HIDE_SHOPPING_LINKS = new BooleanSetting("revanced_hide_shopping_links", TRUE);
public static final BooleanSetting HIDE_VIDEO_ADS = new BooleanSetting("revanced_hide_video_ads", TRUE, true);

View file

@ -14,6 +14,8 @@ import app.morphe.patches.shared.litho.addLithoFilter
import app.morphe.patches.shared.litho.lithoFilterPatch
import app.morphe.patches.shared.spoof.guide.addClientOSVersionHook
import app.morphe.patches.shared.spoof.guide.spoofClientGuideEndpointPatch
import app.morphe.patches.youtube.utils.engagement.addEngagementPanelIdHook
import app.morphe.patches.youtube.utils.engagement.engagementPanelHookPatch
import app.morphe.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.morphe.patches.youtube.utils.extension.Constants.ADS_CLASS_DESCRIPTOR
import app.morphe.patches.youtube.utils.extension.Constants.COMPONENTS_PATH
@ -52,12 +54,14 @@ val adsPatch = adsPatch(
sharedResourceIdPatch,
spoofClientGuideEndpointPatch,
versionCheckPatch,
engagementPanelHookPatch,
)
},
classDescriptor = ADS_CLASS_DESCRIPTOR,
methodDescriptor = "hideVideoAds",
executeBlock = {
addLithoFilter(ADS_FILTER_CLASS_DESCRIPTOR)
addEngagementPanelIdHook("$ADS_CLASS_DESCRIPTOR->hidePlayerPopupAds(Ljava/lang/String;)Z")
// region patch for hide general ads
@ -213,4 +217,4 @@ val adsPatch = adsPatch(
// endregion
}
)
)

View file

@ -2,6 +2,7 @@ package app.morphe.patches.youtube.utils.engagement
import app.morphe.patcher.extensions.InstructionExtensions.addInstruction
import app.morphe.patcher.extensions.InstructionExtensions.addInstructions
import app.morphe.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.morphe.patcher.extensions.InstructionExtensions.getInstruction
import app.morphe.patcher.patch.bytecodePatch
import app.morphe.patcher.util.proxy.mutableTypes.MutableMethod
@ -26,6 +27,7 @@ internal lateinit var engagementPanelBuilderMethod: MutableMethod
internal var engagementPanelFreeRegister = 0
internal var engagementPanelIdIndex = 0
internal var engagementPanelIdRegister = 0
internal var engagementPanelIdInstruction = ""
val engagementPanelHookPatch = bytecodePatch(
description = "engagementPanelHookPatch"
@ -87,6 +89,8 @@ val engagementPanelHookPatch = bytecodePatch(
invoke-static {v$engagementPanelIdRegister}, $EXTENSION_CLASS_DESCRIPTOR->setId(Ljava/lang/String;)V
"""
)
engagementPanelIdInstruction =
"iget-object v$engagementPanelIdRegister, v$classRegister, $engagementPanelIdReference"
engagementPanelIdIndex = insertIndex + 1
engagementPanelBuilderMethod = this
}
@ -98,4 +102,18 @@ val engagementPanelHookPatch = bytecodePatch(
"invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->hide()V"
)
}
}
}
internal fun addEngagementPanelIdHook(descriptor: String) =
engagementPanelBuilderMethod.addInstructionsWithLabels(
engagementPanelIdIndex, """
$engagementPanelIdInstruction
invoke-static {v$engagementPanelIdRegister}, $descriptor
move-result v$engagementPanelFreeRegister
if-eqz v$engagementPanelFreeRegister, :shown
const/4 v$engagementPanelFreeRegister, 0x0
return-object v$engagementPanelFreeRegister
:shown
nop
"""
)

View file

@ -1011,6 +1011,9 @@ Words with uppercase letters in the middle must be entered with the casing (ie:
<string name="revanced_hide_paid_promotion_label_summary_off">Paid promotion label is shown.</string>
<string name="revanced_hide_paid_promotion_label_summary_on">Paid promotion label is hidden.</string>
<string name="revanced_hide_paid_promotion_label_title">Hide paid promotion label</string>
<string name="revanced_hide_player_popup_ads_summary_off">Player popup ads are shown.</string>
<string name="revanced_hide_player_popup_ads_summary_on">Player popup ads are hidden.</string>
<string name="revanced_hide_player_popup_ads_title">Hide player popup ads</string>
<string name="revanced_hide_playables_summary_off">Playables are shown.</string>
<string name="revanced_hide_playables_summary_on">Playables are hidden.</string>
<string name="revanced_hide_playables_title">Hide Playables</string>

View file

@ -195,6 +195,7 @@
<SwitchPreference android:title="@string/revanced_hide_general_ads_title" android:key="revanced_hide_general_ads" android:summaryOn="@string/revanced_hide_general_ads_summary_on" android:summaryOff="@string/revanced_hide_general_ads_summary_off" />
<SwitchPreference android:title="@string/revanced_hide_merchandise_shelf_title" android:key="revanced_hide_merchandise_shelf" android:summaryOn="@string/revanced_hide_merchandise_shelf_summary_on" android:summaryOff="@string/revanced_hide_merchandise_shelf_summary_off" />
<SwitchPreference android:title="@string/revanced_hide_paid_promotion_label_title" android:key="revanced_hide_paid_promotion_label" android:summaryOn="@string/revanced_hide_paid_promotion_label_summary_on" android:summaryOff="@string/revanced_hide_paid_promotion_label_summary_off" />
<SwitchPreference android:title="@string/revanced_hide_player_popup_ads_title" android:key="revanced_hide_player_popup_ads" android:summaryOn="@string/revanced_hide_player_popup_ads_summary_on" android:summaryOff="@string/revanced_hide_player_popup_ads_summary_off" />
<SwitchPreference android:title="@string/revanced_hide_promotion_alert_banner_title" android:key="revanced_hide_promotion_alert_banner" android:summaryOn="@string/revanced_hide_promotion_alert_banner_summary_on" android:summaryOff="@string/revanced_hide_promotion_alert_banner_summary_off" />
<SwitchPreference android:title="@string/revanced_hide_self_sponsor_cards_title" android:key="revanced_hide_self_sponsor_cards" android:summaryOn="@string/revanced_hide_self_sponsor_cards_summary_on" android:summaryOff="@string/revanced_hide_self_sponsor_cards_summary_off" />
<SwitchPreference android:title="@string/revanced_hide_shopping_links_title" android:key="revanced_hide_shopping_links" android:summaryOn="@string/revanced_hide_shopping_links_summary_on" android:summaryOff="@string/revanced_hide_shopping_links_summary_off" />