fix(Patch options): some patch options in RVX Manager are marked with custom value

This commit is contained in:
inotia00 2024-06-12 21:45:05 +09:00
parent f7fe7e8caf
commit 8dc8bffea7
15 changed files with 473 additions and 432 deletions

View File

@ -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,12 +130,15 @@ object CustomBrandingIconPatch : BaseResourcePatch(
)
override fun execute(context: ResourceContext) {
AppIcon?.let { appIcon ->
val appIconValue = appIcon.lowercase().replace(" ", "_")
val appIconResourcePath = "music/branding/$appIconValue"
// Check patch options first.
val appIcon = AppIcon
.underBarOrThrow()
val appIconResourcePath = "music/branding/$appIcon"
// Check if a custom path is used in the patch options.
if (!availableIcon.containsValue(appIconValue)) {
if (!availableIcon.containsValue(appIcon)) {
launcherIconResourceGroups.let { resourceGroups ->
try {
val path = File(appIcon)
@ -193,6 +197,5 @@ object CustomBrandingIconPatch : BaseResourcePatch(
}
}
}
} ?: throw PatchException("Invalid app icon path.")
}
}

View File

@ -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,12 +46,16 @@ 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
@ -68,7 +72,5 @@ object CustomBrandingNamePatch : BaseResourcePatch(
.appendChild(stringElement)
}
}
} ?: throw PatchException("Invalid launcher name.")
} ?: throw PatchException("Invalid notification name.")
}
}

View File

@ -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,7 +202,6 @@ 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")
@ -214,14 +222,18 @@ object SettingsPatch : BaseResourcePatch(
}
}
}
} ?: 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)
}

View File

@ -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,14 +31,14 @@ 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 valuesV24Directory = resDirectory.resolve("values-v24")
@ -66,8 +67,5 @@ object CustomBrandingNamePatch : BaseResourcePatch(
document.getElementsByTagName("resources").item(0).appendChild(stringElement)
}
}
} else {
println("INFO: App name will remain unchanged as it matches the original.")
}
}
}

View File

@ -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,13 +38,14 @@ 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
@ -51,13 +53,11 @@ object ChangePackageNamePatch : BaseResourcePatch(
// 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)
}
} else {
println("INFO: Package name will remain unchanged as it matches the original.")
}
}
override fun close() {

View File

@ -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"]

View File

@ -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,8 +32,10 @@ object ShortsActionButtonsPatch : BaseResourcePatch(
)
override fun execute(context: ResourceContext) {
IconType?.let { iconType ->
val selectedIconType = iconType.lowercase()
// Check patch options first.
val iconType = IconType
.lowerCaseOrThrow()
arrayOf(
"xxxhdpi",
@ -43,7 +45,7 @@ object ShortsActionButtonsPatch : BaseResourcePatch(
"mdpi"
).forEach { dpi ->
context.copyResources(
"youtube/shorts/actionbuttons/$selectedIconType",
"youtube/shorts/actionbuttons/$iconType",
ResourceGroup(
"drawable-$dpi",
"ic_remix_filled_white_shadowed.webp",
@ -67,6 +69,7 @@ object ShortsActionButtonsPatch : BaseResourcePatch(
"ic_right_share_32c.xml"
)
)
}
context.copyResources(
"youtube/shorts/actionbuttons/shared",
@ -77,8 +80,6 @@ object ShortsActionButtonsPatch : BaseResourcePatch(
"reel_search_bold_24dp.xml"
)
)
}
} ?: throw PatchException("Invalid icon type.")
SettingsPatch.updatePatchStatus(this)
}

View File

@ -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,13 +175,16 @@ object CustomBrandingIconPatch : BaseResourcePatch(
// endregion
override fun execute(context: ResourceContext) {
AppIcon?.let { appIcon ->
val appIconValue = appIcon.lowercase().replace(" ", "_")
val appIconResourcePath = "youtube/branding/$appIconValue"
// 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(appIconValue)) {
if (!availableIcon.containsValue(appIcon)) {
val copiedFiles = context.copyFile(
launcherIconResourceGroups,
appIcon,
@ -250,38 +252,7 @@ object CustomBrandingIconPatch : BaseResourcePatch(
context.copyXmlNode("$stockResourcePath/splash", "values-v31/styles.xml", "resources")
}
context.updatePatchStatusIcon(appIconValue)
}
} ?: throw PatchException("Invalid app icon path.")
}
private fun ResourceContext.copyFile(
iconResourceGroup: List<ResourceGroup>,
path: String,
message: String
): Boolean {
iconResourceGroup.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()
)
context.updatePatchStatusIcon(appIcon)
}
}
return true
} catch (_: Exception) {
println(message)
}
}
return false
}
}

View File

@ -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,16 +33,20 @@ 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
mapOf(
"application_name" to it
"application_name" to appName
).forEach { (k, v) ->
val stringElement = document.createElement("string")
@ -52,7 +56,6 @@ object CustomBrandingNamePatch : BaseResourcePatch(
document.getElementsByTagName("resources").item(0).appendChild(stringElement)
}
}
context.updatePatchStatusLabel(it)
} ?: throw PatchException("Invalid app name.")
context.updatePatchStatusLabel(appName)
}
}

View File

@ -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)

View File

@ -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 ->

View File

@ -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,11 +66,9 @@ 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"
"custom_branding_icon" -> "youtube/branding/$customBrandingIconType/settings"
else -> "youtube/visual/icons/$selectedIconType"
}
val resourceGroup = ResourceGroup(
@ -81,8 +88,6 @@ object VisualPreferencesIconsPatch : BaseResourcePatch(
// and will raise an error without fallback icon
context.copyResources(fallbackIconPath, resourceGroup)
}
}
}
// endregion.

View File

@ -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,9 +106,7 @@ 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()
// Apply the selected icon type to the overlay buttons.
val commonResources = arrayOf(
"ic_fullscreen_vertical_button.png",
"ic_vr.png",
@ -123,7 +126,7 @@ object OverlayButtonsPatch : BaseResourcePatch(
"yt_outline_screen_full_exit_white_24.png",
"yt_outline_screen_full_white_24.png"
)
val specificResources = if (iconValue == "thin") {
val specificResources = if (iconType == "thin") {
arrayOf("yt_outline_screen_vertical_vd_theme_24.xml")
} else {
arrayOf("yt_outline_screen_vertical_vd_theme_24.png")
@ -132,11 +135,10 @@ object OverlayButtonsPatch : BaseResourcePatch(
resources.forEach { resource ->
val folderName = if (resource.endsWith(".xml")) "drawable" else "drawable-xxhdpi"
context.copyResources(
"youtube/overlaybuttons/$iconValue",
"youtube/overlaybuttons/$iconType",
ResourceGroup(folderName, resource)
)
}
}
// Merge XML nodes from the host to their respective XML files.
context.copyXmlNode(
@ -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",

View File

@ -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
)
}
/**
* remove ReVanced Extended Settings divider
@ -220,7 +226,6 @@ 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")
@ -241,8 +246,6 @@ object SettingsPatch : BaseResourcePatch(
}
}
}
} ?: println("WARNING: Invalid RVX settings menu name. RVX settings menu name does not change.")
}
private fun setVersionInfo() {

View File

@ -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<String>.valueOrThrow() = value
?: throw PatchException("Invalid patch option: $title.")
fun PatchOption<String>.lowerCaseOrThrow() = valueOrThrow()
.lowercase()
fun PatchOption<String>.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<ResourceGroup>,
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.
*