Skip to content

Commit e775bc2

Browse files
committed
feat(YouTube - Change header): Improve patch option description
1 parent 5c56675 commit e775bc2

File tree

1 file changed

+64
-51
lines changed

1 file changed

+64
-51
lines changed

src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/ChangeHeaderPatch.kt

Lines changed: 64 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -15,62 +15,69 @@ import java.io.File
1515
name = "Change header",
1616
description = "Applies a custom header in the top left corner within the app. Defaults to the ReVanced header.",
1717
compatiblePackages = [
18-
CompatiblePackage("com.google.android.youtube")
18+
CompatiblePackage("com.google.android.youtube"),
1919
],
20-
use = false
20+
use = false,
2121
)
2222
@Suppress("unused")
2323
object ChangeHeaderPatch : ResourcePatch() {
24-
private const val HEADER_NAME = "yt_wordmark_header"
25-
private const val PREMIUM_HEADER_NAME = "yt_premium_wordmark_header"
26-
private const val REVANCED_HEADER_NAME = "ReVanced"
27-
private const val REVANCED_BORDERLESS_HEADER_NAME = "ReVanced (borderless logo)"
28-
29-
private val targetResourceDirectoryNames = arrayOf(
30-
"xxxhdpi",
31-
"xxhdpi",
32-
"xhdpi",
33-
"mdpi",
34-
"hdpi",
35-
).map { dpi ->
36-
"drawable-$dpi"
37-
}
24+
private const val HEADER_FILE_NAME = "yt_wordmark_header"
25+
private const val PREMIUM_HEADER_FILE_NAME = "yt_premium_wordmark_header"
26+
27+
private const val HEADER_OPTION = "header*"
28+
private const val PREMIUM_HEADER_OPTION = "premium*header"
29+
private const val REVANCED_HEADER_OPTION = "revanced*"
30+
private const val REVANCED_BORDERLESS_HEADER_OPTION = "revanced*borderless"
31+
32+
private val targetResourceDirectoryNames = mapOf(
33+
"xxxhdpi" to "512px x 192px",
34+
"xxhdpi" to "387px x 144px",
35+
"xhdpi" to "258px x 96px",
36+
"hdpi" to "194px x 72px",
37+
"mdpi" to "129px x 48px",
38+
).map { (dpi, dim) ->
39+
"drawable-$dpi" to dim
40+
}.toMap()
3841

3942
private val variants = arrayOf("light", "dark")
4043

4144
private val header by stringPatchOption(
4245
key = "header",
43-
default = REVANCED_BORDERLESS_HEADER_NAME,
46+
default = REVANCED_BORDERLESS_HEADER_OPTION,
4447
values = mapOf(
45-
"YouTube" to HEADER_NAME,
46-
"YouTube Premium" to PREMIUM_HEADER_NAME,
47-
"ReVanced" to REVANCED_HEADER_NAME,
48-
"ReVanced (borderless logo)" to REVANCED_BORDERLESS_HEADER_NAME,
48+
"YouTube" to HEADER_OPTION,
49+
"YouTube Premium" to PREMIUM_HEADER_OPTION,
50+
"ReVanced" to REVANCED_HEADER_OPTION,
51+
"ReVanced (borderless logo)" to REVANCED_BORDERLESS_HEADER_OPTION,
4952
),
5053
title = "Header",
5154
description = """
52-
Either a header name or a path to a custom header folder to use in the top bar.
53-
The path to a folder must contain one or more of the following folders matching the DPI of your device:
54-
55-
${targetResourceDirectoryNames.joinToString("\n") { "- $it" }}
56-
57-
These folders must contain the following files:
58-
59-
${variants.joinToString("\n") { variant -> "- ${HEADER_NAME}_$variant.png" }}
55+
The header to apply to the app.
56+
57+
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:
58+
59+
${targetResourceDirectoryNames.keys.joinToString("\n") { "- $it" }}
60+
61+
Each of the folders must contain all of the following files:
62+
63+
${variants.joinToString("\n") { variant -> "- ${HEADER_FILE_NAME}_$variant.png" }}
64+
65+
The image dimensions must be as follows:
66+
${targetResourceDirectoryNames.map { (dpi, dim) -> "- $dpi: $dim" }.joinToString("\n")}
6067
""".trimIndentMultiline(),
6168
required = true,
6269
)
6370

6471
override fun execute(context: ResourceContext) {
6572
// The directories to copy the header to.
66-
val targetResourceDirectories = targetResourceDirectoryNames.mapNotNull {
73+
val targetResourceDirectories = targetResourceDirectoryNames.keys.mapNotNull {
6774
context["res"].resolve(it).takeIf(File::exists)
6875
}
6976
// The files to replace in the target directories.
70-
val targetResourceFiles = targetResourceDirectoryNames.map { directoryName ->
77+
val targetResourceFiles = targetResourceDirectoryNames.keys.map { directoryName ->
7178
ResourceGroup(
7279
directoryName,
73-
*variants.map { variant -> "${HEADER_NAME}_$variant.png" }.toTypedArray()
80+
*variants.map { variant -> "${HEADER_FILE_NAME}_$variant.png" }.toTypedArray(),
7481
)
7582
}
7683

@@ -89,8 +96,8 @@ object ChangeHeaderPatch : ResourcePatch() {
8996
}
9097

9198
// Functions to overwrite the header to the different variants.
92-
val toPremium = { overwriteFromTo(PREMIUM_HEADER_NAME, HEADER_NAME) }
93-
val toHeader = { overwriteFromTo(HEADER_NAME, PREMIUM_HEADER_NAME) }
99+
val toPremium = { overwriteFromTo(PREMIUM_HEADER_FILE_NAME, HEADER_FILE_NAME) }
100+
val toHeader = { overwriteFromTo(HEADER_FILE_NAME, PREMIUM_HEADER_FILE_NAME) }
94101
val toReVanced = {
95102
// Copy the ReVanced header to the resource directories.
96103
targetResourceFiles.forEach { context.copyResources("change-header/revanced", it) }
@@ -106,32 +113,38 @@ object ChangeHeaderPatch : ResourcePatch() {
106113
toHeader()
107114
}
108115
val toCustom = {
109-
var copiedReplacementImages = false
110-
// For all the resource groups in the custom header folder, copy them to the resource directories.
111-
File(header!!).listFiles { file -> file.isDirectory }?.forEach { folder ->
112-
val targetDirectory = context["res"].resolve(folder.name)
113-
// Skip if the target directory (DPI) doesn't exist.
114-
if (!targetDirectory.exists()) return@forEach
115-
116-
folder.listFiles { file -> file.isFile }?.forEach {
117-
val targetResourceFile = targetDirectory.resolve(it.name)
118-
119-
it.copyTo(targetResourceFile, true)
120-
copiedReplacementImages = true
116+
val sourceFolders = File(header!!).listFiles { file -> file.isDirectory }
117+
?: throw PatchException("The provided path is not a directory: $header")
118+
119+
var copiedFiles = false
120+
121+
// For each source folder, copy the files to the target resource directories.
122+
sourceFolders.forEach { dpiSourceFolder ->
123+
val targetDpiFolder = context["res"].resolve(dpiSourceFolder.name)
124+
if (!targetDpiFolder.exists()) return@forEach
125+
126+
val imgSourceFiles = dpiSourceFolder.listFiles { file -> file.isFile }!!
127+
imgSourceFiles.forEach { imgSourceFile ->
128+
val imgTargetFile = targetDpiFolder.resolve(imgSourceFile.name)
129+
imgSourceFile.copyTo(imgTargetFile, true)
130+
131+
copiedFiles = true
121132
}
122133
}
123134

124-
if (!copiedReplacementImages) throw PatchException("Could not find any custom images resources in directory: $header")
135+
if (!copiedFiles) {
136+
throw PatchException("No header files were copied from the provided path: $header.")
137+
}
125138

126139
// Overwrite the premium with the custom header as well.
127140
toHeader()
128141
}
129142

130143
when (header) {
131-
HEADER_NAME -> toHeader
132-
PREMIUM_HEADER_NAME -> toPremium
133-
REVANCED_HEADER_NAME -> toReVanced
134-
REVANCED_BORDERLESS_HEADER_NAME -> toReVancedBorderless
144+
HEADER_OPTION -> toHeader
145+
PREMIUM_HEADER_OPTION -> toPremium
146+
REVANCED_HEADER_OPTION -> toReVanced
147+
REVANCED_BORDERLESS_HEADER_OPTION -> toReVancedBorderless
135148
else -> toCustom
136149
}()
137150
}

0 commit comments

Comments
 (0)