feat: enable RN's LogBox and recovery options alert
This commit is contained in:
parent
2914d08cba
commit
d6435cc5aa
3 changed files with 121 additions and 2 deletions
|
|
@ -14,7 +14,6 @@ import de.robv.android.xposed.XC_MethodReplacement
|
|||
import de.robv.android.xposed.XposedHelpers
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.*
|
||||
import java.io.IOException
|
||||
import java.io.File
|
||||
|
|
|
|||
117
app/src/main/kotlin/io/github/pyoncord/xposed/LogBoxModule.kt
Normal file
117
app/src/main/kotlin/io/github/pyoncord/xposed/LogBoxModule.kt
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
package io.github.pyoncord.xposed
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.app.AndroidAppHelper
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import de.robv.android.xposed.XC_MethodHook
|
||||
import de.robv.android.xposed.XposedBridge
|
||||
import de.robv.android.xposed.XposedHelpers
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
||||
import java.io.File
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
class LogBoxModule: PyonModule() {
|
||||
lateinit var packageParam: XC_LoadPackage.LoadPackageParam
|
||||
|
||||
override fun onInit(packageParam: XC_LoadPackage.LoadPackageParam) = with (packageParam) {
|
||||
this@LogBoxModule.packageParam = packageParam
|
||||
|
||||
val dcdReactNativeHostClass = classLoader.loadClass("com.discord.bridge.DCDReactNativeHost")
|
||||
val bridgeDevSupportManagerClass = classLoader.loadClass("com.facebook.react.devsupport.BridgeDevSupportManager")
|
||||
|
||||
val mReactInstanceDevHelperField = XposedHelpers.findField(bridgeDevSupportManagerClass, "mReactInstanceDevHelper")
|
||||
|
||||
val getUseDeveloperSupportMethod = dcdReactNativeHostClass.methods.first { it.name == "getUseDeveloperSupport" }
|
||||
val handleReloadJSMethod = bridgeDevSupportManagerClass.methods.first { it.name == "handleReloadJS" }
|
||||
val showDevOptionsDialogMethod = bridgeDevSupportManagerClass.methods.first { it.name == "showDevOptionsDialog" }
|
||||
|
||||
var alertDialog: AlertDialog? = null
|
||||
|
||||
// This enables the LogBox and opens dev option on shake
|
||||
XposedBridge.hookMethod(
|
||||
getUseDeveloperSupportMethod,
|
||||
object : XC_MethodHook() {
|
||||
override fun beforeHookedMethod(param: MethodHookParam) {
|
||||
param.result = true
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// Triggered on shake
|
||||
XposedBridge.hookMethod(
|
||||
showDevOptionsDialogMethod,
|
||||
object : XC_MethodHook() {
|
||||
override fun beforeHookedMethod(param: MethodHookParam) {
|
||||
try {
|
||||
if (alertDialog == null) {
|
||||
val mReactInstanceDevHelper =
|
||||
mReactInstanceDevHelperField.get(param.thisObject)
|
||||
val getCurrentActivityMethod =
|
||||
mReactInstanceDevHelper.javaClass.methods.first { it.name == "getCurrentActivity" }
|
||||
|
||||
val context =
|
||||
getCurrentActivityMethod.invoke(mReactInstanceDevHelper) as Context
|
||||
|
||||
alertDialog = showRecoveryAlert(context) {
|
||||
alertDialog = null
|
||||
}
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
Log.e("Bunny", "Failed to show dev options dialog: $ex")
|
||||
alertDialog = null
|
||||
}
|
||||
|
||||
// Ignore the original dev menu
|
||||
param.result = null
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// Replace the method to direct relaunch the app instead of sending reload command to developer server
|
||||
XposedBridge.hookMethod(
|
||||
handleReloadJSMethod,
|
||||
object : XC_MethodHook() {
|
||||
override fun beforeHookedMethod(param: MethodHookParam) {
|
||||
reloadApp()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return@with
|
||||
}
|
||||
|
||||
private fun showRecoveryAlert(context: Context, onClose: () -> Unit): AlertDialog {
|
||||
return AlertDialog.Builder(context)
|
||||
.setTitle("Bunny Recovery Options")
|
||||
.setItems(arrayOf("Reload", "Delete bundle.js")) { _, which ->
|
||||
when (which) {
|
||||
0 -> {
|
||||
reloadApp()
|
||||
}
|
||||
1 -> {
|
||||
val bundleFile = File(packageParam.appInfo.dataDir, "cache/pyoncord/bundle.js")
|
||||
if (bundleFile.exists()) {
|
||||
bundleFile.delete()
|
||||
}
|
||||
|
||||
reloadApp()
|
||||
}
|
||||
}
|
||||
|
||||
onClose()
|
||||
}
|
||||
.setOnDismissListener {
|
||||
onClose()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun reloadApp() {
|
||||
val application = AndroidAppHelper.currentApplication()
|
||||
val intent = application.packageManager.getLaunchIntentForPackage(application.packageName)
|
||||
application.startActivity(Intent.makeRestartActivityTask(intent!!.component))
|
||||
exitProcess(0)
|
||||
}
|
||||
}
|
||||
|
|
@ -27,6 +27,7 @@ data class CustomLoadUrl(
|
|||
val enabled: Boolean,
|
||||
val url: String
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class LoaderConfig(
|
||||
val customLoadUrl: CustomLoadUrl
|
||||
|
|
@ -37,6 +38,7 @@ class Main : IXposedHookLoadPackage {
|
|||
ThemeModule(),
|
||||
SysColorsModule(),
|
||||
FontsModule(),
|
||||
LogBoxModule()
|
||||
)
|
||||
|
||||
fun buildLoaderJsonString(): String {
|
||||
|
|
@ -113,7 +115,8 @@ class Main : IXposedHookLoadPackage {
|
|||
|
||||
val config = try {
|
||||
if (!configFile.exists()) throw Exception()
|
||||
Json { ignoreUnknownKeys = true }.decodeFromString(configFile.readText())
|
||||
val json = Json { ignoreUnknownKeys = true }
|
||||
json.decodeFromString(configFile.readText())
|
||||
} catch (_: Exception) {
|
||||
LoaderConfig(
|
||||
customLoadUrl = CustomLoadUrl(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue