fix: undelay module initialization
This commit is contained in:
parent
42a08d1d21
commit
59d85ef774
11 changed files with 71 additions and 33 deletions
2
.idea/compiler.xml
generated
2
.idea/compiler.xml
generated
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="CompilerConfiguration">
|
<component name="CompilerConfiguration">
|
||||||
<bytecodeTargetLevel target="19" />
|
<bytecodeTargetLevel target="17" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
18
.idea/deploymentTargetSelector.xml
generated
Normal file
18
.idea/deploymentTargetSelector.xml
generated
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="deploymentTargetSelector">
|
||||||
|
<selectionStates>
|
||||||
|
<SelectionState runConfigName="app">
|
||||||
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
|
<DropdownSelection timestamp="2024-10-11T15:31:32.125634Z">
|
||||||
|
<Target type="DEFAULT_BOOT">
|
||||||
|
<handle>
|
||||||
|
<DeviceId pluginId="PhysicalDevice" identifier="serial=4H4HW8U8Z98LCY89" />
|
||||||
|
</handle>
|
||||||
|
</Target>
|
||||||
|
</DropdownSelection>
|
||||||
|
<DialogSelection />
|
||||||
|
</SelectionState>
|
||||||
|
</selectionStates>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
5
.idea/gradle.xml
generated
5
.idea/gradle.xml
generated
|
|
@ -4,16 +4,15 @@
|
||||||
<component name="GradleSettings">
|
<component name="GradleSettings">
|
||||||
<option name="linkedExternalProjectsSettings">
|
<option name="linkedExternalProjectsSettings">
|
||||||
<GradleProjectSettings>
|
<GradleProjectSettings>
|
||||||
<option name="testRunner" value="GRADLE" />
|
|
||||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
<option name="gradleJvm" value="#JAVA_HOME" />
|
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
|
||||||
<option name="modules">
|
<option name="modules">
|
||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
<option value="$PROJECT_DIR$/app" />
|
<option value="$PROJECT_DIR$/app" />
|
||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
|
<option name="resolveExternalAnnotations" value="false" />
|
||||||
</GradleProjectSettings>
|
</GradleProjectSettings>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
|
|
||||||
10
.idea/migrations.xml
generated
Normal file
10
.idea/migrations.xml
generated
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectMigrations">
|
||||||
|
<option name="MigrateToGradleLocalJavaHome">
|
||||||
|
<set>
|
||||||
|
<option value="$PROJECT_DIR$" />
|
||||||
|
</set>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_19" default="true" project-jdk-name="19" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
|
|
||||||
2
.idea/vcs.xml
generated
2
.idea/vcs.xml
generated
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
<mapping directory="" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -12,8 +12,8 @@ android {
|
||||||
applicationId = "io.github.pyoncord.xposed"
|
applicationId = "io.github.pyoncord.xposed"
|
||||||
minSdk = 24
|
minSdk = 24
|
||||||
targetSdk = 33
|
targetSdk = 33
|
||||||
versionCode = 203
|
versionCode = 204
|
||||||
versionName = "0.2.3"
|
versionName = "0.2.4"
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,12 @@ package io.github.pyoncord.xposed
|
||||||
|
|
||||||
import android.content.res.AssetManager
|
import android.content.res.AssetManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.graphics.Typeface.CustomFallbackBuilder
|
import android.graphics.Typeface.CustomFallbackBuilder
|
||||||
import android.graphics.fonts.Font
|
import android.graphics.fonts.Font
|
||||||
import android.graphics.fonts.FontFamily
|
import android.graphics.fonts.FontFamily
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.webkit.URLUtil
|
|
||||||
import de.robv.android.xposed.XC_MethodReplacement
|
import de.robv.android.xposed.XC_MethodReplacement
|
||||||
import de.robv.android.xposed.XposedBridge
|
|
||||||
import de.robv.android.xposed.XposedHelpers
|
import de.robv.android.xposed.XposedHelpers
|
||||||
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
@ -21,8 +18,6 @@ import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.HttpURLConnection
|
|
||||||
import java.net.URL
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
|
|
||||||
import io.ktor.client.*
|
import io.ktor.client.*
|
||||||
|
|
@ -67,7 +62,7 @@ class FontsModule: PyonModule() {
|
||||||
val assetManager: AssetManager = param.args[2] as AssetManager
|
val assetManager: AssetManager = param.args[2] as AssetManager
|
||||||
return createAssetTypeface(fontFamilyName, style, assetManager)
|
return createAssetTypeface(fontFamilyName, style, assetManager)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
val fontDefFile = File(appInfo.dataDir, "files/pyoncord/fonts.json")
|
val fontDefFile = File(appInfo.dataDir, "files/pyoncord/fonts.json")
|
||||||
if (!fontDefFile.exists()) return@with
|
if (!fontDefFile.exists()) return@with
|
||||||
|
|
@ -144,7 +139,7 @@ class FontsModule: PyonModule() {
|
||||||
// ignore
|
// 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) {
|
for (fileExtension in FILE_EXTENSIONS) {
|
||||||
val fileName = java.lang.StringBuilder()
|
val fileName = java.lang.StringBuilder()
|
||||||
.append(fontRootPath)
|
.append(fontRootPath)
|
||||||
|
|
@ -220,7 +215,7 @@ class FontsModule: PyonModule() {
|
||||||
|
|
||||||
// Lastly, after all those checks above, this is the original RN logic for
|
// Lastly, after all those checks above, this is the original RN logic for
|
||||||
// getting the typeface.
|
// 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) {
|
for (fileExtension in FILE_EXTENSIONS) {
|
||||||
val fileName = java.lang.StringBuilder()
|
val fileName = java.lang.StringBuilder()
|
||||||
.append(fontRootPath)
|
.append(fontRootPath)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
package io.github.pyoncord.xposed
|
package io.github.pyoncord.xposed
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.AndroidAppHelper
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.res.AssetManager
|
import android.content.res.AssetManager
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
|
@ -12,7 +10,6 @@ import de.robv.android.xposed.IXposedHookLoadPackage
|
||||||
import de.robv.android.xposed.XC_MethodHook
|
import de.robv.android.xposed.XC_MethodHook
|
||||||
import de.robv.android.xposed.XposedBridge
|
import de.robv.android.xposed.XposedBridge
|
||||||
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
||||||
import io.github.pyoncord.xposed.BuildConfig
|
|
||||||
import io.ktor.client.*
|
import io.ktor.client.*
|
||||||
import io.ktor.client.call.*
|
import io.ktor.client.call.*
|
||||||
import io.ktor.client.request.*
|
import io.ktor.client.request.*
|
||||||
|
|
@ -60,14 +57,27 @@ class Main : IXposedHookLoadPackage {
|
||||||
lpparam.classLoader.loadClass("com.discord.react_activities.ReactActivity")
|
lpparam.classLoader.loadClass("com.discord.react_activities.ReactActivity")
|
||||||
}.getOrElse { return } // Package is not our the target app, return
|
}.getOrElse { return } // 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() {
|
XposedBridge.hookMethod(reactActivity.getDeclaredMethod("onCreate", Bundle::class.java), object : XC_MethodHook() {
|
||||||
override fun beforeHookedMethod(param: MethodHookParam) {
|
override fun beforeHookedMethod(param: MethodHookParam) {
|
||||||
init(lpparam, param.thisObject as Activity)
|
activity = param.thisObject as Activity;
|
||||||
|
onActivityCreateCallback.forEach { cb -> cb(activity!!) }
|
||||||
|
onActivityCreateCallback.clear()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
init(lpparam) { cb ->
|
||||||
|
if (activity != null) cb(activity!!)
|
||||||
|
else onActivityCreateCallback.add(cb)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun init(param: XC_LoadPackage.LoadPackageParam, activity: Activity) = with (param) {
|
private fun init(
|
||||||
|
param: XC_LoadPackage.LoadPackageParam,
|
||||||
|
onActivityCreate: ((activity: Activity) -> Unit) -> Unit
|
||||||
|
) = with (param) {
|
||||||
val catalystInstanceImpl = classLoader.loadClass("com.facebook.react.bridge.CatalystInstanceImpl")
|
val catalystInstanceImpl = classLoader.loadClass("com.facebook.react.bridge.CatalystInstanceImpl")
|
||||||
|
|
||||||
for (module in pyonModules) module.onInit(param)
|
for (module in pyonModules) module.onInit(param)
|
||||||
|
|
@ -150,10 +160,16 @@ class Main : IXposedHookLoadPackage {
|
||||||
return@async
|
return@async
|
||||||
} catch (e: RedirectResponseException) {
|
} catch (e: RedirectResponseException) {
|
||||||
if (e.response.status != HttpStatusCode.NotModified) throw e;
|
if (e.response.status != HttpStatusCode.NotModified) throw e;
|
||||||
Log.e("Bunny", "Server reponded with status code 304 - no changes to file")
|
Log.e("Bunny", "Server responded with status code 304 - no changes to file")
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
|
onActivityCreate { activity ->
|
||||||
activity.runOnUiThread {
|
activity.runOnUiThread {
|
||||||
Toast.makeText(activity.applicationContext, "Failed to fetch JS bundle, Bunny may not load!", Toast.LENGTH_SHORT).show()
|
Toast.makeText(
|
||||||
|
activity.applicationContext,
|
||||||
|
"Failed to fetch JS bundle, Bunny may not load!",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.e("Bunny", "Failed to download bundle", e)
|
Log.e("Bunny", "Failed to download bundle", e)
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ data class SysColors(
|
||||||
|
|
||||||
class SysColorsModule : PyonModule() {
|
class SysColorsModule : PyonModule() {
|
||||||
private lateinit var context: Context
|
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) {
|
override fun buildJson(builder: JsonObjectBuilder) {
|
||||||
context = AndroidAppHelper.currentApplication()
|
context = AndroidAppHelper.currentApplication()
|
||||||
|
|
@ -43,7 +43,7 @@ class SysColorsModule : PyonModule() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun convertToColor(id: Int): String {
|
private fun convertToColor(id: Int): String {
|
||||||
val clr = if (isSupported()) ContextCompat.getColor(context, id) else 0
|
val clr = if (isSupported()) ContextCompat.getColor(context, id) else 0
|
||||||
return String.format("#%06X", 0xFFFFFF and clr)
|
return String.format("#%06X", 0xFFFFFF and clr)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,14 +58,14 @@ class ThemeModule : PyonModule() {
|
||||||
hookTheme()
|
hookTheme()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun File.isValidish(): Boolean {
|
private fun File.isValidish(): Boolean {
|
||||||
if (!this.exists()) return false
|
if (!this.exists()) return false
|
||||||
|
|
||||||
val text = this.readText()
|
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 filesDir = File(param.appInfo.dataDir, "files").apply { mkdirs() }
|
||||||
val pyonDir = File(filesDir, "pyoncord").apply { mkdirs() }
|
val pyonDir = File(filesDir, "pyoncord").apply { mkdirs() }
|
||||||
val themeFile = File(pyonDir, "current-theme.json")
|
val themeFile = File(pyonDir, "current-theme.json")
|
||||||
|
|
@ -139,12 +139,12 @@ class ThemeModule : PyonModule() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert 0xRRGGBBAA to 0XAARRGGBB
|
// Convert 0xRRGGBBAA to 0XAARRGGBB
|
||||||
fun hexStringToColorInt(hexString: String): Int {
|
private fun hexStringToColorInt(hexString: String): Int {
|
||||||
val parsed = Color.parseColor(hexString)
|
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 {
|
try {
|
||||||
themeClass.getDeclaredMethod(methodName).let { method ->
|
themeClass.getDeclaredMethod(methodName).let { method ->
|
||||||
// Log.i("Hooking $methodName -> ${themeValue.toString(16)}")
|
// Log.i("Hooking $methodName -> ${themeValue.toString(16)}")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue