11package app.revanced.patches.shared.layout.branding
22
3+ import app.revanced.patcher.patch.PatchException
34import app.revanced.patcher.patch.ResourcePatch
45import app.revanced.patcher.patch.ResourcePatchBuilder
56import app.revanced.patcher.patch.ResourcePatchContext
@@ -14,7 +15,7 @@ import java.util.logging.Logger
1415
1516private const val REVANCED_ICON = " ReVanced*Logo" // Can never be a valid path.
1617
17- private val mipmapDirectories = arrayOf(
18+ internal val mipmapDirectories = arrayOf(
1819 // Target app does not have ldpi icons.
1920 " mdpi" ,
2021 " hdpi" ,
@@ -63,10 +64,6 @@ internal fun baseCustomBrandingPatch(
6364 description = " Applies a custom app name and icon. Defaults to \" $defaultAppName \" and the ReVanced logo." ,
6465 use = false ,
6566) {
66- fun Array<String>.addPngExtension () = this .map { " $it .png" }.toTypedArray<String >()
67- val iconResourceFileNamesPng = iconResourceFileNames.addPngExtension()
68- val legacyIconResourceFileNamesPng = legacyIconResourceFileNames.addPngExtension()
69-
7067 val appName by stringOption(
7168 key = " appName" ,
7269 default = defaultAppName,
@@ -83,16 +80,13 @@ internal fun baseCustomBrandingPatch(
8380 description = """
8481 The icon to apply to the app.
8582
86- If a path to a folder is provided, the folder must contain the following folders:
87-
83+ If a path to a folder is provided, the folder must contain one or more of the following folders:
8884 ${formatResourceFileList(mipmapDirectories)}
8985
9086 Each of these folders must contain the following files:
91-
92- ${formatResourceFileList((iconResourceFileNamesPng + legacyIconResourceFileNamesPng))}
87+ ${formatResourceFileList((iconResourceFileNames + legacyIconResourceFileNames))}
9388
9489 Optionally, a 'drawable' folder with the monochrome icon files:
95-
9690 ${formatResourceFileList(monochromeIconFileNames)}
9791 """ .trimIndentMultiline(),
9892 )
@@ -103,64 +97,71 @@ internal fun baseCustomBrandingPatch(
10397 val iconPathTrimmed = iconPath!! .trim()
10498
10599 if (iconPathTrimmed == REVANCED_ICON ) {
106- val mipmapIconResourceGroups = mipmapDirectories.map { directory ->
107- ResourceGroup (
108- directory,
109- * legacyIconResourceFileNamesPng,
110- )
111- }
112-
113- // Copy monochrome icons.
100+ // Copy adaptive icons.
114101 copyResources(
115102 resourceFolder,
116- ResourceGroup (" drawable " , * monochromeIconFileNames )
103+ ResourceGroup (" mipmap-anydpi " , * adaptiveIconFileNames )
117104 )
118105
119106 // Copy legacy icons.
120- mipmapIconResourceGroups.forEach { groupResources ->
107+ mipmapDirectories.map { directory ->
108+ ResourceGroup (
109+ directory,
110+ * legacyIconResourceFileNames,
111+ )
112+ }.forEach { groupResources ->
121113 copyResources(resourceFolder, groupResources)
122114 }
123115
124- // Copy adaptive icons.
116+ // Copy monochrome icons.
125117 copyResources(
126118 resourceFolder,
127- ResourceGroup (" mipmap-anydpi " , * adaptiveIconFileNames )
119+ ResourceGroup (" drawable " , * monochromeIconFileNames )
128120 )
129121 } else {
130- val mipmapIconResourceGroups = mipmapDirectories.map { directory ->
131- ResourceGroup (
132- directory,
133- * iconResourceFileNamesPng,
134- )
135- }
136-
137- val filePath = File (iconPathTrimmed)
122+ val iconPathFile = File (iconPathTrimmed)
138123 val resourceDirectory = get(" res" )
124+ var replacedResources = false
139125
140126 // Replace mipmap icons.
141- mipmapIconResourceGroups.forEach { groupResources ->
127+ mipmapDirectories.map { directory ->
128+ ResourceGroup (
129+ directory,
130+ * iconResourceFileNames,
131+ )
132+ }.forEach { groupResources ->
142133 val groupResourceDirectoryName = groupResources.resourceDirectoryName
143- val fromDirectory = filePath .resolve(groupResourceDirectoryName)
134+ val fromDirectory = iconPathFile .resolve(groupResourceDirectoryName)
144135 val toDirectory = resourceDirectory.resolve(groupResourceDirectoryName)
145136
146137 groupResources.resources.forEach { iconFileName ->
147- Files .write(
148- toDirectory.resolve(iconFileName).toPath(),
149- fromDirectory.resolve(iconFileName).readBytes(),
150- )
138+ val replacement = fromDirectory.resolve(iconFileName)
139+ if (replacement.exists()) {
140+ Files .write(
141+ toDirectory.resolve(iconFileName).toPath(),
142+ replacement.readBytes(),
143+ )
144+ replacedResources = true
145+ }
151146 }
152147 }
153148
154149 // Replace monochrome icons if provided.
155- monochromeIconFileNames.forEach { fileName ->
156- val replacementMonochrome = filePath.resolve(" drawable" ).resolve(fileName)
157- if (replacementMonochrome.exists()) {
150+ monochromeIconFileNames.forEach { iconFileName ->
151+ val resourceType = " drawable"
152+ val replacement = iconPathFile.resolve(resourceType).resolve(iconFileName)
153+ if (replacement.exists()) {
158154 Files .write(
159- resourceDirectory.resolve(" drawable " ).resolve(fileName ).toPath(),
160- replacementMonochrome .readBytes(),
155+ resourceDirectory.resolve(resourceType ).resolve(iconFileName ).toPath(),
156+ replacement .readBytes(),
161157 )
158+ replacedResources = true
162159 }
163160 }
161+
162+ if (! replacedResources) {
163+ throw PatchException (" Could not find any replacement images in patch option path: $iconPathTrimmed " )
164+ }
164165 }
165166
166167 // Change the app name.
0 commit comments