feat: merge patch RVX/anddea (#55)
* feat(YouTube): Add `Custom Shorts action buttons` patch (Replaces `Shorts outline icon` patch) * feat(YouTube): Add `Visual preferences icons` patch * feat(Custom branding icon): Add more icons * feat(Custom branding icon): Add patch options `ChangeHeader`, `ChangeSplashIcon`, `RestoreOldSplashAnimation` * feat(Translations): Add patch options to remove languages and provide own translation / strings.xml * feat(YouTube/Settings): Add search bar in settings * feat(YouTube/Shorts components): Add `Hide disabled comments button` and `Hide live chat header` settings * refactor(YouTube/Settings): Fix typos in strings * feat(YouTube/Settings): clarify patch option descriptions Co-authored-by: KobeW50 <84587632+KobeW50@users.noreply.github.com> * feat(YouTube): clarify patch option Co-authored-by: KobeW50 <84587632+KobeW50@users.noreply.github.com> --------- Co-authored-by: inotia00 <108592928+inotia00@users.noreply.github.com> Co-authored-by: KobeW50 <84587632+KobeW50@users.noreply.github.com>
@ -2,6 +2,7 @@ package app.revanced.patches.music.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.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.util.ResourceGroup
|
||||
@ -19,26 +20,79 @@ object CustomBrandingIconPatch : BaseResourcePatch(
|
||||
private const val DEFAULT_ICON_KEY = "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 Red" to "revancify_red"
|
||||
"Revancify Red" to "revancify_red",
|
||||
"YouTube Music" to "youtube_music"
|
||||
)
|
||||
|
||||
private val mipmapIconResourceFileNames = arrayOf(
|
||||
"adaptiveproduct_youtube_music_background_color_108",
|
||||
"adaptiveproduct_youtube_music_foreground_color_108",
|
||||
"ic_launcher_release"
|
||||
).map { "$it.png" }.toTypedArray()
|
||||
|
||||
private val mipmapDirectories = arrayOf(
|
||||
private val sizeArray = arrayOf(
|
||||
"xxxhdpi",
|
||||
"xxhdpi",
|
||||
"xhdpi",
|
||||
"hdpi",
|
||||
"mdpi"
|
||||
).map { "mipmap-$it" }
|
||||
)
|
||||
|
||||
private var AppIcon by stringPatchOption(
|
||||
private val largeSizeArray = arrayOf(
|
||||
"xlarge-hdpi",
|
||||
"xlarge-mdpi",
|
||||
"large-xhdpi",
|
||||
"large-hdpi",
|
||||
"large-mdpi",
|
||||
"xxhdpi",
|
||||
"xhdpi",
|
||||
"hdpi",
|
||||
"mdpi",
|
||||
)
|
||||
|
||||
private val drawableDirectories = sizeArray.map { "drawable-$it" }
|
||||
|
||||
private val largeDrawableDirectories = largeSizeArray.map { "drawable-$it" }
|
||||
|
||||
private val mipmapDirectories = sizeArray.map { "mipmap-$it" }
|
||||
|
||||
private val headerIconResourceFileNames = arrayOf(
|
||||
"action_bar_logo",
|
||||
"logo_music",
|
||||
"ytm_logo"
|
||||
).map { "$it.png" }.toTypedArray()
|
||||
|
||||
private val launcherIconResourceFileNames = arrayOf(
|
||||
"adaptiveproduct_youtube_music_background_color_108",
|
||||
"adaptiveproduct_youtube_music_foreground_color_108",
|
||||
"ic_launcher_release"
|
||||
).map { "$it.png" }.toTypedArray()
|
||||
|
||||
private val splashIconResourceFileNames = arrayOf(
|
||||
// This file only exists in [drawable-hdpi]
|
||||
// Since {@code ResourceUtils#copyResources} checks for null values before copying,
|
||||
// Just adds it to the array.
|
||||
"action_bar_logo_release",
|
||||
"record"
|
||||
).map { "$it.png" }.toTypedArray()
|
||||
|
||||
private val headerIconResourceGroups = drawableDirectories.map { directory ->
|
||||
ResourceGroup(
|
||||
directory, *headerIconResourceFileNames
|
||||
)
|
||||
}
|
||||
|
||||
private val launcherIconResourceGroups = mipmapDirectories.map { directory ->
|
||||
ResourceGroup(
|
||||
directory, *launcherIconResourceFileNames
|
||||
)
|
||||
}
|
||||
|
||||
private val splashIconResourceGroups = largeDrawableDirectories.map { directory ->
|
||||
ResourceGroup(
|
||||
directory, *splashIconResourceFileNames
|
||||
)
|
||||
}
|
||||
|
||||
private val AppIcon by stringPatchOption(
|
||||
key = "AppIcon",
|
||||
default = DEFAULT_ICON_KEY,
|
||||
values = availableIcon,
|
||||
@ -50,22 +104,35 @@ object CustomBrandingIconPatch : BaseResourcePatch(
|
||||
|
||||
Each of these folders has to have the following files:
|
||||
|
||||
${mipmapIconResourceFileNames.joinToString("\n") { "- $it" }}
|
||||
${launcherIconResourceFileNames.joinToString("\n") { "- $it" }}
|
||||
"""
|
||||
.split("\n")
|
||||
.joinToString("\n") { it.trimIndent() } // Remove the leading whitespace from each line.
|
||||
.trimIndent(), // Remove the leading newline.
|
||||
)
|
||||
|
||||
private val ChangeHeader by booleanPatchOption(
|
||||
key = "ChangeHeader",
|
||||
default = false,
|
||||
title = "Change header",
|
||||
description = "Apply the custom branding icon to the header."
|
||||
)
|
||||
|
||||
private val ChangeSplashIcon by booleanPatchOption(
|
||||
key = "ChangeSplashIcon",
|
||||
default = true,
|
||||
title = "Change splash icons",
|
||||
description = "Apply the custom branding icon to the splash screen."
|
||||
)
|
||||
|
||||
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)) {
|
||||
mipmapDirectories.map { directory ->
|
||||
ResourceGroup(
|
||||
directory, *mipmapIconResourceFileNames
|
||||
)
|
||||
}.let { resourceGroups ->
|
||||
launcherIconResourceGroups.let { resourceGroups ->
|
||||
try {
|
||||
val path = File(appIcon)
|
||||
val resourceDirectory = context["res"]
|
||||
@ -82,33 +149,47 @@ object CustomBrandingIconPatch : BaseResourcePatch(
|
||||
}
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
// Exception is thrown if an invalid path is used in the patch option.
|
||||
throw PatchException("Invalid app icon path: $appIcon")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val resourcePath = "music/branding/$appIconValue"
|
||||
|
||||
// change launcher icon.
|
||||
mipmapDirectories.map { directory ->
|
||||
ResourceGroup(
|
||||
directory, *mipmapIconResourceFileNames
|
||||
)
|
||||
}.let { resourceGroups ->
|
||||
// Change launcher icon.
|
||||
launcherIconResourceGroups.let { resourceGroups ->
|
||||
resourceGroups.forEach {
|
||||
context.copyResources("$resourcePath/launcher", it)
|
||||
context.copyResources("$appIconResourcePath/launcher", it)
|
||||
}
|
||||
}
|
||||
|
||||
// change monochrome icon.
|
||||
// Change monochrome icon.
|
||||
arrayOf(
|
||||
ResourceGroup(
|
||||
"drawable",
|
||||
"ic_app_icons_themed_youtube_music.xml"
|
||||
)
|
||||
).forEach { resourceGroup ->
|
||||
context.copyResources("$resourcePath/monochrome", 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} ?: throw PatchException("Invalid app icon path.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,24 +20,26 @@ object CustomBrandingNamePatch : BaseResourcePatch(
|
||||
key = "AppNameNotification",
|
||||
default = APP_NAME_LAUNCHER,
|
||||
values = mapOf(
|
||||
"Full name" to APP_NAME_NOTIFICATION,
|
||||
"Short name" to APP_NAME_LAUNCHER
|
||||
"ReVanced Extended Music" to APP_NAME_NOTIFICATION,
|
||||
"RVX Music" to APP_NAME_LAUNCHER,
|
||||
"YouTube Music" to "YouTube Music",
|
||||
"YT Music" to "YT Music",
|
||||
),
|
||||
title = "App name in notification panel",
|
||||
description = "The name of the app as it appears in the notification panel.",
|
||||
required = true
|
||||
)
|
||||
|
||||
private val AppNameLauncher by stringPatchOption(
|
||||
key = "AppNameLauncher",
|
||||
default = APP_NAME_LAUNCHER,
|
||||
values = mapOf(
|
||||
"Full name" to APP_NAME_NOTIFICATION,
|
||||
"Short name" to APP_NAME_LAUNCHER
|
||||
"ReVanced Extended Music" to APP_NAME_NOTIFICATION,
|
||||
"RVX Music" to APP_NAME_LAUNCHER,
|
||||
"YouTube Music" to "YouTube Music",
|
||||
"YT Music" to "YT Music",
|
||||
),
|
||||
title = "App name in launcher",
|
||||
description = "The name of the app as it appears in the launcher.",
|
||||
required = true
|
||||
)
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
@ -64,7 +66,7 @@ object CustomBrandingNamePatch : BaseResourcePatch(
|
||||
.appendChild(stringElement)
|
||||
}
|
||||
}
|
||||
} ?: throw PatchException("Invalid app name.")
|
||||
} ?: throw PatchException("Invalid app name.")
|
||||
} ?: throw PatchException("Invalid launcher name.")
|
||||
} ?: throw PatchException("Invalid notification name.")
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,60 @@
|
||||
package app.revanced.patches.music.layout.translations
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
|
||||
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.music.utils.settings.SettingsPatch
|
||||
import app.revanced.patches.shared.translations.APP_LANGUAGES
|
||||
import app.revanced.patches.shared.translations.TranslationsUtils.invoke
|
||||
import app.revanced.util.patch.BaseResourcePatch
|
||||
|
||||
@Suppress("unused")
|
||||
object TranslationsPatch : BaseResourcePatch(
|
||||
name = "Translations YouTube Music",
|
||||
description = "Add translations or remove string resources.",
|
||||
dependencies = setOf(SettingsPatch::class),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE
|
||||
) {
|
||||
// Array of supported translations, each represented by its language code.
|
||||
private val TRANSLATIONS = arrayOf(
|
||||
"bg-rBG", "bn", "cs-rCZ", "el-rGR", "es-rES", "fr-rFR", "hu-rHU", "id-rID", "in", "it-rIT",
|
||||
"ja-rJP", "ko-rKR", "nl-rNL", "pl-rPL", "pt-rBR", "ro-rRO", "ru-rRU", "tr-rTR", "uk-rUA",
|
||||
"vi-rVN", "zh-rCN", "zh-rTW"
|
||||
)
|
||||
|
||||
private var CustomTranslations by stringPatchOption(
|
||||
key = "CustomTranslations",
|
||||
default = "",
|
||||
title = "Custom translations",
|
||||
description = """
|
||||
The path to the 'strings.xml' file.
|
||||
Please note that applying the 'strings.xml' file will overwrite all existing language translations.
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
private var SelectedTranslations by stringPatchOption(
|
||||
key = "SelectedTranslations",
|
||||
default = TRANSLATIONS.joinToString(", "),
|
||||
title = "Translations to add",
|
||||
description = "A list of translations to be added for the RVX settings, separated by commas."
|
||||
)
|
||||
|
||||
private var SelectedStringResources by stringPatchOption(
|
||||
key = "SelectedStringResources",
|
||||
default = APP_LANGUAGES.joinToString(", "),
|
||||
title = "String resources to keep",
|
||||
description = """
|
||||
A list of string resources to be kept, separated by commas.
|
||||
String resources not in the list will be removed from the app.
|
||||
|
||||
Default string resource, English, is not removed.
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
context.invoke(
|
||||
CustomTranslations, SelectedTranslations, SelectedStringResources,
|
||||
TRANSLATIONS, "music"
|
||||
)
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package app.revanced.patches.music.misc.translations
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.music.utils.settings.SettingsPatch
|
||||
import app.revanced.patches.shared.translations.TranslationsUtils.copyXml
|
||||
import app.revanced.util.patch.BaseResourcePatch
|
||||
|
||||
@Suppress("unused")
|
||||
object TranslationsPatch : BaseResourcePatch(
|
||||
name = "Translations",
|
||||
description = "Adds Crowdin translations for YouTube Music.",
|
||||
dependencies = setOf(SettingsPatch::class),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE
|
||||
) {
|
||||
override fun execute(context: ResourceContext) {
|
||||
context.copyXml(
|
||||
"music",
|
||||
arrayOf(
|
||||
"bg-rBG",
|
||||
"bn",
|
||||
"cs-rCZ",
|
||||
"el-rGR",
|
||||
"es-rES",
|
||||
"fr-rFR",
|
||||
"hu-rHU",
|
||||
"id-rID",
|
||||
"in",
|
||||
"it-rIT",
|
||||
"ja-rJP",
|
||||
"ko-rKR",
|
||||
"nl-rNL",
|
||||
"pl-rPL",
|
||||
"pt-rBR",
|
||||
"ro-rRO",
|
||||
"ru-rRU",
|
||||
"tr-rTR",
|
||||
"uk-rUA",
|
||||
"vi-rVN",
|
||||
"zh-rCN",
|
||||
"zh-rTW"
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
}
|
@ -26,24 +26,80 @@ object SettingsPatch : BaseResourcePatch(
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
requiresIntegrations = true
|
||||
), Closeable {
|
||||
private val THREAD_COUNT = Runtime.getRuntime().availableProcessors()
|
||||
private val threadPoolExecutor = Executors.newFixedThreadPool(THREAD_COUNT)
|
||||
|
||||
lateinit var contexts: ResourceContext
|
||||
internal var upward0636 = false
|
||||
internal var upward0642 = false
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
|
||||
/**
|
||||
* set resource context
|
||||
*/
|
||||
contexts = context
|
||||
|
||||
val resourceXmlFile = context["res/values/integers.xml"].readBytes()
|
||||
/**
|
||||
* set version info
|
||||
*/
|
||||
setVersionInfo()
|
||||
|
||||
for (threadIndex in 0 until THREAD_COUNT) {
|
||||
/**
|
||||
* copy strings
|
||||
*/
|
||||
context.copyXmlNode("music/settings/host", "values/strings.xml", "resources")
|
||||
|
||||
/**
|
||||
* hide divider
|
||||
*/
|
||||
val styleFile = context["res/values/styles.xml"]
|
||||
|
||||
styleFile.writeText(
|
||||
styleFile.readText()
|
||||
.replace(
|
||||
"allowDividerAbove\">true",
|
||||
"allowDividerAbove\">false"
|
||||
).replace(
|
||||
"allowDividerBelow\">true",
|
||||
"allowDividerBelow\">false"
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
* Copy arrays
|
||||
*/
|
||||
contexts.copyXmlNode("music/settings/host", "values/arrays.xml", "resources")
|
||||
|
||||
/**
|
||||
* Copy colors
|
||||
*/
|
||||
context.xmlEditor["res/values/colors.xml"].use { editor ->
|
||||
val resourcesNode = editor.file.getElementsByTagName("resources").item(0) as Element
|
||||
|
||||
for (i in 0 until resourcesNode.childNodes.length) {
|
||||
val node = resourcesNode.childNodes.item(i) as? Element ?: continue
|
||||
|
||||
node.textContent = when (node.getAttribute("name")) {
|
||||
"material_deep_teal_500" -> "@android:color/white"
|
||||
|
||||
else -> continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.addRVXSettingsPreference()
|
||||
}
|
||||
|
||||
private fun setVersionInfo() {
|
||||
val threadCount = Runtime.getRuntime().availableProcessors()
|
||||
val threadPoolExecutor = Executors.newFixedThreadPool(threadCount)
|
||||
|
||||
val resourceXmlFile = contexts["res/values/integers.xml"].readBytes()
|
||||
|
||||
for (threadIndex in 0 until threadCount) {
|
||||
threadPoolExecutor.execute thread@{
|
||||
context.xmlEditor[resourceXmlFile.inputStream()].use { editor ->
|
||||
contexts.xmlEditor[resourceXmlFile.inputStream()].use { editor ->
|
||||
val resources = editor.file.documentElement.childNodes
|
||||
val resourcesLength = resources.length
|
||||
val jobSize = resourcesLength / THREAD_COUNT
|
||||
val jobSize = resourcesLength / threadCount
|
||||
|
||||
val batchStart = jobSize * threadIndex
|
||||
val batchEnd = jobSize * (threadIndex + 1)
|
||||
@ -71,47 +127,6 @@ object SettingsPatch : BaseResourcePatch(
|
||||
threadPoolExecutor
|
||||
.also { it.shutdown() }
|
||||
.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS)
|
||||
|
||||
/**
|
||||
* copy strings
|
||||
*/
|
||||
context.copyXmlNode("music/settings/host", "values/strings.xml", "resources")
|
||||
|
||||
/**
|
||||
* hide divider
|
||||
*/
|
||||
val styleFile = context["res/values/styles.xml"]
|
||||
|
||||
styleFile.writeText(
|
||||
styleFile.readText()
|
||||
.replace(
|
||||
"allowDividerAbove\">true",
|
||||
"allowDividerAbove\">false"
|
||||
).replace(
|
||||
"allowDividerBelow\">true",
|
||||
"allowDividerBelow\">false"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
/**
|
||||
* Copy colors
|
||||
*/
|
||||
context.xmlEditor["res/values/colors.xml"].use { editor ->
|
||||
val resourcesNode = editor.file.getElementsByTagName("resources").item(0) as Element
|
||||
|
||||
for (i in 0 until resourcesNode.childNodes.length) {
|
||||
val node = resourcesNode.childNodes.item(i) as? Element ?: continue
|
||||
|
||||
node.textContent = when (node.getAttribute("name")) {
|
||||
"material_deep_teal_500" -> "@android:color/white"
|
||||
|
||||
else -> continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.addRVXSettingsPreference()
|
||||
}
|
||||
|
||||
internal fun addSwitchPreference(
|
||||
@ -162,11 +177,6 @@ object SettingsPatch : BaseResourcePatch(
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
/**
|
||||
* Copy arrays
|
||||
*/
|
||||
contexts.copyXmlNode("music/settings/host", "values/arrays.xml", "resources")
|
||||
|
||||
addPreferenceWithIntent(
|
||||
CategoryType.MISC,
|
||||
"revanced_extended_settings_import_export"
|
||||
|
@ -32,7 +32,7 @@ object CustomBrandingNamePatch : BaseResourcePatch(
|
||||
val appName = if (AppName != null) {
|
||||
AppName!!
|
||||
} else {
|
||||
println("WARNING: Invalid name name. Does not apply patches.")
|
||||
println("WARNING: Invalid app name. Does not apply patches.")
|
||||
ORIGINAL_APP_NAME
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ package app.revanced.patches.shared.elements
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@Suppress("DEPRECATION", "unused")
|
||||
object StringsElementsUtils {
|
||||
|
||||
internal fun ResourceContext.removeStringsElements(
|
||||
|
@ -1,28 +1,172 @@
|
||||
package app.revanced.patches.shared.translations
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.util.inputStreamFromBundledResource
|
||||
import org.w3c.dom.Node
|
||||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.StandardCopyOption
|
||||
import javax.xml.parsers.DocumentBuilderFactory
|
||||
import javax.xml.transform.OutputKeys
|
||||
import javax.xml.transform.TransformerFactory
|
||||
import javax.xml.transform.dom.DOMSource
|
||||
import javax.xml.transform.stream.StreamResult
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
object TranslationsUtils {
|
||||
internal fun ResourceContext.copyXml(
|
||||
|
||||
internal fun ResourceContext.invoke(
|
||||
customTranslations: String?,
|
||||
selectedTranslations: String?,
|
||||
selectedStringResources: String?,
|
||||
translationsArray: Array<String>,
|
||||
sourceDirectory: String
|
||||
) {
|
||||
// Check if the custom translation path is valid.
|
||||
customTranslations?.takeIf { it.isNotEmpty() }?.let { customLang ->
|
||||
try {
|
||||
val customLangFile = File(customLang)
|
||||
if (!customLangFile.exists() || !customLangFile.isFile || customLangFile.name != "strings.xml") {
|
||||
throw PatchException("Invalid custom language file: $customLang")
|
||||
}
|
||||
val resourceDirectory = this["res"].resolve("values")
|
||||
val destinationFile = resourceDirectory.resolve("strings.xml")
|
||||
|
||||
updateStringsXml(customLangFile, destinationFile)
|
||||
} catch (e: Exception) {
|
||||
// Exception is thrown if an invalid path is used in the patch option.
|
||||
throw PatchException("Invalid custom translations path: $customLang")
|
||||
}
|
||||
}?: run {
|
||||
// Process selected translations if no custom translation is set.
|
||||
val selectedTranslationsArray =
|
||||
selectedTranslations?.split(",")?.map { it.trim() }?.toTypedArray()
|
||||
?: throw PatchException("Invalid selected languages.")
|
||||
val filteredLanguages = translationsArray.filter { it in selectedTranslationsArray }.toTypedArray()
|
||||
copyXml(sourceDirectory, filteredLanguages)
|
||||
}
|
||||
|
||||
// Process selected string resources.
|
||||
val selectedStringResourcesArray =
|
||||
selectedStringResources?.split(",")?.map { it.trim() }?.toTypedArray()
|
||||
?: throw PatchException("Invalid selected string resources.")
|
||||
val filteredStringResources =
|
||||
APP_LANGUAGES.filter { it in selectedStringResourcesArray }.toTypedArray()
|
||||
val resourceDirectory = this["res"]
|
||||
|
||||
// Remove unselected app languages.
|
||||
APP_LANGUAGES.filter { it !in filteredStringResources }.forEach { language ->
|
||||
resourceDirectory.resolve("values-$language").takeIf { it.exists() && it.isDirectory }
|
||||
?.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension function to ResourceContext to copy XML translation files.
|
||||
*
|
||||
* @param sourceDirectory The source directory containing the translation files.
|
||||
* @param languageArray The array of language codes to process.
|
||||
*/
|
||||
private fun ResourceContext.copyXml(
|
||||
sourceDirectory: String,
|
||||
languageArray: Array<String>
|
||||
) {
|
||||
languageArray.forEach { language ->
|
||||
val directory = "values-$language-v21"
|
||||
this["res/$directory"].mkdir()
|
||||
inputStreamFromBundledResource(
|
||||
"$sourceDirectory/translations",
|
||||
"$language/strings.xml"
|
||||
)?.let { inputStream ->
|
||||
val directory = "values-$language-v21"
|
||||
val valuesV21Directory = this["res"].resolve(directory)
|
||||
if (!valuesV21Directory.isDirectory) Files.createDirectories(valuesV21Directory.toPath())
|
||||
|
||||
Files.copy(
|
||||
inputStreamFromBundledResource(
|
||||
"$sourceDirectory/translations",
|
||||
"$language/strings.xml"
|
||||
)!!,
|
||||
this["res"].resolve("$directory/strings.xml").toPath(),
|
||||
StandardCopyOption.REPLACE_EXISTING
|
||||
)
|
||||
Files.copy(
|
||||
inputStream,
|
||||
this["res"].resolve("$directory/strings.xml").toPath(),
|
||||
StandardCopyOption.REPLACE_EXISTING
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the contents of the destination strings.xml file by merging it with the source strings.xml file.
|
||||
*
|
||||
* This function reads both source and destination XML files, compares each <string> element by their
|
||||
* unique "name" attribute, and if a match is found, it replaces the content in the destination file with
|
||||
* the content from the source file.
|
||||
*
|
||||
* @param sourceFile The source strings.xml file containing new string values.
|
||||
* @param destinationFile The destination strings.xml file to be updated with values from the source file.
|
||||
*/
|
||||
private fun updateStringsXml(sourceFile: File, destinationFile: File) {
|
||||
val documentBuilderFactory = DocumentBuilderFactory.newInstance()
|
||||
val documentBuilder = documentBuilderFactory.newDocumentBuilder()
|
||||
|
||||
// Parse the source and destination XML files into Document objects
|
||||
val sourceDoc = documentBuilder.parse(sourceFile)
|
||||
val destinationDoc = documentBuilder.parse(destinationFile)
|
||||
|
||||
val sourceStrings = sourceDoc.getElementsByTagName("string")
|
||||
val destinationStrings = destinationDoc.getElementsByTagName("string")
|
||||
|
||||
// Create a map to store the <string> elements from the source document by their "name" attribute
|
||||
val sourceMap = mutableMapOf<String, Node>()
|
||||
|
||||
// Populate the map with nodes from the source document
|
||||
for (i in 0 until sourceStrings.length) {
|
||||
val node = sourceStrings.item(i)
|
||||
val name = node.attributes.getNamedItem("name").nodeValue
|
||||
sourceMap[name] = node
|
||||
}
|
||||
|
||||
// Update the destination document with values from the source document
|
||||
for (i in 0 until destinationStrings.length) {
|
||||
val node = destinationStrings.item(i)
|
||||
val name = node.attributes.getNamedItem("name").nodeValue
|
||||
if (sourceMap.containsKey(name)) {
|
||||
node.textContent = sourceMap[name]?.textContent
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the transformer for writing the updated document back to the file.
|
||||
* The transformer is configured to indent the output XML for better readability.
|
||||
*/
|
||||
val transformerFactory = TransformerFactory.newInstance()
|
||||
val transformer = transformerFactory.newTransformer()
|
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes")
|
||||
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2")
|
||||
|
||||
val domSource = DOMSource(destinationDoc)
|
||||
val streamResult = StreamResult(destinationFile)
|
||||
transformer.transform(domSource, streamResult)
|
||||
}
|
||||
}
|
||||
|
||||
// Array of all possible app languages.
|
||||
val APP_LANGUAGES = arrayOf(
|
||||
"af", "am", "ar", "ar-rXB", "as", "az",
|
||||
"b+es+419", "b+sr+Latn", "be", "bg", "bn", "bs",
|
||||
"ca", "cs",
|
||||
"da", "de",
|
||||
"el", "en-rAU", "en-rCA", "en-rGB", "en-rIN", "en-rXA", "en-rXC", "es", "es-rUS", "et", "eu",
|
||||
"fa", "fi", "fr", "fr-rCA",
|
||||
"gl", "gu",
|
||||
"hi", "hr", "hu", "hy",
|
||||
"id", "in", "is", "it", "iw",
|
||||
"ja",
|
||||
"ka", "kk", "km", "kn", "ko", "ky",
|
||||
"lo", "lt", "lv",
|
||||
"mk", "ml", "mn", "mr", "ms", "my",
|
||||
"nb", "ne", "nl", "no",
|
||||
"or",
|
||||
"pa", "pl", "pt", "pt-rBR", "pt-rPT",
|
||||
"ro", "ru",
|
||||
"si", "sk", "sl", "sq", "sr", "sv", "sw",
|
||||
"ta", "te", "th", "tl", "tr",
|
||||
"uk", "ur", "uz",
|
||||
"vi",
|
||||
"zh", "zh-rCN", "zh-rHK", "zh-rTW", "zu",
|
||||
)
|
||||
|
@ -0,0 +1,84 @@
|
||||
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.patch.BaseResourcePatch
|
||||
|
||||
@Suppress("unused")
|
||||
object ShortsActionButtonsPatch : BaseResourcePatch(
|
||||
name = "Custom Shorts action buttons",
|
||||
description = "Changes, at compile time, the icon of the action buttons of the Shorts player.",
|
||||
dependencies = setOf(SettingsPatch::class),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE
|
||||
) {
|
||||
private const val DEFAULT_ICON_KEY = "Round"
|
||||
|
||||
private val IconType by stringPatchOption(
|
||||
key = "IconType",
|
||||
default = DEFAULT_ICON_KEY,
|
||||
values = mapOf(
|
||||
"Outline" to "outline",
|
||||
"OutlineCircle" to "outlinecircle",
|
||||
DEFAULT_ICON_KEY to "round"
|
||||
),
|
||||
title = "Shorts icon style ",
|
||||
description = "The style of the icons for the action buttons in the Shorts player."
|
||||
)
|
||||
|
||||
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",
|
||||
|
||||
// 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.")
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ object AnimatedLikePatch : BaseResourcePatch(
|
||||
* Copy json
|
||||
*/
|
||||
context.copyResources(
|
||||
"youtube/animated",
|
||||
"youtube/shorts/animated",
|
||||
ResourceGroup(
|
||||
"raw",
|
||||
"like_tap_feedback.json"
|
||||
|
@ -2,12 +2,14 @@ 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
|
||||
import app.revanced.patches.youtube.utils.settings.ResourceUtils.updatePatchStatusIcon
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.ResourceGroup
|
||||
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
|
||||
@ -17,47 +19,84 @@ 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
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
) {
|
||||
private const val DEFAULT_ICON_KEY = "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 Red" to "revancify_red"
|
||||
"Revancify Red" to "revancify_red",
|
||||
"YouTube" to "youtube"
|
||||
)
|
||||
|
||||
private val drawableIconResourceFileNames = arrayOf(
|
||||
"product_logo_youtube_color_24",
|
||||
"product_logo_youtube_color_36",
|
||||
"product_logo_youtube_color_144",
|
||||
"product_logo_youtube_color_192"
|
||||
).map { "$it.png" }.toTypedArray()
|
||||
|
||||
private val drawableDirectories = arrayOf(
|
||||
private val sizeArray = arrayOf(
|
||||
"xxxhdpi",
|
||||
"xxhdpi",
|
||||
"xhdpi",
|
||||
"hdpi",
|
||||
"mdpi"
|
||||
).map { "drawable-$it" }
|
||||
)
|
||||
|
||||
private val mipmapIconResourceFileNames = arrayOf(
|
||||
private val drawableDirectories = sizeArray.map { "drawable-$it" }
|
||||
|
||||
private val mipmapDirectories = sizeArray.map { "mipmap-$it" }
|
||||
|
||||
private val headerIconResourceFileNames = arrayOf(
|
||||
"yt_premium_wordmark_header_dark",
|
||||
"yt_premium_wordmark_header_light",
|
||||
"yt_wordmark_header_dark",
|
||||
"yt_wordmark_header_light"
|
||||
).map { "$it.png" }.toTypedArray()
|
||||
|
||||
private val launcherIconResourceFileNames = arrayOf(
|
||||
"adaptiveproduct_youtube_background_color_108",
|
||||
"adaptiveproduct_youtube_foreground_color_108",
|
||||
"ic_launcher",
|
||||
"ic_launcher_round"
|
||||
).map { "$it.png" }.toTypedArray()
|
||||
|
||||
private val mipmapDirectories = arrayOf(
|
||||
"xxxhdpi",
|
||||
"xxhdpi",
|
||||
"xhdpi",
|
||||
"hdpi",
|
||||
"mdpi"
|
||||
).map { "mipmap-$it" }
|
||||
private val splashIconResourceFileNames = arrayOf(
|
||||
"product_logo_youtube_color_24",
|
||||
"product_logo_youtube_color_36",
|
||||
"product_logo_youtube_color_144",
|
||||
"product_logo_youtube_color_192"
|
||||
).map { "$it.png" }.toTypedArray()
|
||||
|
||||
private var AppIcon by stringPatchOption(
|
||||
private val oldSplashAnimationResourceFileNames = arrayOf(
|
||||
"\$\$avd_anim__1__0",
|
||||
"\$\$avd_anim__1__1",
|
||||
"\$\$avd_anim__2__0",
|
||||
"\$\$avd_anim__2__1",
|
||||
"\$\$avd_anim__3__0",
|
||||
"\$\$avd_anim__3__1",
|
||||
"\$avd_anim__0",
|
||||
"\$avd_anim__1",
|
||||
"\$avd_anim__2",
|
||||
"\$avd_anim__3",
|
||||
"\$avd_anim__4",
|
||||
"avd_anim"
|
||||
).map { "$it.xml" }.toTypedArray()
|
||||
|
||||
private fun List<String>.getResourceGroup(fileNames: Array<String>) = map { directory ->
|
||||
ResourceGroup(
|
||||
directory, *fileNames
|
||||
)
|
||||
}
|
||||
|
||||
private val headerIconResourceGroups = drawableDirectories.getResourceGroup(headerIconResourceFileNames)
|
||||
|
||||
private val launcherIconResourceGroups = mipmapDirectories.getResourceGroup(launcherIconResourceFileNames)
|
||||
|
||||
private val splashIconResourceGroups = drawableDirectories.getResourceGroup(splashIconResourceFileNames)
|
||||
|
||||
private val oldSplashAnimationResourceGroups = listOf("drawable").getResourceGroup(oldSplashAnimationResourceFileNames)
|
||||
|
||||
// region patch option
|
||||
|
||||
val AppIcon by stringPatchOption(
|
||||
key = "AppIcon",
|
||||
default = DEFAULT_ICON_KEY,
|
||||
values = availableIcon,
|
||||
@ -69,22 +108,45 @@ object CustomBrandingIconPatch : BaseResourcePatch(
|
||||
|
||||
Each of these folders has to have the following files:
|
||||
|
||||
${mipmapIconResourceFileNames.joinToString("\n") { "- $it" }}
|
||||
${launcherIconResourceFileNames.joinToString("\n") { "- $it" }}
|
||||
"""
|
||||
.split("\n")
|
||||
.joinToString("\n") { it.trimIndent() } // Remove the leading whitespace from each line.
|
||||
.trimIndent(), // Remove the leading newline.
|
||||
)
|
||||
|
||||
private val ChangeHeader by booleanPatchOption(
|
||||
key = "ChangeHeader",
|
||||
default = false,
|
||||
title = "Change header",
|
||||
description = "Apply the custom branding icon to the header."
|
||||
)
|
||||
|
||||
private val ChangeSplashIcon by booleanPatchOption(
|
||||
key = "ChangeSplashIcon",
|
||||
default = true,
|
||||
title = "Change splash icons",
|
||||
description = "Apply the custom branding icon to the splash screen."
|
||||
)
|
||||
|
||||
private val RestoreOldSplashAnimation by booleanPatchOption(
|
||||
key = "RestoreOldSplashAnimation",
|
||||
default = false,
|
||||
title = "Restore old splash animation",
|
||||
description = "Restores old style splash animation."
|
||||
)
|
||||
|
||||
// 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)) {
|
||||
mipmapDirectories.map { directory ->
|
||||
ResourceGroup(
|
||||
directory, *mipmapIconResourceFileNames
|
||||
)
|
||||
}.let { resourceGroups ->
|
||||
launcherIconResourceGroups.let { resourceGroups ->
|
||||
try {
|
||||
val path = File(appIcon)
|
||||
val resourceDirectory = context["res"]
|
||||
@ -100,48 +162,63 @@ object CustomBrandingIconPatch : BaseResourcePatch(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
context.updatePatchStatusIcon("custom")
|
||||
} catch (_: Exception) {
|
||||
// Exception is thrown if an invalid path is used in the patch option.
|
||||
throw PatchException("Invalid app icon path: $appIcon")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val resourcePath = "youtube/branding/$appIconValue"
|
||||
|
||||
// change launcher icon.
|
||||
mipmapDirectories.map { directory ->
|
||||
ResourceGroup(
|
||||
directory, *mipmapIconResourceFileNames
|
||||
)
|
||||
}.let { resourceGroups ->
|
||||
// Change launcher icon.
|
||||
launcherIconResourceGroups.let { resourceGroups ->
|
||||
resourceGroups.forEach {
|
||||
context.copyResources("$resourcePath/launcher", it)
|
||||
context.copyResources("$appIconResourcePath/launcher", it)
|
||||
}
|
||||
}
|
||||
|
||||
// change splash icon.
|
||||
drawableDirectories.map { directory ->
|
||||
ResourceGroup(
|
||||
directory, *drawableIconResourceFileNames
|
||||
)
|
||||
}.let { resourceGroups ->
|
||||
resourceGroups.forEach {
|
||||
context.copyResources("$resourcePath/splash", it)
|
||||
}
|
||||
}
|
||||
|
||||
// change monochrome icon.
|
||||
// Change monochrome icon.
|
||||
arrayOf(
|
||||
ResourceGroup(
|
||||
"drawable",
|
||||
"adaptive_monochrome_ic_youtube_launcher.xml"
|
||||
)
|
||||
).forEach { resourceGroup ->
|
||||
context.copyResources("$resourcePath/monochrome", 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,12 +22,13 @@ object CustomBrandingNamePatch : BaseResourcePatch(
|
||||
key = "AppName",
|
||||
default = APP_NAME,
|
||||
values = mapOf(
|
||||
"Full name" to "ReVanced Extended",
|
||||
"Short name" to APP_NAME
|
||||
"ReVanced Extended" to "ReVanced Extended",
|
||||
"RVX" to APP_NAME,
|
||||
"YouTube RVX" to "YouTube RVX",
|
||||
"YouTube" to "YouTube",
|
||||
),
|
||||
title = "App name",
|
||||
description = "The name of the app.",
|
||||
required = true
|
||||
description = "The name of the app."
|
||||
)
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
|
@ -1,42 +1,61 @@
|
||||
package app.revanced.patches.youtube.layout.translations
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patches.shared.translations.TranslationsUtils.copyXml
|
||||
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
|
||||
import app.revanced.patches.shared.translations.APP_LANGUAGES
|
||||
import app.revanced.patches.shared.translations.TranslationsUtils.invoke
|
||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.patch.BaseResourcePatch
|
||||
|
||||
@Suppress("unused")
|
||||
object TranslationsPatch : BaseResourcePatch(
|
||||
name = "Translations",
|
||||
description = "Adds Crowdin translations for YouTube.",
|
||||
name = "Translations YouTube",
|
||||
description = "Add translations or remove string resources.",
|
||||
dependencies = setOf(SettingsPatch::class),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE
|
||||
) {
|
||||
override fun execute(context: ResourceContext) {
|
||||
// Array of supported translations, each represented by its language code.
|
||||
private val TRANSLATIONS = arrayOf(
|
||||
"ar", "el-rGR", "es-rES", "fr-rFR", "hu-rHU", "it-rIT", "ja-rJP", "ko-rKR", "pl-rPL",
|
||||
"pt-rBR", "ru-rRU", "tr-rTR", "uk-rUA", "vi-rVN", "zh-rCN", "zh-rTW"
|
||||
)
|
||||
|
||||
context.copyXml(
|
||||
"youtube",
|
||||
arrayOf(
|
||||
"ar",
|
||||
"el-rGR",
|
||||
"es-rES",
|
||||
"fr-rFR",
|
||||
"hu-rHU",
|
||||
"it-rIT",
|
||||
"ja-rJP",
|
||||
"ko-rKR",
|
||||
"pl-rPL",
|
||||
"pt-rBR",
|
||||
"ru-rRU",
|
||||
"tr-rTR",
|
||||
"uk-rUA",
|
||||
"vi-rVN",
|
||||
"zh-rCN",
|
||||
"zh-rTW"
|
||||
)
|
||||
private var CustomTranslations by stringPatchOption(
|
||||
key = "CustomTranslations",
|
||||
default = "",
|
||||
title = "Custom translations",
|
||||
description = """
|
||||
The path to the 'strings.xml' file.
|
||||
Please note that applying the 'strings.xml' file will overwrite all existing translations.
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
private var SelectedTranslations by stringPatchOption(
|
||||
key = "SelectedTranslations",
|
||||
default = TRANSLATIONS.joinToString(", "),
|
||||
title = "Translations to add",
|
||||
description = "A list of translations to be added for the RVX settings, separated by commas."
|
||||
)
|
||||
|
||||
private var SelectedStringResources by stringPatchOption(
|
||||
key = "SelectedStringResources",
|
||||
default = APP_LANGUAGES.joinToString(", "),
|
||||
title = "String resources to keep",
|
||||
description = """
|
||||
A list of string resources to be kept, separated by commas.
|
||||
String resources not in the list will be removed from the app.
|
||||
|
||||
Default string resource, English, is not removed.
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
context.invoke(
|
||||
CustomTranslations, SelectedTranslations, SelectedStringResources,
|
||||
TRANSLATIONS, "youtube"
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
SettingsPatch.updatePatchStatus("Translations")
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,377 @@
|
||||
package app.revanced.patches.youtube.layout.visual
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
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
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.copyResources
|
||||
import app.revanced.util.doRecursively
|
||||
import app.revanced.util.patch.BaseResourcePatch
|
||||
import org.w3c.dom.Element
|
||||
|
||||
@Suppress("DEPRECATION", "unused")
|
||||
object VisualPreferencesIconsPatch : BaseResourcePatch(
|
||||
name = "Visual preferences icons",
|
||||
description = "Adds icons to specific preferences in the settings.",
|
||||
dependencies = setOf(SettingsPatch::class),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
use = false
|
||||
) {
|
||||
private const val DEFAULT_ICON_KEY = "Extension"
|
||||
|
||||
private val RVXSettingsMenuIcon by stringPatchOption(
|
||||
key = "RVXSettingsMenuIcon",
|
||||
default = DEFAULT_ICON_KEY,
|
||||
values = mapOf(
|
||||
"Custom branding icon" to "custom_branding_icon",
|
||||
DEFAULT_ICON_KEY to "extension",
|
||||
"Gear" to "gear",
|
||||
"ReVanced" to "revanced",
|
||||
"ReVanced Colored" to "revanced_colored",
|
||||
),
|
||||
title = "RVX settings menu icon",
|
||||
description = "Apply different icons for RVX settings menu."
|
||||
)
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
|
||||
// region copy shared resources.
|
||||
|
||||
arrayOf(
|
||||
ResourceGroup(
|
||||
"drawable",
|
||||
*preferenceIcon.values.map { "$it.xml" }.toTypedArray()
|
||||
),
|
||||
ResourceGroup(
|
||||
"drawable-xxhdpi",
|
||||
"$emptyIcon.png"
|
||||
),
|
||||
).forEach { resourceGroup ->
|
||||
context.copyResources("youtube/visual/shared", resourceGroup)
|
||||
}
|
||||
|
||||
// endregion.
|
||||
|
||||
// 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"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// endregion.
|
||||
|
||||
// region set visual preferences icon.
|
||||
|
||||
arrayOf(
|
||||
"res/xml/revanced_prefs.xml",
|
||||
"res/xml/settings_fragment.xml"
|
||||
).forEach { xmlFile ->
|
||||
context.xmlEditor[xmlFile].use { editor ->
|
||||
editor.file.doRecursively loop@{ node ->
|
||||
if (node !is Element) return@loop
|
||||
|
||||
node.getAttributeNode("android:key")
|
||||
?.textContent
|
||||
?.removePrefix("@string/")
|
||||
?.let { title ->
|
||||
val drawableName = when (title) {
|
||||
in preferenceKey -> preferenceIcon[title]
|
||||
|
||||
// Add custom RVX settings menu icon
|
||||
in intentKey -> intentIcon[title]
|
||||
in emptyTitles -> emptyIcon
|
||||
else -> null
|
||||
}
|
||||
drawableName?.let {
|
||||
node.setAttribute("android:icon", "@drawable/$it")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// endregion.
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
|
||||
// region preference key and icon.
|
||||
|
||||
private val preferenceKey = setOf(
|
||||
// Main settings (sorted as displayed in the settings)
|
||||
"parent_tools_key",
|
||||
"general_key",
|
||||
"account_switcher_key",
|
||||
"data_saving_settings_key",
|
||||
"auto_play_key",
|
||||
"video_quality_settings_key",
|
||||
"offline_key",
|
||||
"pair_with_tv_key",
|
||||
"history_key",
|
||||
"your_data_key",
|
||||
"privacy_key",
|
||||
"premium_early_access_browse_page_key",
|
||||
"subscription_product_setting_key",
|
||||
"billing_and_payment_key",
|
||||
"notification_key",
|
||||
"connected_accounts_browse_page_key",
|
||||
"live_chat_key",
|
||||
"captions_key",
|
||||
"accessibility_settings_key",
|
||||
"about_key",
|
||||
|
||||
// Main RVX settings (sorted as displayed in the settings)
|
||||
"revanced_preference_screen_ads",
|
||||
"revanced_preference_screen_alt_thumbnails",
|
||||
"revanced_preference_screen_feed",
|
||||
"revanced_preference_screen_general",
|
||||
"revanced_preference_screen_player",
|
||||
"revanced_preference_screen_shorts",
|
||||
"revanced_preference_screen_swipe_controls",
|
||||
"revanced_preference_screen_video",
|
||||
"revanced_preference_screen_ryd",
|
||||
"revanced_preference_screen_sb",
|
||||
"revanced_preference_screen_misc",
|
||||
|
||||
// Internal RVX settings (items without prefix are listed first, others are sorted alphabetically)
|
||||
"gms_core_settings",
|
||||
"sb_enable_create_segment",
|
||||
"sb_enable_voting",
|
||||
|
||||
"revanced_alt_thumbnail_home",
|
||||
"revanced_alt_thumbnail_library",
|
||||
"revanced_alt_thumbnail_player",
|
||||
"revanced_alt_thumbnail_search",
|
||||
"revanced_alt_thumbnail_subscriptions",
|
||||
"revanced_change_shorts_repeat_state",
|
||||
"revanced_custom_player_overlay_opacity",
|
||||
"revanced_default_app_settings",
|
||||
"revanced_default_playback_speed",
|
||||
"revanced_default_video_quality_wifi",
|
||||
"revanced_disable_hdr_auto_brightness",
|
||||
"revanced_disable_hdr_video",
|
||||
"revanced_disable_quic_protocol",
|
||||
"revanced_enable_debug_logging",
|
||||
"revanced_enable_default_playback_speed_shorts",
|
||||
"revanced_enable_external_browser",
|
||||
"revanced_enable_old_quality_layout",
|
||||
"revanced_enable_open_links_directly",
|
||||
"revanced_enable_swipe_brightness",
|
||||
"revanced_enable_swipe_haptic_feedback",
|
||||
"revanced_enable_swipe_lowest_value_auto_brightness",
|
||||
"revanced_enable_swipe_press_to_engage",
|
||||
"revanced_enable_swipe_volume",
|
||||
"revanced_enable_watch_panel_gestures",
|
||||
"revanced_hide_clip_button",
|
||||
"revanced_hide_download_button",
|
||||
"revanced_hide_keyword_content_comments",
|
||||
"revanced_hide_keyword_content_home",
|
||||
"revanced_hide_keyword_content_search",
|
||||
"revanced_hide_keyword_content_subscriptions",
|
||||
"revanced_hide_like_dislike_button",
|
||||
"revanced_hide_navigation_create_button",
|
||||
"revanced_hide_navigation_home_button",
|
||||
"revanced_hide_navigation_library_button",
|
||||
"revanced_hide_navigation_notifications_button",
|
||||
"revanced_hide_navigation_shorts_button",
|
||||
"revanced_hide_navigation_subscriptions_button",
|
||||
"revanced_hide_player_autoplay_button",
|
||||
"revanced_hide_player_captions_button",
|
||||
"revanced_hide_player_cast_button",
|
||||
"revanced_hide_player_collapse_button",
|
||||
"revanced_hide_player_flyout_menu_ambient_mode",
|
||||
"revanced_hide_player_flyout_menu_audio_track",
|
||||
"revanced_hide_player_flyout_menu_captions",
|
||||
"revanced_hide_player_flyout_menu_help",
|
||||
"revanced_hide_player_flyout_menu_lock_screen",
|
||||
"revanced_hide_player_flyout_menu_loop_video",
|
||||
"revanced_hide_player_flyout_menu_more_info",
|
||||
"revanced_hide_player_flyout_menu_playback_speed",
|
||||
"revanced_hide_player_flyout_menu_quality_footer",
|
||||
"revanced_hide_player_flyout_menu_report",
|
||||
"revanced_hide_player_flyout_menu_stable_volume",
|
||||
"revanced_hide_player_flyout_menu_stats_for_nerds",
|
||||
"revanced_hide_player_flyout_menu_watch_in_vr",
|
||||
"revanced_hide_player_fullscreen_button",
|
||||
"revanced_hide_player_previous_next_button",
|
||||
"revanced_hide_player_youtube_music_button",
|
||||
"revanced_hide_playlist_button",
|
||||
"revanced_hide_quick_actions_comment_button",
|
||||
"revanced_hide_quick_actions_dislike_button",
|
||||
"revanced_hide_quick_actions_like_button",
|
||||
"revanced_hide_quick_actions_live_chat_button",
|
||||
"revanced_hide_quick_actions_more_button",
|
||||
"revanced_hide_quick_actions_save_to_playlist_button",
|
||||
"revanced_hide_quick_actions_share_button",
|
||||
"revanced_hide_remix_button",
|
||||
"revanced_hide_report_button",
|
||||
"revanced_hide_share_button",
|
||||
"revanced_hide_shorts_comments_button",
|
||||
"revanced_hide_shorts_dislike_button",
|
||||
"revanced_hide_shorts_like_button",
|
||||
"revanced_hide_shorts_navigation_bar",
|
||||
"revanced_hide_shorts_remix_button",
|
||||
"revanced_hide_shorts_share_button",
|
||||
"revanced_hide_shorts_shelf_history",
|
||||
"revanced_hide_shorts_shelf_home_related_videos",
|
||||
"revanced_hide_shorts_shelf_search",
|
||||
"revanced_hide_shorts_shelf_subscriptions",
|
||||
"revanced_hide_shorts_toolbar",
|
||||
"revanced_overlay_button_always_repeat",
|
||||
"revanced_overlay_button_copy_video_url",
|
||||
"revanced_overlay_button_copy_video_url_timestamp",
|
||||
"revanced_overlay_button_external_downloader",
|
||||
"revanced_overlay_button_speed_dialog",
|
||||
"revanced_overlay_button_time_ordered_playlist",
|
||||
"revanced_overlay_button_whitelist",
|
||||
"revanced_preference_screen_account_menu",
|
||||
"revanced_preference_screen_action_buttons",
|
||||
"revanced_preference_screen_ambient_mode",
|
||||
"revanced_preference_screen_category_bar",
|
||||
"revanced_preference_screen_channel_bar",
|
||||
"revanced_preference_screen_channel_profile",
|
||||
"revanced_preference_screen_comments",
|
||||
"revanced_preference_screen_community_posts",
|
||||
"revanced_preference_screen_custom_filter",
|
||||
"revanced_preference_screen_feed_flyout_menu",
|
||||
"revanced_preference_screen_fullscreen",
|
||||
"revanced_preference_screen_haptic_feedback",
|
||||
"revanced_preference_screen_import_export",
|
||||
"revanced_preference_screen_navigation_buttons",
|
||||
"revanced_preference_screen_patch_information",
|
||||
"revanced_preference_screen_player_buttons",
|
||||
"revanced_preference_screen_player_flyout_menu",
|
||||
"revanced_preference_screen_seekbar",
|
||||
"revanced_preference_screen_settings_menu",
|
||||
"revanced_preference_screen_shorts_player",
|
||||
"revanced_preference_screen_spoof_client",
|
||||
"revanced_preference_screen_toolbar",
|
||||
"revanced_preference_screen_video_description",
|
||||
"revanced_preference_screen_video_filter",
|
||||
"revanced_sanitize_sharing_links",
|
||||
"revanced_swipe_gestures_lock_mode",
|
||||
"revanced_swipe_magnitude_threshold",
|
||||
"revanced_swipe_overlay_background_alpha",
|
||||
"revanced_swipe_overlay_rect_size",
|
||||
"revanced_swipe_overlay_text_size",
|
||||
"revanced_swipe_overlay_timeout",
|
||||
"revanced_switch_create_with_notifications_button",
|
||||
"revanced_change_player_flyout_menu_toggle",
|
||||
)
|
||||
|
||||
private val intentKey = setOf(
|
||||
"revanced_extended_settings_key",
|
||||
)
|
||||
|
||||
private val emptyTitles = setOf(
|
||||
"revanced_custom_playback_speeds",
|
||||
"revanced_custom_playback_speed_menu_type",
|
||||
"revanced_default_video_quality_mobile",
|
||||
"revanced_disable_default_playback_speed_live",
|
||||
"revanced_enable_custom_playback_speed",
|
||||
"revanced_external_downloader_package_name",
|
||||
"revanced_hide_shorts_comments_disabled_button",
|
||||
"revanced_hide_player_flyout_menu_captions_footer",
|
||||
"revanced_remember_playback_speed_last_selected",
|
||||
"revanced_remember_video_quality_last_selected",
|
||||
"revanced_restore_old_video_quality_menu",
|
||||
"revanced_enable_debug_buffer_logging",
|
||||
"revanced_whitelist_settings",
|
||||
)
|
||||
|
||||
// A lot of mappings here.
|
||||
// The performance impact should be negligible in this context,
|
||||
// as the operations involved are not computationally intensive.
|
||||
private val preferenceIcon = preferenceKey.associateWith { title ->
|
||||
when (title) {
|
||||
// Main RVX settings
|
||||
"revanced_preference_screen_general" -> "general_key_icon"
|
||||
"revanced_preference_screen_sb" -> "sb_enable_create_segment_icon"
|
||||
|
||||
// Internal RVX settings
|
||||
"revanced_alt_thumbnail_home" -> "revanced_hide_navigation_home_button_icon"
|
||||
"revanced_alt_thumbnail_library" -> "revanced_preference_screen_video_icon"
|
||||
"revanced_alt_thumbnail_player" -> "revanced_preference_screen_player_icon"
|
||||
"revanced_alt_thumbnail_search" -> "revanced_hide_shorts_shelf_search_icon"
|
||||
"revanced_alt_thumbnail_subscriptions" -> "revanced_hide_navigation_subscriptions_button_icon"
|
||||
"revanced_custom_player_overlay_opacity" -> "revanced_swipe_overlay_background_alpha_icon"
|
||||
"revanced_default_app_settings" -> "revanced_preference_screen_settings_menu_icon"
|
||||
"revanced_default_playback_speed" -> "revanced_overlay_button_speed_dialog_icon"
|
||||
"revanced_enable_old_quality_layout" -> "revanced_default_video_quality_wifi_icon"
|
||||
"revanced_enable_watch_panel_gestures" -> "revanced_preference_screen_swipe_controls_icon"
|
||||
"revanced_hide_download_button" -> "revanced_overlay_button_external_downloader_icon"
|
||||
"revanced_hide_keyword_content_comments" -> "revanced_hide_quick_actions_comment_button_icon"
|
||||
"revanced_hide_keyword_content_home" -> "revanced_hide_navigation_home_button_icon"
|
||||
"revanced_hide_keyword_content_search" -> "revanced_hide_shorts_shelf_search_icon"
|
||||
"revanced_hide_keyword_content_subscriptions" -> "revanced_hide_navigation_subscriptions_button_icon"
|
||||
"revanced_hide_like_dislike_button" -> "sb_enable_voting_icon"
|
||||
"revanced_hide_navigation_library_button" -> "revanced_preference_screen_video_icon"
|
||||
"revanced_hide_navigation_notifications_button" -> "notification_key_icon"
|
||||
"revanced_hide_navigation_shorts_button" -> "revanced_preference_screen_shorts_icon"
|
||||
"revanced_hide_player_autoplay_button" -> "revanced_change_player_flyout_menu_toggle_icon"
|
||||
"revanced_hide_player_captions_button" -> "captions_key_icon"
|
||||
"revanced_hide_player_flyout_menu_ambient_mode" -> "revanced_preference_screen_ambient_mode_icon"
|
||||
"revanced_hide_player_flyout_menu_captions" -> "captions_key_icon"
|
||||
"revanced_hide_player_flyout_menu_loop_video" -> "revanced_overlay_button_always_repeat_icon"
|
||||
"revanced_hide_player_flyout_menu_more_info" -> "about_key_icon"
|
||||
"revanced_hide_player_flyout_menu_quality_footer" -> "revanced_default_video_quality_wifi_icon"
|
||||
"revanced_hide_player_flyout_menu_report" -> "revanced_hide_report_button_icon"
|
||||
"revanced_hide_player_fullscreen_button" -> "revanced_preference_screen_fullscreen_icon"
|
||||
"revanced_hide_quick_actions_dislike_button" -> "revanced_preference_screen_ryd_icon"
|
||||
"revanced_hide_quick_actions_live_chat_button" -> "live_chat_key_icon"
|
||||
"revanced_hide_quick_actions_save_to_playlist_button" -> "revanced_hide_playlist_button_icon"
|
||||
"revanced_hide_quick_actions_share_button" -> "revanced_hide_shorts_share_button_icon"
|
||||
"revanced_hide_remix_button" -> "revanced_hide_shorts_remix_button_icon"
|
||||
"revanced_hide_share_button" -> "revanced_hide_shorts_share_button_icon"
|
||||
"revanced_hide_shorts_comments_button" -> "revanced_hide_quick_actions_comment_button_icon"
|
||||
"revanced_hide_shorts_dislike_button" -> "revanced_preference_screen_ryd_icon"
|
||||
"revanced_hide_shorts_like_button" -> "revanced_hide_quick_actions_like_button_icon"
|
||||
"revanced_hide_shorts_navigation_bar" -> "revanced_preference_screen_navigation_buttons_icon"
|
||||
"revanced_hide_shorts_shelf_home_related_videos" -> "revanced_hide_navigation_home_button_icon"
|
||||
"revanced_hide_shorts_shelf_subscriptions" -> "revanced_hide_navigation_subscriptions_button_icon"
|
||||
"revanced_hide_shorts_toolbar" -> "revanced_preference_screen_toolbar_icon"
|
||||
"revanced_preference_screen_account_menu" -> "account_switcher_key_icon"
|
||||
"revanced_preference_screen_channel_bar" -> "account_switcher_key_icon"
|
||||
"revanced_preference_screen_channel_profile" -> "account_switcher_key_icon"
|
||||
"revanced_preference_screen_comments" -> "revanced_hide_quick_actions_comment_button_icon"
|
||||
"revanced_preference_screen_feed_flyout_menu" -> "revanced_preference_screen_player_flyout_menu_icon"
|
||||
"revanced_preference_screen_haptic_feedback" -> "revanced_enable_swipe_haptic_feedback_icon"
|
||||
"revanced_preference_screen_patch_information" -> "about_key_icon"
|
||||
"revanced_preference_screen_shorts_player" -> "revanced_preference_screen_shorts_icon"
|
||||
"revanced_preference_screen_video_filter" -> "revanced_preference_screen_video_icon"
|
||||
"revanced_swipe_gestures_lock_mode" -> "revanced_hide_player_flyout_menu_lock_screen_icon"
|
||||
"revanced_disable_hdr_auto_brightness" -> "revanced_disable_hdr_video_icon"
|
||||
else -> "${title}_icon"
|
||||
}
|
||||
}
|
||||
private val intentIcon = intentKey.associateWith { "${it}_icon" }
|
||||
private const val emptyIcon = "empty_icon"
|
||||
|
||||
// endregion.
|
||||
|
||||
}
|
@ -299,12 +299,14 @@ object ShortsComponentPatch : BaseBytecodePatch(
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE_SCREEN: SHORTS",
|
||||
"SETTINGS: SHORTS_COMPONENTS"
|
||||
)
|
||||
var settingArray = arrayOf(
|
||||
"PREFERENCE_SCREEN: SHORTS",
|
||||
"SETTINGS: SHORTS_COMPONENTS"
|
||||
)
|
||||
if (SettingsPatch.upward1834) {
|
||||
settingArray += "SETTINGS: HIDE_SHORTS_COMMENTS_DISABLED_BUTTON"
|
||||
}
|
||||
SettingsPatch.addPreference(settingArray)
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
|
@ -1,60 +0,0 @@
|
||||
package app.revanced.patches.youtube.shorts.outlinebutton
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
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.patch.BaseResourcePatch
|
||||
|
||||
@Suppress("unused")
|
||||
object ShortsOutlineButtonPatch : BaseResourcePatch(
|
||||
name = "Shorts outline button",
|
||||
description = "Applies, at compile time, the outline icon to the action buttons in the Shorts player.",
|
||||
dependencies = setOf(SettingsPatch::class),
|
||||
compatiblePackages = COMPATIBLE_PACKAGE
|
||||
) {
|
||||
override fun execute(context: ResourceContext) {
|
||||
|
||||
arrayOf(
|
||||
"xxxhdpi",
|
||||
"xxhdpi",
|
||||
"xhdpi",
|
||||
"hdpi",
|
||||
"mdpi"
|
||||
).forEach { dpi ->
|
||||
context.copyResources(
|
||||
"youtube/shorts/outline",
|
||||
ResourceGroup(
|
||||
"drawable-$dpi",
|
||||
"ic_remix_filled_white_24.webp",
|
||||
"ic_remix_filled_white_shadowed.webp",
|
||||
"ic_right_comment_shadowed.webp",
|
||||
"ic_right_dislike_off_shadowed.webp",
|
||||
"ic_right_dislike_on_32c.webp",
|
||||
"ic_right_dislike_on_shadowed.webp",
|
||||
"ic_right_like_off_shadowed.webp",
|
||||
"ic_right_like_on_32c.webp",
|
||||
"ic_right_like_on_shadowed.webp",
|
||||
"ic_right_share_shadowed.webp"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
arrayOf(
|
||||
// Shorts outline icons for older versions of YouTube
|
||||
ResourceGroup(
|
||||
"drawable",
|
||||
"ic_right_comment_32c.xml",
|
||||
"ic_right_dislike_off_32c.xml",
|
||||
"ic_right_like_off_32c.xml",
|
||||
"ic_right_share_32c.xml"
|
||||
)
|
||||
).forEach { resourceGroup ->
|
||||
context.copyResources("youtube/shorts/outline", resourceGroup)
|
||||
}
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
|
||||
}
|
||||
}
|
@ -152,7 +152,7 @@ object SwipeControlsPatch : BaseBytecodePatch(
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE_CATEGORY: SWIPE_CONTROLS_EXPERIMENTAL_FLAGS",
|
||||
"SETTINGS: ENABLE_WATCH_PANEL_GESTEURES"
|
||||
"SETTINGS: ENABLE_WATCH_PANEL_GESTURES"
|
||||
)
|
||||
)
|
||||
} ?: println("WARNING: Failed to resolve WatchPanelGesturesFingerprint")
|
||||
|
@ -100,18 +100,33 @@ object ResourceUtils {
|
||||
}
|
||||
}
|
||||
|
||||
fun ResourceContext.addPreferenceFragment(key: String) {
|
||||
fun ResourceContext.addPreferenceFragment(key: String, insertKey: String) {
|
||||
val targetClass =
|
||||
"com.google.android.apps.youtube.app.settings.videoquality.VideoQualitySettingsActivity"
|
||||
|
||||
this.xmlEditor[YOUTUBE_SETTINGS_PATH].use { editor ->
|
||||
with(editor.file) {
|
||||
doRecursively loop@{
|
||||
if (it !is Element) return@loop
|
||||
it.getAttributeNode("android:key")?.let { attribute ->
|
||||
if (attribute.textContent == "@string/about_key" && it.getAttributeNode("app:iconSpaceReserved").textContent == "false") {
|
||||
it.insertNode("Preference", it) {
|
||||
setAttribute("android:title", "@string/" + key + "_title")
|
||||
val processedKeys = mutableSetOf<String>() // To track processed keys
|
||||
|
||||
doRecursively loop@{ node ->
|
||||
if (node !is Element) return@loop // Skip if not an element
|
||||
|
||||
val attributeNode = node.getAttributeNode("android:key")
|
||||
?: return@loop // Skip if no key attribute
|
||||
val currentKey = attributeNode.textContent
|
||||
|
||||
// Check if the current key has already been processed
|
||||
if (processedKeys.contains(currentKey)) {
|
||||
return@loop // Skip if already processed
|
||||
} else {
|
||||
processedKeys.add(currentKey) // Add the current key to processedKeys
|
||||
}
|
||||
|
||||
when (currentKey) {
|
||||
insertKey -> {
|
||||
node.insertNode("Preference", node) {
|
||||
setAttribute("android:key", "${key}_key")
|
||||
setAttribute("android:title", "@string/${key}_title")
|
||||
this.appendChild(
|
||||
ownerDocument.createElement("intent").also { intentNode ->
|
||||
intentNode.setAttribute(
|
||||
@ -120,24 +135,18 @@ object ResourceUtils {
|
||||
)
|
||||
intentNode.setAttribute("android:data", key + "_intent")
|
||||
intentNode.setAttribute("android:targetClass", targetClass)
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
it.getAttributeNode("app:iconSpaceReserved").textContent = "true"
|
||||
return@loop
|
||||
node.setAttribute("app:iconSpaceReserved", "true")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doRecursively loop@{
|
||||
if (it !is Element) return@loop
|
||||
|
||||
it.getAttributeNode("app:iconSpaceReserved")?.let { attribute ->
|
||||
if (attribute.textContent == "true") {
|
||||
attribute.textContent = "false"
|
||||
"true" -> {
|
||||
attributeNode.textContent = "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package app.revanced.patches.youtube.utils.settings
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
|
||||
import app.revanced.patches.shared.elements.StringsElementsUtils.removeStringsElements
|
||||
import app.revanced.patches.shared.mapping.ResourceMappingPatch
|
||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
@ -37,9 +38,48 @@ object SettingsPatch : BaseResourcePatch(
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
requiresIntegrations = true
|
||||
), Closeable {
|
||||
private const val DEFAULT_ELEMENT = "About"
|
||||
private const val DEFAULT_NAME = "ReVanced Extended"
|
||||
|
||||
private val THREAD_COUNT = Runtime.getRuntime().availableProcessors()
|
||||
private val threadPoolExecutor = Executors.newFixedThreadPool(THREAD_COUNT)
|
||||
private val SETTINGS_ELEMENTS_MAP = mapOf(
|
||||
"Parent settings" to "@string/parent_tools_key",
|
||||
"General" to "@string/general_key",
|
||||
"Account" to "@string/account_switcher_key",
|
||||
"Data saving" to "@string/data_saving_settings_key",
|
||||
"Autoplay" to "@string/auto_play_key",
|
||||
"Video quality preferences" to "@string/video_quality_settings_key",
|
||||
"Background" to "@string/offline_key",
|
||||
"Watch on TV" to "@string/pair_with_tv_key",
|
||||
"Manage all history" to "@string/history_key",
|
||||
"Your data in YouTube" to "@string/your_data_key",
|
||||
"Privacy" to "@string/privacy_key",
|
||||
"History & privacy" to "@string/privacy_key",
|
||||
"Try experimental new features" to "@string/premium_early_access_browse_page_key",
|
||||
"Purchases and memberships" to "@string/subscription_product_setting_key",
|
||||
"Billing & payments" to "@string/billing_and_payment_key",
|
||||
"Billing and payments" to "@string/billing_and_payment_key",
|
||||
"Notifications" to "@string/notification_key",
|
||||
"Connected apps" to "@string/connected_accounts_browse_page_key",
|
||||
"Live chat" to "@string/live_chat_key",
|
||||
"Captions" to "@string/captions_key",
|
||||
"Accessibility" to "@string/accessibility_settings_key",
|
||||
DEFAULT_ELEMENT to "@string/about_key"
|
||||
)
|
||||
|
||||
private val InsertPosition by stringPatchOption(
|
||||
key = "InsertPosition",
|
||||
default = DEFAULT_ELEMENT,
|
||||
values = SETTINGS_ELEMENTS_MAP,
|
||||
title = "Insert position",
|
||||
description = "The settings menu name that the RVX settings menu should be above."
|
||||
)
|
||||
|
||||
private val RVXSettingsMenuName by stringPatchOption(
|
||||
key = "RVXSettingsMenuName",
|
||||
default = DEFAULT_NAME,
|
||||
title = "RVX settings menu name",
|
||||
description = "The name of the RVX settings menu."
|
||||
)
|
||||
|
||||
internal lateinit var contexts: ResourceContext
|
||||
internal var upward1831 = false
|
||||
@ -51,48 +91,16 @@ object SettingsPatch : BaseResourcePatch(
|
||||
internal var upward1912 = false
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
|
||||
/**
|
||||
* set resource context
|
||||
*/
|
||||
contexts = context
|
||||
|
||||
val resourceXmlFile = context["res/values/integers.xml"].readBytes()
|
||||
|
||||
for (threadIndex in 0 until THREAD_COUNT) {
|
||||
threadPoolExecutor.execute thread@{
|
||||
context.xmlEditor[resourceXmlFile.inputStream()].use { editor ->
|
||||
val resources = editor.file.documentElement.childNodes
|
||||
val resourcesLength = resources.length
|
||||
val jobSize = resourcesLength / THREAD_COUNT
|
||||
|
||||
val batchStart = jobSize * threadIndex
|
||||
val batchEnd = jobSize * (threadIndex + 1)
|
||||
element@ for (i in batchStart until batchEnd) {
|
||||
if (i >= resourcesLength) return@thread
|
||||
|
||||
val node = resources.item(i)
|
||||
if (node !is Element) continue
|
||||
|
||||
if (node.nodeName != "integer" || !node.getAttribute("name")
|
||||
.startsWith("google_play_services_version")
|
||||
) continue
|
||||
|
||||
val playServicesVersion = node.textContent.toInt()
|
||||
|
||||
upward1831 = 233200000 <= playServicesVersion
|
||||
upward1834 = 233500000 <= playServicesVersion
|
||||
upward1839 = 234000000 <= playServicesVersion
|
||||
upward1842 = 234302000 <= playServicesVersion
|
||||
upward1849 = 235000000 <= playServicesVersion
|
||||
upward1902 = 240204000 < playServicesVersion
|
||||
upward1912 = 241302000 <= playServicesVersion
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
threadPoolExecutor
|
||||
.also { it.shutdown() }
|
||||
.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS)
|
||||
/**
|
||||
* set version info
|
||||
*/
|
||||
setVersionInfo()
|
||||
|
||||
/**
|
||||
* remove strings duplicated with RVX resources
|
||||
@ -138,7 +146,16 @@ object SettingsPatch : BaseResourcePatch(
|
||||
/**
|
||||
* initialize ReVanced Extended Settings
|
||||
*/
|
||||
context.addPreferenceFragment("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
|
||||
@ -164,6 +181,112 @@ object SettingsPatch : BaseResourcePatch(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set revanced-patches version
|
||||
*/
|
||||
val jarManifest = classLoader.getResources("META-INF/MANIFEST.MF")
|
||||
while (jarManifest.hasMoreElements())
|
||||
contexts.updatePatchStatusSettings(
|
||||
"ReVanced Patches",
|
||||
Manifest(jarManifest.nextElement().openStream())
|
||||
.mainAttributes
|
||||
.getValue("Version") + ""
|
||||
)
|
||||
|
||||
/**
|
||||
* set revanced-integrations version
|
||||
*/
|
||||
val versionName = SettingsBytecodePatch.contexts
|
||||
.findClass { it.sourceFile == "BuildConfig.java" }!!
|
||||
.mutableClass
|
||||
.fields
|
||||
.single { it.name == "VERSION_NAME" }
|
||||
.initialValue
|
||||
.toString()
|
||||
.trim()
|
||||
.replace("\"", "")
|
||||
.replace(""", "")
|
||||
|
||||
contexts.updatePatchStatusSettings(
|
||||
"ReVanced Integrations",
|
||||
versionName
|
||||
)
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
/**
|
||||
* 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
|
||||
|
||||
mapOf(
|
||||
"revanced_extended_settings_title" to customName
|
||||
).forEach { (k, v) ->
|
||||
val stringElement = document.createElement("string")
|
||||
|
||||
stringElement.setAttribute("name", k)
|
||||
stringElement.textContent = v
|
||||
|
||||
document.getElementsByTagName("resources").item(0)
|
||||
.appendChild(stringElement)
|
||||
}
|
||||
}
|
||||
}
|
||||
} ?: println("WARNING: Invalid RVX settings menu name. RVX settings menu name does not change.")
|
||||
|
||||
}
|
||||
|
||||
private fun setVersionInfo() {
|
||||
val threadCount = Runtime.getRuntime().availableProcessors()
|
||||
val threadPoolExecutor = Executors.newFixedThreadPool(threadCount)
|
||||
|
||||
val resourceXmlFile = contexts["res/values/integers.xml"].readBytes()
|
||||
|
||||
for (threadIndex in 0 until threadCount) {
|
||||
threadPoolExecutor.execute thread@{
|
||||
contexts.xmlEditor[resourceXmlFile.inputStream()].use { editor ->
|
||||
val resources = editor.file.documentElement.childNodes
|
||||
val resourcesLength = resources.length
|
||||
val jobSize = resourcesLength / threadCount
|
||||
|
||||
val batchStart = jobSize * threadIndex
|
||||
val batchEnd = jobSize * (threadIndex + 1)
|
||||
element@ for (i in batchStart until batchEnd) {
|
||||
if (i >= resourcesLength) return@thread
|
||||
|
||||
val node = resources.item(i)
|
||||
if (node !is Element) continue
|
||||
|
||||
if (node.nodeName != "integer" || !node.getAttribute("name")
|
||||
.startsWith("google_play_services_version")
|
||||
) continue
|
||||
|
||||
val playServicesVersion = node.textContent.toInt()
|
||||
|
||||
upward1831 = 233200000 <= playServicesVersion
|
||||
upward1834 = 233500000 <= playServicesVersion
|
||||
upward1839 = 234000000 <= playServicesVersion
|
||||
upward1842 = 234302000 <= playServicesVersion
|
||||
upward1849 = 235000000 <= playServicesVersion
|
||||
upward1902 = 240204000 < playServicesVersion
|
||||
upward1912 = 241302000 <= playServicesVersion
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
threadPoolExecutor
|
||||
.also { it.shutdown() }
|
||||
.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS)
|
||||
}
|
||||
|
||||
internal fun addPreference(settingArray: Array<String>) {
|
||||
@ -178,39 +301,7 @@ object SettingsPatch : BaseResourcePatch(
|
||||
updatePatchStatus(patch.name!!)
|
||||
}
|
||||
|
||||
internal fun updatePatchStatus(patchTitle: String) {
|
||||
contexts.updatePatchStatus(patchTitle)
|
||||
internal fun updatePatchStatus(patchName: String) {
|
||||
contexts.updatePatchStatus(patchName)
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
|
||||
// region set ReVanced Patches Version
|
||||
|
||||
val jarManifest = classLoader.getResources("META-INF/MANIFEST.MF")
|
||||
while (jarManifest.hasMoreElements())
|
||||
contexts.updatePatchStatusSettings(
|
||||
"ReVanced Patches",
|
||||
Manifest(jarManifest.nextElement().openStream())
|
||||
.mainAttributes
|
||||
.getValue("Version") + ""
|
||||
)
|
||||
|
||||
// endregion
|
||||
|
||||
// region set ReVanced Integrations Version
|
||||
|
||||
val buildConfigMutableClass =
|
||||
SettingsBytecodePatch.contexts.findClass { it.sourceFile == "BuildConfig.java" }!!.mutableClass
|
||||
val versionNameField = buildConfigMutableClass.fields.single { it.name == "VERSION_NAME" }
|
||||
val versionName =
|
||||
versionNameField.initialValue.toString().trim().replace("\"", "").replace(""", "")
|
||||
|
||||
contexts.updatePatchStatusSettings(
|
||||
"ReVanced Integrations",
|
||||
versionName
|
||||
)
|
||||
|
||||
// endregion
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -63,11 +63,14 @@ fun ResourceContext.copyResources(
|
||||
for (resourceGroup in resources) {
|
||||
resourceGroup.resources.forEach { resource ->
|
||||
val resourceFile = "${resourceGroup.resourceDirectoryName}/$resource"
|
||||
Files.copy(
|
||||
inputStreamFromBundledResource(sourceResourceDirectory, resourceFile)!!,
|
||||
targetResourceDirectory.resolve(resourceFile).toPath(),
|
||||
StandardCopyOption.REPLACE_EXISTING,
|
||||
)
|
||||
|
||||
inputStreamFromBundledResource(sourceResourceDirectory, resourceFile)?.let { inputStream ->
|
||||
Files.copy(
|
||||
inputStream,
|
||||
targetResourceDirectory.resolve(resourceFile).toPath(),
|
||||
StandardCopyOption.REPLACE_EXISTING,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 9.3 KiB |
After Width: | Height: | Size: 9.3 KiB |
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 98 B |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 93 B |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 101 B |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 108 B |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 118 B |
After Width: | Height: | Size: 8.7 KiB |
After Width: | Height: | Size: 6.4 KiB |
@ -0,0 +1,788 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108.0dp"
|
||||
android:height="108.0dp"
|
||||
android:viewportWidth="108.0"
|
||||
android:viewportHeight="108.0">
|
||||
<path
|
||||
android:pathData="M0,0h108zM0,1h108zM0,2h108zM0,3h108zM0,4h108zM0,5h108zM0,6h108zM0,7h108zM0,8h108zM0,9h108zM0,10h108zM0,11h108zM0,12h108zM0,13h108zM0,14h108zM0,15h108zM0,16h108zM0,17h108zM0,18h108zM0,19h108zM0,20h108zM0,21h108zM0,22h108zM0,23h108zM0,24h108zM0,25h108zM0,26h108zM0,27h108zM0,28h108zM0,29h108zM0,30h108zM0,31h108zM0,32h108zM0,33h108zM0,34h108zM0,35h108zM0,36h53zM60,36h48zM0,37h48zM64,37h44zM0,38h47zM65,38h43zM0,39h45zM67,39h41zM0,40h44zM69,40h39zM0,41h34zM39,41h4zM69,41h39zM0,42h33zM41,42h1zM70,42h38zM0,43h33zM71,43h37zM0,44h32zM72,44h36zM0,45h32zM72,45h36zM0,46h32zM42,46h2zM73,46h35zM0,47h32zM41,47h4zM54,47h4zM73,47h35zM0,48h32zM41,48h6zM51,48h10zM74,48h34zM0,49h32zM41,49h6zM53,49h9zM74,49h34zM0,50h32zM40,50h7zM55,50h8zM74,50h34zM0,51h32zM40,51h7zM56,51h7zM75,51h33zM0,52h32zM39,52h7zM57,52h6zM75,52h33zM0,53h32zM39,53h7zM57,53h7zM75,53h33zM0,54h32zM39,54h7zM58,54h6zM75,54h33zM0,55h32zM39,55h7zM58,55h6zM75,55h33zM0,56h32zM39,56h7zM57,56h6zM75,56h33zM0,57h32zM40,57h7zM57,57h6zM75,57h33zM0,58h32zM40,58h7zM56,58h7zM74,58h34zM0,59h32zM41,59h6zM53,59h9zM74,59h34zM0,60h32zM41,60h7zM52,60h9zM74,60h34zM0,61h32zM41,61h4zM53,61h6zM73,61h35zM0,62h32zM41,62h3zM55,62h1zM73,62h35zM0,63h32zM73,63h35zM0,64h32zM72,64h36zM0,65h33zM72,65h36zM0,66h33zM71,66h37zM0,67h34zM39,67h3zM70,67h38zM0,68h35zM38,68h5zM69,68h39zM0,69h45zM68,69h40zM0,70h47zM66,70h42zM0,71h48zM64,71h44zM0,72h51zM61,72h47zM0,73h108zM0,74h108zM0,75h108zM0,76h108zM0,77h108zM0,78h108zM0,79h108zM0,80h108zM0,81h108zM0,82h108zM0,83h108zM0,84h108zM0,85h108zM0,86h108zM0,87h108zM0,88h108zM0,89h108zM0,90h108zM0,91h108zM0,92h108zM0,93h108zM0,94h108zM0,95h108zM0,96h108zM0,97h108zM0,98h108zM0,99h108zM0,100h108zM0,101h108zM0,102h108zM0,103h108zM0,104h108zM0,105h108zM0,106h108zM0,107h108z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M53,36h1zM73,48h1zM47,50h1zM54,50h1zM74,52h1zM74,53h1zM51,60h1z"
|
||||
android:strokeColor="#05000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M54,36h1zM57,36h1zM46,54h1zM56,56h1zM47,58h1zM52,72h1z"
|
||||
android:strokeColor="#09000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M55,36h1zM55,46h1zM52,47h1zM54,58h1zM52,59h1zM38,67h1z"
|
||||
android:strokeColor="#10000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M56,36h1zM49,37h1zM44,46h1zM40,48h1zM71,64h1zM66,69h1zM63,71h1z"
|
||||
android:strokeColor="#0f000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M58,36h1zM64,38h1zM66,39h1zM33,42h1zM71,44h1zM72,46h1zM47,48h1zM40,49h1zM54,62h1zM36,68h1z"
|
||||
android:strokeColor="#04000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M59,36h1zM68,40h1zM34,41h1zM38,41h1zM53,47h1zM58,47h1zM47,49h1zM46,52h1zM57,55h1zM39,57h1zM56,57h1zM45,61h1zM59,61h1zM56,62h1zM72,63h1zM71,65h1zM70,66h1zM42,67h1zM69,67h1zM67,69h1zM65,70h1zM51,72h1z"
|
||||
android:strokeColor="#01000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M48,37h1zM63,37h1zM45,39h1zM32,44h1zM41,46h1zM52,49h1zM56,52h1zM63,56h1zM74,57h1zM52,61h1zM57,62h1zM41,66h1z"
|
||||
android:strokeColor="#03000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M50,37h1zM39,58h1zM54,72h1z"
|
||||
android:strokeColor="#29000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M51,37h1zM50,60h1z"
|
||||
android:strokeColor="#57000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M52,37h1zM43,45h1z"
|
||||
android:strokeColor="#6f000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M53,37h1zM43,42h1zM52,46h1zM73,52h1zM38,57h1z"
|
||||
android:strokeColor="#9f000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M54,37h1zM67,41h1z"
|
||||
android:strokeColor="#b9000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M55,37h1zM35,42h1zM63,49h1zM52,58h1z"
|
||||
android:strokeColor="#c1000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M56,37h1zM42,44h1zM73,55h1zM68,66h1z"
|
||||
android:strokeColor="#c2000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M57,37h1zM49,38h1zM63,70h1z"
|
||||
android:strokeColor="#b8000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M58,37h1z"
|
||||
android:strokeColor="#98000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M59,37h1z"
|
||||
android:strokeColor="#7c000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M60,37h1z"
|
||||
android:strokeColor="#59000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M61,37h1zM49,71h1zM57,72h1z"
|
||||
android:strokeColor="#30000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M62,37h1zM37,41h1zM60,61h1z"
|
||||
android:strokeColor="#15000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,38h1zM40,42h1zM45,47h1zM46,53h1zM32,64h1z"
|
||||
android:strokeColor="#07000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M48,38h1z"
|
||||
android:strokeColor="#69000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M50,38h1zM43,64h1z"
|
||||
android:strokeColor="#ed000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M51,38h1zM48,47h1zM39,65h1z"
|
||||
android:strokeColor="#f6000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M52,38h1zM59,38h1zM64,40h1zM69,44h1zM59,45h1zM49,47h1zM48,52h1zM37,55h1zM55,55h1zM54,56h1zM36,66h1zM45,67h1zM50,70h1z"
|
||||
android:strokeColor="#fb000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M53,38h1zM58,38h1zM35,43h1zM44,43h1zM34,44h1zM39,44h1zM44,44h1zM39,45h1zM46,45h1zM51,45h1zM50,46h1zM62,46h1zM70,47h1zM64,49h1zM71,49h1zM37,51h1zM52,51h1zM37,52h1zM53,52h1zM37,56h1zM53,56h1zM37,57h1zM71,59h1zM70,61h1zM62,62h1zM39,63h1zM34,64h1zM39,64h1zM54,64h1zM56,64h2zM44,65h1zM67,66h1zM66,67h1zM64,68h1zM63,69h1zM52,70h1z"
|
||||
android:strokeColor="#fe000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M54,38h4zM49,39h14zM48,40h16zM46,41h20zM45,42h22zM36,43h2zM45,43h23zM35,44h4zM45,44h24zM34,45h5zM47,45h4zM60,45h10zM34,46h5zM48,46h2zM63,46h7zM34,47h5zM63,47h7zM34,48h5zM64,48h7zM34,49h5zM65,49h6zM34,50h4zM65,50h7zM34,51h3zM49,51h3zM65,51h8zM34,52h3zM49,52h4zM65,52h8zM34,53h3zM48,53h7zM66,53h7zM34,54h3zM48,54h7zM66,54h7zM34,55h3zM48,55h7zM66,55h7zM34,56h3zM49,56h4zM65,56h8zM34,57h3zM49,57h4zM65,57h8zM34,58h4zM50,58h1zM65,58h7zM34,59h5zM65,59h6zM34,60h5zM64,60h7zM34,61h5zM63,61h7zM34,62h5zM48,62h2zM63,62h7zM34,63h5zM47,63h4zM61,63h9zM35,64h4zM45,64h9zM55,64h1zM58,64h11zM35,65h4zM45,65h23zM45,66h22zM46,67h20zM48,68h16zM48,69h15zM53,70h7z"
|
||||
android:strokeColor="#ff000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M60,38h1zM47,40h1zM66,41h1zM43,44h1zM39,46h1zM64,50h1zM65,53h1zM60,63h1zM40,64h1z"
|
||||
android:strokeColor="#fa000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M61,38h1zM49,59h1zM39,61h1zM59,63h1z"
|
||||
android:strokeColor="#ec000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M62,38h1z"
|
||||
android:strokeColor="#c5000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M63,38h1zM39,59h1zM65,69h1z"
|
||||
android:strokeColor="#6d000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M46,39h1zM39,42h1zM64,70h1z"
|
||||
android:strokeColor="#2e000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,39h1zM42,43h1z"
|
||||
android:strokeColor="#86000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M48,39h1zM63,39h1zM45,45h1zM62,61h1zM37,66h1z"
|
||||
android:strokeColor="#f1000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M64,39h1zM40,43h1zM33,44h1z"
|
||||
android:strokeColor="#97000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M65,39h1zM55,72h1z"
|
||||
android:strokeColor="#33000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M44,40h1zM32,45h1zM59,47h1zM39,51h1zM40,60h1zM32,63h1z"
|
||||
android:strokeColor="#0a000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M45,40h1z"
|
||||
android:strokeColor="#80000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M46,40h1zM50,47h1zM53,51h1z"
|
||||
android:strokeColor="#dd000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M65,40h1z"
|
||||
android:strokeColor="#e5000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M66,40h1z"
|
||||
android:strokeColor="#82000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M67,40h1z"
|
||||
android:strokeColor="#1a000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M35,41h1zM69,42h1zM48,71h1z"
|
||||
android:strokeColor="#0e000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M36,41h1z"
|
||||
android:strokeColor="#26000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M43,41h1zM46,61h1z"
|
||||
android:strokeColor="#12000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M44,41h1z"
|
||||
android:strokeColor="#8b000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M45,41h1zM72,50h1z"
|
||||
android:strokeColor="#f3000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M68,41h1zM53,50h1z"
|
||||
android:strokeColor="#22000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M34,42h1z"
|
||||
android:strokeColor="#3e000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M36,42h1zM39,43h1zM49,70h1zM54,71h1z"
|
||||
android:strokeColor="#e3000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M37,42h1zM44,67h1z"
|
||||
android:strokeColor="#cc000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M38,42h1zM64,53h1z"
|
||||
android:strokeColor="#6e000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M42,42h1zM56,46h1zM72,62h1z"
|
||||
android:strokeColor="#0d000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M44,42h1zM65,55h1zM39,62h1zM61,62h1zM70,63h1z"
|
||||
android:strokeColor="#f7000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M67,42h1zM52,45h1zM70,46h1zM49,50h2zM37,53h1zM71,60h1zM46,63h1zM44,64h1zM43,65h1zM68,65h1zM51,70h1z"
|
||||
android:strokeColor="#fc000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M68,42h1zM72,60h1z"
|
||||
android:strokeColor="#a2000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M33,43h1zM43,63h1z"
|
||||
android:strokeColor="#44000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M34,43h1zM54,45h1zM46,46h1zM49,49h1z"
|
||||
android:strokeColor="#dc000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M38,43h1zM40,44h1zM62,47h1zM37,54h1zM72,58h1z"
|
||||
android:strokeColor="#f9000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M41,43h1zM47,51h1z"
|
||||
android:strokeColor="#2c000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M43,43h1zM68,43h1zM71,48h1zM50,62h1zM65,68h1zM61,70h1z"
|
||||
android:strokeColor="#f8000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M69,43h1zM62,48h1z"
|
||||
android:strokeColor="#92000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M70,43h1zM40,66h1z"
|
||||
android:strokeColor="#11000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M41,44h1z"
|
||||
android:strokeColor="#b5000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M70,44h1z"
|
||||
android:strokeColor="#79000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M33,45h1zM33,52h1zM33,56h1zM58,63h1z"
|
||||
android:strokeColor="#c9000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M40,45h1zM51,50h1z"
|
||||
android:strokeColor="#d7000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M41,45h1zM46,47h1zM45,62h1z"
|
||||
android:strokeColor="#37000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M42,45h1z"
|
||||
android:strokeColor="#16000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M44,45h1zM47,54h1z"
|
||||
android:strokeColor="#b6000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M53,45h1zM34,65h1z"
|
||||
android:strokeColor="#ee000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M55,45h1zM33,48h1zM33,60h1zM53,63h1z"
|
||||
android:strokeColor="#cb000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M56,45h1zM33,51h1zM33,57h1z"
|
||||
android:strokeColor="#c7000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M57,45h1z"
|
||||
android:strokeColor="#d1000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M58,45h1zM56,71h1z"
|
||||
android:strokeColor="#eb000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M70,45h1zM48,51h1z"
|
||||
android:strokeColor="#ea000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M71,45h1zM70,65h1zM56,72h1z"
|
||||
android:strokeColor="#36000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M32,46h1zM32,47h1zM32,48h1zM32,49h1zM32,50h1zM32,51h1zM32,52h1zM32,53h1zM32,54h1zM74,54h1zM32,55h1zM32,56h1zM32,57h1zM32,58h1zM32,59h1zM62,59h1zM32,60h1zM61,60h1zM32,61h1zM32,62h1zM33,66h1z"
|
||||
android:strokeColor="#0b000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M33,46h1zM33,49h1zM33,54h1zM48,58h1zM33,59h1zM33,62h1z"
|
||||
android:strokeColor="#c6000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M40,46h1z"
|
||||
android:strokeColor="#77000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M45,46h1zM38,55h1z"
|
||||
android:strokeColor="#6b000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,46h1zM61,46h1zM55,54h1zM48,56h1zM49,58h1zM64,59h1zM70,62h1zM51,63h1zM69,64h1zM44,66h1zM47,68h1zM60,70h1z"
|
||||
android:strokeColor="#fd000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M51,46h1zM63,60h1z"
|
||||
android:strokeColor="#e7000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M53,46h1zM64,54h1z"
|
||||
android:strokeColor="#4e000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M54,46h1z"
|
||||
android:strokeColor="#2a000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M57,46h1zM53,62h1z"
|
||||
android:strokeColor="#1b000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M58,46h1zM63,58h1z"
|
||||
android:strokeColor="#45000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M59,46h1z"
|
||||
android:strokeColor="#95000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M60,46h1z"
|
||||
android:strokeColor="#e0000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M71,46h1z"
|
||||
android:strokeColor="#93000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M33,47h1zM33,61h1z"
|
||||
android:strokeColor="#ca000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M39,47h1zM65,54h1zM51,58h1zM46,68h1z"
|
||||
android:strokeColor="#f2000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M40,47h1zM55,57h1z"
|
||||
android:strokeColor="#40000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,47h1z"
|
||||
android:strokeColor="#a8000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M51,47h1zM68,67h1z"
|
||||
android:strokeColor="#4c000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M60,47h1zM50,48h1z"
|
||||
android:strokeColor="#48000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M61,47h1zM64,69h1z"
|
||||
android:strokeColor="#df000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M71,47h1zM53,71h1z"
|
||||
android:strokeColor="#d4000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M72,47h1zM61,48h1zM73,59h1z"
|
||||
android:strokeColor="#24000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M39,48h1zM40,65h1z"
|
||||
android:strokeColor="#c4000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M48,48h1z"
|
||||
android:strokeColor="#52000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M49,48h1zM64,57h1z"
|
||||
android:strokeColor="#c3000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M63,48h1zM38,50h1zM53,57h1zM49,61h1z"
|
||||
android:strokeColor="#f5000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M72,48h1z"
|
||||
android:strokeColor="#7f000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M39,49h1zM42,64h1z"
|
||||
android:strokeColor="#88000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M48,49h1zM67,68h1z"
|
||||
android:strokeColor="#43000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M50,49h1zM42,65h1z"
|
||||
android:strokeColor="#ac000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M51,49h1z"
|
||||
android:strokeColor="#25000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M62,49h1zM51,61h1zM69,66h1z"
|
||||
android:strokeColor="#1e000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M72,49h1zM33,50h1zM33,58h1z"
|
||||
android:strokeColor="#ce000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M73,49h1z"
|
||||
android:strokeColor="#17000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M39,50h1zM48,60h1zM43,67h1z"
|
||||
android:strokeColor="#3d000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M48,50h1zM48,70h1z"
|
||||
android:strokeColor="#af000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M52,50h1zM73,57h1z"
|
||||
android:strokeColor="#8d000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M63,50h1zM47,61h1z"
|
||||
android:strokeColor="#5c000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M73,50h1z"
|
||||
android:strokeColor="#4d000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M38,51h1z"
|
||||
android:strokeColor="#b2000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M54,51h1z"
|
||||
android:strokeColor="#75000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M55,51h1z"
|
||||
android:strokeColor="#18000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M63,51h1z"
|
||||
android:strokeColor="#13000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M64,51h1z"
|
||||
android:strokeColor="#d2000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M73,51h1z"
|
||||
android:strokeColor="#81000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M74,51h1zM57,54h1zM46,56h1zM55,58h1zM40,59h1zM47,59h1zM44,62h1zM35,68h1zM37,68h1zM43,68h1zM60,72h1z"
|
||||
android:strokeColor="#02000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M38,52h1z"
|
||||
android:strokeColor="#94000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,52h1zM46,69h1z"
|
||||
android:strokeColor="#5b000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M54,52h1zM48,57h1zM47,62h1z"
|
||||
android:strokeColor="#f0000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M55,52h1z"
|
||||
android:strokeColor="#7d000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M63,52h1zM74,55h1zM74,56h1zM42,63h1zM34,67h1zM68,68h1z"
|
||||
android:strokeColor="#06000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M64,52h1zM61,61h1zM54,63h1z"
|
||||
android:strokeColor="#a1000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M33,53h1zM33,55h1zM33,63h1zM47,69h1z"
|
||||
android:strokeColor="#cd000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M38,53h1z"
|
||||
android:strokeColor="#78000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,53h1z"
|
||||
android:strokeColor="#9b000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M55,53h1zM64,58h1zM52,63h1z"
|
||||
android:strokeColor="#f4000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M56,53h1z"
|
||||
android:strokeColor="#2d000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M73,53h1z"
|
||||
android:strokeColor="#bf000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M38,54h1zM33,65h1zM41,65h1z"
|
||||
android:strokeColor="#61000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M56,54h1z"
|
||||
android:strokeColor="#74000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M73,54h1zM38,66h1z"
|
||||
android:strokeColor="#ba000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M46,55h1z"
|
||||
android:strokeColor="#08000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,55h1z"
|
||||
android:strokeColor="#a6000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M56,55h1z"
|
||||
android:strokeColor="#47000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M64,55h1z"
|
||||
android:strokeColor="#63000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M38,56h1zM64,56h1zM55,63h2z"
|
||||
android:strokeColor="#90000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,56h1z"
|
||||
android:strokeColor="#73000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M55,56h1z"
|
||||
android:strokeColor="#b0000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M73,56h1zM46,62h1z"
|
||||
android:strokeColor="#a9000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,57h1z"
|
||||
android:strokeColor="#3a000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M54,57h1z"
|
||||
android:strokeColor="#ae000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M63,57h1zM73,60h1zM45,69h1zM59,72h1z"
|
||||
android:strokeColor="#0c000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M38,58h1zM48,61h1zM67,67h1z"
|
||||
android:strokeColor="#e4000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M53,58h1z"
|
||||
android:strokeColor="#49000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M73,58h1zM34,66h1z"
|
||||
android:strokeColor="#65000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M48,59h1z"
|
||||
android:strokeColor="#5d000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M50,59h1z"
|
||||
android:strokeColor="#db000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M51,59h1zM40,62h1zM52,62h1z"
|
||||
android:strokeColor="#62000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M63,59h1z"
|
||||
android:strokeColor="#a0000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M72,59h1z"
|
||||
android:strokeColor="#e2000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M39,60h1zM71,62h1zM70,64h1z"
|
||||
android:strokeColor="#b4000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M49,60h1z"
|
||||
android:strokeColor="#b7000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M62,60h1z"
|
||||
android:strokeColor="#67000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M40,61h1z"
|
||||
android:strokeColor="#34000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M50,61h1z"
|
||||
android:strokeColor="#b3000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M71,61h1z"
|
||||
android:strokeColor="#e6000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M72,61h1z"
|
||||
android:strokeColor="#3c000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M51,62h1zM40,63h1z"
|
||||
android:strokeColor="#be000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M58,62h1z"
|
||||
android:strokeColor="#14000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M59,62h1z"
|
||||
android:strokeColor="#4a000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M60,62h1z"
|
||||
android:strokeColor="#a3000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M41,63h1zM44,68h1z"
|
||||
android:strokeColor="#20000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M44,63h1z"
|
||||
android:strokeColor="#85000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M45,63h1z"
|
||||
android:strokeColor="#da000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M57,63h1z"
|
||||
android:strokeColor="#9c000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M71,63h1zM50,71h1z"
|
||||
android:strokeColor="#51000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M33,64h1zM52,71h1z"
|
||||
android:strokeColor="#ad000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M41,64h1z"
|
||||
android:strokeColor="#9d000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M69,65h1z"
|
||||
android:strokeColor="#bc000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M35,66h1zM55,71h1zM57,71h1z"
|
||||
android:strokeColor="#e8000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M39,66h1z"
|
||||
android:strokeColor="#58000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M42,66h1zM58,72h1z"
|
||||
android:strokeColor="#1c000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M43,66h1z"
|
||||
android:strokeColor="#c8000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M35,67h1z"
|
||||
android:strokeColor="#4b000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M36,67h1z"
|
||||
android:strokeColor="#84000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M37,67h1z"
|
||||
android:strokeColor="#5a000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M45,68h1z"
|
||||
android:strokeColor="#aa000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M66,68h1z"
|
||||
android:strokeColor="#b1000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,70h1z"
|
||||
android:strokeColor="#28000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M62,70h1z"
|
||||
android:strokeColor="#e9000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M51,71h1z"
|
||||
android:strokeColor="#8c000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M58,71h1z"
|
||||
android:strokeColor="#d8000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M59,71h1z"
|
||||
android:strokeColor="#bb000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M60,71h1z"
|
||||
android:strokeColor="#8e000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M61,71h1z"
|
||||
android:strokeColor="#54000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M62,71h1z"
|
||||
android:strokeColor="#38000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M53,72h1z"
|
||||
android:strokeColor="#19000000"
|
||||
android:strokeWidth="1.0" />
|
||||
</vector>
|
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 8.4 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 9.8 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 9.8 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 98 B |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 93 B |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 101 B |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 108 B |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 118 B |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 8.0 KiB |
@ -0,0 +1,788 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108.0dp"
|
||||
android:height="108.0dp"
|
||||
android:viewportWidth="108.0"
|
||||
android:viewportHeight="108.0">
|
||||
<path
|
||||
android:pathData="M0,0h108zM0,1h108zM0,2h108zM0,3h108zM0,4h108zM0,5h108zM0,6h108zM0,7h108zM0,8h108zM0,9h108zM0,10h108zM0,11h108zM0,12h108zM0,13h108zM0,14h108zM0,15h108zM0,16h108zM0,17h108zM0,18h108zM0,19h108zM0,20h108zM0,21h108zM0,22h108zM0,23h108zM0,24h108zM0,25h108zM0,26h108zM0,27h108zM0,28h108zM0,29h108zM0,30h108zM0,31h108zM0,32h108zM0,33h108zM0,34h108zM0,35h108zM0,36h53zM60,36h48zM0,37h48zM64,37h44zM0,38h47zM65,38h43zM0,39h45zM67,39h41zM0,40h44zM69,40h39zM0,41h34zM39,41h4zM69,41h39zM0,42h33zM41,42h1zM70,42h38zM0,43h33zM71,43h37zM0,44h32zM72,44h36zM0,45h32zM72,45h36zM0,46h32zM42,46h2zM73,46h35zM0,47h32zM41,47h4zM54,47h4zM73,47h35zM0,48h32zM41,48h6zM51,48h10zM74,48h34zM0,49h32zM41,49h6zM53,49h9zM74,49h34zM0,50h32zM40,50h7zM55,50h8zM74,50h34zM0,51h32zM40,51h7zM56,51h7zM75,51h33zM0,52h32zM39,52h7zM57,52h6zM75,52h33zM0,53h32zM39,53h7zM57,53h7zM75,53h33zM0,54h32zM39,54h7zM58,54h6zM75,54h33zM0,55h32zM39,55h7zM58,55h6zM75,55h33zM0,56h32zM39,56h7zM57,56h6zM75,56h33zM0,57h32zM40,57h7zM57,57h6zM75,57h33zM0,58h32zM40,58h7zM56,58h7zM74,58h34zM0,59h32zM41,59h6zM53,59h9zM74,59h34zM0,60h32zM41,60h7zM52,60h9zM74,60h34zM0,61h32zM41,61h4zM53,61h6zM73,61h35zM0,62h32zM41,62h3zM55,62h1zM73,62h35zM0,63h32zM73,63h35zM0,64h32zM72,64h36zM0,65h33zM72,65h36zM0,66h33zM71,66h37zM0,67h34zM39,67h3zM70,67h38zM0,68h35zM38,68h5zM69,68h39zM0,69h45zM68,69h40zM0,70h47zM66,70h42zM0,71h48zM64,71h44zM0,72h51zM61,72h47zM0,73h108zM0,74h108zM0,75h108zM0,76h108zM0,77h108zM0,78h108zM0,79h108zM0,80h108zM0,81h108zM0,82h108zM0,83h108zM0,84h108zM0,85h108zM0,86h108zM0,87h108zM0,88h108zM0,89h108zM0,90h108zM0,91h108zM0,92h108zM0,93h108zM0,94h108zM0,95h108zM0,96h108zM0,97h108zM0,98h108zM0,99h108zM0,100h108zM0,101h108zM0,102h108zM0,103h108zM0,104h108zM0,105h108zM0,106h108zM0,107h108z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M53,36h1zM73,48h1zM47,50h1zM54,50h1zM74,52h1zM74,53h1zM51,60h1z"
|
||||
android:strokeColor="#05000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M54,36h1zM57,36h1zM46,54h1zM56,56h1zM47,58h1zM52,72h1z"
|
||||
android:strokeColor="#09000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M55,36h1zM55,46h1zM52,47h1zM54,58h1zM52,59h1zM38,67h1z"
|
||||
android:strokeColor="#10000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M56,36h1zM49,37h1zM44,46h1zM40,48h1zM71,64h1zM66,69h1zM63,71h1z"
|
||||
android:strokeColor="#0f000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M58,36h1zM64,38h1zM66,39h1zM33,42h1zM71,44h1zM72,46h1zM47,48h1zM40,49h1zM54,62h1zM36,68h1z"
|
||||
android:strokeColor="#04000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M59,36h1zM68,40h1zM34,41h1zM38,41h1zM53,47h1zM58,47h1zM47,49h1zM46,52h1zM57,55h1zM39,57h1zM56,57h1zM45,61h1zM59,61h1zM56,62h1zM72,63h1zM71,65h1zM70,66h1zM42,67h1zM69,67h1zM67,69h1zM65,70h1zM51,72h1z"
|
||||
android:strokeColor="#01000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M48,37h1zM63,37h1zM45,39h1zM32,44h1zM41,46h1zM52,49h1zM56,52h1zM63,56h1zM74,57h1zM52,61h1zM57,62h1zM41,66h1z"
|
||||
android:strokeColor="#03000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M50,37h1zM39,58h1zM54,72h1z"
|
||||
android:strokeColor="#29000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M51,37h1zM50,60h1z"
|
||||
android:strokeColor="#57000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M52,37h1zM43,45h1z"
|
||||
android:strokeColor="#6f000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M53,37h1zM43,42h1zM52,46h1zM73,52h1zM38,57h1z"
|
||||
android:strokeColor="#9f000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M54,37h1zM67,41h1z"
|
||||
android:strokeColor="#b9000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M55,37h1zM35,42h1zM63,49h1zM52,58h1z"
|
||||
android:strokeColor="#c1000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M56,37h1zM42,44h1zM73,55h1zM68,66h1z"
|
||||
android:strokeColor="#c2000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M57,37h1zM49,38h1zM63,70h1z"
|
||||
android:strokeColor="#b8000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M58,37h1z"
|
||||
android:strokeColor="#98000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M59,37h1z"
|
||||
android:strokeColor="#7c000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M60,37h1z"
|
||||
android:strokeColor="#59000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M61,37h1zM49,71h1zM57,72h1z"
|
||||
android:strokeColor="#30000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M62,37h1zM37,41h1zM60,61h1z"
|
||||
android:strokeColor="#15000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,38h1zM40,42h1zM45,47h1zM46,53h1zM32,64h1z"
|
||||
android:strokeColor="#07000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M48,38h1z"
|
||||
android:strokeColor="#69000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M50,38h1zM43,64h1z"
|
||||
android:strokeColor="#ed000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M51,38h1zM48,47h1zM39,65h1z"
|
||||
android:strokeColor="#f6000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M52,38h1zM59,38h1zM64,40h1zM69,44h1zM59,45h1zM49,47h1zM48,52h1zM37,55h1zM55,55h1zM54,56h1zM36,66h1zM45,67h1zM50,70h1z"
|
||||
android:strokeColor="#fb000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M53,38h1zM58,38h1zM35,43h1zM44,43h1zM34,44h1zM39,44h1zM44,44h1zM39,45h1zM46,45h1zM51,45h1zM50,46h1zM62,46h1zM70,47h1zM64,49h1zM71,49h1zM37,51h1zM52,51h1zM37,52h1zM53,52h1zM37,56h1zM53,56h1zM37,57h1zM71,59h1zM70,61h1zM62,62h1zM39,63h1zM34,64h1zM39,64h1zM54,64h1zM56,64h2zM44,65h1zM67,66h1zM66,67h1zM64,68h1zM63,69h1zM52,70h1z"
|
||||
android:strokeColor="#fe000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M54,38h4zM49,39h14zM48,40h16zM46,41h20zM45,42h22zM36,43h2zM45,43h23zM35,44h4zM45,44h24zM34,45h5zM47,45h4zM60,45h10zM34,46h5zM48,46h2zM63,46h7zM34,47h5zM63,47h7zM34,48h5zM64,48h7zM34,49h5zM65,49h6zM34,50h4zM65,50h7zM34,51h3zM49,51h3zM65,51h8zM34,52h3zM49,52h4zM65,52h8zM34,53h3zM48,53h7zM66,53h7zM34,54h3zM48,54h7zM66,54h7zM34,55h3zM48,55h7zM66,55h7zM34,56h3zM49,56h4zM65,56h8zM34,57h3zM49,57h4zM65,57h8zM34,58h4zM50,58h1zM65,58h7zM34,59h5zM65,59h6zM34,60h5zM64,60h7zM34,61h5zM63,61h7zM34,62h5zM48,62h2zM63,62h7zM34,63h5zM47,63h4zM61,63h9zM35,64h4zM45,64h9zM55,64h1zM58,64h11zM35,65h4zM45,65h23zM45,66h22zM46,67h20zM48,68h16zM48,69h15zM53,70h7z"
|
||||
android:strokeColor="#ff000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M60,38h1zM47,40h1zM66,41h1zM43,44h1zM39,46h1zM64,50h1zM65,53h1zM60,63h1zM40,64h1z"
|
||||
android:strokeColor="#fa000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M61,38h1zM49,59h1zM39,61h1zM59,63h1z"
|
||||
android:strokeColor="#ec000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M62,38h1z"
|
||||
android:strokeColor="#c5000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M63,38h1zM39,59h1zM65,69h1z"
|
||||
android:strokeColor="#6d000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M46,39h1zM39,42h1zM64,70h1z"
|
||||
android:strokeColor="#2e000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,39h1zM42,43h1z"
|
||||
android:strokeColor="#86000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M48,39h1zM63,39h1zM45,45h1zM62,61h1zM37,66h1z"
|
||||
android:strokeColor="#f1000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M64,39h1zM40,43h1zM33,44h1z"
|
||||
android:strokeColor="#97000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M65,39h1zM55,72h1z"
|
||||
android:strokeColor="#33000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M44,40h1zM32,45h1zM59,47h1zM39,51h1zM40,60h1zM32,63h1z"
|
||||
android:strokeColor="#0a000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M45,40h1z"
|
||||
android:strokeColor="#80000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M46,40h1zM50,47h1zM53,51h1z"
|
||||
android:strokeColor="#dd000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M65,40h1z"
|
||||
android:strokeColor="#e5000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M66,40h1z"
|
||||
android:strokeColor="#82000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M67,40h1z"
|
||||
android:strokeColor="#1a000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M35,41h1zM69,42h1zM48,71h1z"
|
||||
android:strokeColor="#0e000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M36,41h1z"
|
||||
android:strokeColor="#26000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M43,41h1zM46,61h1z"
|
||||
android:strokeColor="#12000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M44,41h1z"
|
||||
android:strokeColor="#8b000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M45,41h1zM72,50h1z"
|
||||
android:strokeColor="#f3000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M68,41h1zM53,50h1z"
|
||||
android:strokeColor="#22000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M34,42h1z"
|
||||
android:strokeColor="#3e000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M36,42h1zM39,43h1zM49,70h1zM54,71h1z"
|
||||
android:strokeColor="#e3000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M37,42h1zM44,67h1z"
|
||||
android:strokeColor="#cc000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M38,42h1zM64,53h1z"
|
||||
android:strokeColor="#6e000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M42,42h1zM56,46h1zM72,62h1z"
|
||||
android:strokeColor="#0d000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M44,42h1zM65,55h1zM39,62h1zM61,62h1zM70,63h1z"
|
||||
android:strokeColor="#f7000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M67,42h1zM52,45h1zM70,46h1zM49,50h2zM37,53h1zM71,60h1zM46,63h1zM44,64h1zM43,65h1zM68,65h1zM51,70h1z"
|
||||
android:strokeColor="#fc000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M68,42h1zM72,60h1z"
|
||||
android:strokeColor="#a2000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M33,43h1zM43,63h1z"
|
||||
android:strokeColor="#44000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M34,43h1zM54,45h1zM46,46h1zM49,49h1z"
|
||||
android:strokeColor="#dc000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M38,43h1zM40,44h1zM62,47h1zM37,54h1zM72,58h1z"
|
||||
android:strokeColor="#f9000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M41,43h1zM47,51h1z"
|
||||
android:strokeColor="#2c000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M43,43h1zM68,43h1zM71,48h1zM50,62h1zM65,68h1zM61,70h1z"
|
||||
android:strokeColor="#f8000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M69,43h1zM62,48h1z"
|
||||
android:strokeColor="#92000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M70,43h1zM40,66h1z"
|
||||
android:strokeColor="#11000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M41,44h1z"
|
||||
android:strokeColor="#b5000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M70,44h1z"
|
||||
android:strokeColor="#79000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M33,45h1zM33,52h1zM33,56h1zM58,63h1z"
|
||||
android:strokeColor="#c9000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M40,45h1zM51,50h1z"
|
||||
android:strokeColor="#d7000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M41,45h1zM46,47h1zM45,62h1z"
|
||||
android:strokeColor="#37000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M42,45h1z"
|
||||
android:strokeColor="#16000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M44,45h1zM47,54h1z"
|
||||
android:strokeColor="#b6000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M53,45h1zM34,65h1z"
|
||||
android:strokeColor="#ee000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M55,45h1zM33,48h1zM33,60h1zM53,63h1z"
|
||||
android:strokeColor="#cb000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M56,45h1zM33,51h1zM33,57h1z"
|
||||
android:strokeColor="#c7000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M57,45h1z"
|
||||
android:strokeColor="#d1000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M58,45h1zM56,71h1z"
|
||||
android:strokeColor="#eb000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M70,45h1zM48,51h1z"
|
||||
android:strokeColor="#ea000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M71,45h1zM70,65h1zM56,72h1z"
|
||||
android:strokeColor="#36000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M32,46h1zM32,47h1zM32,48h1zM32,49h1zM32,50h1zM32,51h1zM32,52h1zM32,53h1zM32,54h1zM74,54h1zM32,55h1zM32,56h1zM32,57h1zM32,58h1zM32,59h1zM62,59h1zM32,60h1zM61,60h1zM32,61h1zM32,62h1zM33,66h1z"
|
||||
android:strokeColor="#0b000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M33,46h1zM33,49h1zM33,54h1zM48,58h1zM33,59h1zM33,62h1z"
|
||||
android:strokeColor="#c6000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M40,46h1z"
|
||||
android:strokeColor="#77000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M45,46h1zM38,55h1z"
|
||||
android:strokeColor="#6b000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,46h1zM61,46h1zM55,54h1zM48,56h1zM49,58h1zM64,59h1zM70,62h1zM51,63h1zM69,64h1zM44,66h1zM47,68h1zM60,70h1z"
|
||||
android:strokeColor="#fd000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M51,46h1zM63,60h1z"
|
||||
android:strokeColor="#e7000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M53,46h1zM64,54h1z"
|
||||
android:strokeColor="#4e000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M54,46h1z"
|
||||
android:strokeColor="#2a000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M57,46h1zM53,62h1z"
|
||||
android:strokeColor="#1b000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M58,46h1zM63,58h1z"
|
||||
android:strokeColor="#45000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M59,46h1z"
|
||||
android:strokeColor="#95000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M60,46h1z"
|
||||
android:strokeColor="#e0000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M71,46h1z"
|
||||
android:strokeColor="#93000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M33,47h1zM33,61h1z"
|
||||
android:strokeColor="#ca000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M39,47h1zM65,54h1zM51,58h1zM46,68h1z"
|
||||
android:strokeColor="#f2000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M40,47h1zM55,57h1z"
|
||||
android:strokeColor="#40000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,47h1z"
|
||||
android:strokeColor="#a8000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M51,47h1zM68,67h1z"
|
||||
android:strokeColor="#4c000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M60,47h1zM50,48h1z"
|
||||
android:strokeColor="#48000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M61,47h1zM64,69h1z"
|
||||
android:strokeColor="#df000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M71,47h1zM53,71h1z"
|
||||
android:strokeColor="#d4000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M72,47h1zM61,48h1zM73,59h1z"
|
||||
android:strokeColor="#24000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M39,48h1zM40,65h1z"
|
||||
android:strokeColor="#c4000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M48,48h1z"
|
||||
android:strokeColor="#52000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M49,48h1zM64,57h1z"
|
||||
android:strokeColor="#c3000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M63,48h1zM38,50h1zM53,57h1zM49,61h1z"
|
||||
android:strokeColor="#f5000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M72,48h1z"
|
||||
android:strokeColor="#7f000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M39,49h1zM42,64h1z"
|
||||
android:strokeColor="#88000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M48,49h1zM67,68h1z"
|
||||
android:strokeColor="#43000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M50,49h1zM42,65h1z"
|
||||
android:strokeColor="#ac000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M51,49h1z"
|
||||
android:strokeColor="#25000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M62,49h1zM51,61h1zM69,66h1z"
|
||||
android:strokeColor="#1e000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M72,49h1zM33,50h1zM33,58h1z"
|
||||
android:strokeColor="#ce000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M73,49h1z"
|
||||
android:strokeColor="#17000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M39,50h1zM48,60h1zM43,67h1z"
|
||||
android:strokeColor="#3d000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M48,50h1zM48,70h1z"
|
||||
android:strokeColor="#af000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M52,50h1zM73,57h1z"
|
||||
android:strokeColor="#8d000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M63,50h1zM47,61h1z"
|
||||
android:strokeColor="#5c000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M73,50h1z"
|
||||
android:strokeColor="#4d000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M38,51h1z"
|
||||
android:strokeColor="#b2000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M54,51h1z"
|
||||
android:strokeColor="#75000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M55,51h1z"
|
||||
android:strokeColor="#18000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M63,51h1z"
|
||||
android:strokeColor="#13000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M64,51h1z"
|
||||
android:strokeColor="#d2000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M73,51h1z"
|
||||
android:strokeColor="#81000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M74,51h1zM57,54h1zM46,56h1zM55,58h1zM40,59h1zM47,59h1zM44,62h1zM35,68h1zM37,68h1zM43,68h1zM60,72h1z"
|
||||
android:strokeColor="#02000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M38,52h1z"
|
||||
android:strokeColor="#94000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,52h1zM46,69h1z"
|
||||
android:strokeColor="#5b000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M54,52h1zM48,57h1zM47,62h1z"
|
||||
android:strokeColor="#f0000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M55,52h1z"
|
||||
android:strokeColor="#7d000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M63,52h1zM74,55h1zM74,56h1zM42,63h1zM34,67h1zM68,68h1z"
|
||||
android:strokeColor="#06000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M64,52h1zM61,61h1zM54,63h1z"
|
||||
android:strokeColor="#a1000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M33,53h1zM33,55h1zM33,63h1zM47,69h1z"
|
||||
android:strokeColor="#cd000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M38,53h1z"
|
||||
android:strokeColor="#78000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,53h1z"
|
||||
android:strokeColor="#9b000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M55,53h1zM64,58h1zM52,63h1z"
|
||||
android:strokeColor="#f4000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M56,53h1z"
|
||||
android:strokeColor="#2d000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M73,53h1z"
|
||||
android:strokeColor="#bf000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M38,54h1zM33,65h1zM41,65h1z"
|
||||
android:strokeColor="#61000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M56,54h1z"
|
||||
android:strokeColor="#74000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M73,54h1zM38,66h1z"
|
||||
android:strokeColor="#ba000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M46,55h1z"
|
||||
android:strokeColor="#08000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,55h1z"
|
||||
android:strokeColor="#a6000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M56,55h1z"
|
||||
android:strokeColor="#47000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M64,55h1z"
|
||||
android:strokeColor="#63000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M38,56h1zM64,56h1zM55,63h2z"
|
||||
android:strokeColor="#90000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,56h1z"
|
||||
android:strokeColor="#73000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M55,56h1z"
|
||||
android:strokeColor="#b0000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M73,56h1zM46,62h1z"
|
||||
android:strokeColor="#a9000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,57h1z"
|
||||
android:strokeColor="#3a000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M54,57h1z"
|
||||
android:strokeColor="#ae000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M63,57h1zM73,60h1zM45,69h1zM59,72h1z"
|
||||
android:strokeColor="#0c000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M38,58h1zM48,61h1zM67,67h1z"
|
||||
android:strokeColor="#e4000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M53,58h1z"
|
||||
android:strokeColor="#49000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M73,58h1zM34,66h1z"
|
||||
android:strokeColor="#65000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M48,59h1z"
|
||||
android:strokeColor="#5d000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M50,59h1z"
|
||||
android:strokeColor="#db000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M51,59h1zM40,62h1zM52,62h1z"
|
||||
android:strokeColor="#62000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M63,59h1z"
|
||||
android:strokeColor="#a0000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M72,59h1z"
|
||||
android:strokeColor="#e2000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M39,60h1zM71,62h1zM70,64h1z"
|
||||
android:strokeColor="#b4000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M49,60h1z"
|
||||
android:strokeColor="#b7000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M62,60h1z"
|
||||
android:strokeColor="#67000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M40,61h1z"
|
||||
android:strokeColor="#34000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M50,61h1z"
|
||||
android:strokeColor="#b3000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M71,61h1z"
|
||||
android:strokeColor="#e6000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M72,61h1z"
|
||||
android:strokeColor="#3c000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M51,62h1zM40,63h1z"
|
||||
android:strokeColor="#be000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M58,62h1z"
|
||||
android:strokeColor="#14000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M59,62h1z"
|
||||
android:strokeColor="#4a000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M60,62h1z"
|
||||
android:strokeColor="#a3000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M41,63h1zM44,68h1z"
|
||||
android:strokeColor="#20000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M44,63h1z"
|
||||
android:strokeColor="#85000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M45,63h1z"
|
||||
android:strokeColor="#da000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M57,63h1z"
|
||||
android:strokeColor="#9c000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M71,63h1zM50,71h1z"
|
||||
android:strokeColor="#51000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M33,64h1zM52,71h1z"
|
||||
android:strokeColor="#ad000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M41,64h1z"
|
||||
android:strokeColor="#9d000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M69,65h1z"
|
||||
android:strokeColor="#bc000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M35,66h1zM55,71h1zM57,71h1z"
|
||||
android:strokeColor="#e8000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M39,66h1z"
|
||||
android:strokeColor="#58000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M42,66h1zM58,72h1z"
|
||||
android:strokeColor="#1c000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M43,66h1z"
|
||||
android:strokeColor="#c8000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M35,67h1z"
|
||||
android:strokeColor="#4b000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M36,67h1z"
|
||||
android:strokeColor="#84000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M37,67h1z"
|
||||
android:strokeColor="#5a000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M45,68h1z"
|
||||
android:strokeColor="#aa000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M66,68h1z"
|
||||
android:strokeColor="#b1000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M47,70h1z"
|
||||
android:strokeColor="#28000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M62,70h1z"
|
||||
android:strokeColor="#e9000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M51,71h1z"
|
||||
android:strokeColor="#8c000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M58,71h1z"
|
||||
android:strokeColor="#d8000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M59,71h1z"
|
||||
android:strokeColor="#bb000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M60,71h1z"
|
||||
android:strokeColor="#8e000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M61,71h1z"
|
||||
android:strokeColor="#54000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M62,71h1z"
|
||||
android:strokeColor="#38000000"
|
||||
android:strokeWidth="1.0" />
|
||||
<path
|
||||
android:pathData="M53,72h1z"
|
||||
android:strokeColor="#19000000"
|
||||
android:strokeWidth="1.0" />
|
||||
</vector>
|
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 6.6 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 8.8 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 23 KiB |