From 831d2a1e76ed757b080ccae24b83bc380befb438 Mon Sep 17 00:00:00 2001 From: inotia00 <108592928+inotia00@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:55:12 +0900 Subject: [PATCH] feat(YouTube - Navigation bar components): Add missing resource for Cairo notification icon (YouTube 19.34.42+) https://github.com/inotia00/ReVanced_Extended/issues/2553 --- .../youtube/patches/general/GeneralPatch.java | 14 +++ .../general/navigation/Fingerprints.kt | 17 +++- .../NavigationBarComponentsPatch.kt | 84 +++++++++++++++++- .../utils/resourceid/SharedResourceIdPatch.kt | 6 ++ .../yt_fill_bell_cairo_black_24.png | Bin 0 -> 518 bytes .../yt_fill_bell_cairo_black_24.png | Bin 0 -> 394 bytes .../yt_fill_bell_cairo_black_24.png | Bin 0 -> 627 bytes .../yt_fill_bell_cairo_black_24.png | Bin 0 -> 860 bytes .../yt_fill_bell_cairo_black_24.png | Bin 0 -> 1097 bytes 9 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 patches/src/main/resources/youtube/navigationbuttons/drawable-hdpi/yt_fill_bell_cairo_black_24.png create mode 100644 patches/src/main/resources/youtube/navigationbuttons/drawable-mdpi/yt_fill_bell_cairo_black_24.png create mode 100644 patches/src/main/resources/youtube/navigationbuttons/drawable-xhdpi/yt_fill_bell_cairo_black_24.png create mode 100644 patches/src/main/resources/youtube/navigationbuttons/drawable-xxhdpi/yt_fill_bell_cairo_black_24.png create mode 100644 patches/src/main/resources/youtube/navigationbuttons/drawable-xxxhdpi/yt_fill_bell_cairo_black_24.png diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/general/GeneralPatch.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/general/GeneralPatch.java index cccf47d41..f1dd20b99 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/general/GeneralPatch.java +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/general/GeneralPatch.java @@ -197,6 +197,8 @@ public class GeneralPatch { // region [Hide navigation bar components] patch + private static final int fillBellCairoBlack = ResourceUtils.getDrawableIdentifier("yt_fill_bell_cairo_black_24"); + private static final Map shouldHideMap = new EnumMap<>(NavigationButton.class) { { put(NavigationButton.HOME, Settings.HIDE_NAVIGATION_HOME_BUTTON.get()); @@ -216,6 +218,18 @@ public class GeneralPatch { return Settings.ENABLE_TRANSLUCENT_NAVIGATION_BAR.get(); } + /** + * @noinspection ALL + */ + public static void setCairoNotificationFilledIcon(EnumMap enumMap, Enum tabActivityCairo) { + if (fillBellCairoBlack != 0) { + // It's very unlikely, but Google might fix this issue someday. + // If so, [fillBellCairoBlack] might already be in enumMap. + // That's why 'EnumMap.putIfAbsent()' is used instead of 'EnumMap.put()'. + enumMap.putIfAbsent(tabActivityCairo, Integer.valueOf(fillBellCairoBlack)); + } + } + public static boolean switchCreateWithNotificationButton(boolean original) { return Settings.SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON.get() || original; } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/general/navigation/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/general/navigation/Fingerprints.kt index c1fbb878f..adc587729 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/general/navigation/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/general/navigation/Fingerprints.kt @@ -1,10 +1,14 @@ package app.revanced.patches.youtube.general.navigation +import app.revanced.patches.youtube.utils.resourceid.ytFillBell import app.revanced.util.fingerprint.legacyFingerprint import app.revanced.util.or import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode +internal const val ANDROID_AUTOMOTIVE_STRING = "Android Automotive" +internal const val TAB_ACTIVITY_CAIRO_STRING = "TAB_ACTIVITY_CAIRO" + internal val autoMotiveFingerprint = legacyFingerprint( name = "autoMotiveFingerprint", opcodes = listOf( @@ -13,7 +17,13 @@ internal val autoMotiveFingerprint = legacyFingerprint( Opcode.MOVE_RESULT, Opcode.IF_EQZ ), - strings = listOf("Android Automotive") + strings = listOf(ANDROID_AUTOMOTIVE_STRING) +) + +internal val imageEnumConstructorFingerprint = legacyFingerprint( + name = "imageEnumConstructorFingerprint", + returnType = "V", + strings = listOf(TAB_ACTIVITY_CAIRO_STRING) ) internal val pivotBarChangedFingerprint = legacyFingerprint( @@ -59,6 +69,11 @@ internal val pivotBarStyleFingerprint = legacyFingerprint( } ) +internal val setEnumMapFingerprint = legacyFingerprint( + name = "setEnumMapFingerprint", + literals = listOf(ytFillBell), +) + internal val translucentNavigationBarFingerprint = legacyFingerprint( name = "translucentNavigationBarFingerprint", literals = listOf(45630927L), diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/general/navigation/NavigationBarComponentsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/general/navigation/NavigationBarComponentsPatch.kt index 8a41f9bd8..3b0e48a3e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/general/navigation/NavigationBarComponentsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/general/navigation/NavigationBarComponentsPatch.kt @@ -4,6 +4,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.bytecodePatch +import app.revanced.patcher.patch.resourcePatch import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.extension.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.navigation.addBottomBarContainerHook @@ -11,20 +12,54 @@ import app.revanced.patches.youtube.utils.navigation.hookNavigationButtonCreated import app.revanced.patches.youtube.utils.navigation.navigationBarHookPatch import app.revanced.patches.youtube.utils.patch.PatchList.NAVIGATION_BAR_COMPONENTS import app.revanced.patches.youtube.utils.playservice.is_19_23_or_greater +import app.revanced.patches.youtube.utils.playservice.is_19_28_or_greater import app.revanced.patches.youtube.utils.playservice.versionCheckPatch +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.ResourceGroup +import app.revanced.util.copyResources import app.revanced.util.fingerprint.injectLiteralInstructionBooleanCall import app.revanced.util.fingerprint.matchOrThrow import app.revanced.util.fingerprint.methodOrThrow import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.indexOfFirstStringInstructionOrThrow 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.reference.MethodReference +private val navigationBarComponentsResourcePatch = resourcePatch( + description = "navigationBarComponentsResourcePatch" +) { + dependsOn(versionCheckPatch) + + execute { + if (is_19_28_or_greater) { + // Since I couldn't get the Cairo notification filled icon anywhere, + // I just made it as close as possible. + arrayOf( + "xxxhdpi", + "xxhdpi", + "xhdpi", + "hdpi", + "mdpi" + ).forEach { dpi -> + copyResources( + "youtube/navigationbuttons", + ResourceGroup( + "drawable-$dpi", + "yt_fill_bell_cairo_black_24.png" + ) + ) + } + } + } +} + @Suppress("unused") val navigationBarComponentsPatch = bytecodePatch( NAVIGATION_BAR_COMPONENTS.title, @@ -33,7 +68,9 @@ val navigationBarComponentsPatch = bytecodePatch( compatibleWith(COMPATIBLE_PACKAGE) dependsOn( + navigationBarComponentsResourcePatch, settingsPatch, + sharedResourceIdPatch, navigationBarHookPatch, versionCheckPatch, ) @@ -90,7 +127,7 @@ val navigationBarComponentsPatch = bytecodePatch( // region patch for hide navigation buttons autoMotiveFingerprint.methodOrThrow().apply { - val insertIndex = indexOfFirstStringInstructionOrThrow("Android Automotive") - 1 + val insertIndex = indexOfFirstStringInstructionOrThrow(ANDROID_AUTOMOTIVE_STRING) - 1 val insertRegister = getInstruction(insertIndex).registerA addInstructions( @@ -122,6 +159,51 @@ val navigationBarComponentsPatch = bytecodePatch( // endregion + // region fix for cairo notification icon + + /** + * The Cairo navigation bar was widely rolled out in YouTube 19.28.42. + * + * Unlike Home, Shorts, and Subscriptions, which have Cairo icons, + * Notifications does not have a Cairo icon. + * + * This led to an issue revanced-patches#4046, + * Which was closed as not planned because it was a YouTube issue and not a ReVanced issue. + * + * It was not too hard to fix, so it was implemented as a patch. + */ + if (is_19_28_or_greater) { + val cairoNotificationEnumReference = with (imageEnumConstructorFingerprint.methodOrThrow()) { + val stringIndex = indexOfFirstStringInstructionOrThrow(TAB_ACTIVITY_CAIRO_STRING) + val cairoNotificationEnumIndex = indexOfFirstInstructionOrThrow(stringIndex) { + opcode == Opcode.SPUT_OBJECT + } + getInstruction(cairoNotificationEnumIndex).reference + } + + setEnumMapFingerprint.methodOrThrow().apply { + val enumMapIndex = indexOfFirstInstructionReversedOrThrow { + val reference = getReference() + opcode == Opcode.INVOKE_VIRTUAL && + reference?.definingClass == "Ljava/util/EnumMap;" && + reference.name == "put" && + reference.parameterTypes.firstOrNull() == "Ljava/lang/Enum;" + } + val (enumMapRegister, enumRegister) = getInstruction(enumMapIndex).let { + Pair(it.registerC, it.registerD) + } + + addInstructions( + enumMapIndex + 1, """ + sget-object v$enumRegister, $cairoNotificationEnumReference + invoke-static {v$enumMapRegister, v$enumRegister}, $GENERAL_CLASS_DESCRIPTOR->setCairoNotificationFilledIcon(Ljava/util/EnumMap;Ljava/lang/Enum;)V + """ + ) + } + } + + // endregion + // Hook navigation button created, in order to hide them. hookNavigationButtonCreated(GENERAL_CLASS_DESCRIPTOR) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt index 17b8bba16..31bb20af6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/SharedResourceIdPatch.kt @@ -216,6 +216,8 @@ var youTubeControlsOverlaySubtitleButton = -1L private set var youTubeLogo = -1L private set +var ytFillBell = -1L + private set var ytOutlinePictureInPictureWhite = -1L private set var ytOutlineVideoCamera = -1L @@ -638,6 +640,10 @@ internal val sharedResourceIdPatch = resourcePatch( ID, "youtube_logo" ] + ytFillBell = resourceMappings[ + DRAWABLE, + "yt_fill_bell_black_24" + ] ytOutlinePictureInPictureWhite = resourceMappings[ DRAWABLE, "yt_outline_picture_in_picture_white_24" diff --git a/patches/src/main/resources/youtube/navigationbuttons/drawable-hdpi/yt_fill_bell_cairo_black_24.png b/patches/src/main/resources/youtube/navigationbuttons/drawable-hdpi/yt_fill_bell_cairo_black_24.png new file mode 100644 index 0000000000000000000000000000000000000000..bec5bd78b024b8aa96843832086d5d8f5dd68d85 GIT binary patch literal 518 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB6p}rHd>I(3)EF2VS{N990fib~ zFff!FFfhDIU|_HUsu3@kvn$XBD8Z8M=jA5L~c#IY^qbz$3Dlfr0M`2s2LA=930$iS=}G45_%4oFKvK%wrI=Vm@of?FI|M ztZPgP>sTJ$eZok2P~XXB6!>C6gwoL$j}+1s#11H(<3FPJ z#mD)TgN=B{TFw>LTt`ki)J&e1d4jLwJL5(z!K|kXE|$x5$X`0-xM0G~Zsl18jC=}w z43Bsn{!E*d$sw|Jvu6np4~N57qoB)16aB|Hk=7jI_|h&#iJ#S%^%d5WB7~|)fj^q93+oU5n=z^oD|jg zf5(~Q*Sm^azirN7>|^}+F7fWvXUvbR9dx>!|CtJ`X85RHRl2m^>38(Oh%-M}j}$u8 zbl$72p3q#zxRFJmo8e=5hPkHTt#WBrWo8D3=bgHNi?4d~14Ey|)78&qol`;+0E*PV A9RL6T literal 0 HcmV?d00001 diff --git a/patches/src/main/resources/youtube/navigationbuttons/drawable-mdpi/yt_fill_bell_cairo_black_24.png b/patches/src/main/resources/youtube/navigationbuttons/drawable-mdpi/yt_fill_bell_cairo_black_24.png new file mode 100644 index 0000000000000000000000000000000000000000..415a6cccae6023c9705e0452deb023be437ce6f6 GIT binary patch literal 394 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`Gj3dtTpz6=aiY77hwEes65fIMkwj-+?Y#Jkck3<~cIpXQCra?uGUo?4{Nk>a#g}Q+B;|cccNAev0 zh|Papz$m6*$8bcg;)(~;Mqz>T?2qb~um$ok9!_LfqBd=gg@=kFqsoNjMm0{cjETvO z8k}Ms0m||dSliaK+NI2R>b!_PX_2(g}u;-J-(5GXFVdQ&MBb@07{60vj6}9 literal 0 HcmV?d00001 diff --git a/patches/src/main/resources/youtube/navigationbuttons/drawable-xhdpi/yt_fill_bell_cairo_black_24.png b/patches/src/main/resources/youtube/navigationbuttons/drawable-xhdpi/yt_fill_bell_cairo_black_24.png new file mode 100644 index 0000000000000000000000000000000000000000..4c837aabcd39315e01b143f25e95dda057d880fc GIT binary patch literal 627 zcmV-(0*w8MP)004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00004XF*Lt006O$eEU(800001 zb5ch_0Itp)=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01m_e01m_fl`9S#0005X zNklR#IyMb!Ry%F0Dlt6dL{Vs~JE(ds{Ho*+& zh=_d#XJ7@~* zq-Y?B8imY1$fB0f8_*91H67%`^aM`87IHSmd3Cg=bF N002ovPDHLkV1iG8`q=;g literal 0 HcmV?d00001 diff --git a/patches/src/main/resources/youtube/navigationbuttons/drawable-xxhdpi/yt_fill_bell_cairo_black_24.png b/patches/src/main/resources/youtube/navigationbuttons/drawable-xxhdpi/yt_fill_bell_cairo_black_24.png new file mode 100644 index 0000000000000000000000000000000000000000..4ee5124c2d2a6449a68e853664e64c0f4cb3e93f GIT binary patch literal 860 zcmV-i1Ec(jP)004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00004XF*Lt006O$eEU(800001 zb5ch_0Itp)=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01m_e01m_fl`9S#0008B zNkl9_%6_$ohTQ_u!??oq6ARpLh59!soOzvoD`{=XvLSXGSTB zL?V$$d`*l&8!EvFNP{Nbre9zlEP&&37L)*AK-WKh{|WlRA6E^ma407Z)<9>0Z7zd* zU=HNUP0%>VoMXF7U{CiZCuh-Bo)od|u*+`lD(#lGEg3;4mbUe}2GI#gfw!Qgi2W{t zZg2p$qb%4_4)eFbJJ1~RICPIR0kWkc=mL19M=Vp9H1(ia@C+RJe2LY7WiVv;WYDoX zz+Ld!rX-t!YQYA$Zt*`FzySCN4t)|t^Q*7=EZa_qm_o z1$8SPOSm!J7IuPeD?YiyQBabRpd?2@b&LchI0{OLpu(wUB&gcdfDu;`5hQ{{kO&e% zB1i;@Ac+VPL2L!}DISYuXVcF`5WRUZ&G6*E)@=(F6OTwQ^MD5f5f$rH)PlGcX5$4rXp!bxn2i_gAU%kCVK!Q@ z;{m&Cm4|`?m4#vjJ@BM37b@7jHU*8A!1QXwrl4F22+G+M^xktx)bfijU`a_N5-y2)6_DOxTnTxM9s|dSWHuiptKeIR{l7;k$AusYea!nez<#t( zI_k!{`09BdY=TEcEJ2W*L9kU0f+)M-6KDhV|JgRH=YLx+8p`2O4HfP&a6>OgP@8^( mA1eQe(~6QvBoc{45+J8~vRSn2B5<+*0000004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00004XF*Lt006O$eEU(800001 zb5ch_0Itp)=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01m_e01m_fl`9S#000A^ zNkl|Ibvo9~R+cOYiwX z571(PpV1G?@GKl;0KZrO&*>3t63D#KZupcVVWn2UUOnJSidlM$ za38+NasXT56_`)qvt@9%MF;RGivh^Q+66c=~R3iAq3FqaR7}BfB{&Ug7B4w5CX`19Dt05 z>wFJ@FaQQX7yttx41fU;2EYIa17HAz0Wbi<02lxRi240jD?isH`kght1|a|ETM6JI zt>|Nkg*czrIRe)Q5P&?U_ygYbsRhUy4W)p(YFRF4j!yxcQ4TK;;8J%QM*vcI*9LgQ zBE`7f^#DRCyonWL+eJ8(!kbt@w%GzgE4+ymWSaqmR(KQXW^Dx!YT=E&Am?1WBC=MH zZ4}|q3va9i*|Y^@rSQg9kWB+9Wu)-_tNSgd89=Kdt!V}@$n&4>T~IGiq1g)UrU4v> zZ!>)IWew6}Y2Jo@f!%P5inbQXXXM1oLa^81CisS(03n2sT5$21otf~tinbuJiR`E( zOJ+K?&zOr(#=Tb27F4$BQ4VhM=IWz~GRgJH;`{Zh+IC`!9ak4p`mCa5gg02|CS|&0 z7re^=s^hV41#Jc)$jO&&4ZB=DNY|GVy9b}BXmRao_Y#v)`gVApcR}XJG{*iy` P00000NkvXXu0mjfZgb(L literal 0 HcmV?d00001