diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Flash.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Flash.kt index 932b438a..eefa9a53 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Flash.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Flash.kt @@ -59,6 +59,7 @@ import kotlinx.coroutines.withContext import kotlinx.parcelize.Parcelize import com.rifsxd.ksunext.R import com.rifsxd.ksunext.ui.component.KeyEventBlocker +import com.rifsxd.ksunext.ui.util.FlashResult import com.rifsxd.ksunext.ui.util.LkmSelection import com.rifsxd.ksunext.ui.util.LocalSnackbarHost import com.rifsxd.ksunext.ui.util.flashModule @@ -80,38 +81,17 @@ enum class FlashingStatus { // Lets you flash modules sequentially when mutiple zipUris are selected fun flashModulesSequentially( uris: List, - onFinish: (Boolean, Int) -> Unit, onStdout: (String) -> Unit, onStderr: (String) -> Unit -) { - val iterator = uris.iterator() - - // Start processing from the first module inside a coroutine - CoroutineScope(Dispatchers.IO).launch { - // Define the recursive function within the coroutine - suspend fun processNext() { - if (iterator.hasNext()) { - // Flash the current module - flashModule(iterator.next(), onFinish = { showReboot, code -> - // If successful, continue to the next one - if (code == 0) { - // Recursively call to process the next module - launch { - processNext() - } - } else { - onFinish(showReboot, code) // If failed, finish the process - } - }, onStdout, onStderr) - } else { - // No more modules to process, finish the process - onFinish(true, 0) +): FlashResult { + for (uri in uris) { + flashModule(uri, onStdout, onStderr).apply { + if (code != 0) { + return FlashResult(code, err, showReboot) } } - - // Start the process - processNext() } + return FlashResult(0, "", true) } /** @@ -124,7 +104,7 @@ fun flashModulesSequentially( fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) { var text by rememberSaveable { mutableStateOf("") } - var tempText : String + var tempText: String val logContent = rememberSaveable { StringBuilder() } var showFloatAction by rememberSaveable { mutableStateOf(false) } @@ -145,16 +125,7 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) { return@LaunchedEffect } withContext(Dispatchers.IO) { - flashIt(flashIt, onFinish = { showReboot, code -> - if (code != 0) { - text += "Error: exit code = $code.\nPlease save and check the log.\n" - } - if (showReboot) { - text += "\n\n\n" - showFloatAction = true - } - flashing = if (code == 0) FlashingStatus.SUCCESS else FlashingStatus.FAILED - }, onStdout = { + flashIt(flashIt, onStdout = { tempText = "$it\n" if (tempText.startsWith("")) { // clear command text = tempText.substring(6) @@ -164,7 +135,16 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) { logContent.append(it).append("\n") }, onStderr = { logContent.append(it).append("\n") - }) + }).apply { + if (code != 0) { + text += "Error code: $code.\n $err Please save and check the log.\n" + } + if (showReboot) { + text += "\n\n\n" + showFloatAction = true + } + flashing = if (code == 0) FlashingStatus.SUCCESS else FlashingStatus.FAILED + } } } @@ -248,16 +228,15 @@ sealed class FlashIt : Parcelable { } fun flashIt( - flashIt: FlashIt, onFinish: (Boolean, Int) -> Unit, + flashIt: FlashIt, onStdout: (String) -> Unit, onStderr: (String) -> Unit -) { - when (flashIt) { +): FlashResult { + return when (flashIt) { is FlashIt.FlashBoot -> installBoot( flashIt.boot, flashIt.lkm, flashIt.ota, - onFinish, onStdout, onStderr ) diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/KsuCli.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/KsuCli.kt index cc6dceb7..6070de76 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/KsuCli.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/KsuCli.kt @@ -49,6 +49,11 @@ fun getKsuDaemonPath(): String { } } +data class FlashResult(val code: Int, val err: String, val showReboot: Boolean) { + constructor(result: Shell.Result, showReboot: Boolean) : this(result.code, result.err.joinToString("\n"), showReboot) + constructor(result: Shell.Result) : this(result, result.isSuccess) +} + object KsuCli { val SHELL: Shell = createRootShell() val GLOBAL_MNT_SHELL: Shell = createRootShell(true) @@ -190,10 +195,9 @@ private fun flashWithIO( fun flashModule( uri: Uri, - onFinish: (Boolean, Int) -> Unit, onStdout: (String) -> Unit, onStderr: (String) -> Unit -): Boolean { +): FlashResult { val resolver = ksuApp.contentResolver with(resolver.openInputStream(uri)) { val file = File(ksuApp.cacheDir, "module.zip") @@ -206,9 +210,7 @@ fun flashModule( file.delete() - onFinish(result.isSuccess, result.code) - return result.isSuccess - } + return FlashResult(result) } fun runModuleAction( @@ -236,21 +238,19 @@ fun runModuleAction( } fun restoreBoot( - onFinish: (Boolean, Int) -> Unit, onStdout: (String) -> Unit, onStderr: (String) -> Unit -): Boolean { + onStdout: (String) -> Unit, onStderr: (String) -> Unit +): FlashResult { val magiskboot = File(ksuApp.applicationInfo.nativeLibraryDir, "libmagiskboot.so") val result = flashWithIO("${getKsuDaemonPath()} boot-restore -f --magiskboot $magiskboot", onStdout, onStderr) - onFinish(result.isSuccess, result.code) - return result.isSuccess + return FlashResult(result) } fun uninstallPermanently( - onFinish: (Boolean, Int) -> Unit, onStdout: (String) -> Unit, onStderr: (String) -> Unit -): Boolean { + onStdout: (String) -> Unit, onStderr: (String) -> Unit +): FlashResult { val magiskboot = File(ksuApp.applicationInfo.nativeLibraryDir, "libmagiskboot.so") val result = flashWithIO("${getKsuDaemonPath()} uninstall --magiskboot $magiskboot", onStdout, onStderr) - onFinish(result.isSuccess, result.code) - return result.isSuccess + return FlashResult(result) } suspend fun shrinkModules(): Boolean = withContext(Dispatchers.IO) { @@ -268,10 +268,9 @@ fun installBoot( bootUri: Uri?, lkm: LkmSelection, ota: Boolean, - onFinish: (Boolean, Int) -> Unit, onStdout: (String) -> Unit, onStderr: (String) -> Unit, -): Boolean { +): FlashResult { val resolver = ksuApp.contentResolver val bootFile = bootUri?.let { uri -> @@ -334,8 +333,7 @@ fun installBoot( lkmFile?.delete() // if boot uri is empty, it is direct install, when success, we should show reboot button - onFinish(bootUri == null && result.isSuccess, result.code) - return result.isSuccess + return FlashResult(result, bootUri == null && result.isSuccess) } fun reboot(reason: String = "") {