From 175f721cfdfd9bd5f88b5fc6d83e8b60353e314f Mon Sep 17 00:00:00 2001 From: inotia00 <108592928+inotia00@users.noreply.github.com> Date: Wed, 12 Jun 2024 22:46:11 +0900 Subject: [PATCH] feat(YouTube): split `Custom header for YouTube` patch from the `Custom branding icon for YouTube` patch --- .../branding/icon/CustomBrandingIconPatch.kt | 71 ---------- .../layout/header/ChangeHeaderPatch.kt | 126 ++++++++++++++++++ .../youtube/utils/settings/ResourceUtils.kt | 4 + 3 files changed, 130 insertions(+), 71 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/header/ChangeHeaderPatch.kt diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/CustomBrandingIconPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/CustomBrandingIconPatch.kt index ad5df2d1a..8dfe71baf 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/CustomBrandingIconPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/CustomBrandingIconPatch.kt @@ -44,25 +44,6 @@ object CustomBrandingIconPatch : BaseResourcePatch( private val mipmapDirectories = sizeArray.map { "mipmap-$it" } - private val headerResourceDirectoryNames = mapOf( - "xxxhdpi" to "512px x 192px", - "xxhdpi" to "387px x 144px", - "xhdpi" to "258px x 96px", - "hdpi" to "194px x 72px", - "mdpi" to "129px x 48px", - ).map { (dpi, dim) -> - "drawable-$dpi" to dim - }.toMap() - - private val variants = arrayOf("light", "dark") - - private val headerIconResourceFileNames = arrayOf( - "yt_premium_wordmark_header_dark", - "yt_premium_wordmark_header_light", - "yt_wordmark_header_dark", - "yt_wordmark_header_light" - ).map { "$it.png" }.toTypedArray() - private val launcherIconResourceFileNames = arrayOf( "adaptiveproduct_youtube_background_color_108", "adaptiveproduct_youtube_foreground_color_108", @@ -98,8 +79,6 @@ object CustomBrandingIconPatch : BaseResourcePatch( ) } - private val headerIconResourceGroups = drawableDirectories.getResourceGroup(headerIconResourceFileNames) - private val launcherIconResourceGroups = mipmapDirectories.getResourceGroup(launcherIconResourceFileNames) private val splashIconResourceGroups = drawableDirectories.getResourceGroup(splashIconResourceFileNames) @@ -127,35 +106,6 @@ object CustomBrandingIconPatch : BaseResourcePatch( required = true ) - private val ChangeHeader by booleanPatchOption( - key = "ChangeHeader", - default = false, - title = "Change header", - description = "Apply the custom branding icon to the header.", - required = true - ) - - private val CustomHeader by stringPatchOption( - key = "CustomHeader", - default = "", - title = "Custom header", - description = """ - The header to apply to the app. - - If a path to a folder is provided, the folder must contain one or more of the following folders, depending on the DPI of the device: - - ${headerResourceDirectoryNames.keys.joinToString("\n") { "- $it" }} - - Each of the folders must contain all of the following files: - - ${headerIconResourceFileNames.joinToString("\n") { "- $it" }} - - The image dimensions must be as follows: - ${headerResourceDirectoryNames.map { (dpi, dim) -> "- $dpi: $dim" }.joinToString("\n")} - """.trimIndentMultiline(), - required = true - ) - private val ChangeSplashIcon by booleanPatchOption( key = "ChangeSplashIcon", default = true, @@ -210,27 +160,6 @@ object CustomBrandingIconPatch : BaseResourcePatch( context.copyResources("$appIconResourcePath/monochrome", resourceGroup) } - // Change header. - if (ChangeHeader == true) { - CustomHeader?.let { customHeader -> - var copiedFiles = false - if (customHeader.isNotEmpty()) { - copiedFiles = context.copyFile( - headerIconResourceGroups, - customHeader, - "WARNING: Invalid header path: $customHeader. Does not apply patches." - ) - } - if (!copiedFiles) { - headerIconResourceGroups.let { resourceGroups -> - resourceGroups.forEach { - context.copyResources("$appIconResourcePath/header", it) - } - } - } - } - } - // Change splash icon. if (ChangeSplashIcon == true) { splashIconResourceGroups.let { resourceGroups -> diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/header/ChangeHeaderPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/header/ChangeHeaderPatch.kt new file mode 100644 index 000000000..72c74549e --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/header/ChangeHeaderPatch.kt @@ -0,0 +1,126 @@ +package app.revanced.patches.youtube.layout.header + +import app.revanced.patcher.data.ResourceContext +import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption +import app.revanced.patches.youtube.utils.compatibility.Constants +import app.revanced.patches.youtube.utils.settings.ResourceUtils +import app.revanced.util.ResourceGroup +import app.revanced.util.Utils.trimIndentMultiline +import app.revanced.util.copyFile +import app.revanced.util.copyResources +import app.revanced.util.patch.BaseResourcePatch +import app.revanced.util.underBarOrThrow + +@Suppress("unused") +object ChangeHeaderPatch : BaseResourcePatch( + name = "Custom header for YouTube", + description = "Applies a custom header in the top left corner within the app.", + compatiblePackages = Constants.COMPATIBLE_PACKAGE, + use = false, +) { + private const val GENERIC_HEADER_FILE_NAME = "yt_wordmark_header" + private const val PREMIUM_HEADER_FILE_NAME = "yt_premium_wordmark_header" + + private const val DEFAULT_HEADER_KEY = "Custom branding icon" + private const val DEFAULT_HEADER_VALUE = "custom_branding_icon" + + private val genericHeaderResourceDirectoryNames = mapOf( + "xxxhdpi" to "488px x 192px", + "xxhdpi" to "366px x 144px", + "xhdpi" to "244px x 96px", + "hdpi" to "184px x 72px", + "mdpi" to "122px x 48px", + ).map { (dpi, dim) -> + "drawable-$dpi" to dim + }.toMap() + + private val premiumHeaderResourceDirectoryNames = mapOf( + "xxxhdpi" to "516px x 192px", + "xxhdpi" to "387px x 144px", + "xhdpi" to "258px x 96px", + "hdpi" to "194px x 72px", + "mdpi" to "129px x 48px", + ).map { (dpi, dim) -> + "drawable-$dpi" to dim + }.toMap() + + private val variants = arrayOf("light", "dark") + + private val headerIconResourceGroups = + premiumHeaderResourceDirectoryNames.keys.map { directory -> + ResourceGroup( + directory, + *variants.map { variant -> "${GENERIC_HEADER_FILE_NAME}_$variant.png" }.toTypedArray(), + *variants.map { variant -> "${PREMIUM_HEADER_FILE_NAME}_$variant.png" }.toTypedArray(), + ) + } + + private val CustomHeader = stringPatchOption( + key = "CustomHeader", + default = DEFAULT_HEADER_VALUE, + values = mapOf( + DEFAULT_HEADER_KEY to DEFAULT_HEADER_VALUE + ), + title = "Custom header", + description = """ + The header to apply to the app. + + Patch option '$DEFAULT_HEADER_KEY' applies only when: + + 1. Patch 'Custom branding icon for YouTube' is included. + 2. Patch option for 'Custom branding icon for YouTube' is selected from the preset. + + If a path to a folder is provided, the folder must contain one or more of the following folders, depending on the DPI of the device: + + ${premiumHeaderResourceDirectoryNames.keys.joinToString("\n") { "- $it" }} + + Each of the folders must contain all of the following files: + + [Generic header] + + ${variants.joinToString("\n") { variant -> "- ${GENERIC_HEADER_FILE_NAME}_$variant.png" }} + + The image dimensions must be as follows: + + ${genericHeaderResourceDirectoryNames.map { (dpi, dim) -> "- $dpi: $dim" }.joinToString("\n")} + + [Premium header] + + ${variants.joinToString("\n") { variant -> "- ${PREMIUM_HEADER_FILE_NAME}_$variant.png" }} + + The image dimensions must be as follows: + ${premiumHeaderResourceDirectoryNames.map { (dpi, dim) -> "- $dpi: $dim" }.joinToString("\n")} + """.trimIndentMultiline(), + required = true, + ) + + override fun execute(context: ResourceContext) { + + // Check patch options first. + val customHeader = CustomHeader + .underBarOrThrow() + + val customBrandingIconType = ResourceUtils.getIconType() + val customBrandingIconIncluded = + customBrandingIconType != "default" && customBrandingIconType != "custom" + + val warnings = "WARNING: Invalid header path: $customHeader. Does not apply patches." + + if (customHeader != DEFAULT_HEADER_VALUE) { + context.copyFile( + headerIconResourceGroups, + customHeader, + warnings + ) + } else if (customBrandingIconIncluded) { + headerIconResourceGroups.let { resourceGroups -> + resourceGroups.forEach { + context.copyResources("youtube/branding/$customBrandingIconType/header", it) + } + } + } else { + println(warnings) + } + + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/settings/ResourceUtils.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/settings/ResourceUtils.kt index 61710f90e..4e78244ff 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/settings/ResourceUtils.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/settings/ResourceUtils.kt @@ -14,6 +14,9 @@ object ResourceUtils { var youtubePackageName = "com.google.android.youtube" + private var iconType = "default" + fun getIconType() = iconType + fun ResourceContext.updatePackageName( fromPackageName: String, toPackageName: String @@ -72,6 +75,7 @@ object ResourceUtils { } fun ResourceContext.updatePatchStatusIcon(iconName: String) { + iconType = iconName updatePatchStatusSettings("Icon", "@string/revanced_icon_$iconName") }