From 90cbdedefd5f6fa610743d2170ae43918ace9f29 Mon Sep 17 00:00:00 2001 From: kmmiio99o <164557248+kmmiio99o@users.noreply.github.com> Date: Sun, 12 Oct 2025 21:17:00 +0200 Subject: [PATCH] Remove safe mode toggle and logic from modules Simplify preload loading and LogBox UI by removing safe mode support. Only custom URL configuration is persisted. --- app/build.gradle.kts | 4 +- .../xposed/modules/HookScriptLoaderModule.kt | 24 +- .../revenge/xposed/modules/LogBoxModule.kt | 326 +++++++----------- .../revenge/xposed/modules/UpdaterModule.kt | 7 +- 4 files changed, 136 insertions(+), 225 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ae14cad..bab7ca1 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -12,8 +12,8 @@ android { applicationId = "ShiggyXposed.xposed" minSdk = 22 targetSdk = 36 - versionCode = 1010 - versionName = "1.0.1" + versionCode = 1020 + versionName = "1.0.2" } buildTypes { diff --git a/app/src/main/kotlin/io/github/revenge/xposed/modules/HookScriptLoaderModule.kt b/app/src/main/kotlin/io/github/revenge/xposed/modules/HookScriptLoaderModule.kt index 3d300da..bf57f07 100644 --- a/app/src/main/kotlin/io/github/revenge/xposed/modules/HookScriptLoaderModule.kt +++ b/app/src/main/kotlin/io/github/revenge/xposed/modules/HookScriptLoaderModule.kt @@ -110,30 +110,8 @@ class HookScriptLoaderModule : Module() { } try { - // Safe mode enforcement: - // If a preload file with a '00_' prefix exists (or legacy 'rv_safe_mode.js'), treat - // this as a safe-mode indicator and load only those safe preloads (skip other - // preloads), but still load the main bundle afterwards. - val safeFiles = - preloadsDir - .listFiles() - ?.filter { - it.isFile && - (it.name.startsWith("00_") || it.name == "rv_safe_mode.js") - } - ?.sortedBy { it.name } - if (!safeFiles.isNullOrEmpty()) { - Log.i( - "Safe mode detected - loading only safe preloads: ${safeFiles.map { it.name }}" - ) - // Load only safe preloads; do not load other preloads. Continue and load main - // bundle. - safeFiles.forEach(runScriptFile) - } else { - // Normal behavior: run all preloads - preloadsDir.walk().filter { it.isFile }.forEach(runScriptFile) - } + preloadsDir.walk().filter { it.isFile }.forEach(runScriptFile) if (mainScript.exists()) runScriptFile(mainScript) else { diff --git a/app/src/main/kotlin/io/github/revenge/xposed/modules/LogBoxModule.kt b/app/src/main/kotlin/io/github/revenge/xposed/modules/LogBoxModule.kt index 47b4c81..e167f28 100644 --- a/app/src/main/kotlin/io/github/revenge/xposed/modules/LogBoxModule.kt +++ b/app/src/main/kotlin/io/github/revenge/xposed/modules/LogBoxModule.kt @@ -24,13 +24,11 @@ import kotlinx.serialization.json.* /** * Replacement for the old recovery/dev dialog. Shows a dark-themed dialog on the main thread with: - * - Safe Mode toggle (writes/removes preloads/00_rv_safe_mode.js) * - Load from custom URL toggle + URL input (persists to files/pyoncord/loader.json) * - Save & Reload, Delete bundle, Close actions * - * Safe Mode toggle now behaves like the React snippet: toggles immediately (no reload) and opens a - * confirmation modal asking whether to reload now or later. The confirmation modal uses a custom - * in-dialog layout so button colors and text can be controlled for dark styling. + * This simplified version removes the Safe Mode toggle and the per-addon list. Save only persists + * the custom URL configuration. */ class LogBoxModule : Module() { lateinit var packageParam: XC_LoadPackage.LoadPackageParam @@ -135,10 +133,6 @@ class LogBoxModule : Module() { // Always perform UI operations on the main thread to avoid runtime exceptions Handler(Looper.getMainLooper()).post { try { - // Wrap with a dark dialog theme from module resources (AppCompat-based). - // Use the provided activity/context directly to avoid inflating module resources - // into the host process (some hosts fail to resolve module resources). We set - // colors programmatically on views instead of relying on theme attributes. val themed = context // Prepare paths @@ -148,7 +142,7 @@ class LogBoxModule : Module() { val preloadsDir = File(filesDir, HookScriptLoaderModule.PRELOADS_DIR).apply { mkdirs() } - // Read existing loader.json (guarded) + // Read existing loader.json (guarded) for custom URL var customEnabled = false var customUrl = "" try { @@ -167,9 +161,7 @@ class LogBoxModule : Module() { ) } - // Build the dialog UI programmatically to avoid inflating module resources which - // can - // fail when injected into some host apps. + // Build the dialog UI programmatically. val padding = (themed.resources.displayMetrics.density * 16).toInt() val container = LinearLayout(themed).apply { @@ -218,128 +210,10 @@ class LogBoxModule : Module() { return Pair(tv, sw) } - // Create rows - val safeRow = addSwitchRow("Safe mode (disable add-ons)", false) - val safeSwitch = safeRow.second + // Create rows: custom URL toggle val customRow = addSwitchRow("Load from custom URL", false) val customSwitch = customRow.second - // URL label + input - val lblUrl = - TextView(themed).apply { - text = "Custom bundle URL" - setTextColor(0xFFFFFFFF.toInt()) - textSize = 13f - val lp = - LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT - ) - lp.topMargin = (themed.resources.displayMetrics.density * 8).toInt() - layoutParams = lp - } - val urlInput = - EditText(themed).apply { - hint = "https://example.com/bundle.js" - setTextColor(0xFFFFFFFF.toInt()) - setHintTextColor(0xFFBDBDBD.toInt()) - setBackgroundColor(0xFF1E1E1E.toInt()) - val lp = - LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT - ) - lp.topMargin = (themed.resources.displayMetrics.density * 6).toInt() - layoutParams = lp - visibility = View.GONE - } - container.addView(lblUrl) - container.addView(urlInput) - - // Buttons row - keep primary actions (Delete / Close) on one row, - // place the Save & Reload button on a separate row below so it's not squeezed. - val buttonsRow = - LinearLayout(themed).apply { - orientation = LinearLayout.HORIZONTAL - val lp = - LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT - ) - lp.topMargin = (themed.resources.displayMetrics.density * 12).toInt() - layoutParams = lp - } - - fun createButton(text: String): Button { - return Button(themed).apply { - this.text = text - setAllCaps(false) - setTextColor(0xFFFFFFFF.toInt()) - val bLp = - LinearLayout.LayoutParams( - LinearLayout.LayoutParams.WRAP_CONTENT, - LinearLayout.LayoutParams.WRAP_CONTENT - ) - bLp.marginEnd = (themed.resources.displayMetrics.density * 8).toInt() - layoutParams = bLp - // default transparent background so host drawable still applies - setBackgroundColor(0x00000000) - } - } - - val deleteBtn = createButton("Delete bundle") - val closeBtn = createButton("Close") - val saveBtn = - createButton("Save & Reload").apply { - // accent background + readable text - setBackgroundColor(0xFFBB86FC.toInt()) - setTextColor(0xFF000000.toInt()) - } - - // Add Delete and Close to the top (horizontal) row - buttonsRow.addView(deleteBtn) - buttonsRow.addView(closeBtn) - container.addView(buttonsRow) - - // Create a separate row for the Save button so it sits below and can span full - // width - val saveRow = - LinearLayout(themed).apply { - orientation = LinearLayout.HORIZONTAL - val lp = - LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT - ) - lp.topMargin = (themed.resources.displayMetrics.density * 8).toInt() - layoutParams = lp - } - - val saveLp = - LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT - ) - saveRow.addView(saveBtn, saveLp) - container.addView(saveRow) - - // Expose these variables below using the local names expected by the rest of the - // function (safeSwitch, customSwitch, urlInput, saveBtn, deleteBtn, closeBtn). - // They are already defined above as local vals. - - // Initialize state - check for any sentinel file that indicates safe mode. - // Be robust: accept any file that starts with "00_" (legacy sentinel pattern) - // or the legacy "rv_safe_mode.js". - val safePresent = - preloadsDir.listFiles()?.any { - it.isFile && (it.name.startsWith("00_") || it.name == "rv_safe_mode.js") - } - ?: false - safeSwitch.isChecked = safePresent - customSwitch.isChecked = customEnabled - urlInput.setText(customUrl) - urlInput.visibility = if (customEnabled) View.VISIBLE else View.GONE - // Confirmation modal helper (keeps previous messaging/behavior) fun showReloadConfirmModal(parentCtx: Context, turningOn: Boolean) { try { @@ -382,6 +256,14 @@ class LogBoxModule : Module() { text = "Reload Now" setTextColor(0xFF000000.toInt()) setBackgroundColor(0xFFBB86FC.toInt()) + val wlp = + LinearLayout.LayoutParams( + 0, + LinearLayout.LayoutParams.WRAP_CONTENT, + 1f + ) + wlp.marginEnd = 8 + layoutParams = wlp setOnClickListener { try { reloadApp() @@ -392,24 +274,32 @@ class LogBoxModule : Module() { Button(parentCtx).apply { text = "Later" setTextColor(0xFFFFFFFF.toInt()) + val wlp = + LinearLayout.LayoutParams( + 0, + LinearLayout.LayoutParams.WRAP_CONTENT, + 1f + ) + layoutParams = wlp } - val lpBtn = + buttonsRow.addView( + reloadNowBtn, LinearLayout.LayoutParams( 0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f ) .apply { marginEnd = 8 } - val lpBtn2 = + ) + buttonsRow.addView( + laterBtn, LinearLayout.LayoutParams( 0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f ) - - buttonsRow.addView(reloadNowBtn, lpBtn) - buttonsRow.addView(laterBtn, lpBtn2) + ) dialogContainer.addView(buttonsRow) @@ -436,54 +326,115 @@ class LogBoxModule : Module() { } } - // Safe switch toggles the safe preload file immediately (no automatic reload), - // then prompts the user whether to reload now or later (matching React UI). - safeSwitch.setOnCheckedChangeListener { - _: android.widget.CompoundButton, - checked: Boolean -> - try { - val safeFile = File(preloadsDir, "00_rv_safe_mode.js") - if (checked) { - val safeJs = - "(function(){try{var g=(typeof globalThis!=='undefined'?globalThis:(typeof global!=='undefined'?global:this));if(!g)g={};if(!g.console)g.console={log:function(){},error:function(){},warn:function(){},info:function(){}};g.__SHIGGY_SAFE_MODE=true;}catch(e){}})();" - runCatching { safeFile.writeText(safeJs) }.onFailure { t -> - Log.e("Failed to write safe preload: ${t.message}", t) - XposedBridge.log( - "ShiggyXposed: write safe preload failed: ${android.util.Log.getStackTraceString(t)}" - ) - } - } else { - // Remove any safe-mode sentinel files (be forgiving about filenames) - try { - preloadsDir - .listFiles() - ?.filter { - it.isFile && - (it.name.startsWith("00_") || - it.name == "rv_safe_mode.js") - } - ?.forEach { it.delete() } - } catch (_: Throwable) {} - } - } catch (t: Throwable) { - Log.e("Safe toggle persistence failed: ${t.message}", t) - XposedBridge.log( - "ShiggyXposed: Safe toggle persistence failed: ${android.util.Log.getStackTraceString(t)}" - ) - } + // Safe mode toggle removed; no-op. - // Show confirmation (no automatic reload) with option to reload now - showReloadConfirmModal(themed, checked) + // URL label + input + val lblUrl = + TextView(themed).apply { + text = "Custom bundle URL" + setTextColor(0xFFFFFFFF.toInt()) + textSize = 13f + val lp = + LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + lp.topMargin = (themed.resources.displayMetrics.density * 8).toInt() + layoutParams = lp + } + val urlInput = + EditText(themed).apply { + hint = "https://example.com/bundle.js" + setTextColor(0xFFFFFFFF.toInt()) + setHintTextColor(0xFFBDBDBD.toInt()) + setBackgroundColor(0xFF1E1E1E.toInt()) + val lp = + LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + lp.topMargin = (themed.resources.displayMetrics.density * 6).toInt() + layoutParams = lp + visibility = View.GONE + } + container.addView(lblUrl) + container.addView(urlInput) + + // Buttons row - weighted buttons for consistent spacing + val buttonsRow = + LinearLayout(themed).apply { + orientation = LinearLayout.HORIZONTAL + val lp = + LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + lp.topMargin = (themed.resources.displayMetrics.density * 12).toInt() + layoutParams = lp + } + + fun createButton(text: String): Button { + return Button(themed).apply { + this.text = text + setAllCaps(false) + setTextColor(0xFFFFFFFF.toInt()) + val bLp = + LinearLayout.LayoutParams( + 0, + LinearLayout.LayoutParams.WRAP_CONTENT, + 1f + ) + bLp.marginEnd = (themed.resources.displayMetrics.density * 8).toInt() + layoutParams = bLp + minHeight = (themed.resources.displayMetrics.density * 36).toInt() + setBackgroundColor(0x00000000) + } } - // Custom URL toggle behavior - customSwitch.setOnCheckedChangeListener { - _: android.widget.CompoundButton, - checked: Boolean -> + val deleteBtn = createButton("Delete bundle") + val closeBtn = createButton("Close") + val saveBtn = + createButton("Save & Reload").apply { + setBackgroundColor(0xFFBB86FC.toInt()) + setTextColor(0xFF000000.toInt()) + } + + // Add Delete and Close to the top row (equal width) + buttonsRow.addView(deleteBtn) + buttonsRow.addView(closeBtn) + container.addView(buttonsRow) + + // Save button in its own row (full-width look) + val saveRow = + LinearLayout(themed).apply { + orientation = LinearLayout.HORIZONTAL + val lp = + LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + lp.topMargin = (themed.resources.displayMetrics.density * 8).toInt() + layoutParams = lp + } + + val saveLp = + LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f) + saveBtn.layoutParams = saveLp + saveBtn.minHeight = (themed.resources.displayMetrics.density * 40).toInt() + saveRow.addView(saveBtn) + container.addView(saveRow) + + // Initialize UI state + customSwitch.isChecked = customEnabled + urlInput.setText(customUrl) + urlInput.visibility = if (customEnabled) View.VISIBLE else View.GONE + + // Toggle URL input visibility when switching custom URL on/off + customSwitch.setOnCheckedChangeListener { _, checked -> urlInput.visibility = if (checked) View.VISIBLE else View.GONE } - // Save button: persist loader.json and safe file state, then reload + // Save button: only persist custom URL config and then reload saveBtn.setOnClickListener { try { val enabled = customSwitch.isChecked @@ -497,25 +448,6 @@ class LogBoxModule : Module() { "ShiggyXposed: write loader.json failed: ${android.util.Log.getStackTraceString(t)}" ) } - // ensure safe file persisted if switch is checked - val safeFile = File(preloadsDir, "00_rv_safe_mode.js") - if (safeSwitch.isChecked) { - val safeJs = - "(function(){try{var g=(typeof globalThis!=='undefined'?globalThis:(typeof global!=='undefined'?global:this));if(!g)g={};if(!g.console)g.console={log:function(){},error:function(){},warn:function(){},info:function(){}};g.__SHIGGY_SAFE_MODE=true;}catch(e){}})();" - runCatching { safeFile.writeText(safeJs) } - } else { - // Ensure we remove any existing safe-mode sentinel files - try { - preloadsDir - .listFiles() - ?.filter { - it.isFile && - (it.name.startsWith("00_") || - it.name == "rv_safe_mode.js") - } - ?.forEach { it.delete() } - } catch (_: Throwable) {} - } } catch (t: Throwable) { Log.e("Failed to save loader.json: ${t.message}", t) } diff --git a/app/src/main/kotlin/io/github/revenge/xposed/modules/UpdaterModule.kt b/app/src/main/kotlin/io/github/revenge/xposed/modules/UpdaterModule.kt index d199f09..9411655 100644 --- a/app/src/main/kotlin/io/github/revenge/xposed/modules/UpdaterModule.kt +++ b/app/src/main/kotlin/io/github/revenge/xposed/modules/UpdaterModule.kt @@ -98,9 +98,10 @@ class UpdaterModule : Module() { // Retries don't need timeout if (activity != null) { - val timeoutMs = - if (!bundle.exists()) TIMEOUT - else TIMEOUT_CACHED + var timeoutMs = TIMEOUT_CACHED + if (!bundle.exists()) { + timeoutMs = TIMEOUT + } timeout { requestTimeoutMillis = timeoutMs } } }