From ccd0a1f066e53088aa00de44feb46d4579dd5d12 Mon Sep 17 00:00:00 2001 From: OTKUSteyler <90369564+OTKUSteyler@users.noreply.github.com> Date: Thu, 6 Nov 2025 22:58:27 +0100 Subject: [PATCH] Update ThemesModule.kt --- .../xposed/modules/appearance/ThemesModule.kt | 148 +----------------- 1 file changed, 2 insertions(+), 146 deletions(-) diff --git a/app/src/main/kotlin/io/github/revenge/xposed/modules/appearance/ThemesModule.kt b/app/src/main/kotlin/io/github/revenge/xposed/modules/appearance/ThemesModule.kt index 37e647f..8ec5d25 100644 --- a/app/src/main/kotlin/io/github/revenge/xposed/modules/appearance/ThemesModule.kt +++ b/app/src/main/kotlin/io/github/revenge/xposed/modules/appearance/ThemesModule.kt @@ -1,9 +1,10 @@ -package GoonXposed.xposed.module.appearance +package GoonXposed.xposed.modules.appearance import GoonXposed.xposed.Module import GoonXposed.xposed.Constants import GoonXposed.xposed.Utils.Companion.JSON import GoonXposed.xposed.MethodHookBuilder +// import GoonXposed.xposed.modules.appearance.ThemesModule import android.content.Context import android.content.res.Resources import androidx.core.graphics.toColorInt @@ -14,148 +15,3 @@ import kotlinx.serialization.Serializable import kotlinx.serialization.json.JsonObjectBuilder import kotlinx.serialization.json.encodeToJsonElement import kotlinx.serialization.json.put - -@Serializable data class Author(val name: String, val id: String? = null) - -@Serializable -data class ThemeData( - val name: String, - val description: String? = null, - val authors: List? = null, - val spec: Int, - val semanticColors: Map>? = null, - val rawColors: Map? = null -) - -@Serializable data class Theme(val id: String, val selected: Boolean, val data: ThemeData) - -class ThemesModule : Module() { - private lateinit var param: XC_LoadPackage.LoadPackageParam - - private var theme: Theme? = null - private val rawColorMap = mutableMapOf() - - private companion object { - const val THEME_FILE = "current-theme.json" - } - - @ExperimentalSerializationApi - override fun buildPayload(builder: JsonObjectBuilder) { - builder.apply { - put("hasThemeSupport", true) - if (theme != null) put("storedTheme", JSON.encodeToJsonElement(theme!!)) - else put("storedTheme", null) - } - } - - private fun String.fromScreamingSnakeToCamelCase() = - this.split("_").joinToString("") { it -> - it.lowercase().replaceFirstChar { it.uppercase() } - } - - override fun onLoad(packageParam: XC_LoadPackage.LoadPackageParam) { - param = packageParam - theme = getTheme() - hookTheme() - } - - private fun File.isValidish(): Boolean { - if (!this.exists()) return false - - val text = this.readText() - return text.isNotBlank() && text != "{}" && text != "null" - } - - private fun getTheme(): Theme? { - val themeFile = - File(param.appInfo.dataDir, "${Constants.FILES_DIR}/${THEME_FILE}").apply { - asFile() - } - if (!themeFile.isValidish()) return null - - return try { - val themeText = themeFile.readText() - JSON.decodeFromString(themeText) - } catch (_: Exception) { - null - } - } - - fun hookTheme() { - val themeManager = param.classLoader.loadClass("com.discord.theme.utils.ColorUtilsKt") - val darkTheme = param.classLoader.loadClass("com.discord.theme.DarkerTheme") - val lightTheme = param.classLoader.loadClass("com.discord.theme.LightTheme") - - val theme = this.theme ?: return - - // Apply rawColors - theme.data.rawColors?.forEach { (key, value) -> - rawColorMap[key.lowercase()] = hexStringToColorInt(value) - } - - // Apply semanticColors - theme.data.semanticColors?.forEach { (key, value) -> - // TEXT_NORMAL -> getTextNormal - val methodName = "get${key.fromScreamingSnakeToCamelCase()}" - value.forEachIndexed { index, v -> - when (index) { - 0 -> hookThemeMethod(darkTheme, methodName, hexStringToColorInt(v)) - 1 -> hookThemeMethod(lightTheme, methodName, hexStringToColorInt(v)) - } - } - } - - // If there's any rawColors value, hook the color getter - if (!theme.data.rawColors.isNullOrEmpty()) { - val getColorCompat = - themeManager.getDeclaredMethod( - "getColorCompat", - Resources::class.java, - Int::class.javaPrimitiveType, - Resources.Theme::class.java, - ) - - val getColorCompatLegacy = - themeManager.getDeclaredMethod( - "getColorCompat", - Context::class.java, - Int::class.javaPrimitiveType - ) - - val patch = - MethodHookBuilder().run { - before { - val arg1 = args[0] - val resources = - if (arg1 is Context) arg1.resources else (arg1 as Resources) - val name = resources.getResourceEntryName(args[1] as Int) - - if (rawColorMap[name] != null) result = rawColorMap[name] - } - - build() - } - - getColorCompat.hook(patch) - getColorCompatLegacy.hook(patch) - } - } - - // Parse HEX colour string to INT. Takes "#RRGGBBAA" or "#RRGGBB" - private fun hexStringToColorInt(hexString: String): Int { - return if (hexString.length == 9) { - // Rearrange RRGGBBAA -> AARRGGBB so parseColor() is happy - val alpha = hexString.substring(7, 9) - val rrggbb = hexString.substring(1, 7) - "#$alpha$rrggbb".toColorInt() - } else hexString.toColorInt() - } - - private fun hookThemeMethod(themeClass: Class<*>, methodName: String, themeValue: Int) { - try { - themeClass.getDeclaredMethod(methodName).let { method -> - method.hook { before { result = themeValue } } - } - } catch (_: NoSuchMethodException) {} - } -}