diff --git a/app/src/main/java/org/andbootmgr/app/BackupRestoreFlow.kt b/app/src/main/java/org/andbootmgr/app/BackupRestoreFlow.kt index 254a0873..f1c213b1 100644 --- a/app/src/main/java/org/andbootmgr/app/BackupRestoreFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/BackupRestoreFlow.kt @@ -100,15 +100,15 @@ private fun SelectDroidBoot(c: CreateBackupDataHolder) { c.vm.activity.chooseFile("*/*") { c.path = it nextButtonAvailable = true - c.vm.nextText.value = c.vm.activity.getString(R.string.next) - c.vm.onNext.value = { i -> i.navigate("go") } + c.vm.nextText = c.vm.activity.getString(R.string.next) + c.vm.onNext = { i -> i.navigate("go") } } } else { c.vm.activity.createFile("${c.meta!!.dumpKernelPartition(c.pi).name}.img") { c.path = it nextButtonAvailable = true - c.vm.nextText.value = c.vm.activity.getString(R.string.next) - c.vm.onNext.value = { i -> i.navigate("go") } + c.vm.nextText = c.vm.activity.getString(R.string.next) + c.vm.onNext = { i -> i.navigate("go") } } } }) { @@ -159,8 +159,7 @@ private fun Flash(c: CreateBackupDataHolder) { terminal.add(c.vm.activity.getString(R.string.term_contact_support)) } terminal.add(c.vm.activity.getString(R.string.term_success)) - c.vm.btnsOverride = true - c.vm.nextText.value = c.vm.activity.getString(R.string.finish) - c.vm.onNext.value = { it.finish() } + c.vm.nextText = c.vm.activity.getString(R.string.finish) + c.vm.onNext = { it.finish() } } } \ No newline at end of file diff --git a/app/src/main/java/org/andbootmgr/app/CreatePartFlow.kt b/app/src/main/java/org/andbootmgr/app/CreatePartFlow.kt index 42f6c35a..c73f7556 100644 --- a/app/src/main/java/org/andbootmgr/app/CreatePartFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/CreatePartFlow.kt @@ -719,13 +719,14 @@ private fun Os(c: CreatePartDataHolder) { } } } - c.vm.btnsOverride = true - if (e) { - c.vm.onNext.value = {} - c.vm.nextText.value = "" - } else { - c.vm.onNext.value = { it.navigate("dload") } - c.vm.nextText.value = stringResource(R.string.install) + LaunchedEffect(e) { + if (e) { + c.vm.onNext = {} + c.vm.nextText = "" + } else { + c.vm.onNext = { it.navigate("dload") } + c.vm.nextText = c.vm.activity.getString(R.string.install) + } } } @@ -889,13 +890,15 @@ private fun Download(c: CreatePartDataHolder) { } } } - c.vm.btnsOverride = true - if (c.idNeeded.find { !c.chosen.containsKey(it) } == null && c.chosen.containsKey("_install.sh_")) { - c.vm.onNext.value = { it.navigate("flash") } - c.vm.nextText.value = stringResource(id = R.string.install) - } else { - c.vm.onNext.value = {} - c.vm.nextText.value = "" + val isOk = c.idNeeded.find { !c.chosen.containsKey(it) } == null && c.chosen.containsKey("_install.sh_") + LaunchedEffect(isOk) { + if (isOk) { + c.vm.onNext = { it.navigate("flash") } + c.vm.nextText = c.vm.activity.getString(R.string.install) + } else { + c.vm.onNext = {} + c.vm.nextText = "" + } } } } @@ -984,9 +987,8 @@ private fun Flash(c: CreatePartDataHolder) { } terminal.add(vm.activity.getString(R.string.term_success)) - vm.btnsOverride = true - vm.nextText.value = vm.activity.getString(R.string.finish) - vm.onNext.value = { it.finish() } + vm.nextText = vm.activity.getString(R.string.finish) + vm.onNext = { it.finish() } } // Fucking complicated code to fairly and flexibly partition space based on preset percentage & bytes values @@ -1048,11 +1050,8 @@ private fun Flash(c: CreatePartDataHolder) { terminal.add(vm.activity.getString(R.string.term_reboot_asap)) } if (r.isSuccess) { - vm.btnsOverride = true - vm.nextText.value = c.vm.activity.getString(R.string.finish) - vm.onNext.value = { - it.finish() - } + vm.nextText = c.vm.activity.getString(R.string.finish) + vm.onNext = { it.finish() } terminal.add(vm.activity.getString(R.string.term_success)) } else { terminal.add(vm.activity.getString(R.string.term_failure)) diff --git a/app/src/main/java/org/andbootmgr/app/DroidBootFlow.kt b/app/src/main/java/org/andbootmgr/app/DroidBootFlow.kt index b970e7e9..e02f0cee 100644 --- a/app/src/main/java/org/andbootmgr/app/DroidBootFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/DroidBootFlow.kt @@ -16,6 +16,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextField import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -101,7 +102,7 @@ private fun Input(vm: WizardActivityState) { modifier = Modifier.fillMaxSize() ) { var text by remember { mutableStateOf(vm.activity.getString(R.string.android)) } - vm.texts["OsName"] = text.trim() + LaunchedEffect(text) { vm.texts["OsName"] = text.trim() } val e = text.isBlank() || !text.matches(Regex("[\\dA-Za-z]+")) Text(stringResource(R.string.enter_name_for_current), textAlign = TextAlign.Center, modifier = Modifier.padding(vertical = 5.dp)) @@ -115,21 +116,26 @@ private fun Input(vm: WizardActivityState) { isError = e ) if (e) { - vm.nextText.value = "" - vm.onNext.value = {} Text(stringResource(R.string.invalid_in), color = MaterialTheme.colorScheme.error) } else { - vm.nextText.value = stringResource(id = R.string.next) - vm.onNext.value = { it.navigate("select") } Text("") // Budget spacer } + LaunchedEffect(e) { + if (e) { + vm.nextText = "" + vm.onNext = {} + } else { + vm.nextText = vm.activity.getString(R.string.next) + vm.onNext = { it.navigate("select") } + } + } } } // shared across DroidBootFlow, UpdateDroidBootFlow, FixDroidBootFlow @Composable fun SelectDroidBoot(vm: WizardActivityState) { - val nextButtonAvailable = remember { mutableStateOf(false) } + var nextButtonAvailable by remember { mutableStateOf(false) } Column(horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, modifier = Modifier.fillMaxSize() @@ -140,16 +146,16 @@ fun SelectDroidBoot(vm: WizardActivityState) { Modifier.defaultMinSize(32.dp, 32.dp) ) - if (nextButtonAvailable.value) { + if (nextButtonAvailable) { Text(stringResource(id = R.string.successfully_selected)) - vm.nextText.value = stringResource(id = R.string.next) - vm.onNext.value = { it.navigate("flash") } } else { Text(stringResource(R.string.choose_droidboot_online)) Button(onClick = { vm.activity.chooseFile("*/*") { vm.flashes["DroidBootFlashType"] = Pair(it, null) - nextButtonAvailable.value = true + nextButtonAvailable = true + vm.nextText = vm.activity.getString(R.string.next) + vm.onNext = { n -> n.navigate("flash") } } }) { Text(stringResource(id = R.string.choose_file)) @@ -167,7 +173,9 @@ fun SelectDroidBoot(vm: WizardActivityState) { val url = bl.getString("url") val sha = if (bl.has("sha256")) bl.getString("sha256") else null vm.flashes["DroidBootFlashType"] = Pair(Uri.parse(url), sha) - nextButtonAvailable.value = true + nextButtonAvailable = true + vm.nextText = vm.activity.getString(R.string.next) + vm.onNext = { n -> n.navigate("flash") } } catch (e: Exception) { Handler(Looper.getMainLooper()).post { Toast.makeText(ctx, R.string.dl_error, Toast.LENGTH_LONG).show() @@ -185,22 +193,23 @@ fun SelectDroidBoot(vm: WizardActivityState) { // shared across DroidBootFlow, UpdateDroidBootFlow, FixDroidBootFlow @Composable fun SelectInstallSh(vm: WizardActivityState, update: Boolean = false) { - val nextButtonAvailable = remember { mutableStateOf(false) } + var nextButtonAvailable by remember { mutableStateOf(false) } val flashType = "InstallShFlashType" Column(horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, modifier = Modifier.fillMaxSize() ) { - if (nextButtonAvailable.value) { + if (nextButtonAvailable) { Text(stringResource(id = R.string.successfully_selected)) - vm.nextText.value = stringResource(id = R.string.next) - vm.onNext.value = { it.navigate(if (!vm.deviceInfo.isBooted(vm.logic) || update) "select" else "flash") } } else { Text(stringResource(R.string.choose_install_s_online)) Button(onClick = { vm.activity.chooseFile("*/*") { vm.flashes[flashType] = Pair(it, null) - nextButtonAvailable.value = true + nextButtonAvailable = true + vm.nextText = vm.activity.getString(R.string.next) + vm.onNext = { n -> n.navigate( + if (!vm.deviceInfo.isBooted(vm.logic) || update) "select" else "flash") } } }) { Text(stringResource(id = R.string.choose_file)) @@ -218,7 +227,10 @@ fun SelectInstallSh(vm: WizardActivityState, update: Boolean = false) { val url = i.getString("url") val sha = if (i.has("sha256")) i.getString("sha256") else null vm.flashes[flashType] = Pair(Uri.parse(url), sha) - nextButtonAvailable.value = true + nextButtonAvailable = true + vm.nextText = vm.activity.getString(R.string.next) + vm.onNext = { n -> n.navigate( + if (!vm.deviceInfo.isBooted(vm.logic) || update) "select" else "flash") } } catch (e: Exception) { Handler(Looper.getMainLooper()).post { Toast.makeText(ctx, R.string.dl_error, Toast.LENGTH_LONG).show() @@ -374,9 +386,8 @@ private fun Flash(vm: WizardActivityState) { terminal.add(vm.activity.getString(R.string.term_success)) vm.logic.unmountBootset() withContext(Dispatchers.Main) { - vm.btnsOverride = true - vm.nextText.value = vm.activity.getString(R.string.finish) - vm.onNext.value = { + vm.nextText = vm.activity.getString(R.string.finish) + vm.onNext = { if (vm.deviceInfo.isBooted(vm.logic)) { it.finish() } else { diff --git a/app/src/main/java/org/andbootmgr/app/FixDroidBootFlow.kt b/app/src/main/java/org/andbootmgr/app/FixDroidBootFlow.kt index 8b665941..5dcf49d3 100644 --- a/app/src/main/java/org/andbootmgr/app/FixDroidBootFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/FixDroidBootFlow.kt @@ -92,9 +92,8 @@ private fun Flash(vm: WizardActivityState) { } terminal.add(vm.activity.getString(R.string.term_success)) withContext(Dispatchers.Main) { - vm.btnsOverride = true - vm.nextText.value = vm.activity.getString(R.string.finish) - vm.onNext.value = { + vm.nextText = vm.activity.getString(R.string.finish) + vm.onNext = { it.finish() } } diff --git a/app/src/main/java/org/andbootmgr/app/MainActivity.kt b/app/src/main/java/org/andbootmgr/app/MainActivity.kt index f2a376a7..18a00320 100644 --- a/app/src/main/java/org/andbootmgr/app/MainActivity.kt +++ b/app/src/main/java/org/andbootmgr/app/MainActivity.kt @@ -270,22 +270,17 @@ class MainActivity : ComponentActivity() { } BackHandler {} Column(modifier = Modifier.fillMaxSize()) { - Row(modifier = Modifier.fillMaxWidth().weight(1.0f)) { + Box(modifier = Modifier.fillMaxWidth().weight(1.0f)) { Terminal(null, { canFinish = true }, null) } - Row(modifier = Modifier.fillMaxWidth()) { - TextButton(onClick = { - }, modifier = Modifier.weight(1f, true)) { - Text("") // This button is useless. - } - TextButton(onClick = { + Box(modifier = Modifier.fillMaxWidth()) { + BasicButtonRow("", {}, if (canFinish) + stringResource(R.string.finish) else "") { if (canFinish) CoroutineScope(Dispatchers.IO).launch { vm.init() showTerminal = false } - }, modifier = Modifier.weight(1f, true)) { - Text(if (canFinish) stringResource(R.string.finish) else "") } } } diff --git a/app/src/main/java/org/andbootmgr/app/UpdateDroidBootFlow.kt b/app/src/main/java/org/andbootmgr/app/UpdateDroidBootFlow.kt index 2c800495..e5394fae 100644 --- a/app/src/main/java/org/andbootmgr/app/UpdateDroidBootFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/UpdateDroidBootFlow.kt @@ -92,11 +92,8 @@ private fun Flash(vm: WizardActivityState) { } terminal.add(vm.activity.getString(R.string.term_success)) withContext(Dispatchers.Main) { - vm.btnsOverride = true - vm.nextText.value = vm.activity.getString(R.string.finish) - vm.onNext.value = { - it.finish() - } + vm.nextText = vm.activity.getString(R.string.finish) + vm.onNext = { it.finish() } } } } \ No newline at end of file diff --git a/app/src/main/java/org/andbootmgr/app/UpdateFlow.kt b/app/src/main/java/org/andbootmgr/app/UpdateFlow.kt index 9fadc291..0db40713 100644 --- a/app/src/main/java/org/andbootmgr/app/UpdateFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/UpdateFlow.kt @@ -254,9 +254,8 @@ private fun Flash(u: UpdateFlowDataHolder) { Shell.cmd(SDUtils.umsd(meta)).exec() if (u.hasUpdate) { // online - u.vm.btnsOverride = true - u.vm.nextText.value = u.vm.activity.getString(R.string.cancel) - u.vm.onNext.value = { u.currentDl?.cancel() } + u.vm.nextText = u.vm.activity.getString(R.string.cancel) + u.vm.onNext = { u.currentDl?.cancel() } try { val bootfile = ArrayList() if (u.extraParts.isNotEmpty()) { @@ -293,8 +292,8 @@ private fun Flash(u: UpdateFlowDataHolder) { val tmpFile = createTempFileSu("abm", ".sh", u.vm.logic.rootTmpDir) u.vm.copyPriv(u.vm.flashStream("InstallShFlashType"), tmpFile) tmpFile.setExecutable(true) - u.vm.nextText.value = "" - u.vm.onNext.value = {} + u.vm.nextText = "" + u.vm.onNext = {} for (p in u.partMapping.entries) { val v = sp.find { p.key.toString() == it } @@ -366,13 +365,10 @@ private fun Flash(u: UpdateFlowDataHolder) { throw IllegalStateException(u.vm.activity.getString(R.string.term_script_fail)) } terminal.add(u.vm.activity.getString(R.string.term_success)) - u.vm.btnsOverride = true } else { terminal.add(u.vm.activity.getString(R.string.term_update_failed_prep)) } - u.vm.nextText.value = u.vm.activity.getString(R.string.finish) - u.vm.onNext.value = { - it.finish() - } + u.vm.nextText = u.vm.activity.getString(R.string.finish) + u.vm.onNext = { it.finish() } } } \ No newline at end of file diff --git a/app/src/main/java/org/andbootmgr/app/WizardActivity.kt b/app/src/main/java/org/andbootmgr/app/WizardActivity.kt index 670924b6..707d18df 100644 --- a/app/src/main/java/org/andbootmgr/app/WizardActivity.kt +++ b/app/src/main/java/org/andbootmgr/app/WizardActivity.kt @@ -12,9 +12,10 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect -import androidx.compose.runtime.MutableState +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.core.net.toFile import androidx.navigation.NavHostController @@ -56,33 +57,31 @@ fun WizardCompat(mvm: MainActivityState, flow: String) { val vm = remember { WizardActivityState(mvm) } vm.navController = rememberNavController() val wizardPages = remember(flow) { WizardPageFactory(vm).get(flow) } - BackHandler { - vm.onPrev.value.invoke(vm) - } - Column(modifier = Modifier.fillMaxSize()) { NavHost( navController = vm.navController, startDestination = "start", modifier = Modifier .fillMaxWidth() - .weight(1.0f) ) { for (i in wizardPages) { composable(i.name) { - if (!vm.btnsOverride) { - vm.prevText.value = i.prev.text - vm.nextText.value = i.next.text - vm.onPrev.value = i.prev.onClick - vm.onNext.value = i.next.onClick + Column(modifier = Modifier.fillMaxSize()) { + BackHandler { + (vm.onPrev ?: i.prev.onClick)(vm) + } + Box(Modifier.fillMaxWidth().weight(1f)) { + i.run() + } + Box(Modifier.fillMaxWidth()) { + BasicButtonRow(vm.prevText ?: i.prev.text, + { (vm.onPrev ?: i.prev.onClick)(vm) }, + vm.nextText ?: i.next.text, + { (vm.onNext ?: i.next.onClick)(vm) }) + } } - i.run() } } } - Box(Modifier.fillMaxWidth()) { - BtnsRow(vm) - } - } } private class ExpectedDigestInputStream(stream: InputStream?, @@ -100,26 +99,29 @@ class HashMismatchException(message: String) : Exception(message) class WizardActivityState(val mvm: MainActivityState) { val codename = mvm.deviceInfo!!.codename - var btnsOverride = false val activity = mvm.activity!! lateinit var navController: NavHostController val logic = mvm.logic!! val deviceInfo = mvm.deviceInfo!! - var prevText = mutableStateOf("") - var nextText = mutableStateOf("") - var onPrev: MutableState<(WizardActivityState) -> Unit> = mutableStateOf({}) - var onNext: MutableState<(WizardActivityState) -> Unit> = mutableStateOf({}) + var prevText by mutableStateOf(null) + var nextText by mutableStateOf(null) + var onPrev by mutableStateOf<((WizardActivityState) -> Unit)?>(null) + var onNext by mutableStateOf<((WizardActivityState) -> Unit)?>(null) var flashes: HashMap> = HashMap() var texts: HashMap = HashMap() fun navigate(next: String) { - btnsOverride = false + prevText = null + nextText = null + onPrev = null + onNext = null navController.navigate(next) { launchSingleTop = true } } fun finish() { + mvm.init() mvm.wizardCompat = null mvm.wizardCompatE = null mvm.wizardCompatPid = null @@ -184,17 +186,18 @@ interface IWizardPage { } @Composable -private fun BtnsRow(vm: WizardActivityState) { +fun BasicButtonRow(prev: String, onPrev: () -> Unit, + next: String, onNext: () -> Unit) { Row { TextButton(onClick = { - vm.onPrev.value(vm) + onPrev() }, modifier = Modifier.weight(1f, true)) { - Text(vm.prevText.value) + Text(prev) } TextButton(onClick = { - vm.onNext.value(vm) + onNext() }, modifier = Modifier.weight(1f, true)) { - Text(vm.nextText.value) + Text(next) } } } \ No newline at end of file