package app.revanced.patches.youtube.misc.settings import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.patch.PatchException import app.revanced.patches.all.misc.resources.AddResourcesPatch import app.revanced.patches.shared.misc.mapping.ResourceMappingPatch import app.revanced.patches.shared.misc.settings.BaseSettingsResourcePatch import app.revanced.patches.shared.misc.settings.preference.IntentPreference import app.revanced.util.ResourceGroup import app.revanced.util.copyResources import org.w3c.dom.Element object SettingsResourcePatch : BaseSettingsResourcePatch( IntentPreference( titleKey = "revanced_settings_title", summaryKey = null, intent = SettingsPatch.newIntent("revanced_settings_intent"), ) to "settings_fragment", dependencies = setOf( ResourceMappingPatch::class, AddResourcesPatch::class, ), ) { // Used for a fingerprint from SettingsPatch. internal var appearanceStringId = -1L override fun execute(context: ResourceContext) { super.execute(context) AddResourcesPatch(this::class) // Used for a fingerprint from SettingsPatch. appearanceStringId = ResourceMappingPatch.resourceMappings.find { it.type == "string" && it.name == "app_theme_appearance_dark" }!!.id arrayOf( ResourceGroup("layout", "revanced_settings_with_toolbar.xml"), ).forEach { resourceGroup -> context.copyResources("settings", resourceGroup) } // Remove horizontal divider from the settings Preferences // To better match the appearance of the stock YouTube settings. context.xmlEditor["res/values/styles.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 val name = node.getAttribute("name") if (name == "Theme.YouTube.Settings" || name == "Theme.YouTube.Settings.Dark") { val listDividerNode = editor.file.createElement("item") listDividerNode.setAttribute("name", "android:listDivider") listDividerNode.appendChild(editor.file.createTextNode("@null")) node.appendChild(listDividerNode) } } } // Modify the manifest and add a data intent filter to the LicenseActivity. // Some devices freak out if undeclared data is passed to an intent, // and this change appears to fix the issue. var modifiedIntent = false context.xmlEditor["AndroidManifest.xml"].use { editor -> val document = editor.file // A xml regular-expression would probably work better than this manual searching. val manifestNodes = document.getElementsByTagName("manifest").item(0).childNodes for (i in 0..manifestNodes.length) { val node = manifestNodes.item(i) if (node != null && node.nodeName == "application") { val applicationNodes = node.childNodes for (j in 0..applicationNodes.length) { val applicationChild = applicationNodes.item(j) if (applicationChild is Element && applicationChild.nodeName == "activity" && applicationChild.getAttribute("android:name") == "com.google.android.libraries.social.licenses.LicenseActivity" ) { val intentFilter = document.createElement("intent-filter") val mimeType = document.createElement("data") mimeType.setAttribute("android:mimeType", "text/plain") intentFilter.appendChild(mimeType) applicationChild.appendChild(intentFilter) modifiedIntent = true break } } } } } if (!modifiedIntent) throw PatchException("Could not modify activity intent") } }