diff --git a/src/main/kotlin/app/revanced/patches/music/layout/branding/icon/CustomBrandingIconPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/branding/icon/CustomBrandingIconPatch.kt
index 71c8a8458..e7c39f05c 100644
--- a/src/main/kotlin/app/revanced/patches/music/layout/branding/icon/CustomBrandingIconPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/layout/branding/icon/CustomBrandingIconPatch.kt
@@ -9,6 +9,7 @@ import app.revanced.util.ResourceGroup
import app.revanced.util.Utils.trimIndentMultiline
import app.revanced.util.copyResources
import app.revanced.util.patch.BaseResourcePatch
+import app.revanced.util.underBarOrThrow
import java.io.File
import java.nio.file.Files
@@ -18,13 +19,13 @@ object CustomBrandingIconPatch : BaseResourcePatch(
description = "Changes the YouTube Music app icon to the icon specified in options.json.",
compatiblePackages = COMPATIBLE_PACKAGE
) {
- private const val DEFAULT_ICON_KEY = "Revancify Blue"
+ private const val DEFAULT_ICON = "revancify_blue"
private val availableIcon = mapOf(
"AFN Blue" to "afn_blue",
"AFN Red" to "afn_red",
"MMT" to "mmt",
- DEFAULT_ICON_KEY to "revancify_blue",
+ "Revancify Blue" to DEFAULT_ICON,
"Revancify Red" to "revancify_red",
"YouTube Music" to "youtube_music"
)
@@ -93,9 +94,9 @@ object CustomBrandingIconPatch : BaseResourcePatch(
)
}
- private val AppIcon by stringPatchOption(
+ private val AppIcon = stringPatchOption(
key = "AppIcon",
- default = DEFAULT_ICON_KEY,
+ default = DEFAULT_ICON,
values = availableIcon,
title = "App icon",
description = """
@@ -129,70 +130,72 @@ object CustomBrandingIconPatch : BaseResourcePatch(
)
override fun execute(context: ResourceContext) {
- AppIcon?.let { appIcon ->
- val appIconValue = appIcon.lowercase().replace(" ", "_")
- val appIconResourcePath = "music/branding/$appIconValue"
- // Check if a custom path is used in the patch options.
- if (!availableIcon.containsValue(appIconValue)) {
- launcherIconResourceGroups.let { resourceGroups ->
- try {
- val path = File(appIcon)
- val resourceDirectory = context["res"]
+ // Check patch options first.
+ val appIcon = AppIcon
+ .underBarOrThrow()
- resourceGroups.forEach { group ->
- val fromDirectory = path.resolve(group.resourceDirectoryName)
- val toDirectory = resourceDirectory.resolve(group.resourceDirectoryName)
+ val appIconResourcePath = "music/branding/$appIcon"
- group.resources.forEach { iconFileName ->
- Files.write(
- toDirectory.resolve(iconFileName).toPath(),
- fromDirectory.resolve(iconFileName).readBytes()
- )
- }
+ // Check if a custom path is used in the patch options.
+ if (!availableIcon.containsValue(appIcon)) {
+ launcherIconResourceGroups.let { resourceGroups ->
+ try {
+ val path = File(appIcon)
+ val resourceDirectory = context["res"]
+
+ resourceGroups.forEach { group ->
+ val fromDirectory = path.resolve(group.resourceDirectoryName)
+ val toDirectory = resourceDirectory.resolve(group.resourceDirectoryName)
+
+ group.resources.forEach { iconFileName ->
+ Files.write(
+ toDirectory.resolve(iconFileName).toPath(),
+ fromDirectory.resolve(iconFileName).readBytes()
+ )
}
- } catch (_: Exception) {
- // Exception is thrown if an invalid path is used in the patch option.
- throw PatchException("Invalid app icon path: $appIcon")
}
+ } catch (_: Exception) {
+ // Exception is thrown if an invalid path is used in the patch option.
+ throw PatchException("Invalid app icon path: $appIcon")
}
- } else {
+ }
+ } else {
- // Change launcher icon.
- launcherIconResourceGroups.let { resourceGroups ->
+ // Change launcher icon.
+ launcherIconResourceGroups.let { resourceGroups ->
+ resourceGroups.forEach {
+ context.copyResources("$appIconResourcePath/launcher", it)
+ }
+ }
+
+ // Change monochrome icon.
+ arrayOf(
+ ResourceGroup(
+ "drawable",
+ "ic_app_icons_themed_youtube_music.xml"
+ )
+ ).forEach { resourceGroup ->
+ context.copyResources("$appIconResourcePath/monochrome", resourceGroup)
+ }
+
+ // Change header.
+ if (ChangeHeader == true) {
+ headerIconResourceGroups.let { resourceGroups ->
resourceGroups.forEach {
- context.copyResources("$appIconResourcePath/launcher", it)
- }
- }
-
- // Change monochrome icon.
- arrayOf(
- ResourceGroup(
- "drawable",
- "ic_app_icons_themed_youtube_music.xml"
- )
- ).forEach { resourceGroup ->
- context.copyResources("$appIconResourcePath/monochrome", resourceGroup)
- }
-
- // Change header.
- if (ChangeHeader == true) {
- headerIconResourceGroups.let { resourceGroups ->
- resourceGroups.forEach {
- context.copyResources("$appIconResourcePath/header", it)
- }
- }
- }
-
- // Change splash icon.
- if (ChangeSplashIcon == true) {
- splashIconResourceGroups.let { resourceGroups ->
- resourceGroups.forEach {
- context.copyResources("$appIconResourcePath/splash", it)
- }
+ context.copyResources("$appIconResourcePath/header", it)
}
}
}
- } ?: throw PatchException("Invalid app icon path.")
+
+ // Change splash icon.
+ if (ChangeSplashIcon == true) {
+ splashIconResourceGroups.let { resourceGroups ->
+ resourceGroups.forEach {
+ context.copyResources("$appIconResourcePath/splash", it)
+ }
+ }
+ }
+ }
}
}
diff --git a/src/main/kotlin/app/revanced/patches/music/layout/branding/name/CustomBrandingNamePatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/branding/name/CustomBrandingNamePatch.kt
index 021f8c65e..9d161a74d 100644
--- a/src/main/kotlin/app/revanced/patches/music/layout/branding/name/CustomBrandingNamePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/layout/branding/name/CustomBrandingNamePatch.kt
@@ -1,11 +1,11 @@
package app.revanced.patches.music.layout.branding.name
import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.shared.elements.StringsElementsUtils.removeStringsElements
import app.revanced.util.patch.BaseResourcePatch
+import app.revanced.util.valueOrThrow
@Suppress("DEPRECATION", "unused")
object CustomBrandingNamePatch : BaseResourcePatch(
@@ -16,7 +16,7 @@ object CustomBrandingNamePatch : BaseResourcePatch(
private const val APP_NAME_NOTIFICATION = "ReVanced Extended Music"
private const val APP_NAME_LAUNCHER = "RVX Music"
- private val AppNameNotification by stringPatchOption(
+ private val AppNameNotification = stringPatchOption(
key = "AppNameNotification",
default = APP_NAME_LAUNCHER,
values = mapOf(
@@ -30,7 +30,7 @@ object CustomBrandingNamePatch : BaseResourcePatch(
required = true
)
- private val AppNameLauncher by stringPatchOption(
+ private val AppNameLauncher = stringPatchOption(
key = "AppNameLauncher",
default = APP_NAME_LAUNCHER,
values = mapOf(
@@ -46,29 +46,31 @@ object CustomBrandingNamePatch : BaseResourcePatch(
override fun execute(context: ResourceContext) {
+ // Check patch options first.
+ val notificationName = AppNameNotification
+ .valueOrThrow()
+ val launcherName = AppNameLauncher
+ .valueOrThrow()
+
context.removeStringsElements(
arrayOf("app_launcher_name", "app_name")
)
- AppNameNotification?.let { notificationName ->
- AppNameLauncher?.let { launcherName ->
- context.xmlEditor["res/values/strings.xml"].use { editor ->
- val document = editor.file
+ context.xmlEditor["res/values/strings.xml"].use { editor ->
+ val document = editor.file
- mapOf(
- "app_name" to notificationName,
- "app_launcher_name" to launcherName
- ).forEach { (k, v) ->
- val stringElement = document.createElement("string")
+ mapOf(
+ "app_name" to notificationName,
+ "app_launcher_name" to launcherName
+ ).forEach { (k, v) ->
+ val stringElement = document.createElement("string")
- stringElement.setAttribute("name", k)
- stringElement.textContent = v
+ stringElement.setAttribute("name", k)
+ stringElement.textContent = v
- document.getElementsByTagName("resources").item(0)
- .appendChild(stringElement)
- }
- }
- } ?: throw PatchException("Invalid launcher name.")
- } ?: throw PatchException("Invalid notification name.")
+ document.getElementsByTagName("resources").item(0)
+ .appendChild(stringElement)
+ }
+ }
}
}
diff --git a/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsPatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsPatch.kt
index 558547e6c..f00dc88f6 100644
--- a/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsPatch.kt
@@ -12,6 +12,7 @@ import app.revanced.patches.music.utils.settings.ResourceUtils.sortPreferenceCat
import app.revanced.patches.shared.elements.StringsElementsUtils.removeStringsElements
import app.revanced.util.copyXmlNode
import app.revanced.util.patch.BaseResourcePatch
+import app.revanced.util.valueOrThrow
import org.w3c.dom.Element
import java.io.Closeable
import java.util.concurrent.Executors
@@ -30,7 +31,7 @@ object SettingsPatch : BaseResourcePatch(
), Closeable {
private const val DEFAULT_NAME = "ReVanced Extended"
- private val RVXSettingsMenuName by stringPatchOption(
+ private val RVXSettingsMenuName = stringPatchOption(
key = "RVXSettingsMenuName",
default = DEFAULT_NAME,
title = "RVX settings menu name",
@@ -38,12 +39,20 @@ object SettingsPatch : BaseResourcePatch(
required = true
)
+ private lateinit var customName: String
+
lateinit var contexts: ResourceContext
internal var upward0636 = false
internal var upward0642 = false
override fun execute(context: ResourceContext) {
+ /**
+ * check patch options
+ */
+ customName = RVXSettingsMenuName
+ .valueOrThrow()
+
/**
* set resource context
*/
@@ -193,35 +202,38 @@ object SettingsPatch : BaseResourcePatch(
* change RVX settings menu name
* since it must be invoked after the Translations patch, it must be the last in the order.
*/
- RVXSettingsMenuName?.let { customName ->
- if (customName != DEFAULT_NAME) {
- contexts.removeStringsElements(
- arrayOf("revanced_extended_settings_title")
- )
- contexts.xmlEditor["res/values/strings.xml"].use { editor ->
- val document = editor.file
+ if (customName != DEFAULT_NAME) {
+ contexts.removeStringsElements(
+ arrayOf("revanced_extended_settings_title")
+ )
+ contexts.xmlEditor["res/values/strings.xml"].use { editor ->
+ val document = editor.file
- mapOf(
- "revanced_extended_settings_title" to customName
- ).forEach { (k, v) ->
- val stringElement = document.createElement("string")
+ mapOf(
+ "revanced_extended_settings_title" to customName
+ ).forEach { (k, v) ->
+ val stringElement = document.createElement("string")
- stringElement.setAttribute("name", k)
- stringElement.textContent = v
+ stringElement.setAttribute("name", k)
+ stringElement.textContent = v
- document.getElementsByTagName("resources").item(0)
- .appendChild(stringElement)
- }
+ document.getElementsByTagName("resources").item(0)
+ .appendChild(stringElement)
}
}
- } ?: println("WARNING: Invalid RVX settings menu name. RVX settings menu name does not change.")
-
+ }
+ /**
+ * add import export settings
+ */
addPreferenceWithIntent(
CategoryType.MISC,
"revanced_extended_settings_import_export"
)
+ /**
+ * sort preference
+ */
CategoryType.entries.sorted().forEach {
contexts.sortPreferenceCategory(it.value)
}
diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/branding/name/CustomBrandingNamePatch.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/branding/name/CustomBrandingNamePatch.kt
index 95c609ca5..29968ff2c 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/layout/branding/name/CustomBrandingNamePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/layout/branding/name/CustomBrandingNamePatch.kt
@@ -4,6 +4,7 @@ import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
import app.revanced.patches.reddit.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.util.patch.BaseResourcePatch
+import app.revanced.util.valueOrThrow
import java.io.FileWriter
import java.nio.file.Files
@@ -17,7 +18,7 @@ object CustomBrandingNamePatch : BaseResourcePatch(
private const val ORIGINAL_APP_NAME = "Reddit"
private const val APP_NAME = "RVX Reddit"
- private val AppName by stringPatchOption(
+ private val AppName = stringPatchOption(
key = "AppName",
default = ORIGINAL_APP_NAME,
values = mapOf(
@@ -30,44 +31,41 @@ object CustomBrandingNamePatch : BaseResourcePatch(
)
override fun execute(context: ResourceContext) {
- val appName = if (AppName != null) {
- AppName!!
- } else {
- println("WARNING: Invalid app name. Does not apply patches.")
- ORIGINAL_APP_NAME
+ val appName = AppName
+ .valueOrThrow()
+
+ if (appName == ORIGINAL_APP_NAME) {
+ println("INFO: App name will remain unchanged as it matches the original.")
+ return
}
- if (appName != ORIGINAL_APP_NAME) {
- val resDirectory = context["res"]
+ val resDirectory = context["res"]
- val valuesV24Directory = resDirectory.resolve("values-v24")
- if (!valuesV24Directory.isDirectory)
- Files.createDirectories(valuesV24Directory.toPath())
+ val valuesV24Directory = resDirectory.resolve("values-v24")
+ if (!valuesV24Directory.isDirectory)
+ Files.createDirectories(valuesV24Directory.toPath())
- val stringsXml = valuesV24Directory.resolve("strings.xml")
+ val stringsXml = valuesV24Directory.resolve("strings.xml")
- if (!stringsXml.exists()) {
- FileWriter(stringsXml).use {
- it.write("")
- }
+ if (!stringsXml.exists()) {
+ FileWriter(stringsXml).use {
+ it.write("")
}
+ }
- context.xmlEditor["res/values-v24/strings.xml"].use { editor ->
- val document = editor.file
+ context.xmlEditor["res/values-v24/strings.xml"].use { editor ->
+ val document = editor.file
- mapOf(
- "app_name" to appName
- ).forEach { (k, v) ->
- val stringElement = document.createElement("string")
+ mapOf(
+ "app_name" to appName
+ ).forEach { (k, v) ->
+ val stringElement = document.createElement("string")
- stringElement.setAttribute("name", k)
- stringElement.textContent = v
+ stringElement.setAttribute("name", k)
+ stringElement.textContent = v
- document.getElementsByTagName("resources").item(0).appendChild(stringElement)
- }
+ document.getElementsByTagName("resources").item(0).appendChild(stringElement)
}
- } else {
- println("INFO: App name will remain unchanged as it matches the original.")
}
}
}
diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/branding/packagename/ChangePackageNamePatch.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/branding/packagename/ChangePackageNamePatch.kt
index f33af78a1..5bfd6d575 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/layout/branding/packagename/ChangePackageNamePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/layout/branding/packagename/ChangePackageNamePatch.kt
@@ -4,6 +4,7 @@ import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
import app.revanced.patches.reddit.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.util.patch.BaseResourcePatch
+import app.revanced.util.valueOrThrow
import org.w3c.dom.Element
import java.io.Closeable
@@ -21,7 +22,7 @@ object ChangePackageNamePatch : BaseResourcePatch(
private lateinit var context: ResourceContext
private var redditPackageName = PACKAGE_NAME_REDDIT
- private val PackageNameReddit by stringPatchOption(
+ private val PackageNameReddit = stringPatchOption(
key = "PackageNameReddit",
default = PACKAGE_NAME_REDDIT,
values = mapOf(
@@ -37,26 +38,25 @@ object ChangePackageNamePatch : BaseResourcePatch(
override fun execute(context: ResourceContext) {
this.context = context
- if (PackageNameReddit != null) {
- redditPackageName = PackageNameReddit!!
- } else {
- println("WARNING: Invalid package name. Does not apply patches.")
+ redditPackageName = PackageNameReddit
+ .valueOrThrow()
+
+ if (redditPackageName == PACKAGE_NAME_REDDIT) {
+ println("INFO: Package name will remain unchanged as it matches the original.")
+ return
}
- if (redditPackageName != PACKAGE_NAME_REDDIT) {
- // Ensure device runs Android.
- try {
- // RVX Manager
- // ====
- // For some reason, in Android AAPT2, a compilation error occurs when changing the [strings.xml] of the Reddit
- // This only affects RVX Manager, and has not yet found a valid workaround
- Class.forName("android.os.Environment")
- } catch (_: ClassNotFoundException) {
- // CLI
- context.replacePackageName(redditPackageName)
- }
- } else {
- println("INFO: Package name will remain unchanged as it matches the original.")
+ // Ensure device runs Android.
+ try {
+ // RVX Manager
+ // ====
+ // For some reason, in Android AAPT2, a compilation error occurs when changing the [strings.xml] of the Reddit
+ // This only affects RVX Manager, and has not yet found a valid workaround
+ Class.forName("android.os.Environment")
+ return
+ } catch (_: ClassNotFoundException) {
+ // CLI
+ context.replacePackageName(redditPackageName)
}
}
diff --git a/src/main/kotlin/app/revanced/patches/reddit/utils/settings/SettingsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/utils/settings/SettingsPatch.kt
index f4f202c73..4edff9682 100644
--- a/src/main/kotlin/app/revanced/patches/reddit/utils/settings/SettingsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/reddit/utils/settings/SettingsPatch.kt
@@ -6,6 +6,7 @@ import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatc
import app.revanced.patches.reddit.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.reddit.utils.integrations.IntegrationsPatch
import app.revanced.util.patch.BaseResourcePatch
+import app.revanced.util.valueOrThrow
import kotlin.io.path.exists
@Suppress("DEPRECATION")
@@ -21,7 +22,7 @@ object SettingsPatch : BaseResourcePatch(
) {
private const val DEFAULT_NAME = "ReVanced Extended"
- private val RVXSettingsMenuName by stringPatchOption(
+ private val RVXSettingsMenuName = stringPatchOption(
key = "RVXSettingsMenuName",
default = DEFAULT_NAME,
title = "RVX settings menu name",
@@ -32,11 +33,8 @@ object SettingsPatch : BaseResourcePatch(
/**
* Replace settings icon and label
*/
-
- var settingsLabel = DEFAULT_NAME
-
- if (!RVXSettingsMenuName.isNullOrEmpty())
- settingsLabel = RVXSettingsMenuName!!
+ val settingsLabel = RVXSettingsMenuName
+ .valueOrThrow()
arrayOf("preferences", "preferences_logged_in").forEach { targetXML ->
val resDirectory = context["res"]
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/actionbuttons/ShortsActionButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/actionbuttons/ShortsActionButtonsPatch.kt
index 9f3272f70..dad721bda 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/actionbuttons/ShortsActionButtonsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/actionbuttons/ShortsActionButtonsPatch.kt
@@ -1,12 +1,12 @@
package app.revanced.patches.youtube.layout.actionbuttons
import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.youtube.utils.settings.SettingsPatch
import app.revanced.util.ResourceGroup
import app.revanced.util.copyResources
+import app.revanced.util.lowerCaseOrThrow
import app.revanced.util.patch.BaseResourcePatch
@Suppress("unused")
@@ -16,15 +16,15 @@ object ShortsActionButtonsPatch : BaseResourcePatch(
dependencies = setOf(SettingsPatch::class),
compatiblePackages = COMPATIBLE_PACKAGE
) {
- private const val DEFAULT_ICON_KEY = "Round"
+ private const val DEFAULT_ICON = "round"
- private val IconType by stringPatchOption(
+ private val IconType = stringPatchOption(
key = "IconType",
- default = DEFAULT_ICON_KEY,
+ default = DEFAULT_ICON,
values = mapOf(
"Outline" to "outline",
"OutlineCircle" to "outlinecircle",
- DEFAULT_ICON_KEY to "round"
+ "Round" to DEFAULT_ICON
),
title = "Shorts icon style ",
description = "The style of the icons for the action buttons in the Shorts player.",
@@ -32,53 +32,54 @@ object ShortsActionButtonsPatch : BaseResourcePatch(
)
override fun execute(context: ResourceContext) {
- IconType?.let { iconType ->
- val selectedIconType = iconType.lowercase()
- arrayOf(
- "xxxhdpi",
- "xxhdpi",
- "xhdpi",
- "hdpi",
- "mdpi"
- ).forEach { dpi ->
- context.copyResources(
- "youtube/shorts/actionbuttons/$selectedIconType",
- ResourceGroup(
- "drawable-$dpi",
- "ic_remix_filled_white_shadowed.webp",
- "ic_right_comment_shadowed.webp",
- "ic_right_dislike_off_shadowed.webp",
- "ic_right_dislike_on_shadowed.webp",
- "ic_right_like_off_shadowed.webp",
- "ic_right_like_on_shadowed.webp",
- "ic_right_share_shadowed.webp",
+ // Check patch options first.
+ val iconType = IconType
+ .lowerCaseOrThrow()
- // for older versions only
- "ic_remix_filled_white_24.webp",
- "ic_right_dislike_on_32c.webp",
- "ic_right_like_on_32c.webp"
- ),
- ResourceGroup(
- "drawable",
- "ic_right_comment_32c.xml",
- "ic_right_dislike_off_32c.xml",
- "ic_right_like_off_32c.xml",
- "ic_right_share_32c.xml"
- )
+ arrayOf(
+ "xxxhdpi",
+ "xxhdpi",
+ "xhdpi",
+ "hdpi",
+ "mdpi"
+ ).forEach { dpi ->
+ context.copyResources(
+ "youtube/shorts/actionbuttons/$iconType",
+ ResourceGroup(
+ "drawable-$dpi",
+ "ic_remix_filled_white_shadowed.webp",
+ "ic_right_comment_shadowed.webp",
+ "ic_right_dislike_off_shadowed.webp",
+ "ic_right_dislike_on_shadowed.webp",
+ "ic_right_like_off_shadowed.webp",
+ "ic_right_like_on_shadowed.webp",
+ "ic_right_share_shadowed.webp",
+
+ // for older versions only
+ "ic_remix_filled_white_24.webp",
+ "ic_right_dislike_on_32c.webp",
+ "ic_right_like_on_32c.webp"
+ ),
+ ResourceGroup(
+ "drawable",
+ "ic_right_comment_32c.xml",
+ "ic_right_dislike_off_32c.xml",
+ "ic_right_like_off_32c.xml",
+ "ic_right_share_32c.xml"
)
+ )
+ }
- context.copyResources(
- "youtube/shorts/actionbuttons/shared",
- ResourceGroup(
- "drawable",
- "reel_camera_bold_24dp.xml",
- "reel_more_vertical_bold_24dp.xml",
- "reel_search_bold_24dp.xml"
- )
- )
- }
- } ?: throw PatchException("Invalid icon type.")
+ context.copyResources(
+ "youtube/shorts/actionbuttons/shared",
+ ResourceGroup(
+ "drawable",
+ "reel_camera_bold_24dp.xml",
+ "reel_more_vertical_bold_24dp.xml",
+ "reel_search_bold_24dp.xml"
+ )
+ )
SettingsPatch.updatePatchStatus(this)
}
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 ab6c75943..73fababf4 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
@@ -1,7 +1,6 @@
package app.revanced.patches.youtube.layout.branding.icon
import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.booleanPatchOption
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
@@ -9,26 +8,26 @@ import app.revanced.patches.youtube.utils.settings.ResourceUtils.updatePatchStat
import app.revanced.patches.youtube.utils.settings.SettingsPatch
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.copyXmlNode
import app.revanced.util.patch.BaseResourcePatch
-import java.io.File
-import java.nio.file.Files
+import app.revanced.util.underBarOrThrow
-@Suppress("DEPRECATION", "unused")
+@Suppress("unused")
object CustomBrandingIconPatch : BaseResourcePatch(
name = "Custom branding icon YouTube",
description = "Changes the YouTube app icon to the icon specified in options.json.",
dependencies = setOf(SettingsPatch::class),
compatiblePackages = COMPATIBLE_PACKAGE,
) {
- private const val DEFAULT_ICON_KEY = "Revancify Blue"
+ private const val DEFAULT_ICON = "revancify_blue"
private val availableIcon = mapOf(
"AFN Blue" to "afn_blue",
"AFN Red" to "afn_red",
"MMT" to "mmt",
- DEFAULT_ICON_KEY to "revancify_blue",
+ "Revancify Blue" to DEFAULT_ICON,
"Revancify Red" to "revancify_red",
"YouTube" to "youtube"
)
@@ -109,9 +108,9 @@ object CustomBrandingIconPatch : BaseResourcePatch(
// region patch option
- val AppIcon by stringPatchOption(
+ val AppIcon = stringPatchOption(
key = "AppIcon",
- default = DEFAULT_ICON_KEY,
+ default = DEFAULT_ICON,
values = availableIcon,
title = "App icon",
description = """
@@ -176,112 +175,84 @@ object CustomBrandingIconPatch : BaseResourcePatch(
// endregion
override fun execute(context: ResourceContext) {
- AppIcon?.let { appIcon ->
- val appIconValue = appIcon.lowercase().replace(" ", "_")
- val appIconResourcePath = "youtube/branding/$appIconValue"
- val stockResourcePath = "youtube/branding/stock"
- // Check if a custom path is used in the patch options.
- if (!availableIcon.containsValue(appIconValue)) {
- val copiedFiles = context.copyFile(
- launcherIconResourceGroups,
- appIcon,
- "WARNING: Invalid app icon path: $appIcon. Does not apply patches."
+ // Check patch options first.
+ val appIcon = AppIcon
+ .underBarOrThrow()
+
+ val appIconResourcePath = "youtube/branding/$appIcon"
+ val stockResourcePath = "youtube/branding/stock"
+
+ // Check if a custom path is used in the patch options.
+ if (!availableIcon.containsValue(appIcon)) {
+ val copiedFiles = context.copyFile(
+ launcherIconResourceGroups,
+ appIcon,
+ "WARNING: Invalid app icon path: $appIcon. Does not apply patches."
+ )
+ if (copiedFiles)
+ context.updatePatchStatusIcon("custom")
+ } else {
+ // Change launcher icon.
+ launcherIconResourceGroups.let { resourceGroups ->
+ resourceGroups.forEach {
+ context.copyResources("$appIconResourcePath/launcher", it)
+ }
+ }
+
+ // Change monochrome icon.
+ arrayOf(
+ ResourceGroup(
+ "drawable",
+ "adaptive_monochrome_ic_youtube_launcher.xml"
)
- if (copiedFiles)
- context.updatePatchStatusIcon("custom")
- } else {
- // Change launcher icon.
- launcherIconResourceGroups.let { resourceGroups ->
- resourceGroups.forEach {
- context.copyResources("$appIconResourcePath/launcher", it)
+ ).forEach { resourceGroup ->
+ 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."
+ )
}
- }
-
- // Change monochrome icon.
- arrayOf(
- ResourceGroup(
- "drawable",
- "adaptive_monochrome_ic_youtube_launcher.xml"
- )
- ).forEach { resourceGroup ->
- 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)
- }
+ if (!copiedFiles) {
+ headerIconResourceGroups.let { resourceGroups ->
+ resourceGroups.forEach {
+ context.copyResources("$appIconResourcePath/header", it)
}
}
}
}
-
- // Change splash icon.
- if (ChangeSplashIcon == true) {
- splashIconResourceGroups.let { resourceGroups ->
- resourceGroups.forEach {
- context.copyResources("$appIconResourcePath/splash", it)
- }
- }
- }
-
- // Change splash screen.
- if (RestoreOldSplashAnimation == true) {
- oldSplashAnimationResourceGroups.let { resourceGroups ->
- resourceGroups.forEach {
- context.copyResources("$stockResourcePath/splash", it)
- context.copyResources("$appIconResourcePath/splash", it)
- }
- }
-
- context.copyXmlNode("$stockResourcePath/splash", "values-v31/styles.xml", "resources")
- }
-
- context.updatePatchStatusIcon(appIconValue)
}
- } ?: throw PatchException("Invalid app icon path.")
- }
- private fun ResourceContext.copyFile(
- iconResourceGroup: List,
- path: String,
- message: String
- ): Boolean {
- iconResourceGroup.let { resourceGroups ->
- try {
- val filePath = File(path)
- val resourceDirectory = this["res"]
+ // Change splash icon.
+ if (ChangeSplashIcon == true) {
+ splashIconResourceGroups.let { resourceGroups ->
+ resourceGroups.forEach {
+ context.copyResources("$appIconResourcePath/splash", it)
+ }
+ }
+ }
- resourceGroups.forEach { group ->
- val fromDirectory = filePath.resolve(group.resourceDirectoryName)
- val toDirectory = resourceDirectory.resolve(group.resourceDirectoryName)
-
- group.resources.forEach { iconFileName ->
- Files.write(
- toDirectory.resolve(iconFileName).toPath(),
- fromDirectory.resolve(iconFileName).readBytes()
- )
+ // Change splash screen.
+ if (RestoreOldSplashAnimation == true) {
+ oldSplashAnimationResourceGroups.let { resourceGroups ->
+ resourceGroups.forEach {
+ context.copyResources("$stockResourcePath/splash", it)
+ context.copyResources("$appIconResourcePath/splash", it)
}
}
- return true
- } catch (_: Exception) {
- println(message)
+ context.copyXmlNode("$stockResourcePath/splash", "values-v31/styles.xml", "resources")
}
+
+ context.updatePatchStatusIcon(appIcon)
}
- return false
}
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/name/CustomBrandingNamePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/name/CustomBrandingNamePatch.kt
index 01e0e79c2..c351e9160 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/name/CustomBrandingNamePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/name/CustomBrandingNamePatch.kt
@@ -1,13 +1,13 @@
package app.revanced.patches.youtube.layout.branding.name
import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
import app.revanced.patches.shared.elements.StringsElementsUtils.removeStringsElements
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.youtube.utils.settings.ResourceUtils.updatePatchStatusLabel
import app.revanced.patches.youtube.utils.settings.SettingsPatch
import app.revanced.util.patch.BaseResourcePatch
+import app.revanced.util.valueOrThrow
@Suppress("DEPRECATION", "unused")
object CustomBrandingNamePatch : BaseResourcePatch(
@@ -18,7 +18,7 @@ object CustomBrandingNamePatch : BaseResourcePatch(
) {
private const val APP_NAME = "RVX"
- private val AppName by stringPatchOption(
+ private val AppName = stringPatchOption(
key = "AppName",
default = APP_NAME,
values = mapOf(
@@ -33,26 +33,29 @@ object CustomBrandingNamePatch : BaseResourcePatch(
)
override fun execute(context: ResourceContext) {
+
+ // Check patch options first.
+ val appName = AppName
+ .valueOrThrow()
+
context.removeStringsElements(
arrayOf("application_name")
)
- AppName?.let {
- context.xmlEditor["res/values/strings.xml"].use { editor ->
- val document = editor.file
+ context.xmlEditor["res/values/strings.xml"].use { editor ->
+ val document = editor.file
- mapOf(
- "application_name" to it
- ).forEach { (k, v) ->
- val stringElement = document.createElement("string")
+ mapOf(
+ "application_name" to appName
+ ).forEach { (k, v) ->
+ val stringElement = document.createElement("string")
- stringElement.setAttribute("name", k)
- stringElement.textContent = v
+ stringElement.setAttribute("name", k)
+ stringElement.textContent = v
- document.getElementsByTagName("resources").item(0).appendChild(stringElement)
- }
+ document.getElementsByTagName("resources").item(0).appendChild(stringElement)
}
- context.updatePatchStatusLabel(it)
- } ?: throw PatchException("Invalid app name.")
+ }
+ context.updatePatchStatusLabel(appName)
}
}
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/doubletaplength/DoubleTapLengthPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/doubletaplength/DoubleTapLengthPatch.kt
index e3e2ced6a..170a03a33 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/doubletaplength/DoubleTapLengthPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/doubletaplength/DoubleTapLengthPatch.kt
@@ -27,6 +27,15 @@ object DoubleTapLengthPatch : BaseResourcePatch(
)
override fun execute(context: ResourceContext) {
+
+ // Check patch options first.
+ val splits = DoubleTapLengthArrays
+ ?.replace(" ", "")
+ ?.split(",")
+ ?: throw PatchException("Invalid double-tap length array.")
+ if (splits.isEmpty()) throw IllegalArgumentException("Invalid double-tap length elements")
+ val lengthElements = splits.map { it }
+
val arrayPath = "res/values-v21/arrays.xml"
val entriesName = "double_tap_length_entries"
val entryValueName = "double_tap_length_values"
@@ -46,12 +55,6 @@ object DoubleTapLengthPatch : BaseResourcePatch(
)
)
- val length = DoubleTapLengthArrays
- ?: throw PatchException("Invalid double-tap length array.")
-
- val splits = length.replace(" ", "").split(",")
- if (splits.isEmpty()) throw IllegalArgumentException("Invalid double-tap length elements")
- val lengthElements = splits.map { it }
for (index in 0 until splits.count()) {
context.addEntryValues(arrayPath, lengthElements[index], entryValueName)
context.addEntryValues(arrayPath, lengthElements[index], entriesName)
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt
index 32f74d47e..f6c0d58a4 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt
@@ -1,13 +1,13 @@
package app.revanced.patches.youtube.layout.theme
import app.revanced.patcher.data.ResourceContext
-import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
import app.revanced.patches.youtube.layout.theme.BaseThemePatch.isMonetPatchIncluded
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.youtube.utils.settings.ResourceUtils.updatePatchStatusTheme
import app.revanced.patches.youtube.utils.settings.SettingsPatch
import app.revanced.util.patch.BaseResourcePatch
+import app.revanced.util.valueOrThrow
import org.w3c.dom.Element
@Suppress("DEPRECATION", "unused")
@@ -38,7 +38,7 @@ object ThemePatch : BaseResourcePatch(
private const val LIGHT_ORANGE_COLOR = "#FFFFE6CC"
private const val LIGHT_RED_COLOR = "#FFFFD6D6"
- private val DarkThemeBackgroundColor by stringPatchOption(
+ private val DarkThemeBackgroundColor = stringPatchOption(
key = "DarkThemeBackgroundColor",
default = AMOLED_BLACK_COLOR,
values = mapOf(
@@ -56,7 +56,7 @@ object ThemePatch : BaseResourcePatch(
required = true
)
- private val LightThemeBackgroundColor by stringPatchOption(
+ private val LightThemeBackgroundColor = stringPatchOption(
key = "LightThemeBackgroundColor",
default = WHITE_COLOR,
values = mapOf(
@@ -111,11 +111,12 @@ object ThemePatch : BaseResourcePatch(
override fun execute(context: ResourceContext) {
+ // Check patch options first.
val darkThemeColor = DarkThemeBackgroundColor
- ?: throw PatchException("Invalid dark color.")
+ .valueOrThrow()
val lightThemeColor = LightThemeBackgroundColor
- ?: throw PatchException("Invalid light color.")
+ .valueOrThrow()
arrayOf("values", "values-v31").forEach { path ->
context.xmlEditor["res/$path/colors.xml"].use { editor ->
diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/visual/VisualPreferencesIconsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/visual/VisualPreferencesIconsPatch.kt
index 44783280d..40fb7477f 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/layout/visual/VisualPreferencesIconsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/layout/visual/VisualPreferencesIconsPatch.kt
@@ -1,6 +1,7 @@
package app.revanced.patches.youtube.layout.visual
import app.revanced.patcher.data.ResourceContext
+import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
import app.revanced.patches.youtube.layout.branding.icon.CustomBrandingIconPatch
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
@@ -9,6 +10,7 @@ import app.revanced.util.ResourceGroup
import app.revanced.util.copyResources
import app.revanced.util.doRecursively
import app.revanced.util.patch.BaseResourcePatch
+import app.revanced.util.underBarOrThrow
import org.w3c.dom.Element
@Suppress("DEPRECATION", "unused")
@@ -19,14 +21,14 @@ object VisualPreferencesIconsPatch : BaseResourcePatch(
compatiblePackages = COMPATIBLE_PACKAGE,
use = false
) {
- private const val DEFAULT_ICON_KEY = "Extension"
+ private const val DEFAULT_ICON = "extension"
- private val RVXSettingsMenuIcon by stringPatchOption(
+ private val RVXSettingsMenuIcon = stringPatchOption(
key = "RVXSettingsMenuIcon",
- default = DEFAULT_ICON_KEY,
+ default = DEFAULT_ICON,
values = mapOf(
"Custom branding icon" to "custom_branding_icon",
- DEFAULT_ICON_KEY to "extension",
+ "Extension" to DEFAULT_ICON,
"Gear" to "gear",
"ReVanced" to "revanced",
"ReVanced Colored" to "revanced_colored",
@@ -38,6 +40,13 @@ object VisualPreferencesIconsPatch : BaseResourcePatch(
override fun execute(context: ResourceContext) {
+ // Check patch options first.
+ val selectedIconType = RVXSettingsMenuIcon
+ .underBarOrThrow()
+
+ val customBrandingIconType = CustomBrandingIconPatch.AppIcon
+ .underBarOrThrow()
+
// region copy shared resources.
arrayOf(
@@ -57,31 +66,27 @@ object VisualPreferencesIconsPatch : BaseResourcePatch(
// region copy RVX settings menu icon.
- RVXSettingsMenuIcon?.lowercase()?.replace(" ", "_")?.let { selectedIconType ->
- CustomBrandingIconPatch.AppIcon?.lowercase()?.replace(" ", "_")?.let { appIconValue ->
- val fallbackIconPath = "youtube/visual/icons/extension"
- val iconPath = when (selectedIconType) {
- "custom_branding_icon" -> "youtube/branding/$appIconValue/settings"
- else -> "youtube/visual/icons/$selectedIconType"
- }
- val resourceGroup = ResourceGroup(
- "drawable",
- "revanced_extended_settings_key_icon.xml"
- )
+ val fallbackIconPath = "youtube/visual/icons/extension"
+ val iconPath = when (selectedIconType) {
+ "custom_branding_icon" -> "youtube/branding/$customBrandingIconType/settings"
+ else -> "youtube/visual/icons/$selectedIconType"
+ }
+ val resourceGroup = ResourceGroup(
+ "drawable",
+ "revanced_extended_settings_key_icon.xml"
+ )
- try {
- context.copyResources(iconPath, resourceGroup)
- } catch (_: Exception) {
- // Ignore if resource copy fails
+ try {
+ context.copyResources(iconPath, resourceGroup)
+ } catch (_: Exception) {
+ // Ignore if resource copy fails
- // Add a fallback extended icon
- // It's needed if someone provides custom path to icon(s) folder
- // but custom branding icons for Extended setting are predefined,
- // so it won't copy custom branding icon
- // and will raise an error without fallback icon
- context.copyResources(fallbackIconPath, resourceGroup)
- }
- }
+ // Add a fallback extended icon
+ // It's needed if someone provides custom path to icon(s) folder
+ // but custom branding icons for Extended setting are predefined,
+ // so it won't copy custom branding icon
+ // and will raise an error without fallback icon
+ context.copyResources(fallbackIconPath, resourceGroup)
}
// endregion.
diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/overlaybuttons/OverlayButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/overlaybuttons/OverlayButtonsPatch.kt
index 992e87210..618451dcb 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/player/overlaybuttons/OverlayButtonsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/player/overlaybuttons/OverlayButtonsPatch.kt
@@ -12,6 +12,7 @@ import app.revanced.util.ResourceGroup
import app.revanced.util.copyResources
import app.revanced.util.copyXmlNode
import app.revanced.util.doRecursively
+import app.revanced.util.lowerCaseOrThrow
import app.revanced.util.patch.BaseResourcePatch
import org.w3c.dom.Element
@@ -37,27 +38,24 @@ object OverlayButtonsPatch : BaseResourcePatch(
private const val DEFAULT_MARGIN = "0.0dip"
private const val WIDER_MARGIN = "6.0dip"
- private const val DEFAULT_ICON_KEY = "Bold"
-
- // Mapping of icon types to their respective resource folder names
- private val iconTypes = mapOf(
- DEFAULT_ICON_KEY to "bold",
- "Rounded" to "rounded",
- "Thin" to "thin"
- )
+ private const val DEFAULT_ICON = "bold"
// Option to select icon type
- private val IconType by stringPatchOption(
+ private val IconType = stringPatchOption(
key = "IconType",
- default = DEFAULT_ICON_KEY,
- values = iconTypes,
+ default = DEFAULT_ICON,
+ values = mapOf(
+ "Bold" to DEFAULT_ICON,
+ "Rounded" to "rounded",
+ "Thin" to "thin"
+ ),
title = "Icon type",
description = "The icon type.",
required = true
)
// Option to set bottom margin
- private val BottomMargin by stringPatchOption(
+ private val BottomMargin = stringPatchOption(
key = "BottomMargin",
default = DEFAULT_MARGIN,
values = mapOf(
@@ -76,6 +74,13 @@ object OverlayButtonsPatch : BaseResourcePatch(
*/
override fun execute(context: ResourceContext) {
+ // Check patch options first.
+ val iconType = IconType
+ .lowerCaseOrThrow()
+
+ val marginBottom = BottomMargin
+ .lowerCaseOrThrow()
+
// Inject hooks for overlay buttons.
arrayOf(
"AlwaysRepeat;",
@@ -101,41 +106,38 @@ object OverlayButtonsPatch : BaseResourcePatch(
context.copyResources("youtube/overlaybuttons/shared", resourceGroup)
}
- // Apply the selected icon type to the overlay buttons
- IconType?.let { iconType ->
- val iconValue = iconType.lowercase()
- val commonResources = arrayOf(
- "ic_fullscreen_vertical_button.png",
- "ic_vr.png",
- "quantum_ic_fullscreen_exit_grey600_24.png",
- "quantum_ic_fullscreen_exit_white_24.png",
- "quantum_ic_fullscreen_grey600_24.png",
- "quantum_ic_fullscreen_white_24.png",
- "revanced_time_ordered_playlist_icon.png",
- "revanced_copy_icon.png",
- "revanced_copy_icon_with_time.png",
- "revanced_download_icon.png",
- "revanced_speed_icon.png",
- "revanced_whitelist_icon.png",
- "yt_fill_arrow_repeat_white_24.png",
- "yt_outline_arrow_repeat_1_white_24.png",
- "yt_outline_arrow_shuffle_1_white_24.png",
- "yt_outline_screen_full_exit_white_24.png",
- "yt_outline_screen_full_white_24.png"
+ // Apply the selected icon type to the overlay buttons.
+ val commonResources = arrayOf(
+ "ic_fullscreen_vertical_button.png",
+ "ic_vr.png",
+ "quantum_ic_fullscreen_exit_grey600_24.png",
+ "quantum_ic_fullscreen_exit_white_24.png",
+ "quantum_ic_fullscreen_grey600_24.png",
+ "quantum_ic_fullscreen_white_24.png",
+ "revanced_time_ordered_playlist_icon.png",
+ "revanced_copy_icon.png",
+ "revanced_copy_icon_with_time.png",
+ "revanced_download_icon.png",
+ "revanced_speed_icon.png",
+ "revanced_whitelist_icon.png",
+ "yt_fill_arrow_repeat_white_24.png",
+ "yt_outline_arrow_repeat_1_white_24.png",
+ "yt_outline_arrow_shuffle_1_white_24.png",
+ "yt_outline_screen_full_exit_white_24.png",
+ "yt_outline_screen_full_white_24.png"
+ )
+ val specificResources = if (iconType == "thin") {
+ arrayOf("yt_outline_screen_vertical_vd_theme_24.xml")
+ } else {
+ arrayOf("yt_outline_screen_vertical_vd_theme_24.png")
+ }
+ val resources = commonResources + specificResources
+ resources.forEach { resource ->
+ val folderName = if (resource.endsWith(".xml")) "drawable" else "drawable-xxhdpi"
+ context.copyResources(
+ "youtube/overlaybuttons/$iconType",
+ ResourceGroup(folderName, resource)
)
- val specificResources = if (iconValue == "thin") {
- arrayOf("yt_outline_screen_vertical_vd_theme_24.xml")
- } else {
- arrayOf("yt_outline_screen_vertical_vd_theme_24.png")
- }
- val resources = commonResources + specificResources
- resources.forEach { resource ->
- val folderName = if (resource.endsWith(".xml")) "drawable" else "drawable-xxhdpi"
- context.copyResources(
- "youtube/overlaybuttons/$iconValue",
- ResourceGroup(folderName, resource)
- )
- }
}
// Merge XML nodes from the host to their respective XML files.
@@ -145,9 +147,6 @@ object OverlayButtonsPatch : BaseResourcePatch(
"android.support.constraint.ConstraintLayout"
)
- val marginBottom = BottomMargin
- ?: DEFAULT_MARGIN
-
// Modify the layout of fullscreen button for newer YouTube versions (19.09.xx+)
arrayOf(
"youtube_controls_cf_fullscreen_button.xml",
diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/settings/SettingsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/settings/SettingsPatch.kt
index b199b3575..3c0b97e89 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/utils/settings/SettingsPatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/utils/settings/SettingsPatch.kt
@@ -18,6 +18,7 @@ import app.revanced.util.copyResources
import app.revanced.util.copyXmlNode
import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.patch.BaseResourcePatch
+import app.revanced.util.valueOrThrow
import org.w3c.dom.Element
import java.io.Closeable
import java.util.concurrent.Executors
@@ -38,7 +39,7 @@ object SettingsPatch : BaseResourcePatch(
compatiblePackages = COMPATIBLE_PACKAGE,
requiresIntegrations = true
), Closeable {
- private const val DEFAULT_ELEMENT = "About"
+ private const val DEFAULT_ELEMENT = "@string/about_key"
private const val DEFAULT_NAME = "ReVanced Extended"
private val SETTINGS_ELEMENTS_MAP = mapOf(
@@ -63,10 +64,10 @@ object SettingsPatch : BaseResourcePatch(
"Live chat" to "@string/live_chat_key",
"Captions" to "@string/captions_key",
"Accessibility" to "@string/accessibility_settings_key",
- DEFAULT_ELEMENT to "@string/about_key"
+ "About" to DEFAULT_ELEMENT
)
- private val InsertPosition by stringPatchOption(
+ private val InsertPosition = stringPatchOption(
key = "InsertPosition",
default = DEFAULT_ELEMENT,
values = SETTINGS_ELEMENTS_MAP,
@@ -75,7 +76,7 @@ object SettingsPatch : BaseResourcePatch(
required = true
)
- private val RVXSettingsMenuName by stringPatchOption(
+ private val RVXSettingsMenuName = stringPatchOption(
key = "RVXSettingsMenuName",
default = DEFAULT_NAME,
title = "RVX settings menu name",
@@ -83,6 +84,8 @@ object SettingsPatch : BaseResourcePatch(
required = true
)
+ private lateinit var customName: String
+
internal lateinit var contexts: ResourceContext
internal var upward1831 = false
internal var upward1834 = false
@@ -94,6 +97,15 @@ object SettingsPatch : BaseResourcePatch(
override fun execute(context: ResourceContext) {
+ /**
+ * check patch options
+ */
+ customName = RVXSettingsMenuName
+ .valueOrThrow()
+
+ val insertKey = InsertPosition
+ .valueOrThrow()
+
/**
* set resource context
*/
@@ -148,16 +160,10 @@ object SettingsPatch : BaseResourcePatch(
/**
* initialize ReVanced Extended Settings
*/
- val elementKey = SETTINGS_ELEMENTS_MAP[InsertPosition]
- ?: InsertPosition
- ?: SETTINGS_ELEMENTS_MAP[DEFAULT_ELEMENT]
-
- elementKey?.let { insertKey ->
- context.addPreferenceFragment(
- "revanced_extended_settings",
- insertKey
- )
- }
+ context.addPreferenceFragment(
+ "revanced_extended_settings",
+ insertKey
+ )
/**
* remove ReVanced Extended Settings divider
@@ -220,29 +226,26 @@ object SettingsPatch : BaseResourcePatch(
* change RVX settings menu name
* since it must be invoked after the Translations patch, it must be the last in the order.
*/
- RVXSettingsMenuName?.let { customName ->
- if (customName != DEFAULT_NAME) {
- contexts.removeStringsElements(
- arrayOf("revanced_extended_settings_title")
- )
- contexts.xmlEditor["res/values/strings.xml"].use { editor ->
- val document = editor.file
+ if (customName != DEFAULT_NAME) {
+ contexts.removeStringsElements(
+ arrayOf("revanced_extended_settings_title")
+ )
+ contexts.xmlEditor["res/values/strings.xml"].use { editor ->
+ val document = editor.file
- mapOf(
- "revanced_extended_settings_title" to customName
- ).forEach { (k, v) ->
- val stringElement = document.createElement("string")
+ mapOf(
+ "revanced_extended_settings_title" to customName
+ ).forEach { (k, v) ->
+ val stringElement = document.createElement("string")
- stringElement.setAttribute("name", k)
- stringElement.textContent = v
+ stringElement.setAttribute("name", k)
+ stringElement.textContent = v
- document.getElementsByTagName("resources").item(0)
- .appendChild(stringElement)
- }
+ document.getElementsByTagName("resources").item(0)
+ .appendChild(stringElement)
}
}
- } ?: println("WARNING: Invalid RVX settings menu name. RVX settings menu name does not change.")
-
+ }
}
private fun setVersionInfo() {
diff --git a/src/main/kotlin/app/revanced/util/ResourceUtils.kt b/src/main/kotlin/app/revanced/util/ResourceUtils.kt
index b4a391876..2592a7519 100644
--- a/src/main/kotlin/app/revanced/util/ResourceUtils.kt
+++ b/src/main/kotlin/app/revanced/util/ResourceUtils.kt
@@ -3,15 +3,27 @@
package app.revanced.util
import app.revanced.patcher.data.ResourceContext
+import app.revanced.patcher.patch.PatchException
+import app.revanced.patcher.patch.options.PatchOption
import app.revanced.patcher.util.DomFileEditor
import org.w3c.dom.Element
import org.w3c.dom.Node
+import java.io.File
import java.io.InputStream
import java.nio.file.Files
import java.nio.file.StandardCopyOption
val classLoader: ClassLoader = object {}.javaClass.classLoader
+fun PatchOption.valueOrThrow() = value
+ ?: throw PatchException("Invalid patch option: $title.")
+
+fun PatchOption.lowerCaseOrThrow() = valueOrThrow()
+ .lowercase()
+
+fun PatchOption.underBarOrThrow() = lowerCaseOrThrow()
+ .replace(" ", "_")
+
fun Node.adoptChild(tagName: String, block: Element.() -> Unit) {
val child = ownerDocument.createElement(tagName)
child.block()
@@ -48,6 +60,36 @@ fun String.startsWithAny(vararg prefixes: String): Boolean {
return false
}
+fun ResourceContext.copyFile(
+ resourceGroup: List,
+ path: String,
+ warning: String
+): Boolean {
+ resourceGroup.let { resourceGroups ->
+ try {
+ val filePath = File(path)
+ val resourceDirectory = this["res"]
+
+ resourceGroups.forEach { group ->
+ val fromDirectory = filePath.resolve(group.resourceDirectoryName)
+ val toDirectory = resourceDirectory.resolve(group.resourceDirectoryName)
+
+ group.resources.forEach { iconFileName ->
+ Files.write(
+ toDirectory.resolve(iconFileName).toPath(),
+ fromDirectory.resolve(iconFileName).readBytes()
+ )
+ }
+ }
+
+ return true
+ } catch (_: Exception) {
+ println(warning)
+ }
+ }
+ return false
+}
+
/**
* Copy resources from the current class loader to the resource directory.
*