@@ -21,7 +21,6 @@ import app.revanced.util.findElementByAttributeValueOrThrow
2121import app.revanced.util.removeFromParent
2222import app.revanced.util.returnEarly
2323import org.w3c.dom.Element
24- import org.w3c.dom.Node
2524import org.w3c.dom.NodeList
2625import java.io.File
2726import java.util.logging.Logger
@@ -106,6 +105,7 @@ internal fun baseCustomBrandingPatch(
106105
107106 dependsOn(
108107 addResourcesPatch,
108+
109109 bytecodePatch {
110110 execute {
111111 mainActivityOnCreateFingerprint.method.addInstruction(
@@ -201,68 +201,6 @@ internal fun baseCustomBrandingPatch(
201201 )
202202 }
203203
204- if (useCustomIcon) {
205- // Copy user provided files
206- val iconPathFile = File (customIcon!! .trim())
207-
208- if (! iconPathFile.exists()) {
209- throw PatchException (
210- " The custom icon path cannot be found: " + iconPathFile.absolutePath
211- )
212- }
213-
214- if (! iconPathFile.isDirectory) {
215- throw PatchException (
216- " The custom icon path must be a folder: " + iconPathFile.absolutePath
217- )
218- }
219-
220- val sourceFolders = iconPathFile.listFiles { file -> file.isDirectory }
221- ? : throw PatchException (" The custom icon path contains no subfolders: " +
222- iconPathFile.absolutePath)
223-
224- val resourceDirectory = get(" res" )
225- var copiedFiles = false
226-
227- // For each source folder, copy the files to the target resource directories.
228- sourceFolders.forEach { dpiSourceFolder ->
229- val targetDpiFolder = resourceDirectory.resolve(dpiSourceFolder.name)
230- if (! targetDpiFolder.exists()) return @forEach
231-
232- val customFiles = dpiSourceFolder.listFiles { file ->
233- file.isFile && file.name in USER_CUSTOM_ADAPTIVE_FILE_NAMES
234- }!!
235-
236- if (customFiles.size > 0 && customFiles.size != USER_CUSTOM_ADAPTIVE_FILE_NAMES .size) {
237- throw PatchException (" Must include all required icon files " +
238- " but only found " + customFiles.map { it.name })
239- }
240-
241- customFiles.forEach { imgSourceFile ->
242- val imgTargetFile = targetDpiFolder.resolve(imgSourceFile.name)
243- imgSourceFile.copyTo(target = imgTargetFile, overwrite = true )
244-
245- copiedFiles = true
246- }
247- }
248-
249- // Copy monochrome if it provided.
250- val monochromeRelativePath = " drawable/$USER_CUSTOM_MONOCHROME_NAME "
251- val monochromeFile = iconPathFile.resolve(monochromeRelativePath)
252- if (monochromeFile.exists()) {
253- monochromeFile.copyTo(
254- target = resourceDirectory.resolve(monochromeRelativePath),
255- overwrite = true
256- )
257- copiedFiles = true
258- }
259-
260- if (! copiedFiles) {
261- throw PatchException (" Could not find any replacement images in " +
262- " patch option path: " + iconPathFile.absolutePath)
263- }
264- }
265-
266204 document(" AndroidManifest.xml" ).use { document ->
267205 // Create launch aliases that can be programmatically selected in app.
268206 fun createAlias (
@@ -316,12 +254,20 @@ internal fun baseCustomBrandingPatch(
316254 return alias
317255 }
318256
257+ val application = document.getElementsByTagName(" application" ).item(0 ) as Element
319258 val intentFilters = document.childNodes.findElementByAttributeValueOrThrow(
320259 " android:name" ,
321260 activityAliasNameWithIntents
322261 ).childNodes
323262
324- val application = document.getElementsByTagName(" application" ).item(0 ) as Element
263+ // The YT application name can appear in some places along side the system
264+ // YouTube app, such as the settings app list and in the "open with" file picker.
265+ // Because the YouTube app cannot be completely uninstalled and only disabled,
266+ // use a custom name for this situation to disambiguate which app is which.
267+ application.setAttribute(
268+ " android:label" ,
269+ " @string/revanced_custom_branding_name_entry_2"
270+ )
325271
326272 for (appNameIndex in 1 .. numberOfPresetAppNames) {
327273 fun aliasName (name : String ): String = " .revanced_" + name + ' _' + appNameIndex
@@ -382,6 +328,70 @@ internal fun baseCustomBrandingPatch(
382328 ).removeFromParent()
383329 }
384330
331+ // Copy custom icons last, so if the user enters an invalid icon path
332+ // and an exception is thrown then the critical manifest changes are still made.
333+ if (useCustomIcon) {
334+ // Copy user provided files
335+ val iconPathFile = File (customIcon!! .trim())
336+
337+ if (! iconPathFile.exists()) {
338+ throw PatchException (
339+ " The custom icon path cannot be found: " + iconPathFile.absolutePath
340+ )
341+ }
342+
343+ if (! iconPathFile.isDirectory) {
344+ throw PatchException (
345+ " The custom icon path must be a folder: " + iconPathFile.absolutePath
346+ )
347+ }
348+
349+ val sourceFolders = iconPathFile.listFiles { file -> file.isDirectory }
350+ ? : throw PatchException (" The custom icon path contains no subfolders: " +
351+ iconPathFile.absolutePath)
352+
353+ val resourceDirectory = get(" res" )
354+ var copiedFiles = false
355+
356+ // For each source folder, copy the files to the target resource directories.
357+ sourceFolders.forEach { dpiSourceFolder ->
358+ val targetDpiFolder = resourceDirectory.resolve(dpiSourceFolder.name)
359+ if (! targetDpiFolder.exists()) return @forEach
360+
361+ val customFiles = dpiSourceFolder.listFiles { file ->
362+ file.isFile && file.name in USER_CUSTOM_ADAPTIVE_FILE_NAMES
363+ }!!
364+
365+ if (customFiles.size > 0 && customFiles.size != USER_CUSTOM_ADAPTIVE_FILE_NAMES .size) {
366+ throw PatchException (" Must include all required icon files " +
367+ " but only found " + customFiles.map { it.name })
368+ }
369+
370+ customFiles.forEach { imgSourceFile ->
371+ val imgTargetFile = targetDpiFolder.resolve(imgSourceFile.name)
372+ imgSourceFile.copyTo(target = imgTargetFile, overwrite = true )
373+
374+ copiedFiles = true
375+ }
376+ }
377+
378+ // Copy monochrome if it provided.
379+ val monochromeRelativePath = " drawable/$USER_CUSTOM_MONOCHROME_NAME "
380+ val monochromeFile = iconPathFile.resolve(monochromeRelativePath)
381+ if (monochromeFile.exists()) {
382+ monochromeFile.copyTo(
383+ target = resourceDirectory.resolve(monochromeRelativePath),
384+ overwrite = true
385+ )
386+ copiedFiles = true
387+ }
388+
389+ if (! copiedFiles) {
390+ throw PatchException (" Could not find any replacement images in " +
391+ " patch option path: " + iconPathFile.absolutePath)
392+ }
393+ }
394+
385395 executeBlock()
386396 }
387397}
0 commit comments