mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-05-29 05:10:20 +02:00
feat(YouTube): Add Snack bar components
patch
This commit is contained in:
parent
e85a343c02
commit
78f1d962cd
@ -61,7 +61,7 @@ public abstract class Filter {
|
||||
*/
|
||||
public boolean skip(String conversionContext, SpannableString spannableString, Object span, int start, int end,
|
||||
int flags, boolean isWord, SpanType spanType, StringFilterGroup matchedGroup) {
|
||||
if (BaseSettings.ENABLE_DEBUG_LOGGING.get()) {
|
||||
if (BaseSettings.ENABLE_DEBUG_BUFFER_LOGGING.get()) {
|
||||
String filterSimpleName = getClass().getSimpleName();
|
||||
Logger.printDebug(() -> filterSimpleName + " Removed setSpan: " + spanType.type);
|
||||
}
|
||||
|
@ -188,10 +188,6 @@ public class GeneralPatch {
|
||||
return Settings.HIDE_FLOATING_MICROPHONE.get() || original;
|
||||
}
|
||||
|
||||
public static boolean hideSnackBar() {
|
||||
return Settings.HIDE_SNACK_BAR.get();
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region [Hide navigation bar components] patch
|
||||
|
@ -0,0 +1,115 @@
|
||||
package app.revanced.extension.youtube.patches.general;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import app.revanced.extension.shared.utils.ResourceUtils;
|
||||
import app.revanced.extension.shared.utils.Utils;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.utils.ThemeUtils;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class SnackBarPatch {
|
||||
private static final boolean HIDE_SNACK_BAR =
|
||||
Settings.HIDE_SNACK_BAR.get();
|
||||
private static final boolean HIDE_SERVER_SIDE_SNACK_BAR =
|
||||
Settings.HIDE_SERVER_SIDE_SNACK_BAR.get();
|
||||
private static final boolean CHANGE_SERVER_SIDE_SNACK_BAR_BACKGROUND =
|
||||
!HIDE_SNACK_BAR && !HIDE_SERVER_SIDE_SNACK_BAR && Settings.CHANGE_SERVER_SIDE_SNACK_BAR_BACKGROUND.get();
|
||||
private static final boolean INVERT_SNACK_BAR_THEME =
|
||||
!HIDE_SNACK_BAR && Settings.INVERT_SNACK_BAR_THEME.get();
|
||||
private static final boolean INVERT_SERVER_SIDE_SNACK_BAR_THEME =
|
||||
!HIDE_SERVER_SIDE_SNACK_BAR && INVERT_SNACK_BAR_THEME;
|
||||
private static final int SNACK_BAR_BLACK_COLOR = 0xFF0F0F0F;
|
||||
private static final int SNACK_BAR_WHITE_COLOR = 0xFFF1F1F1;
|
||||
private static final AtomicBoolean lithoSnackBarLoaded = new AtomicBoolean(false);
|
||||
private static int blackColor = 0;
|
||||
private static int whiteColor = 0;
|
||||
|
||||
public static boolean hideSnackBar() {
|
||||
return HIDE_SNACK_BAR;
|
||||
}
|
||||
|
||||
public static void hideLithoSnackBar(FrameLayout frameLayout) {
|
||||
if (HIDE_SERVER_SIDE_SNACK_BAR) {
|
||||
Utils.hideViewByLayoutParams(frameLayout);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setLithoSnackBarBackground(View view) {
|
||||
if (CHANGE_SERVER_SIDE_SNACK_BAR_BACKGROUND) {
|
||||
int snackBarRoundedCornersBackgroundIdentifier =
|
||||
ResourceUtils.getDrawableIdentifier("snackbar_rounded_corners_background");
|
||||
Context mContext = invertSnackBarTheme(view.getContext());
|
||||
Drawable snackBarRoundedCornersBackground = mContext.getDrawable(snackBarRoundedCornersBackgroundIdentifier);
|
||||
if (snackBarRoundedCornersBackground != null) {
|
||||
view.setBackground(snackBarRoundedCornersBackground);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setLithoSnackBarBackgroundColor(FrameLayout frameLayout, int color) {
|
||||
if (CHANGE_SERVER_SIDE_SNACK_BAR_BACKGROUND) {
|
||||
return;
|
||||
}
|
||||
frameLayout.setBackgroundColor(color);
|
||||
}
|
||||
|
||||
public static Context invertSnackBarTheme(Context mContext) {
|
||||
if (INVERT_SERVER_SIDE_SNACK_BAR_THEME) {
|
||||
String styleId = ThemeUtils.isDarkTheme()
|
||||
? "Base.Theme.YouTube.Light"
|
||||
: "Base.Theme.YouTube.Dark";
|
||||
int styleIdentifier = ResourceUtils.getStyleIdentifier(styleId);
|
||||
mContext = new ContextThemeWrapper(mContext, styleIdentifier);
|
||||
}
|
||||
|
||||
return mContext;
|
||||
}
|
||||
|
||||
public static Enum<?> invertSnackBarTheme(Enum<?> appTheme, Enum<?> darkTheme) {
|
||||
if (INVERT_SNACK_BAR_THEME) {
|
||||
return appTheme == darkTheme
|
||||
? null
|
||||
: darkTheme;
|
||||
}
|
||||
|
||||
return appTheme;
|
||||
}
|
||||
|
||||
public static void lithoSnackBarLoaded() {
|
||||
lithoSnackBarLoaded.compareAndSet(false, true);
|
||||
}
|
||||
|
||||
public static int getLithoColor(int originalValue) {
|
||||
if (CHANGE_SERVER_SIDE_SNACK_BAR_BACKGROUND &&
|
||||
lithoSnackBarLoaded.compareAndSet(true, false)) {
|
||||
if (originalValue == SNACK_BAR_BLACK_COLOR) {
|
||||
return INVERT_SERVER_SIDE_SNACK_BAR_THEME
|
||||
? getWhiteColor()
|
||||
: getBlackColor();
|
||||
} else if (originalValue == SNACK_BAR_WHITE_COLOR) {
|
||||
return INVERT_SERVER_SIDE_SNACK_BAR_THEME
|
||||
? getBlackColor()
|
||||
: getWhiteColor();
|
||||
}
|
||||
}
|
||||
|
||||
return originalValue;
|
||||
}
|
||||
|
||||
private static int getBlackColor() {
|
||||
if (blackColor == 0) blackColor = ResourceUtils.getColor("revanced_snack_bar_color_dark");
|
||||
return blackColor;
|
||||
}
|
||||
|
||||
private static int getWhiteColor() {
|
||||
if (whiteColor == 0) whiteColor = ResourceUtils.getColor("revanced_snack_bar_color_light");
|
||||
return whiteColor;
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package app.revanced.extension.youtube.patches.spans;
|
||||
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
|
||||
import app.revanced.extension.shared.patches.spans.Filter;
|
||||
import app.revanced.extension.shared.patches.spans.SpanType;
|
||||
import app.revanced.extension.shared.patches.spans.StringFilterGroup;
|
||||
import app.revanced.extension.shared.utils.ResourceUtils;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.utils.ThemeUtils;
|
||||
|
||||
@SuppressWarnings({"unused", "FieldCanBeLocal"})
|
||||
public final class SnackBarFilter extends Filter {
|
||||
private static final boolean HIDE_SNACK_BAR =
|
||||
Settings.HIDE_SNACK_BAR.get() || Settings.HIDE_SERVER_SIDE_SNACK_BAR.get();
|
||||
private static final boolean CHANGE_SERVER_SIDE_SNACK_BAR_BACKGROUND =
|
||||
!HIDE_SNACK_BAR && Settings.CHANGE_SERVER_SIDE_SNACK_BAR_BACKGROUND.get();
|
||||
private static final boolean INVERT_SNACK_BAR_THEME =
|
||||
!HIDE_SNACK_BAR && Settings.INVERT_SNACK_BAR_THEME.get();
|
||||
|
||||
private final ForegroundColorSpan foregroundColorSpanBlack =
|
||||
new ForegroundColorSpan(ResourceUtils.getColor("yt_black1"));
|
||||
private final ForegroundColorSpan foregroundColorSpanWhite =
|
||||
new ForegroundColorSpan(ResourceUtils.getColor("yt_white1"));
|
||||
|
||||
public SnackBarFilter() {
|
||||
addCallbacks(
|
||||
new StringFilterGroup(
|
||||
Settings.CHANGE_SERVER_SIDE_SNACK_BAR_BACKGROUND,
|
||||
"snackbar.eml|"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private ForegroundColorSpan getForegroundColorSpan() {
|
||||
if (INVERT_SNACK_BAR_THEME) {
|
||||
return ThemeUtils.isDarkTheme()
|
||||
? foregroundColorSpanWhite
|
||||
: foregroundColorSpanBlack;
|
||||
}
|
||||
return ThemeUtils.isDarkTheme()
|
||||
? foregroundColorSpanBlack
|
||||
: foregroundColorSpanWhite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean skip(String conversionContext, SpannableString spannableString, Object span,
|
||||
int start, int end, int flags, boolean isWord, SpanType spanType, StringFilterGroup matchedGroup) {
|
||||
if (CHANGE_SERVER_SIDE_SNACK_BAR_BACKGROUND && spanType == SpanType.FOREGROUND_COLOR) {
|
||||
spannableString.setSpan(
|
||||
getForegroundColorSpan(),
|
||||
start,
|
||||
end,
|
||||
flags
|
||||
);
|
||||
return super.skip(conversionContext, spannableString, span, start, end, flags, isWord, spanType, matchedGroup);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -93,7 +93,6 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting HIDE_FEED_SURVEY = new BooleanSetting("revanced_hide_feed_survey", TRUE);
|
||||
public static final BooleanSetting HIDE_TICKET_SHELF = new BooleanSetting("revanced_hide_ticket_shelf", TRUE);
|
||||
|
||||
|
||||
// PreferenceScreen: Feed - Category bar
|
||||
public static final BooleanSetting HIDE_CATEGORY_BAR_IN_FEED = new BooleanSetting("revanced_hide_category_bar_in_feed", FALSE, true);
|
||||
public static final BooleanSetting HIDE_CATEGORY_BAR_IN_SEARCH = new BooleanSetting("revanced_hide_category_bar_in_search", FALSE, true);
|
||||
@ -152,7 +151,6 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting ENABLE_GRADIENT_LOADING_SCREEN = new BooleanSetting("revanced_enable_gradient_loading_screen", FALSE, true);
|
||||
public static final BooleanSetting HIDE_FLOATING_MICROPHONE = new BooleanSetting("revanced_hide_floating_microphone", TRUE, true);
|
||||
public static final BooleanSetting HIDE_GRAY_SEPARATOR = new BooleanSetting("revanced_hide_gray_separator", TRUE);
|
||||
public static final BooleanSetting HIDE_SNACK_BAR = new BooleanSetting("revanced_hide_snack_bar", FALSE);
|
||||
public static final BooleanSetting REMOVE_VIEWER_DISCRETION_DIALOG = new BooleanSetting("revanced_remove_viewer_discretion_dialog", FALSE);
|
||||
|
||||
public static final EnumSetting<FormFactor> CHANGE_LAYOUT = new EnumSetting<>("revanced_change_layout", FormFactor.ORIGINAL, true);
|
||||
@ -232,6 +230,12 @@ public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting HIDE_SETTINGS_MENU_POST_PURCHASE = new BooleanSetting("revanced_hide_settings_menu_post_purchase", FALSE, true);
|
||||
public static final BooleanSetting HIDE_SETTINGS_MENU_THIRD_PARTY = new BooleanSetting("revanced_hide_settings_menu_third_party", FALSE, true);
|
||||
|
||||
// PreferenceScreen: General - Snack bar
|
||||
public static final BooleanSetting HIDE_SNACK_BAR = new BooleanSetting("revanced_hide_snack_bar", FALSE, true);
|
||||
public static final BooleanSetting HIDE_SERVER_SIDE_SNACK_BAR = new BooleanSetting("revanced_hide_server_side_snack_bar", FALSE, true);
|
||||
public static final BooleanSetting CHANGE_SERVER_SIDE_SNACK_BAR_BACKGROUND = new BooleanSetting("revanced_change_server_side_snack_bar_background", FALSE, true, "revanced_change_server_side_snack_bar_background_user_dialog_message");
|
||||
public static final BooleanSetting INVERT_SNACK_BAR_THEME = new BooleanSetting("revanced_invert_snack_bar_theme", FALSE, true);
|
||||
|
||||
// PreferenceScreen: General - Toolbar
|
||||
public static final BooleanSetting CHANGE_YOUTUBE_HEADER = new BooleanSetting("revanced_change_youtube_header", TRUE, true);
|
||||
public static final BooleanSetting ENABLE_WIDE_SEARCH_BAR = new BooleanSetting("revanced_enable_wide_search_bar", FALSE, true);
|
||||
|
@ -30,10 +30,12 @@ val drawableColorHookPatch = bytecodePatch(
|
||||
}
|
||||
|
||||
internal fun addDrawableColorHook(
|
||||
methodDescriptor: String
|
||||
methodDescriptor: String,
|
||||
highPriority: Boolean = false
|
||||
) {
|
||||
insertMethod.addInstructions(
|
||||
insertIndex + offset, """
|
||||
if (highPriority) insertIndex else insertIndex + offset,
|
||||
"""
|
||||
invoke-static {v$insertRegister}, $methodDescriptor
|
||||
move-result v$insertRegister
|
||||
"""
|
||||
|
@ -69,16 +69,6 @@ internal val appBlockingCheckResultToStringFingerprint = legacyFingerprint(
|
||||
strings = listOf("AppBlockingCheckResult{intent=")
|
||||
)
|
||||
|
||||
internal val bottomUiContainerFingerprint = legacyFingerprint(
|
||||
name = "bottomUiContainerFingerprint",
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("L", "L"),
|
||||
customFingerprint = { method, _ ->
|
||||
method.definingClass.endsWith("/BottomUiContainer;")
|
||||
}
|
||||
)
|
||||
|
||||
internal val floatingMicrophoneFingerprint = legacyFingerprint(
|
||||
name = "floatingMicrophoneFingerprint",
|
||||
returnType = "V",
|
||||
|
@ -2,12 +2,10 @@ package app.revanced.patches.youtube.general.components
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.shared.litho.addLithoFilter
|
||||
import app.revanced.patches.shared.litho.lithoFilterPatch
|
||||
import app.revanced.patches.shared.settingmenu.settingsMenuPatch
|
||||
@ -215,21 +213,6 @@ val layoutComponentsPatch = bytecodePatch(
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for hide snack bar
|
||||
|
||||
bottomUiContainerFingerprint.methodOrThrow().apply {
|
||||
addInstructionsWithLabels(
|
||||
0, """
|
||||
invoke-static {}, $GENERAL_CLASS_DESCRIPTOR->hideSnackBar()Z
|
||||
move-result v0
|
||||
if-eqz v0, :show
|
||||
return-void
|
||||
""", ExternalLabel("show", getInstruction(0))
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region patch for hide tooltip content
|
||||
|
||||
tooltipContentFullscreenFingerprint.methodOrThrow().apply {
|
||||
|
@ -0,0 +1,68 @@
|
||||
package app.revanced.patches.youtube.general.snackbar
|
||||
|
||||
import app.revanced.patches.youtube.utils.resourceid.insetElementsWrapper
|
||||
import app.revanced.util.fingerprint.legacyFingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionReversed
|
||||
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
|
||||
|
||||
private const val BOTTOM_UI_CONTAINER_CLASS_DESCRIPTOR =
|
||||
"Lcom/google/android/apps/youtube/app/common/ui/bottomui/BottomUiContainer;"
|
||||
|
||||
internal val bottomUiContainerFingerprint = legacyFingerprint(
|
||||
name = "bottomUiContainerFingerprint",
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("L", "L"),
|
||||
customFingerprint = { _, classDef ->
|
||||
classDef.type == BOTTOM_UI_CONTAINER_CLASS_DESCRIPTOR
|
||||
}
|
||||
)
|
||||
|
||||
internal val bottomUiContainerPreFingerprint = legacyFingerprint(
|
||||
name = "bottomUiContainerPreFingerprint",
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("L", "L", "L"),
|
||||
opcodes = listOf(
|
||||
Opcode.IF_NEZ,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.RETURN_VOID
|
||||
),
|
||||
customFingerprint = { _, classDef ->
|
||||
classDef.type == BOTTOM_UI_CONTAINER_CLASS_DESCRIPTOR
|
||||
}
|
||||
)
|
||||
|
||||
internal val bottomUiContainerThemeFingerprint = legacyFingerprint(
|
||||
name = "bottomUiContainerThemeFingerprint",
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf(BOTTOM_UI_CONTAINER_CLASS_DESCRIPTOR),
|
||||
opcodes = listOf(
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.IF_NE,
|
||||
Opcode.CONST,
|
||||
),
|
||||
)
|
||||
|
||||
internal val lithoSnackBarFingerprint = legacyFingerprint(
|
||||
name = "lithoSnackBarFingerprint",
|
||||
returnType = "Landroid/view/View;",
|
||||
literals = listOf(insetElementsWrapper),
|
||||
customFingerprint = { method, _ ->
|
||||
indexOfBackGroundColor(method) >= 0
|
||||
}
|
||||
)
|
||||
|
||||
internal fun indexOfBackGroundColor(method: Method) =
|
||||
method.indexOfFirstInstructionReversed {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>()?.name == "setBackgroundColor"
|
||||
}
|
@ -0,0 +1,340 @@
|
||||
package app.revanced.patches.youtube.general.snackbar
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
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.resourcePatch
|
||||
import app.revanced.patcher.patch.stringOption
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.shared.drawable.addDrawableColorHook
|
||||
import app.revanced.patches.shared.drawable.drawableColorHookPatch
|
||||
import app.revanced.patches.shared.spans.addSpanFilter
|
||||
import app.revanced.patches.shared.spans.inclusiveSpanPatch
|
||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.extension.Constants.GENERAL_PATH
|
||||
import app.revanced.patches.youtube.utils.extension.Constants.SPANS_PATH
|
||||
import app.revanced.patches.youtube.utils.patch.PatchList.SNACK_BAR_COMPONENTS
|
||||
import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.settings.ResourceUtils.addPreference
|
||||
import app.revanced.patches.youtube.utils.settings.settingsPatch
|
||||
import app.revanced.util.findElementByAttributeValueOrThrow
|
||||
import app.revanced.util.findMethodOrThrow
|
||||
import app.revanced.util.fingerprint.matchOrThrow
|
||||
import app.revanced.util.fingerprint.methodOrThrow
|
||||
import app.revanced.util.getNode
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.valueOrThrow
|
||||
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 org.w3c.dom.Element
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"$GENERAL_PATH/SnackBarPatch;"
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"$SPANS_PATH/SnackBarFilter;"
|
||||
|
||||
private val snackBarComponentsBytecodePatch = bytecodePatch(
|
||||
description = "snackBarComponentsBytecodePatch"
|
||||
) {
|
||||
dependsOn(
|
||||
settingsPatch,
|
||||
sharedResourceIdPatch,
|
||||
drawableColorHookPatch,
|
||||
inclusiveSpanPatch,
|
||||
)
|
||||
|
||||
execute {
|
||||
bottomUiContainerFingerprint.methodOrThrow().apply {
|
||||
addInstructionsWithLabels(
|
||||
0, """
|
||||
invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->hideSnackBar()Z
|
||||
move-result v0
|
||||
if-eqz v0, :show
|
||||
return-void
|
||||
""", ExternalLabel("show", getInstruction(0))
|
||||
)
|
||||
}
|
||||
|
||||
bottomUiContainerPreFingerprint.matchOrThrow().let {
|
||||
it.method.apply {
|
||||
val insertIndex = it.patternMatch!!.startIndex + 1
|
||||
|
||||
addInstruction(
|
||||
insertIndex,
|
||||
"invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->lithoSnackBarLoaded()V"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
bottomUiContainerThemeFingerprint.matchOrThrow().let {
|
||||
it.method.apply {
|
||||
val startIndex = it.patternMatch!!.startIndex
|
||||
val appThemeIndex = startIndex + 1
|
||||
val darkThemeIndex = startIndex + 2
|
||||
val insertIndex = startIndex + 3
|
||||
|
||||
val appThemeRegister =
|
||||
getInstruction<OneRegisterInstruction>(appThemeIndex).registerA
|
||||
val darkThemeRegister =
|
||||
getInstruction<OneRegisterInstruction>(darkThemeIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex, """
|
||||
invoke-static {v$appThemeRegister, v$darkThemeRegister}, $EXTENSION_CLASS_DESCRIPTOR->invertSnackBarTheme(Ljava/lang/Enum;Ljava/lang/Enum;)Ljava/lang/Enum;
|
||||
move-result-object v$appThemeRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun MutableMethod.setBackground(index: Int, register: Int) =
|
||||
addInstruction(
|
||||
index,
|
||||
"invoke-static {v$register}, $EXTENSION_CLASS_DESCRIPTOR->setLithoSnackBarBackground(Landroid/view/View;)V"
|
||||
)
|
||||
|
||||
lithoSnackBarFingerprint.methodOrThrow().apply {
|
||||
val backGroundColorIndex = indexOfBackGroundColor(this)
|
||||
val viewRegister =
|
||||
getInstruction<FiveRegisterInstruction>(backGroundColorIndex).registerC
|
||||
val colorRegister =
|
||||
getInstruction<FiveRegisterInstruction>(backGroundColorIndex).registerD
|
||||
|
||||
replaceInstruction(
|
||||
backGroundColorIndex,
|
||||
"invoke-static {v$viewRegister, v$colorRegister}, $EXTENSION_CLASS_DESCRIPTOR->" +
|
||||
"setLithoSnackBarBackgroundColor(Landroid/widget/FrameLayout;I)V"
|
||||
)
|
||||
setBackground(backGroundColorIndex + 2, viewRegister)
|
||||
|
||||
implementation!!.instructions
|
||||
.withIndex()
|
||||
.filter { (_, instruction) ->
|
||||
instruction.opcode == Opcode.CHECK_CAST &&
|
||||
(instruction as? ReferenceInstruction)?.reference?.toString() == "Landroid/widget/FrameLayout;"
|
||||
}
|
||||
.map { (index, _) -> index }
|
||||
.reversed()
|
||||
.forEach { index ->
|
||||
val register =
|
||||
getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
setBackground(index + 1, register)
|
||||
}
|
||||
|
||||
findMethodOrThrow(definingClass).apply {
|
||||
val contextIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.IPUT_OBJECT &&
|
||||
getReference<FieldReference>()?.type == "Landroid/content/Context;"
|
||||
}
|
||||
val contextRegister =
|
||||
getInstruction<TwoRegisterInstruction>(contextIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
contextIndex, """
|
||||
invoke-static {v$contextRegister}, $EXTENSION_CLASS_DESCRIPTOR->invertSnackBarTheme(Landroid/content/Context;)Landroid/content/Context;
|
||||
move-result-object v$contextRegister
|
||||
"""
|
||||
)
|
||||
|
||||
val viewIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.IPUT_OBJECT &&
|
||||
getReference<FieldReference>()?.type == "Landroid/widget/FrameLayout;"
|
||||
}
|
||||
val viewRegister =
|
||||
getInstruction<TwoRegisterInstruction>(viewIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
viewIndex,
|
||||
"invoke-static {v$viewRegister}, $EXTENSION_CLASS_DESCRIPTOR->hideLithoSnackBar(Landroid/widget/FrameLayout;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
addDrawableColorHook("$EXTENSION_CLASS_DESCRIPTOR->getLithoColor(I)I", true)
|
||||
addSpanFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
val snackBarComponentsPatch = resourcePatch(
|
||||
SNACK_BAR_COMPONENTS.title,
|
||||
SNACK_BAR_COMPONENTS.summary,
|
||||
) {
|
||||
compatibleWith(COMPATIBLE_PACKAGE)
|
||||
|
||||
dependsOn(
|
||||
settingsPatch,
|
||||
snackBarComponentsBytecodePatch,
|
||||
)
|
||||
|
||||
val catppuccinMochaColor = "#FF181825"
|
||||
val catppuccinLatteColor = "#FFE6E9EF"
|
||||
|
||||
val availableDarkTheme = mapOf(
|
||||
"Amoled Black" to "@android:color/black",
|
||||
"Catppuccin (Mocha)" to "#FF181825",
|
||||
"Dark Pink" to "#FF290025",
|
||||
"Dark Blue" to "#FF001029",
|
||||
"Dark Green" to "#FF002905",
|
||||
"Dark Yellow" to "#FF282900",
|
||||
"Dark Orange" to "#FF291800",
|
||||
"Dark Red" to "#FF290000",
|
||||
)
|
||||
|
||||
val availableLightTheme = mapOf(
|
||||
"White" to "@android:color/white",
|
||||
"Catppuccin (Latte)" to "#FFE6E9EF",
|
||||
"Light Pink" to "#FFFCCFF3",
|
||||
"Light Blue" to "#FFD1E0FF",
|
||||
"Light Green" to "#FFCCFFCC",
|
||||
"Light Yellow" to "#FFFDFFCC",
|
||||
"Light Orange" to "#FFFFE6CC",
|
||||
"Light Red" to "#FFFFD6D6",
|
||||
)
|
||||
|
||||
val cornerRadiusOption = stringOption(
|
||||
key = "cornerRadius",
|
||||
default = "8.0dip",
|
||||
title = "Corner radius",
|
||||
description = "Specify a corner radius for the snack bar.",
|
||||
required = true,
|
||||
)
|
||||
|
||||
val darkThemeBackgroundColor = stringOption(
|
||||
key = "darkThemeBackgroundColor",
|
||||
default = catppuccinMochaColor,
|
||||
values = availableDarkTheme,
|
||||
title = "Dark theme background color",
|
||||
description = "Specify a background color for the snack bar. You can specify hex color (#AARRGGBB) or color resource reference.",
|
||||
required = true,
|
||||
)
|
||||
|
||||
val lightThemeBackgroundColor = stringOption(
|
||||
key = "lightThemeBackgroundColor",
|
||||
default = catppuccinLatteColor,
|
||||
values = availableLightTheme,
|
||||
title = "Light theme background color",
|
||||
description = "Specify a background color for the snack bar. You can specify hex color (#AARRGGBB) or color resource reference.",
|
||||
required = true,
|
||||
)
|
||||
|
||||
val strokeColorOption = stringOption(
|
||||
key = "strokeColor",
|
||||
default = "",
|
||||
values = mapOf(
|
||||
"None" to "",
|
||||
"Blue" to "?attr/ytThemedBlue",
|
||||
"Chip" to "?attr/ytChipBackground"
|
||||
),
|
||||
title = "Stroke color",
|
||||
description = "Specify a stroke color for the snack bar. You can specify hex color.",
|
||||
required = true,
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
// Check patch options first.
|
||||
val cornerRadius = cornerRadiusOption
|
||||
.valueOrThrow()
|
||||
val darkThemeColor = darkThemeBackgroundColor
|
||||
.valueOrThrow()
|
||||
val lightThemeColor = lightThemeBackgroundColor
|
||||
.valueOrThrow()
|
||||
val strokeColor = strokeColorOption
|
||||
.valueOrThrow()
|
||||
|
||||
val snackBarColorAttr = "snackBarColor"
|
||||
val snackBarColorAttrReference = "?attr/$snackBarColorAttr"
|
||||
val snackBarColorDark = "revanced_snack_bar_color_dark"
|
||||
val snackBarColorDarkReference = "@color/$snackBarColorDark"
|
||||
val snackBarColorLight = "revanced_snack_bar_color_light"
|
||||
val snackBarColorLightReference = "@color/$snackBarColorLight"
|
||||
|
||||
document("res/values/colors.xml").use { document ->
|
||||
mapOf(
|
||||
snackBarColorDark to darkThemeColor,
|
||||
snackBarColorLight to lightThemeColor,
|
||||
).forEach { (k, v) ->
|
||||
val colorElement = document.createElement("color")
|
||||
|
||||
colorElement.setAttribute("name", k)
|
||||
colorElement.textContent = v
|
||||
|
||||
document.getElementsByTagName("resources").item(0)
|
||||
.appendChild(colorElement)
|
||||
}
|
||||
}
|
||||
|
||||
document("res/values/attrs.xml").use { document ->
|
||||
(document.getElementsByTagName("resources").item(0) as Element).appendChild(
|
||||
document.createElement("attr").apply {
|
||||
setAttribute("format", "reference|color")
|
||||
setAttribute("name", snackBarColorAttr)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
document("res/values/styles.xml").use { document ->
|
||||
mapOf(
|
||||
"Base.Theme.YouTube.Dark" to snackBarColorLightReference,
|
||||
"Base.Theme.YouTube.Light" to snackBarColorDarkReference,
|
||||
).forEach { (styleName, colorName) ->
|
||||
val snackBarColorNode = document.createElement("item")
|
||||
snackBarColorNode.setAttribute("name", snackBarColorAttr)
|
||||
snackBarColorNode.appendChild(document.createTextNode(colorName))
|
||||
|
||||
document.childNodes.findElementByAttributeValueOrThrow(
|
||||
"name",
|
||||
styleName,
|
||||
).appendChild(snackBarColorNode)
|
||||
}
|
||||
}
|
||||
|
||||
document("res/drawable/snackbar_rounded_corners_background.xml").use { document ->
|
||||
document.getNode("corners").apply {
|
||||
arrayOf(
|
||||
"android:bottomLeftRadius",
|
||||
"android:bottomRightRadius",
|
||||
"android:topLeftRadius",
|
||||
"android:topRightRadius",
|
||||
).forEach {
|
||||
attributes.getNamedItem(it).nodeValue = cornerRadius
|
||||
}
|
||||
}
|
||||
document.getNode("solid").apply {
|
||||
attributes.getNamedItem("android:color").nodeValue = snackBarColorAttrReference
|
||||
}
|
||||
if (!strokeColor.isEmpty()) {
|
||||
(document.getElementsByTagName("shape").item(0) as Element).appendChild(
|
||||
document.createElement("stroke").apply {
|
||||
setAttribute("android:width", "1.0dip")
|
||||
setAttribute("android:color", strokeColor)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// region add settings
|
||||
|
||||
addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE_SCREEN: GENERAL",
|
||||
"SETTINGS: SNACK_BAR_COMPONENTS"
|
||||
),
|
||||
SNACK_BAR_COMPONENTS
|
||||
)
|
||||
|
||||
// endregion
|
||||
|
||||
}
|
||||
}
|
@ -217,6 +217,10 @@ internal enum class PatchList(
|
||||
"Shorts components",
|
||||
"Adds options to hide or change components related to YouTube Shorts."
|
||||
),
|
||||
SNACK_BAR_COMPONENTS(
|
||||
"Snack bar components",
|
||||
"Adds options to hide or change components related to the snack bar."
|
||||
),
|
||||
SPONSORBLOCK(
|
||||
"SponsorBlock",
|
||||
"Adds options to enable and configure SponsorBlock, which can skip undesired video segments, such as sponsored content."
|
||||
|
@ -121,6 +121,8 @@ var insetOverlayViewLayout = -1L
|
||||
private set
|
||||
var interstitialsContainer = -1L
|
||||
private set
|
||||
var insetElementsWrapper = -1L
|
||||
private set
|
||||
var menuItemView = -1L
|
||||
private set
|
||||
var metaPanel = -1L
|
||||
@ -461,6 +463,10 @@ internal val sharedResourceIdPatch = resourcePatch(
|
||||
ID,
|
||||
"interstitials_container"
|
||||
]
|
||||
insetElementsWrapper = resourceMappings[
|
||||
LAYOUT,
|
||||
"inset_elements_wrapper"
|
||||
]
|
||||
menuItemView = resourceMappings[
|
||||
ID,
|
||||
"menu_item_view"
|
||||
|
@ -425,9 +425,6 @@ Limitation: Back button on the toolbar may not work."</string>
|
||||
<string name="revanced_hide_gray_separator_title">Hide gray separators</string>
|
||||
<string name="revanced_hide_gray_separator_summary_on">Gray separators are hidden.</string>
|
||||
<string name="revanced_hide_gray_separator_summary_off">Gray separators are shown.</string>
|
||||
<string name="revanced_hide_snack_bar_title">Hide snack bar</string>
|
||||
<string name="revanced_hide_snack_bar_summary_on">Snack bar is hidden.</string>
|
||||
<string name="revanced_hide_snack_bar_summary_off">Snack bar is shown.</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_title">Remove viewer discretion dialog</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_summary">"Removes the viewer discretion dialog.
|
||||
This does not bypass the age restriction. It just accepts it automatically."</string>
|
||||
@ -677,6 +674,28 @@ If this setting do not take effect, try switching to Incognito mode."</string>
|
||||
<string name="revanced_hide_settings_menu_about_summary_on">About menu is hidden.</string>
|
||||
<string name="revanced_hide_settings_menu_about_summary_off">About menu is shown.</string>
|
||||
|
||||
<!-- PreferenceScreen: General, PreferenceCategory: General, PreferenceScreen: Snack bar -->
|
||||
<string name="revanced_preference_screen_snack_bar_title">Snack bar</string>
|
||||
<string name="revanced_preference_screen_snack_bar_summary">Hide or change components related to snack bar.</string>
|
||||
|
||||
<string name="revanced_hide_snack_bar_title">Hide snack bar</string>
|
||||
<string name="revanced_hide_snack_bar_summary_on">Snack bar is hidden.</string>
|
||||
<string name="revanced_hide_snack_bar_summary_off">Snack bar is shown.</string>
|
||||
<string name="revanced_hide_server_side_snack_bar_title">Hide server-side snack bar</string>
|
||||
<string name="revanced_hide_server_side_snack_bar_summary_on">Server-side snack bar is hidden.</string>
|
||||
<string name="revanced_hide_server_side_snack_bar_summary_off">Server-side snack bar is shown.</string>
|
||||
<string name="revanced_invert_snack_bar_theme_title">Invert snack bar theme</string>
|
||||
<string name="revanced_invert_snack_bar_theme_summary_on">Theme of the snack bar is inverted.</string>
|
||||
<string name="revanced_invert_snack_bar_theme_summary_off">Theme of the snack bar is not inverted.</string>
|
||||
<string name="revanced_change_server_side_snack_bar_background_title">Change server-side snack bar background</string>
|
||||
<string name="revanced_change_server_side_snack_bar_background_summary_on">Background color of the server-side snackbar has changed.</string>
|
||||
<string name="revanced_change_server_side_snack_bar_background_summary_off">Background color of the server-side snackbar has not changed.</string>
|
||||
<string name="revanced_change_server_side_snack_bar_background_user_dialog_message">"Some snack bars use a theme defined on the server side, not the app theme.
|
||||
|
||||
Change the background color of these snack bars.
|
||||
|
||||
If there are server-side changes, the background color of the snack bar may not change."</string>
|
||||
|
||||
<!-- PreferenceScreen: General, PreferenceCategory: General, PreferenceScreen: Toolbar -->
|
||||
<string name="revanced_preference_screen_toolbar_title">Toolbar</string>
|
||||
<string name="revanced_preference_screen_toolbar_summary">Hide or change components located on the toolbar, such as the search bar, toolbar buttons, and header.</string>
|
||||
|
@ -244,6 +244,15 @@
|
||||
<SwitchPreference android:title="@string/revanced_hide_settings_menu_about_title" android:key="revanced_hide_settings_menu_about" android:summaryOn="@string/revanced_hide_settings_menu_about_summary_on" android:summaryOff="@string/revanced_hide_settings_menu_about_summary_off" />
|
||||
</PreferenceScreen>SETTINGS: HIDE_LAYOUT_COMPONENTS -->
|
||||
|
||||
<!-- SETTINGS: SNACK_BAR_COMPONENTS
|
||||
<PreferenceScreen android:title="@string/revanced_preference_screen_snack_bar_title" android:key="revanced_preference_screen_snack_bar" android:summary="@string/revanced_preference_screen_snack_bar_summary">
|
||||
<SwitchPreference android:title="@string/revanced_hide_snack_bar_title" android:key="revanced_hide_snack_bar" android:summaryOn="@string/revanced_hide_snack_bar_summary_on" android:summaryOff="@string/revanced_hide_snack_bar_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_hide_server_side_snack_bar_title" android:key="revanced_hide_server_side_snack_bar" android:summaryOn="@string/revanced_hide_server_side_snack_bar_summary_on" android:summaryOff="@string/revanced_hide_server_side_snack_bar_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_invert_snack_bar_theme_title" android:key="revanced_invert_snack_bar_theme" android:summaryOn="@string/revanced_invert_snack_bar_theme_summary_on" android:summaryOff="@string/revanced_invert_snack_bar_theme_summary_off" />
|
||||
<PreferenceCategory android:title="@string/revanced_preference_category_experimental_flag" android:layout="@layout/revanced_settings_preferences_category"/>
|
||||
<SwitchPreference android:title="@string/revanced_change_server_side_snack_bar_background_title" android:key="revanced_change_server_side_snack_bar_background" android:summaryOn="@string/revanced_change_server_side_snack_bar_background_summary_on" android:summaryOff="@string/revanced_change_server_side_snack_bar_background_summary_off" />
|
||||
</PreferenceScreen>SETTINGS: SNACK_BAR_COMPONENTS -->
|
||||
|
||||
<!-- SETTINGS: TOOLBAR_COMPONENTS
|
||||
<PreferenceScreen android:title="@string/revanced_preference_screen_toolbar_title" android:key="revanced_preference_screen_toolbar" android:summary="@string/revanced_preference_screen_toolbar_summary">
|
||||
<SwitchPreference android:title="@string/revanced_change_youtube_header_title" android:key="revanced_change_youtube_header" android:summaryOn="@string/revanced_change_youtube_header_summary_on" android:summaryOff="@string/revanced_change_youtube_header_summary_off" />
|
||||
@ -289,8 +298,7 @@
|
||||
|
||||
<!-- SETTINGS: HIDE_LAYOUT_COMPONENTS
|
||||
<SwitchPreference android:title="@string/revanced_hide_floating_microphone_title" android:key="revanced_hide_floating_microphone" android:summaryOn="@string/revanced_hide_floating_microphone_summary_on" android:summaryOff="@string/revanced_hide_floating_microphone_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_hide_gray_separator_title" android:key="revanced_hide_gray_separator" android:summaryOn="@string/revanced_hide_gray_separator_summary_on" android:summaryOff="@string/revanced_hide_gray_separator_summary_off" />
|
||||
<SwitchPreference android:title="@string/revanced_hide_snack_bar_title" android:key="revanced_hide_snack_bar" android:summaryOn="@string/revanced_hide_snack_bar_summary_on" android:summaryOff="@string/revanced_hide_snack_bar_summary_off" />SETTINGS: HIDE_LAYOUT_COMPONENTS -->
|
||||
<SwitchPreference android:title="@string/revanced_hide_gray_separator_title" android:key="revanced_hide_gray_separator" android:summaryOn="@string/revanced_hide_gray_separator_summary_on" android:summaryOff="@string/revanced_hide_gray_separator_summary_off" />SETTINGS: HIDE_LAYOUT_COMPONENTS -->
|
||||
|
||||
<!-- SETTINGS: MINIPLAYER_TYPE_19_14
|
||||
<ListPreference android:entries="@array/revanced_miniplayer_type_19_14_entries" android:title="@string/revanced_miniplayer_type_title" android:key="revanced_miniplayer_type" android:entryValues="@array/revanced_miniplayer_type_19_14_entry_values" />SETTINGS: MINIPLAYER_TYPE_19_14 -->
|
||||
@ -914,6 +922,7 @@
|
||||
<Preference android:title="Miniplayer" android:summary="@string/revanced_patches_excluded" android:selectable="false"/>
|
||||
<Preference android:title="Navigation bar components" android:summary="@string/revanced_patches_excluded" android:selectable="false"/>
|
||||
<Preference android:title="Remove viewer discretion dialog" android:summary="@string/revanced_patches_excluded" android:selectable="false"/>
|
||||
<Preference android:title="Snack bar components" android:summary="@string/revanced_patches_excluded" android:selectable="false"/>
|
||||
<Preference android:title="Spoof app version" android:summary="@string/revanced_patches_excluded" android:selectable="false"/>
|
||||
<Preference android:title="Toolbar components" android:summary="@string/revanced_patches_excluded" android:selectable="false"/>
|
||||
</PreferenceCategory>
|
||||
|
Loading…
x
Reference in New Issue
Block a user