From d2db9998316d7152069de3dd1a960914ab9786fc Mon Sep 17 00:00:00 2001 From: nift4 Date: Wed, 21 Aug 2024 10:14:21 +0200 Subject: [PATCH] refactoring --- .../org/andbootmgr/app/BackupRestoreFlow.kt | 30 +++---- .../java/org/andbootmgr/app/CreatePartFlow.kt | 56 ++++++------- .../java/org/andbootmgr/app/DroidBootFlow.kt | 4 +- .../org/andbootmgr/app/FixDroidBootFlow.kt | 4 +- .../java/org/andbootmgr/app/MainActivity.kt | 32 +------- .../main/java/org/andbootmgr/app/Settings.kt | 2 +- app/src/main/java/org/andbootmgr/app/Start.kt | 19 +++-- .../org/andbootmgr/app/UpdateDroidBootFlow.kt | 4 +- .../java/org/andbootmgr/app/UpdateFlow.kt | 59 ++++++++------ .../java/org/andbootmgr/app/WizardActivity.kt | 23 ++---- .../java/org/andbootmgr/app/util/Terminal.kt | 79 +++++++++++-------- app/src/main/res/values/strings.xml | 1 + 12 files changed, 143 insertions(+), 170 deletions(-) diff --git a/app/src/main/java/org/andbootmgr/app/BackupRestoreFlow.kt b/app/src/main/java/org/andbootmgr/app/BackupRestoreFlow.kt index f1c213b1..ffe364b6 100644 --- a/app/src/main/java/org/andbootmgr/app/BackupRestoreFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/BackupRestoreFlow.kt @@ -23,9 +23,9 @@ import org.andbootmgr.app.util.Terminal import java.io.File import java.io.IOException -class BackupRestoreWizardPageFactory(private val vm: WizardActivityState) { - fun get(): List { - val c = CreateBackupDataHolder(vm) +class BackupRestoreFlow(private val partitionId: Int): WizardFlow() { + override fun get(vm: WizardActivityState): List { + val c = CreateBackupDataHolder(vm, partitionId) return listOf(WizardPage("start", NavButton(vm.activity.getString(R.string.cancel)) { it.finish() }, NavButton("") {}) @@ -45,8 +45,7 @@ class BackupRestoreWizardPageFactory(private val vm: WizardActivityState) { } } -private class CreateBackupDataHolder(val vm: WizardActivityState) { - var pi: Int = -1 +private class CreateBackupDataHolder(val vm: WizardActivityState, val pi: Int) { var action: Int = 0 var path: Uri? = null var meta: SDUtils.SDPartitionMeta? = null @@ -56,7 +55,6 @@ private class CreateBackupDataHolder(val vm: WizardActivityState) { private fun ChooseAction(c: CreateBackupDataHolder) { LaunchedEffect(Unit) { c.meta = SDUtils.generateMeta(c.vm.deviceInfo) - c.pi = c.vm.mvm.wizardCompatPid!! } Column(horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, @@ -95,21 +93,17 @@ private fun SelectDroidBoot(c: CreateBackupDataHolder) { else -> "" } ) + val next = { it: Uri -> + c.path = it + nextButtonAvailable = true + c.vm.nextText = c.vm.activity.getString(R.string.next) + c.vm.onNext = { i -> i.navigate("go") } + } Button(onClick = { if (c.action != 1) { - c.vm.activity.chooseFile("*/*") { - c.path = it - nextButtonAvailable = true - c.vm.nextText = c.vm.activity.getString(R.string.next) - c.vm.onNext = { i -> i.navigate("go") } - } + c.vm.activity.chooseFile("*/*", next) } else { - c.vm.activity.createFile("${c.meta!!.dumpKernelPartition(c.pi).name}.img") { - c.path = it - nextButtonAvailable = true - c.vm.nextText = c.vm.activity.getString(R.string.next) - c.vm.onNext = { i -> i.navigate("go") } - } + c.vm.activity.createFile("${c.meta!!.dumpKernelPartition(c.pi).name}.img", next) } }) { Text(stringResource(if (c.action != 1) R.string.choose_file else R.string.create_file)) diff --git a/app/src/main/java/org/andbootmgr/app/CreatePartFlow.kt b/app/src/main/java/org/andbootmgr/app/CreatePartFlow.kt index c73f7556..dd1881da 100644 --- a/app/src/main/java/org/andbootmgr/app/CreatePartFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/CreatePartFlow.kt @@ -42,9 +42,9 @@ import java.math.BigDecimal import java.net.URL import java.util.concurrent.TimeUnit -class CreatePartWizardPageFactory(private val vm: WizardActivityState) { - fun get(): List { - val c = CreatePartDataHolder(vm) +class CreatePartFlow(private val desiredStartSector: Long): WizardFlow() { + override fun get(vm: WizardActivityState): List { + val c = CreatePartDataHolder(vm, desiredStartSector) return listOf(WizardPage("start", NavButton(vm.activity.getString(R.string.cancel)) { it.finish() }, NavButton("") {} @@ -120,7 +120,7 @@ internal interface ProgressListener { fun update(bytesRead: Long, contentLength: Long, done: Boolean) } -private class CreatePartDataHolder(val vm: WizardActivityState): ProgressListener { +private class CreatePartDataHolder(val vm: WizardActivityState, private val desiredStartSector: Long): ProgressListener { var meta: SDUtils.SDPartitionMeta? = null lateinit var p: SDUtils.Partition.FreeSpace @@ -128,13 +128,12 @@ private class CreatePartDataHolder(val vm: WizardActivityState): ProgressListene lateinit var u: String var f = 0L var t: String? = null - var noobMode: Boolean = false var scriptInet: String? = null var scriptShaInet: String? = null var painter: @Composable (() -> Painter)? = null - var rtype by mutableStateOf("") - var cmdline by mutableStateOf("") + var rtype = "" + var cmdline = "" val dmaMeta = ArrayMap() val count = mutableIntStateOf(0) val intVals = mutableStateListOf() @@ -156,8 +155,8 @@ private class CreatePartDataHolder(val vm: WizardActivityState): ProgressListene }.build() var pl: ProgressListener? = null var cl: (() -> Unit)? = null - lateinit var t2: MutableState - val t3 = mutableStateOf("") + var t2 by mutableStateOf("") + var t3 by mutableStateOf("") var availableSize: Long = 0 override fun update(bytesRead: Long, contentLength: Long, done: Boolean) { @@ -179,12 +178,9 @@ private class CreatePartDataHolder(val vm: WizardActivityState): ProgressListene idNeeded.removeAll(idUnneeded) } - @SuppressLint("ComposableNaming") - @Composable fun lateInit() { - noobMode = LocalContext.current.getSharedPreferences("abm", 0).getBoolean("noob_mode", BuildConfig.DEFAULT_NOOB_MODE) meta = SDUtils.generateMeta(vm.deviceInfo) - p = (meta?.s?.find { vm.mvm.wizardCompatSid == it.startSector } as SDUtils.Partition.FreeSpace?)!! + p = (meta?.s?.find { desiredStartSector == it.startSector } as SDUtils.Partition.FreeSpace?)!! } fun painterFromRtype(type: String): @Composable () -> Painter { @@ -263,7 +259,7 @@ private fun Start(c: CreatePartDataHolder) { } } - if (remember { ctx.getSharedPreferences("abm", 0).getBoolean("noob_mode", BuildConfig.DEFAULT_NOOB_MODE) }) { + if (c.vm.mvm.noobMode) { Card( modifier = Modifier .fillMaxWidth() @@ -471,12 +467,14 @@ private fun Os(c: CreatePartDataHolder) { a.sortWith(Comparator.comparingInt { c -> c.substring(3, c.length - 5).toInt() }) val b = if (a.size > 0) a.last().substring(3, a.last().length - 5).toInt() + 1 else 0 c.t2 = mutableStateOf("rom$b") - c.t3.value = c.dmaMeta["name"]!! + c.t3 = c.dmaMeta["name"]!! } val s = rememberScrollState() var expanded by remember { mutableIntStateOf(0) } - var e by remember { mutableStateOf(false) } + val et2 by remember { derivedStateOf { !(c.t2.matches(Regex("\\A\\p{ASCII}*\\z"))) } } + val et3 by remember { derivedStateOf { !(c.t3.matches(Regex("\\A\\p{ASCII}*\\z"))) } } + val e = et2 || et3 Column( Modifier .fillMaxSize() @@ -502,7 +500,7 @@ private fun Os(c: CreatePartDataHolder) { } } } - if (!c.noobMode) + if (!c.vm.mvm.noobMode) Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center, modifier = Modifier .fillMaxWidth() .padding(5.dp) @@ -516,32 +514,26 @@ private fun Os(c: CreatePartDataHolder) { Icon(painterResource(id = R.drawable.ic_baseline_keyboard_arrow_down_24), stringResource(R.string.expand_content_desc)) } } - if (expanded == 1 || c.noobMode) { + if (expanded == 1 || c.vm.mvm.noobMode) { Column( Modifier .fillMaxWidth() .padding(5.dp) ) { - var et2 by remember { mutableStateOf(false) } - var et3 by remember { mutableStateOf(false) } - if (!c.noobMode) - TextField(value = c.t2.value, onValueChange = { - c.t2.value = it - et2 = !(c.t2.value.matches(Regex("\\A\\p{ASCII}*\\z"))) - e = et2 || et3 + if (!c.vm.mvm.noobMode) + TextField(value = c.t2, onValueChange = { + c.t2 = it }, isError = et2, label = { Text(stringResource(R.string.internal_id)) }) - TextField(value = c.t3.value, onValueChange = { - c.t3.value = it - et3 = !(c.t3.value.matches(Regex("\\A\\p{ASCII}*\\z"))) - e = et2 || et3 + TextField(value = c.t3, onValueChange = { + c.t3 = it }, isError = et3, label = { Text(stringResource(R.string.name_in_boot)) }) } } - if (!c.noobMode) + if (!c.vm.mvm.noobMode) Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center, modifier = Modifier .fillMaxWidth() .padding(5.dp) @@ -910,8 +902,8 @@ private fun Flash(c: CreatePartDataHolder) { c.vm.logic.extractToolkit(terminal) if (c.t == null) { // OS install val parts = ArrayMap() - val fn = c.t2.value - val gn = c.t3.value + val fn = c.t2 + val gn = c.t3 terminal.add(vm.activity.getString(R.string.term_f_name, fn)) terminal.add(vm.activity.getString(R.string.term_g_name, gn)) val tmpFile = c.chosen["_install.sh_"]!!.toFile(vm) diff --git a/app/src/main/java/org/andbootmgr/app/DroidBootFlow.kt b/app/src/main/java/org/andbootmgr/app/DroidBootFlow.kt index e02f0cee..15700ba3 100644 --- a/app/src/main/java/org/andbootmgr/app/DroidBootFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/DroidBootFlow.kt @@ -44,8 +44,8 @@ import java.io.File import java.io.IOException import java.net.URL -class DroidBootWizardPageFactory(private val vm: WizardActivityState) { - fun get(): List { +class DroidBootFlow() : WizardFlow() { + override fun get(vm: WizardActivityState): List { return listOf(WizardPage("start", NavButton(vm.activity.getString(R.string.cancel)) { it.finish() }, NavButton(vm.activity.getString(R.string.next)) { it.navigate("input") }) diff --git a/app/src/main/java/org/andbootmgr/app/FixDroidBootFlow.kt b/app/src/main/java/org/andbootmgr/app/FixDroidBootFlow.kt index 5dcf49d3..d053d74b 100644 --- a/app/src/main/java/org/andbootmgr/app/FixDroidBootFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/FixDroidBootFlow.kt @@ -16,8 +16,8 @@ import org.andbootmgr.app.util.Terminal import java.io.File import java.io.IOException -class FixDroidBootWizardPageFactory(private val vm: WizardActivityState) { - fun get(): List { +class FixDroidBootFlow(): WizardFlow() { + override fun get(vm: WizardActivityState): List { return listOf(WizardPage("start", NavButton(vm.activity.getString(R.string.cancel)) { it.finish() }, NavButton(vm.activity.getString(R.string.next)) { it.navigate(if (vm.deviceInfo.postInstallScript) "shSel" else "select") }) diff --git a/app/src/main/java/org/andbootmgr/app/MainActivity.kt b/app/src/main/java/org/andbootmgr/app/MainActivity.kt index 18a00320..eb92e66d 100644 --- a/app/src/main/java/org/andbootmgr/app/MainActivity.kt +++ b/app/src/main/java/org/andbootmgr/app/MainActivity.kt @@ -14,7 +14,6 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -34,7 +33,6 @@ import androidx.compose.material3.ModalNavigationDrawer import androidx.compose.material3.NavigationDrawerItem import androidx.compose.material3.Scaffold import androidx.compose.material3.Text -import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberDrawerState import androidx.compose.runtime.Composable @@ -68,36 +66,12 @@ import org.andbootmgr.app.themes.ThemeViewModel import org.andbootmgr.app.themes.Themes import org.andbootmgr.app.util.AbmTheme import org.andbootmgr.app.util.ConfigFile -import org.andbootmgr.app.util.SDUtils import org.andbootmgr.app.util.StayAliveService import org.andbootmgr.app.util.Terminal import java.util.concurrent.atomic.AtomicBoolean class MainActivityState(val activity: MainActivity?) { - var wizardCompat by mutableStateOf(null) - - fun startFlow(flow: String) { - wizardCompat = flow - } - - var wizardCompatSid: Long? = null - fun startCreateFlow(freeSpace: SDUtils.Partition.FreeSpace) { - wizardCompatSid = freeSpace.startSector - startFlow("create_part") - } - - var wizardCompatE: String? = null - fun startUpdateFlow(e: String) { - wizardCompatE = e - startFlow("update") - } - - var wizardCompatPid: Int? = null - fun startBackupAndRestoreFlow(partition: SDUtils.Partition) { - wizardCompatPid = partition.id - startFlow("backup_restore") - } - + var currentWizardFlow by mutableStateOf(null) var noobMode by mutableStateOf(false) var deviceInfo: DeviceInfo? = null val theme = ThemeViewModel(this) @@ -284,8 +258,8 @@ class MainActivity : ComponentActivity() { } } } - } else if (vm.wizardCompat != null) { - WizardCompat(vm, vm.wizardCompat!!) + } else if (vm.currentWizardFlow != null) { + WizardCompat(vm, vm.currentWizardFlow!!) } else { val navController = rememberNavController() AppContent(vm, navController) { diff --git a/app/src/main/java/org/andbootmgr/app/Settings.kt b/app/src/main/java/org/andbootmgr/app/Settings.kt index 9ab6e861..25cc3bf4 100644 --- a/app/src/main/java/org/andbootmgr/app/Settings.kt +++ b/app/src/main/java/org/andbootmgr/app/Settings.kt @@ -86,7 +86,7 @@ fun Settings(vm: MainActivityState) { Text(stringResource(R.string.save_changes)) } Button(onClick = { - vm.startFlow("update_droidboot") + vm.currentWizardFlow = UpdateDroidBootFlow() }) { Text(stringResource(R.string.update_droidboot)) } diff --git a/app/src/main/java/org/andbootmgr/app/Start.kt b/app/src/main/java/org/andbootmgr/app/Start.kt index f4801169..65936df6 100644 --- a/app/src/main/java/org/andbootmgr/app/Start.kt +++ b/app/src/main/java/org/andbootmgr/app/Start.kt @@ -151,13 +151,15 @@ fun Start(vm: MainActivityState) { } else if (metaOnSd && !sdPresent) { Text(stringResource(R.string.need_sd), textAlign = TextAlign.Center) } else if (!installed && !mounted) { - Button(onClick = { vm.startFlow("droidboot") }) { + Button(onClick = { + vm.currentWizardFlow = DroidBootFlow() + }) { Text(stringResource(if (metaOnSd) R.string.setup_sd else R.string.install)) } } else if (!booted && mounted) { Text(stringResource(R.string.installed_not_booted), textAlign = TextAlign.Center) Button(onClick = { - vm.startFlow("fix_droidboot") + vm.currentWizardFlow = FixDroidBootFlow() }) { Text(stringResource(R.string.repair_droidboot)) } @@ -462,11 +464,15 @@ private fun PartTool(vm: MainActivityState) { } } } - Button(onClick = { vm.startBackupAndRestoreFlow(p) }) { + Button(onClick = { + vm.currentWizardFlow = BackupRestoreFlow(p.id) + }) { Text(stringResource(R.string.backupnrestore)) } } else { - Button(onClick = { vm.startCreateFlow(p as SDUtils.Partition.FreeSpace) }) { + Button(onClick = { + vm.currentWizardFlow = CreatePartFlow(p.startSector) + }) { Text(stringResource(R.string.create)) } } @@ -715,8 +721,9 @@ private fun PartTool(vm: MainActivityState) { Column(Modifier.verticalScroll(rememberScrollState())) { Button( onClick = { - if (e.has("xupdate") && !e["xupdate"].isNullOrBlank()) - vm.startUpdateFlow(entries!![e]!!.absolutePath) + if (e.has("xupdate") && !e["xupdate"].isNullOrBlank()) { + vm.currentWizardFlow = UpdateFlow(entries!![e]!!.name) + } }, enabled = e.has("xupdate") && !e["xupdate"].isNullOrBlank()) { Text(stringResource(R.string.update)) } diff --git a/app/src/main/java/org/andbootmgr/app/UpdateDroidBootFlow.kt b/app/src/main/java/org/andbootmgr/app/UpdateDroidBootFlow.kt index e5394fae..0a6582db 100644 --- a/app/src/main/java/org/andbootmgr/app/UpdateDroidBootFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/UpdateDroidBootFlow.kt @@ -16,8 +16,8 @@ import org.andbootmgr.app.util.Terminal import java.io.File import java.io.IOException -class UpdateDroidBootWizardPageFactory(private val vm: WizardActivityState) { - fun get(): List { +class UpdateDroidBootFlow(): WizardFlow() { + override fun get(vm: WizardActivityState): List { return listOf(WizardPage("start", NavButton(vm.activity.getString(R.string.cancel)) { it.finish() }, NavButton(vm.activity.getString(R.string.next)) { it.navigate(if (vm.deviceInfo.postInstallScript) "shSel" else "select") }) diff --git a/app/src/main/java/org/andbootmgr/app/UpdateFlow.kt b/app/src/main/java/org/andbootmgr/app/UpdateFlow.kt index 0db40713..4bb6b077 100644 --- a/app/src/main/java/org/andbootmgr/app/UpdateFlow.kt +++ b/app/src/main/java/org/andbootmgr/app/UpdateFlow.kt @@ -3,20 +3,26 @@ package org.andbootmgr.app import android.net.Uri import android.util.Log import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.Button +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.io.SuFile -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import okhttp3.Call @@ -34,15 +40,14 @@ import java.io.File import java.net.URL import java.util.concurrent.TimeUnit -class UpdateFlowWizardPageFactory(private val vm: WizardActivityState) { - fun get(): List { - val c = UpdateFlowDataHolder(vm) - val noobMode = c.vm.activity.getSharedPreferences("abm", 0).getBoolean("noob_mode", BuildConfig.DEFAULT_NOOB_MODE) +class UpdateFlow(private val entryName: String): WizardFlow() { + override fun get(vm: WizardActivityState): List { + val c = UpdateFlowDataHolder(vm, entryName) return listOf(WizardPage("start", NavButton(vm.activity.getString(R.string.cancel)) { it.finish() }, - if (noobMode) NavButton("") {} else NavButton(vm.activity.getString(R.string.local_update)) { vm.navigate("local") } + if (c.vm.mvm.noobMode) NavButton("") {} else NavButton(vm.activity.getString(R.string.local_update)) { vm.navigate("local") } ) { Start(c) }, WizardPage("local", @@ -59,7 +64,7 @@ class UpdateFlowWizardPageFactory(private val vm: WizardActivityState) { } } -private class UpdateFlowDataHolder(val vm: WizardActivityState) { +private class UpdateFlowDataHolder(val vm: WizardActivityState, val entryFilename: String) { val client = OkHttpClient().newBuilder().readTimeout(1L, TimeUnit.HOURS).build() var json: JSONObject? = null var currentDl: Call? = null @@ -68,7 +73,6 @@ private class UpdateFlowDataHolder(val vm: WizardActivityState) { var e: ConfigFile? = null var ef: File? = null var hasUpdate = false - var hasChecked by mutableStateOf(false) val partMapping = HashMap() var extraParts = ArrayList() var updateJson: String? = null @@ -77,20 +81,16 @@ private class UpdateFlowDataHolder(val vm: WizardActivityState) { @Composable private fun Start(u: UpdateFlowDataHolder) { + var hasChecked by remember { mutableStateOf(false) } + val ioDispatcher = rememberCoroutineScope { Dispatchers.IO } LaunchedEffect(Unit) { - val entries = mutableMapOf() - val list = SuFile.open(u.vm.logic.abmEntries.absolutePath).listFiles() - for (i in list!!) { - try { - entries[ConfigFile.importFromFile(i)] = i - } catch (e: ActionAbortedCleanlyError) { - Log.e("ABM", Log.getStackTraceString(e)) - } - } - val toFind = u.vm.mvm.wizardCompatE!! - u.e = entries.entries.find { it.value.absolutePath == toFind }!!.also { u.ef = it.value }.key - - CoroutineScope(Dispatchers.IO).launch { + ioDispatcher.launch { + u.e = ConfigFile.importFromFile( + SuFile.open( + u.vm.logic.abmEntries.absolutePath, + u.entryFilename + ) + ) try { val jsonText = URL(u.e!!["xupdate"]).readText() @@ -101,11 +101,11 @@ private fun Start(u: UpdateFlowDataHolder) { if (u.json != null) { u.hasUpdate = u.json!!.optBoolean("hasUpdate", false) } - u.hasChecked = true + hasChecked = true } } - Column { - if (u.hasChecked) { + if (hasChecked) { + Column(modifier = Modifier.fillMaxSize()) { if (u.json == null) { Text(stringResource(R.string.update_check_failed)) } else { @@ -124,7 +124,8 @@ private fun Start(u: UpdateFlowDataHolder) { } vm.flashes["InstallShFlashType"] = Pair( Uri.parse(j.getString("script")), - if (j.has("scriptSha256")) j.getString("scriptSha256") else null) + if (j.has("scriptSha256")) j.getString("scriptSha256") else null + ) } if (j.has("parts")) { val sp = u.e!!["xpart"]!!.split(":") @@ -156,7 +157,15 @@ private fun Start(u: UpdateFlowDataHolder) { } } } + } else { + Box(contentAlignment = Alignment.Center) { + Row { + CircularProgressIndicator() + Text(stringResource(R.string.checking_for_update)) + } + } } + } @Composable diff --git a/app/src/main/java/org/andbootmgr/app/WizardActivity.kt b/app/src/main/java/org/andbootmgr/app/WizardActivity.kt index 707d18df..692948f2 100644 --- a/app/src/main/java/org/andbootmgr/app/WizardActivity.kt +++ b/app/src/main/java/org/andbootmgr/app/WizardActivity.kt @@ -34,29 +34,19 @@ import java.nio.file.StandardCopyOption import java.security.DigestInputStream import java.security.MessageDigest -class WizardPageFactory(private val vm: WizardActivityState) { - fun get(flow: String): List { - return when (flow) { - "droidboot" -> DroidBootWizardPageFactory(vm).get() - "fix_droidboot" -> FixDroidBootWizardPageFactory(vm).get() - "update_droidboot" -> UpdateDroidBootWizardPageFactory(vm).get() - "create_part" -> CreatePartWizardPageFactory(vm).get() - "backup_restore" -> BackupRestoreWizardPageFactory(vm).get() - "update" -> UpdateFlowWizardPageFactory(vm).get() - else -> listOf() - } - } +abstract class WizardFlow { + abstract fun get(vm: WizardActivityState): List } @Composable -fun WizardCompat(mvm: MainActivityState, flow: String) { +fun WizardCompat(mvm: MainActivityState, flow: WizardFlow) { DisposableEffect(Unit) { mvm.activity!!.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) onDispose { mvm.activity.window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) } } val vm = remember { WizardActivityState(mvm) } vm.navController = rememberNavController() - val wizardPages = remember(flow) { WizardPageFactory(vm).get(flow) } + val wizardPages = remember(flow) { flow.get(vm) } NavHost( navController = vm.navController, startDestination = "start", @@ -122,10 +112,7 @@ class WizardActivityState(val mvm: MainActivityState) { } fun finish() { mvm.init() - mvm.wizardCompat = null - mvm.wizardCompatE = null - mvm.wizardCompatPid = null - mvm.wizardCompatSid = null + mvm.currentWizardFlow = null } fun copy(inputStream: InputStream, outputStream: OutputStream): Long { diff --git a/app/src/main/java/org/andbootmgr/app/util/Terminal.kt b/app/src/main/java/org/andbootmgr/app/util/Terminal.kt index b6636647..2cd60e30 100644 --- a/app/src/main/java/org/andbootmgr/app/util/Terminal.kt +++ b/app/src/main/java/org/andbootmgr/app/util/Terminal.kt @@ -9,9 +9,12 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Text 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 import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLifecycleOwner @@ -138,7 +141,8 @@ fun Terminal(logFile: String? = null, doWhenDone: (() -> Unit)? = null, val scrollH = rememberScrollState() val scrollV = rememberScrollState() val scope = rememberCoroutineScope() - val text = remember { mutableStateOf("") } + var didConnectAndFinish by rememberSaveable { mutableStateOf(false) } + var text by rememberSaveable { mutableStateOf("") } val ctx = LocalContext.current.applicationContext val lo = LocalLifecycleOwner.current LaunchedEffect(Unit) { @@ -148,48 +152,53 @@ fun Terminal(logFile: String? = null, doWhenDone: (() -> Unit)? = null, if (action != null && doWhenDone != null) { throw IllegalArgumentException("Don't use both action and doWhenDone") } - StayAliveConnection(ctx, lo, doWhenDone) { service -> - if (action != null) { - val logDispatcher = Dispatchers.IO.limitedParallelism(1) - val log = logFile?.let { FileOutputStream(File(ctx.externalCacheDir, it)) } - val s = BudgetCallbackList(CoroutineScope(logDispatcher), log) - s.cb = { element -> - scope.launch { - text.value += element + "\n" - delay(200) // Give it time to re-measure - scrollV.animateScrollTo(scrollV.maxValue) - scrollH.animateScrollTo(0) + if (!didConnectAndFinish) { + StayAliveConnection( + ctx, + lo, + { didConnectAndFinish = true; doWhenDone?.invoke() }) { service -> + if (action != null) { + val logDispatcher = Dispatchers.IO.limitedParallelism(1) + val log = logFile?.let { FileOutputStream(File(ctx.externalCacheDir, it)) } + val s = BudgetCallbackList(CoroutineScope(logDispatcher), log) + s.cb = { element -> + scope.launch { + text += element + "\n" + delay(200) // Give it time to re-measure + scrollV.animateScrollTo(scrollV.maxValue) + scrollH.animateScrollTo(0) + } } - } - service.startWork({ - withContext(Dispatchers.Default) { - try { - action(s) - } catch (e: Throwable) { - s.add(ctx.getString(R.string.term_failure)) - s.add(ctx.getString(R.string.dev_details)) - s.add(Log.getStackTraceString(e)) + service.startWork({ + withContext(Dispatchers.Default) { + try { + action(s) + } catch (e: Throwable) { + s.add(ctx.getString(R.string.term_failure)) + s.add(ctx.getString(R.string.dev_details)) + s.add(Log.getStackTraceString(e)) + } + withContext(logDispatcher) { + log?.close() + } } - withContext(logDispatcher) { - log?.close() + }, s) + } else { + val s = service.workExtra as BudgetCallbackList + text = s.joinToString("\n").let { if (s.isNotEmpty()) it + "\n" else it } + s.cb = { element -> + scope.launch { + text += element + "\n" + delay(200) // Give it time to re-measure + scrollV.animateScrollTo(scrollV.maxValue) + scrollH.animateScrollTo(0) } } - }, s) - } else { - val s = service.workExtra as BudgetCallbackList - text.value = s.joinToString("\n").let { if (s.isNotEmpty()) it + "\n" else it } - s.cb = { element -> - scope.launch { - text.value += element + "\n" - delay(200) // Give it time to re-measure - scrollV.animateScrollTo(scrollV.maxValue) - scrollH.animateScrollTo(0) - } } } } } - Text(text.value, modifier = Modifier + Text(text, modifier = Modifier .fillMaxSize() .horizontalScroll(scrollH) .verticalScroll(scrollV) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 62faca79..e5a800d0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -76,6 +76,7 @@ File not available, please try again later! Local update Online update + Checking for updates… Failed to check for updates! Please try again later. "An update is available for installation.\n\n