diff --git a/.idea/compiler.xml b/.idea/compiler.xml index e58d3e4..b589d56 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml new file mode 100644 index 0000000..19ce6a7 --- /dev/null +++ b/.idea/deploymentTargetSelector.xml @@ -0,0 +1,18 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index cbbe561..0897082 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -4,16 +4,15 @@ diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 9924903..0ad17cb 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,7 +1,7 @@ - + diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7..35eb1dd 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d2bc0dd..c941490 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -12,8 +12,8 @@ android { applicationId = "io.github.revenge.xposed" minSdk = 24 targetSdk = 33 - versionCode = 203 - versionName = "0.2.3" + versionCode = 204 + versionName = "0.2.4" } buildTypes { diff --git a/app/src/main/kotlin/io/github/revenge/xposed/FontsModule.kt b/app/src/main/kotlin/io/github/revenge/xposed/FontsModule.kt index c529974..0481a6f 100644 --- a/app/src/main/kotlin/io/github/revenge/xposed/FontsModule.kt +++ b/app/src/main/kotlin/io/github/revenge/xposed/FontsModule.kt @@ -5,15 +5,12 @@ package io.github.revenge.xposed import android.content.res.AssetManager import android.os.Build -import android.graphics.Color import android.graphics.Typeface import android.graphics.Typeface.CustomFallbackBuilder import android.graphics.fonts.Font import android.graphics.fonts.FontFamily import android.util.Log -import android.webkit.URLUtil import de.robv.android.xposed.XC_MethodReplacement -import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedHelpers import de.robv.android.xposed.callbacks.XC_LoadPackage import kotlinx.serialization.Serializable @@ -21,8 +18,6 @@ import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.* import java.io.IOException import java.io.File -import java.net.HttpURLConnection -import java.net.URL import kotlinx.coroutines.* import io.ktor.client.* @@ -67,7 +62,7 @@ class FontsModule: Module() { val assetManager: AssetManager = param.args[2] as AssetManager return createAssetTypeface(fontFamilyName, style, assetManager) } - }); + }) val fontDefFile = File(appInfo.dataDir, "files/pyoncord/fonts.json") if (!fontDefFile.exists()) return@with @@ -144,7 +139,7 @@ class FontsModule: Module() { // ignore } - for (fontRootPath in arrayOf(fontsAbsPath, FONTS_ASSET_PATH).filter { it != null }) { + for (fontRootPath in arrayOf(fontsAbsPath, FONTS_ASSET_PATH).filterNotNull()) { for (fileExtension in FILE_EXTENSIONS) { val fileName = java.lang.StringBuilder() .append(fontRootPath) @@ -220,7 +215,7 @@ class FontsModule: Module() { // Lastly, after all those checks above, this is the original RN logic for // getting the typeface. - for (fontRootPath in arrayOf(fontsAbsPath, FONTS_ASSET_PATH).filter { it != null }) { + for (fontRootPath in arrayOf(fontsAbsPath, FONTS_ASSET_PATH).filterNotNull()) { for (fileExtension in FILE_EXTENSIONS) { val fileName = java.lang.StringBuilder() .append(fontRootPath) diff --git a/app/src/main/kotlin/io/github/revenge/xposed/Main.kt b/app/src/main/kotlin/io/github/revenge/xposed/Main.kt index 8819eff..7a212a0 100644 --- a/app/src/main/kotlin/io/github/revenge/xposed/Main.kt +++ b/app/src/main/kotlin/io/github/revenge/xposed/Main.kt @@ -1,8 +1,6 @@ package io.github.revenge.xposed -import android.app.Activity -import android.app.AndroidAppHelper -import android.content.Context +import android.app.Activity import android.content.res.AssetManager import android.content.res.Resources import android.util.Log @@ -56,22 +54,32 @@ class Main : IXposedHookLoadPackage { } override fun handleLoadPackage(param: XC_LoadPackage.LoadPackageParam) = with (param) { - // val reactActivity = runCatching { - // lpparam.classLoader.loadClass("com.discord.react_activities.ReactActivity") - // }.getOrElse { return } // Package is not our the target app, return - - // XposedBridge.hookMethod(reactActivity.getDeclaredMethod("onCreate", Bundle::class.java), object : XC_MethodHook() { - // override fun beforeHookedMethod(param: MethodHookParam) { - // init(lpparam, param.thisObject as Activity) - // } - // }) - // } - - // fun init(param: XC_LoadPackage.LoadPackageParam, activity: Activity) = with (param) { - // val catalystInstanceImpl = classLoader.loadClass("com.facebook.react.bridge.CatalystInstanceImpl") - val catalystInstanceImpl = runCatching { - classLoader.loadClass("com.facebook.react.bridge.CatalystInstanceImpl") - }.getOrElse { return@with } + val reactActivity = runCatching { + classLoader.loadClass("com.discord.react_activities.ReactActivity") + }.getOrElse { return@with } // Package is not our the target app, return + + var activity: Activity? = null; + val onActivityCreateCallback = mutableSetOf<(activity: Activity) -> Unit>() + + XposedBridge.hookMethod(reactActivity.getDeclaredMethod("onCreate", Bundle::class.java), object : XC_MethodHook() { + override fun beforeHookedMethod(param: MethodHookParam) { + activity = param.thisObject as Activity; + onActivityCreateCallback.forEach { cb -> cb(activity!!) } + onActivityCreateCallback.clear() + } + }) + + init(param) { cb -> + if (activity != null) cb(activity!!) + else onActivityCreateCallback.add(cb) + } + } + + private fun init( + param: XC_LoadPackage.LoadPackageParam, + onActivityCreate: ((activity: Activity) -> Unit) -> Unit + ) = with (param) { + val catalystInstanceImpl = classLoader.loadClass("com.facebook.react.bridge.CatalystInstanceImpl") for (module in modules) module.onInit(param) @@ -153,12 +161,17 @@ class Main : IXposedHookLoadPackage { return@async } catch (e: RedirectResponseException) { if (e.response.status != HttpStatusCode.NotModified) throw e; - Log.e("Revenge", "Server reponded with status code 304 - no changes to file") + Log.e("Revenge", "Server responded with status code 304 - no changes to file") } catch (e: Throwable) { - // activity.runOnUiThread { - // Toast.makeText(activity.applicationContext, "Failed to fetch JS bundle, Revenge may not load!", Toast.LENGTH_SHORT).show() - // } - // so are we just removing the toast entirely or, cos like commented code without explanation isnt the best + onActivityCreate { activity -> + activity.runOnUiThread { + Toast.makeText( + activity.applicationContext, + "Failed to fetch JS bundle, Revenge may not load!", + Toast.LENGTH_SHORT + ).show() + } + } Log.e("Revenge", "Failed to download bundle", e) } diff --git a/app/src/main/kotlin/io/github/revenge/xposed/PyonModule.kt b/app/src/main/kotlin/io/github/revenge/xposed/Module.kt similarity index 100% rename from app/src/main/kotlin/io/github/revenge/xposed/PyonModule.kt rename to app/src/main/kotlin/io/github/revenge/xposed/Module.kt diff --git a/app/src/main/kotlin/io/github/revenge/xposed/SysColorsModule.kt b/app/src/main/kotlin/io/github/revenge/xposed/SysColorsModule.kt index c4e49aa..9ea6db3 100644 --- a/app/src/main/kotlin/io/github/revenge/xposed/SysColorsModule.kt +++ b/app/src/main/kotlin/io/github/revenge/xposed/SysColorsModule.kt @@ -18,7 +18,7 @@ data class SysColors( class SysColorsModule : Module() { private lateinit var context: Context - fun isSupported() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S + private fun isSupported() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S override fun buildJson(builder: JsonObjectBuilder) { context = AndroidAppHelper.currentApplication() @@ -43,7 +43,7 @@ class SysColorsModule : Module() { } } - fun convertToColor(id: Int): String { + private fun convertToColor(id: Int): String { val clr = if (isSupported()) ContextCompat.getColor(context, id) else 0 return String.format("#%06X", 0xFFFFFF and clr) } diff --git a/app/src/main/kotlin/io/github/revenge/xposed/ThemeModule.kt b/app/src/main/kotlin/io/github/revenge/xposed/ThemeModule.kt index e8da0f8..175993d 100644 --- a/app/src/main/kotlin/io/github/revenge/xposed/ThemeModule.kt +++ b/app/src/main/kotlin/io/github/revenge/xposed/ThemeModule.kt @@ -58,14 +58,14 @@ class ThemeModule : Module() { hookTheme() } - fun File.isValidish(): Boolean { + private fun File.isValidish(): Boolean { if (!this.exists()) return false val text = this.readText() - return !text.isBlank() && text != "{}" && text != "null" + return text.isNotBlank() && text != "{}" && text != "null" } - fun getTheme(): Theme? { + private fun getTheme(): Theme? { val filesDir = File(param.appInfo.dataDir, "files").apply { mkdirs() } val pyonDir = File(filesDir, "pyoncord").apply { mkdirs() } val themeFile = File(pyonDir, "current-theme.json") @@ -139,12 +139,12 @@ class ThemeModule : Module() { } // Convert 0xRRGGBBAA to 0XAARRGGBB - fun hexStringToColorInt(hexString: String): Int { + private fun hexStringToColorInt(hexString: String): Int { val parsed = Color.parseColor(hexString) - return parsed.takeIf { hexString.length == 7 } ?: parsed and 0xFFFFFF or (parsed ushr 24) + return parsed.takeIf { hexString.length == 7 } ?: (parsed and 0xFFFFFF or (parsed ushr 24)) } - fun hookThemeMethod(themeClass: Class<*>, methodName: String, themeValue: Int) { + private fun hookThemeMethod(themeClass: Class<*>, methodName: String, themeValue: Int) { try { themeClass.getDeclaredMethod(methodName).let { method -> // Log.i("Hooking $methodName -> ${themeValue.toString(16)}")