@@ -13,6 +13,7 @@ import android.provider.Settings
1313import android.widget.Toast
1414import androidx.activity.ComponentActivity
1515import androidx.activity.compose.setContent
16+ import androidx.activity.enableEdgeToEdge
1617import androidx.activity.result.ActivityResultLauncher
1718import androidx.activity.result.contract.ActivityResultContracts
1819import androidx.activity.viewModels
@@ -34,6 +35,7 @@ import com.renpytool.keystore.KeystoreInfo
3435import com.renpytool.keystore.KeystoreManager
3536import com.renpytool.keystore.SigningOption
3637import com.renpytool.ui.CompressionSettingsDialog
38+ import com.renpytool.ui.DecompileOptionsDialogContent
3739import com.renpytool.ui.KeystoreSelectionDialog
3840import com.renpytool.ui.MainScreenContent
3941import com.renpytool.ui.RandomKeyWarningDialog
@@ -80,6 +82,9 @@ class MainActivity : ComponentActivity() {
8082 override fun onCreate (savedInstanceState : Bundle ? ) {
8183 super .onCreate(savedInstanceState)
8284
85+ // Enable edge-to-edge display
86+ enableEdgeToEdge()
87+
8388 // Initialize Python (must be done before ViewModel access)
8489 if (! Python .isStarted()) {
8590 Python .start(AndroidPlatform (this ))
@@ -88,6 +93,9 @@ class MainActivity : ComponentActivity() {
8893 // Initialize file picker launchers
8994 initFilePickerLaunchers()
9095
96+ // Store initial theme mode from SharedPreferences (source of truth)
97+ currentThemeMode = ThemeUtils .getThemeMode(this )
98+
9199 // Set up Compose UI
92100 setupMainUI()
93101
@@ -99,13 +107,14 @@ class MainActivity : ComponentActivity() {
99107 }
100108
101109 private fun setupMainUI () {
110+ // Set transparent window background for proper theming in Compose
111+ window.setBackgroundDrawableResource(android.R .color.transparent)
112+
102113 setContent {
103- val themeMode by viewModel.themeMode.collectAsState()
104- val darkTheme = when (themeMode) {
105- MainViewModel .ThemeMode .LIGHT -> false
106- MainViewModel .ThemeMode .DARK -> true
107- MainViewModel .ThemeMode .SYSTEM -> isSystemInDarkTheme()
108- }
114+ // Read theme directly from SharedPreferences (source of truth)
115+ // Don't use ViewModel - it's cached and survives recreate()
116+ val themeMode = ThemeUtils .getThemeMode(this )
117+ val darkTheme = ThemeUtils .shouldUseDarkTheme(themeMode)
109118
110119 RenpytoolTheme (darkTheme = darkTheme) {
111120 MainScreen ()
@@ -140,11 +149,26 @@ class MainActivity : ComponentActivity() {
140149 )
141150 }
142151
152+ private var currentThemeMode: MainViewModel .ThemeMode ? = null
153+
143154 private fun startSettingsActivity () {
144155 val intent = Intent (this , SettingsActivity ::class .java)
145156 startActivity(intent)
146157 }
147158
159+ private fun checkThemeChange () {
160+ // Read theme from SharedPreferences (source of truth)
161+ // ViewModel might have stale value from another activity instance
162+ val newThemeMode = ThemeUtils .getThemeMode(this )
163+ if (currentThemeMode != null && currentThemeMode != newThemeMode) {
164+ // Theme changed, recreate activity
165+ currentThemeMode = newThemeMode
166+ recreate()
167+ return
168+ }
169+ currentThemeMode = newThemeMode
170+ }
171+
148172
149173 private fun checkPermissions () {
150174 // Check notification permission for Android 13+ (for background operation notifications)
@@ -330,6 +354,7 @@ class MainActivity : ComponentActivity() {
330354 // Start decompile with the extracted path - delegate to ViewModel
331355 val intent = Intent (this , ProgressActivity ::class .java).apply {
332356 putExtra(" DECOMPILE_PATH" , chainPath)
357+ putExtra(" OPERATION_TYPE" , " decompile" )
333358 }
334359 startActivity(intent)
335360 viewModel.performDecompile(chainPath)
@@ -522,47 +547,58 @@ class MainActivity : ComponentActivity() {
522547 }
523548
524549 private fun showDecompileOptionsDialog (sourcePath : String ) {
525- // Create custom dialog view with checkbox
526- val dialogView = layoutInflater.inflate(android.R .layout.select_dialog_singlechoice, null )
527- val checkboxView = android.widget.CheckBox (this ).apply {
528- text = " Try Harder Mode (slower, for obfuscated files)"
529- setPadding(50 , 30 , 50 , 30 )
530- isChecked = false
531- }
532-
533- val layout = android.widget.LinearLayout (this ).apply {
534- orientation = android.widget.LinearLayout .VERTICAL
535- setPadding(50 , 20 , 50 , 20 )
536- addView(android.widget.TextView (this @MainActivity).apply {
537- text = " Decompile Options"
538- textSize = 16f
539- setPadding(0 , 0 , 0 , 20 )
540- })
541- addView(checkboxView)
542- addView(android.widget.TextView (this @MainActivity).apply {
543- text = " \n Try Harder Mode performs aggressive decompilation for heavily obfuscated files. " +
544- " This will take significantly longer.\n\n " +
545- " Use this only if default decompilation fails."
546- textSize = 12f
547- setPadding(0 , 20 , 0 , 0 )
548- setTextColor(android.graphics.Color .GRAY )
549- })
550+ // Check if user has disabled the dialog
551+ val prefs = getSharedPreferences(" RentoolPrefs" , MODE_PRIVATE )
552+ val dontShowDialog = prefs.getBoolean(" dont_show_decompile_dialog" , false )
553+
554+ if (dontShowDialog) {
555+ // Skip dialog and proceed with default settings (tryHarder = false)
556+ val intent = Intent (this , ProgressActivity ::class .java).apply {
557+ putExtra(" DECOMPILE_PATH" , sourcePath)
558+ putExtra(" OPERATION_TYPE" , " decompile" )
559+ }
560+ startActivity(intent)
561+ viewModel.performDecompile(sourcePath, false )
562+ return
550563 }
551564
552- MaterialAlertDialogBuilder (this )
553- .setTitle(" Decompile Settings" )
554- .setView(layout)
555- .setPositiveButton(" Start" ) { _, _ ->
556- val tryHarder = checkboxView.isChecked
557- // Launch progress activity and delegate to ViewModel
558- val intent = Intent (this , ProgressActivity ::class .java).apply {
559- putExtra(" DECOMPILE_PATH" , sourcePath)
565+ // Use Compose dialog for proper theming
566+ val dialog = androidx.appcompat.app.AlertDialog .Builder (this )
567+ .create()
568+
569+ dialog.window?.setBackgroundDrawableResource(android.R .color.transparent)
570+
571+ dialog.setOnShowListener {
572+ val composeView = androidx.compose.ui.platform.ComposeView (this ).apply {
573+ setContent {
574+ val themeMode = ThemeUtils .getThemeMode(this @MainActivity)
575+ val darkTheme = ThemeUtils .shouldUseDarkTheme(themeMode)
576+
577+ RenpytoolTheme (darkTheme = darkTheme) {
578+ DecompileOptionsDialogContent (
579+ onStart = { tryHarder, dontShowAgain ->
580+ // Save preference if user checked "Don't show again"
581+ if (dontShowAgain) {
582+ prefs.edit().putBoolean(" dont_show_decompile_dialog" , true ).apply ()
583+ }
584+
585+ dialog.dismiss()
586+ val intent = Intent (this @MainActivity, ProgressActivity ::class .java).apply {
587+ putExtra(" DECOMPILE_PATH" , sourcePath)
588+ putExtra(" OPERATION_TYPE" , " decompile" )
589+ }
590+ startActivity(intent)
591+ viewModel.performDecompile(sourcePath, tryHarder)
592+ },
593+ onCancel = { dialog.dismiss() }
594+ )
595+ }
560596 }
561- startActivity(intent)
562- viewModel.performDecompile(sourcePath, tryHarder)
563597 }
564- .setNegativeButton(" Cancel" , null )
565- .show()
598+ dialog.setContentView(composeView)
599+ }
600+
601+ dialog.show()
566602 }
567603
568604 /* *
@@ -802,6 +838,9 @@ class MainActivity : ComponentActivity() {
802838 val keystoreManager = KeystoreManager (this )
803839 val availableKeystores = keystoreManager.listKeystores()
804840
841+ // Set transparent window background for proper theming
842+ window.setBackgroundDrawableResource(android.R .color.transparent)
843+
805844 setContent {
806845 RenpytoolTheme (
807846 darkTheme = when (viewModel.themeMode.value) {
@@ -854,6 +893,9 @@ class MainActivity : ComponentActivity() {
854893 }
855894
856895 private fun showRandomKeyWarningDialog () {
896+ // Set transparent window background for proper theming
897+ window.setBackgroundDrawableResource(android.R .color.transparent)
898+
857899 setContent {
858900 RenpytoolTheme (
859901 darkTheme = when (viewModel.themeMode.value) {
@@ -888,6 +930,9 @@ class MainActivity : ComponentActivity() {
888930 // Load saved settings
889931 val settings = CompressionSettings .load(this )
890932
933+ // Set transparent window background for proper theming
934+ window.setBackgroundDrawableResource(android.R .color.transparent)
935+
891936 // Show settings dialog using Compose
892937 setContent {
893938 RenpytoolTheme (
@@ -903,7 +948,9 @@ class MainActivity : ComponentActivity() {
903948 // Save settings
904949 newSettings.save(this @MainActivity)
905950 // Start compression
906- val intent = Intent (this @MainActivity, ProgressActivity ::class .java)
951+ val intent = Intent (this @MainActivity, ProgressActivity ::class .java).apply {
952+ putExtra(" OPERATION_TYPE" , " compress" )
953+ }
907954 startActivity(intent)
908955 viewModel.performCompression(sourcePath, outputPath, newSettings, signingOption)
909956 // Reset to main UI
@@ -1025,6 +1072,8 @@ class MainActivity : ComponentActivity() {
10251072
10261073 override fun onResume () {
10271074 super .onResume()
1075+ // Recreate activity if theme changed while in settings
1076+ checkThemeChange()
10281077 // Update edit status when returning from editor
10291078 viewModel.updateEditStatus()
10301079 }
0 commit comments