feat(YouTube Music/Custom branding icon for YouTube Music): add patch option RestoreOldSplashIcon
https://github.com/inotia00/ReVanced_Extended/issues/2368
@ -9,8 +9,10 @@ import app.revanced.patches.music.utils.settings.ResourceUtils.setIconType
|
|||||||
import app.revanced.util.ResourceGroup
|
import app.revanced.util.ResourceGroup
|
||||||
import app.revanced.util.Utils.trimIndentMultiline
|
import app.revanced.util.Utils.trimIndentMultiline
|
||||||
import app.revanced.util.copyResources
|
import app.revanced.util.copyResources
|
||||||
|
import app.revanced.util.getResourceGroup
|
||||||
import app.revanced.util.patch.BaseResourcePatch
|
import app.revanced.util.patch.BaseResourcePatch
|
||||||
import app.revanced.util.underBarOrThrow
|
import app.revanced.util.underBarOrThrow
|
||||||
|
import org.w3c.dom.Element
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
|
|
||||||
@ -71,17 +73,11 @@ object CustomBrandingIconPatch : BaseResourcePatch(
|
|||||||
"record"
|
"record"
|
||||||
).map { "$it.png" }.toTypedArray()
|
).map { "$it.png" }.toTypedArray()
|
||||||
|
|
||||||
private val launcherIconResourceGroups = mipmapDirectories.map { directory ->
|
private val launcherIconResourceGroups =
|
||||||
ResourceGroup(
|
mipmapDirectories.getResourceGroup(launcherIconResourceFileNames)
|
||||||
directory, *launcherIconResourceFileNames
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val splashIconResourceGroups = largeDrawableDirectories.map { directory ->
|
private val splashIconResourceGroups =
|
||||||
ResourceGroup(
|
largeDrawableDirectories.getResourceGroup(splashIconResourceFileNames)
|
||||||
directory, *splashIconResourceFileNames
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val AppIcon = stringPatchOption(
|
private val AppIcon = stringPatchOption(
|
||||||
key = "AppIcon",
|
key = "AppIcon",
|
||||||
@ -110,6 +106,20 @@ object CustomBrandingIconPatch : BaseResourcePatch(
|
|||||||
required = true
|
required = true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val RestoreOldSplashIcon by booleanPatchOption(
|
||||||
|
key = "RestoreOldSplashIcon",
|
||||||
|
default = false,
|
||||||
|
title = "Restore old splash icon",
|
||||||
|
description = """
|
||||||
|
Restore the old style splash icon.
|
||||||
|
|
||||||
|
If you enable both the old style splash icon and the Cairo splash animation,
|
||||||
|
|
||||||
|
Old style splash icon will appear first and then the Cairo splash animation will start.
|
||||||
|
""".trimIndentMultiline(),
|
||||||
|
required = true
|
||||||
|
)
|
||||||
|
|
||||||
override fun execute(context: ResourceContext) {
|
override fun execute(context: ResourceContext) {
|
||||||
|
|
||||||
// Check patch options first.
|
// Check patch options first.
|
||||||
@ -117,6 +127,7 @@ object CustomBrandingIconPatch : BaseResourcePatch(
|
|||||||
.underBarOrThrow()
|
.underBarOrThrow()
|
||||||
|
|
||||||
val appIconResourcePath = "music/branding/$appIcon"
|
val appIconResourcePath = "music/branding/$appIcon"
|
||||||
|
val youtubeMusicIconResourcePath = "music/branding/youtube_music"
|
||||||
|
|
||||||
// Check if a custom path is used in the patch options.
|
// Check if a custom path is used in the patch options.
|
||||||
if (!availableIcon.containsValue(appIcon)) {
|
if (!availableIcon.containsValue(appIcon)) {
|
||||||
@ -160,6 +171,39 @@ object CustomBrandingIconPatch : BaseResourcePatch(
|
|||||||
context.copyResources("$appIconResourcePath/monochrome", resourceGroup)
|
context.copyResources("$appIconResourcePath/monochrome", resourceGroup)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Change splash icon.
|
||||||
|
if (RestoreOldSplashIcon == true) {
|
||||||
|
var oldSplashIconNotExists: Boolean
|
||||||
|
|
||||||
|
context.xmlEditor["res/drawable/splash_screen.xml"].use { editor ->
|
||||||
|
editor.file.apply {
|
||||||
|
val node = getElementsByTagName("layer-list").item(0)
|
||||||
|
oldSplashIconNotExists = (node as Element)
|
||||||
|
.getElementsByTagName("item")
|
||||||
|
.length == 1
|
||||||
|
|
||||||
|
if (oldSplashIconNotExists) {
|
||||||
|
createElement("item").also { itemNode ->
|
||||||
|
itemNode.appendChild(
|
||||||
|
createElement("bitmap").also { bitmapNode ->
|
||||||
|
bitmapNode.setAttribute("android:gravity", "center")
|
||||||
|
bitmapNode.setAttribute("android:src", "@drawable/record")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
node.appendChild(itemNode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (oldSplashIconNotExists) {
|
||||||
|
splashIconResourceGroups.let { resourceGroups ->
|
||||||
|
resourceGroups.forEach {
|
||||||
|
context.copyResources("$youtubeMusicIconResourcePath/splash", it, createDirectoryIfNotExist = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Change splash icon.
|
// Change splash icon.
|
||||||
if (ChangeSplashIcon == true) {
|
if (ChangeSplashIcon == true) {
|
||||||
// Some resources have been removed in the latest YouTube Music.
|
// Some resources have been removed in the latest YouTube Music.
|
||||||
|
@ -11,6 +11,7 @@ import app.revanced.util.Utils.trimIndentMultiline
|
|||||||
import app.revanced.util.copyFile
|
import app.revanced.util.copyFile
|
||||||
import app.revanced.util.copyResources
|
import app.revanced.util.copyResources
|
||||||
import app.revanced.util.copyXmlNode
|
import app.revanced.util.copyXmlNode
|
||||||
|
import app.revanced.util.getResourceGroup
|
||||||
import app.revanced.util.patch.BaseResourcePatch
|
import app.revanced.util.patch.BaseResourcePatch
|
||||||
import app.revanced.util.underBarOrThrow
|
import app.revanced.util.underBarOrThrow
|
||||||
|
|
||||||
@ -73,12 +74,6 @@ object CustomBrandingIconPatch : BaseResourcePatch(
|
|||||||
"avd_anim"
|
"avd_anim"
|
||||||
).map { "$it.xml" }.toTypedArray()
|
).map { "$it.xml" }.toTypedArray()
|
||||||
|
|
||||||
private fun List<String>.getResourceGroup(fileNames: Array<String>) = map { directory ->
|
|
||||||
ResourceGroup(
|
|
||||||
directory, *fileNames
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val launcherIconResourceGroups =
|
private val launcherIconResourceGroups =
|
||||||
mipmapDirectories.getResourceGroup(launcherIconResourceFileNames)
|
mipmapDirectories.getResourceGroup(launcherIconResourceFileNames)
|
||||||
|
|
||||||
|
@ -63,6 +63,12 @@ fun String.startsWithAny(vararg prefixes: String): Boolean {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun List<String>.getResourceGroup(fileNames: Array<String>) = map { directory ->
|
||||||
|
ResourceGroup(
|
||||||
|
directory, *fileNames
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun ResourceContext.copyFile(
|
fun ResourceContext.copyFile(
|
||||||
resourceGroup: List<ResourceGroup>,
|
resourceGroup: List<ResourceGroup>,
|
||||||
path: String,
|
path: String,
|
||||||
@ -98,16 +104,25 @@ fun ResourceContext.copyFile(
|
|||||||
*
|
*
|
||||||
* @param sourceResourceDirectory The source resource directory name.
|
* @param sourceResourceDirectory The source resource directory name.
|
||||||
* @param resources The resources to copy.
|
* @param resources The resources to copy.
|
||||||
|
* @param createDirectoryIfNotExist Whether to create a new directory if it does not exist.
|
||||||
*/
|
*/
|
||||||
fun ResourceContext.copyResources(
|
fun ResourceContext.copyResources(
|
||||||
sourceResourceDirectory: String,
|
sourceResourceDirectory: String,
|
||||||
vararg resources: ResourceGroup,
|
vararg resources: ResourceGroup,
|
||||||
|
createDirectoryIfNotExist: Boolean = false,
|
||||||
) {
|
) {
|
||||||
val targetResourceDirectory = this["res"]
|
val targetResourceDirectory = this["res"]
|
||||||
|
|
||||||
for (resourceGroup in resources) {
|
for (resourceGroup in resources) {
|
||||||
resourceGroup.resources.forEach { resource ->
|
resourceGroup.resources.forEach { resource ->
|
||||||
val resourceFile = "${resourceGroup.resourceDirectoryName}/$resource"
|
val resourceDirectoryName = resourceGroup.resourceDirectoryName
|
||||||
|
|
||||||
|
if (createDirectoryIfNotExist) {
|
||||||
|
val targetDirectory = targetResourceDirectory.resolve(resourceDirectoryName)
|
||||||
|
if (!targetDirectory.isDirectory) Files.createDirectories(targetDirectory.toPath())
|
||||||
|
}
|
||||||
|
|
||||||
|
val resourceFile = "$resourceDirectoryName/$resource"
|
||||||
|
|
||||||
inputStreamFromBundledResource(
|
inputStreamFromBundledResource(
|
||||||
sourceResourceDirectory,
|
sourceResourceDirectory,
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 3.5 KiB |