Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Resource strings getting corrupted, resulting on failure to patch on revanced manager #439

Merged
merged 10 commits into from
Oct 20, 2024
43 changes: 32 additions & 11 deletions src/main/kotlin/app/util/ResourceUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import app.revanced.patcher.util.DomFileEditor
import app.revanced.util.resource.BaseResource
import org.w3c.dom.Node
import org.w3c.dom.NodeList
import java.io.FileNotFoundException
import java.io.InputStream
import java.nio.file.Files
import java.nio.file.StandardCopyOption
Expand All @@ -24,10 +25,9 @@ fun Node.childElementsSequence() = this.childNodes.asSequence().filter { it.node
/**
* Performs the given [action] on each child element.
*/
fun Node.forEachChildElement(action: (Node) -> Unit) =
childElementsSequence().forEach {
action(it)
}
fun Node.forEachChildElement(action: (Node) -> Unit) = childElementsSequence().forEach {
action(it)
}

/**
* Recursively traverse the DOM tree starting from the given root node.
Expand Down Expand Up @@ -119,21 +119,42 @@ fun String.copyXmlNode(source: DomFileEditor, target: DomFileEditor): AutoClosea
* @param elementTag The element to copy.
*/
fun ResourceContext.copyXmlNode(
resourceDirectory: String,
targetResource: String,
elementTag: String
resourceDirectory: String, targetResource: String, elementTag: String
) {
val stringsResourceInputStream =
classLoader.getResourceAsStream("$resourceDirectory/$targetResource")!!
val stringsResourceInputStream = classLoader.getResourceAsStream("$resourceDirectory/$targetResource")!!

// Copy nodes from the resources node to the real resource node
elementTag.copyXmlNode(
this.xmlEditor[stringsResourceInputStream],
this.xmlEditor["res/$targetResource"]
this.xmlEditor[stringsResourceInputStream], this.xmlEditor["res/$targetResource"]
).close()
}


fun ResourceContext.appendStrings(
resourceDirectory: String,
targetResource: String,
) {
val source = classLoader.getResourceAsStream("$resourceDirectory/$targetResource") ?: throw FileNotFoundException()

val target = this["res/$targetResource"]
val targetContent = target.readLines().dropLastWhile { it != "</resources>" }.dropLast(1)

target.bufferedWriter().use { writer ->
targetContent.forEach {
writer.write(it)
}

source.bufferedReader().useLines { lines ->
lines.dropWhile {
it != "<resources>"
}.drop(1).forEach { line ->
writer.write(line)
}
}
}
}


// /**
// * Copies the specified node of the source [Document] to the target [Document].
// * @param source the source [Document].
Expand Down
8 changes: 8 additions & 0 deletions src/main/kotlin/app/util/Utils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package app.util

inline fun measureExecutionTime(block: () -> Unit): Long {
val start = System.currentTimeMillis()
block()
val end = System.currentTimeMillis()
return end - start
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.util.ResourceGroup
import app.revanced.util.appendStrings
import app.revanced.util.copyResources
import app.revanced.util.copyXmlNode
import org.w3c.dom.Element

@Patch(
compatiblePackages = [CompatiblePackage("com.twitter.android")],
)
object SettingsResourcePatch: ResourcePatch() {
object SettingsResourcePatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
val settingsRoot = context["res/xml/settings_root.xml"]
if (!settingsRoot.exists()) throw PatchException("settings_root not found")
Expand All @@ -37,7 +37,8 @@ object SettingsResourcePatch: ResourcePatch() {
context.xmlEditor["res/layout/main_activity_app_bar.xml"].use { editor ->
val parent = editor.file.getElementsByTagName("FrameLayout").item(1) as Element

val sideBtn = editor.file.createElement("app.revanced.integrations.twitter.settings.widgets.PikoSettingsButton")
val sideBtn =
editor.file.createElement("app.revanced.integrations.twitter.settings.widgets.PikoSettingsButton")
sideBtn.setAttribute("android:text", "Piko")
sideBtn.setAttribute("android:textAllCaps", "false")
sideBtn.setAttribute("android:background", "?android:attr/selectableItemBackground")
Expand All @@ -53,31 +54,19 @@ object SettingsResourcePatch: ResourcePatch() {
}

//credits @inotia00
context.copyXmlNode("twitter/settings", "values/strings.xml", "resources")
context.copyXmlNode("twitter/settings", "values/arrays.xml", "resources")
context.appendStrings("twitter/settings", "values/strings.xml")
context.appendStrings("twitter/settings", "values/arrays.xml")

/**
* create directory for the untranslated language resources
*/
//Strings
val languages = arrayOf(
"es",
"ar",
"ja",
"hi",
"in",
"zh-rCN",
"ru",
"pl",
"pt-rBR",
"v21",
"tr",
"zh-rTW"
"es", "ar", "ja", "hi", "in", "zh-rCN", "ru", "pl", "pt-rBR", "v21", "tr", "zh-rTW"
).map { "values-$it" }

languages.forEach {
if (context["res/$it"].exists()) {
context.copyXmlNode("twitter/settings", "$it/strings.xml", "resources")
context.appendStrings("twitter/settings", "$it/strings.xml")
} else {
context["res/$it"].mkdirs()
context.copyResources("twitter/settings", ResourceGroup(it, "strings.xml"))
Expand Down
Loading