fix(YouTube - Hide Ads): Hide end screen store banner without leaving empty space (#4367)

This commit is contained in:
LisoUseInAIKyrios 2025-01-29 09:40:59 +02:00 committed by GitHub
parent 9b6f78a7e8
commit 7e68390641
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 88 additions and 32 deletions

View file

@ -5,10 +5,13 @@ import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class VideoAdsPatch { public class VideoAdsPatch {
// Used by app.revanced.patches.youtube.ad.general.video.patch.VideoAdsPatch private static final boolean SHOW_VIDEO_ADS = !Settings.HIDE_VIDEO_ADS.get();
// depends on Whitelist patch (still needs to be written)
/**
* Injection point.
*/
public static boolean shouldShowAds() { public static boolean shouldShowAds() {
return !Settings.HIDE_VIDEO_ADS.get(); // TODO && Whitelist.shouldShowAds(); return SHOW_VIDEO_ADS;
} }
} }

View file

@ -8,10 +8,12 @@ import android.view.View;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import app.revanced.extension.youtube.settings.Settings; import java.util.List;
import app.revanced.extension.shared.Logger; import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils; import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.StringTrieSearch; import app.revanced.extension.youtube.StringTrieSearch;
import app.revanced.extension.youtube.settings.Settings;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class AdsFilter extends Filter { public final class AdsFilter extends Filter {
@ -22,14 +24,16 @@ public final class AdsFilter extends Filter {
// endregion // endregion
// https://encrypted-tbn0.gstatic.com/shopping?q=abc
private static final String STORE_BANNER_DOMAIN = "gstatic.com/shopping";
private static final boolean HIDE_END_SCREEN_STORE_BANNER =
Settings.HIDE_END_SCREEN_STORE_BANNER.get();
private final StringTrieSearch exceptions = new StringTrieSearch(); private final StringTrieSearch exceptions = new StringTrieSearch();
private final StringFilterGroup playerShoppingShelf; private final StringFilterGroup playerShoppingShelf;
private final ByteArrayFilterGroup playerShoppingShelfBuffer; private final ByteArrayFilterGroup playerShoppingShelfBuffer;
private final StringFilterGroup fullscreenOverlay;
private final ByteArrayFilterGroup endScreenStoreBannerBuffer;
private final StringFilterGroup channelProfile; private final StringFilterGroup channelProfile;
private final ByteArrayFilterGroup visitStoreButton; private final ByteArrayFilterGroup visitStoreButton;
@ -116,32 +120,22 @@ public final class AdsFilter extends Filter {
); );
playerShoppingShelf = new StringFilterGroup( playerShoppingShelf = new StringFilterGroup(
null, Settings.HIDE_PLAYER_STORE_SHELF,
"horizontal_shelf.eml" "horizontal_shelf.eml"
); );
playerShoppingShelfBuffer = new ByteArrayFilterGroup( playerShoppingShelfBuffer = new ByteArrayFilterGroup(
Settings.HIDE_PLAYER_STORE_SHELF, null,
"shopping_item_card_list.eml" "shopping_item_card_list.eml"
); );
fullscreenOverlay = new StringFilterGroup(
Settings.HIDE_END_SCREEN_STORE_BANNER,
"fullscreen_overlay.eml"
);
endScreenStoreBannerBuffer = new ByteArrayFilterGroup(
null,
"gstatic.com/shopping"
);
channelProfile = new StringFilterGroup( channelProfile = new StringFilterGroup(
null, Settings.HIDE_VISIT_STORE_BUTTON,
"channel_profile.eml" "channel_profile.eml"
); );
visitStoreButton = new ByteArrayFilterGroup( visitStoreButton = new ByteArrayFilterGroup(
Settings.HIDE_VISIT_STORE_BUTTON, null,
"header_store_button" "header_store_button"
); );
@ -167,7 +161,6 @@ public final class AdsFilter extends Filter {
viewProducts, viewProducts,
selfSponsor, selfSponsor,
fullscreenAd, fullscreenAd,
fullscreenOverlay,
channelProfile, channelProfile,
webLinkPanel, webLinkPanel,
shoppingLinks, shoppingLinks,
@ -186,10 +179,8 @@ public final class AdsFilter extends Filter {
return false; return false;
} }
if (matchedGroup == fullscreenOverlay) { // Check for the index because of likelihood of false positives.
if (contentIndex == 0 && endScreenStoreBannerBuffer.check(protobufBufferArray).isFiltered()) { if (matchedGroup == shoppingLinks && contentIndex != 0) {
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
}
return false; return false;
} }
@ -209,13 +200,25 @@ public final class AdsFilter extends Filter {
return false; return false;
} }
// Check for the index because of likelihood of false positives.
if (matchedGroup == shoppingLinks && contentIndex != 0)
return false;
return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex); return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
} }
/**
* Injection point.
*
* @param elementsList List of components of the end screen container.
* @param protobufList Component (ProtobufList).
*/
public static void hideEndScreenStoreBanner(List<Object> elementsList, Object protobufList) {
if (HIDE_END_SCREEN_STORE_BANNER && protobufList.toString().contains(STORE_BANNER_DOMAIN)) {
Logger.printDebug(() -> "Hiding store banner");
return;
}
elementsList.add(protobufList);
}
/** /**
* Hide the view, which shows ads in the homepage. * Hide the view, which shows ads in the homepage.
* *

View file

@ -64,7 +64,7 @@ public class Settings extends BaseSettings {
// Ads // Ads
public static final BooleanSetting HIDE_BUTTONED_ADS = new BooleanSetting("revanced_hide_buttoned_ads", TRUE); public static final BooleanSetting HIDE_BUTTONED_ADS = new BooleanSetting("revanced_hide_buttoned_ads", TRUE);
public static final BooleanSetting HIDE_END_SCREEN_STORE_BANNER = new BooleanSetting("revanced_hide_end_screen_store_banner", FALSE); public static final BooleanSetting HIDE_END_SCREEN_STORE_BANNER = new BooleanSetting("revanced_hide_end_screen_store_banner", TRUE, true);
public static final BooleanSetting HIDE_FULLSCREEN_ADS = new BooleanSetting("revanced_hide_fullscreen_ads", TRUE); public static final BooleanSetting HIDE_FULLSCREEN_ADS = new BooleanSetting("revanced_hide_fullscreen_ads", TRUE);
public static final BooleanSetting HIDE_GENERAL_ADS = new BooleanSetting("revanced_hide_general_ads", TRUE); public static final BooleanSetting HIDE_GENERAL_ADS = new BooleanSetting("revanced_hide_general_ads", TRUE);
public static final BooleanSetting HIDE_GET_PREMIUM = new BooleanSetting("revanced_hide_get_premium", TRUE); public static final BooleanSetting HIDE_GET_PREMIUM = new BooleanSetting("revanced_hide_get_premium", TRUE);

View file

@ -0,0 +1,25 @@
package app.revanced.patches.youtube.ad.general
import app.revanced.patcher.fingerprint
import app.revanced.util.containsLiteralInstruction
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionReversed
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal val fullScreenEngagementAdContainerFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("V")
parameters()
custom { method, _ ->
method.containsLiteralInstruction(fullScreenEngagementAdContainer)
&& indexOfAddListInstruction(method) >= 0
}
}
internal fun indexOfAddListInstruction(method: Method) =
method.indexOfFirstInstructionReversed {
getReference<MethodReference>()?.name == "add"
}

View file

@ -1,5 +1,7 @@
package app.revanced.patches.youtube.ad.general package app.revanced.patches.youtube.ad.general
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.patch.resourcePatch
import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResources
@ -18,11 +20,16 @@ import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.util.findMutableMethodOf import app.revanced.util.findMutableMethodOf
import app.revanced.util.injectHideViewCall import app.revanced.util.injectHideViewCall
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction31i import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction31i
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
internal var adAttributionId = -1L internal var adAttributionId = -1L
private set private set
internal var fullScreenEngagementAdContainer = -1L
private set
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/components/AdsFilter;"
private val hideAdsResourcePatch = resourcePatch { private val hideAdsResourcePatch = resourcePatch {
dependsOn( dependsOn(
@ -53,6 +60,7 @@ private val hideAdsResourcePatch = resourcePatch {
addLithoFilter("Lapp/revanced/extension/youtube/patches/components/AdsFilter;") addLithoFilter("Lapp/revanced/extension/youtube/patches/components/AdsFilter;")
adAttributionId = resourceMappings["id", "ad_attribution"] adAttributionId = resourceMappings["id", "ad_attribution"]
fullScreenEngagementAdContainer = resourceMappings["id", "fullscreen_engagement_ad_container"]
} }
} }
@ -83,6 +91,23 @@ val hideAdsPatch = bytecodePatch(
) )
execute { execute {
// Hide end screen store banner
fullScreenEngagementAdContainerFingerprint.method.apply {
val addListIndex = indexOfAddListInstruction(this)
val addListInstruction = getInstruction<FiveRegisterInstruction>(addListIndex)
val listRegister = addListInstruction.registerC
val objectRegister = addListInstruction.registerD
replaceInstruction(
addListIndex,
"invoke-static { v$listRegister, v$objectRegister }, $EXTENSION_CLASS_DESCRIPTOR" +
"->hideEndScreenStoreBanner(Ljava/util/List;Ljava/lang/Object;)V"
)
}
// Hide ad views
classes.forEach { classDef -> classes.forEach { classDef ->
classDef.methods.forEach { method -> classDef.methods.forEach { method ->
with(method.implementation) { with(method.implementation) {
@ -111,7 +136,7 @@ val hideAdsPatch = bytecodePatch(
.injectHideViewCall( .injectHideViewCall(
insertIndex, insertIndex,
viewRegister, viewRegister,
"Lapp/revanced/extension/youtube/patches/components/AdsFilter;", EXTENSION_CLASS_DESCRIPTOR,
"hideAdAttributionView", "hideAdAttributionView",
) )
} }