manager: allow multiple modules to be installed sequentially (#2459)

It's now okay to merge
This commit is contained in:
Rifat Azad
2025-02-23 10:10:58 +06:00
committed by GitHub
parent a41f454fa5
commit 7a6ec8b284
4 changed files with 62 additions and 27 deletions

View File

@@ -56,7 +56,7 @@ import me.weishu.kernelsu.ui.component.KeyEventBlocker
import me.weishu.kernelsu.ui.util.FlashResult import me.weishu.kernelsu.ui.util.FlashResult
import me.weishu.kernelsu.ui.util.LkmSelection import me.weishu.kernelsu.ui.util.LkmSelection
import me.weishu.kernelsu.ui.util.LocalSnackbarHost import me.weishu.kernelsu.ui.util.LocalSnackbarHost
import me.weishu.kernelsu.ui.util.flashModules import me.weishu.kernelsu.ui.util.flashModule
import me.weishu.kernelsu.ui.util.installBoot import me.weishu.kernelsu.ui.util.installBoot
import me.weishu.kernelsu.ui.util.reboot import me.weishu.kernelsu.ui.util.reboot
import me.weishu.kernelsu.ui.util.restoreBoot import me.weishu.kernelsu.ui.util.restoreBoot
@@ -66,16 +66,33 @@ import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
/**
* @author weishu
* @date 2023/1/1.
*/
enum class FlashingStatus { enum class FlashingStatus {
FLASHING, FLASHING,
SUCCESS, SUCCESS,
FAILED FAILED
} }
/** // Lets you flash modules sequentially when mutiple zipUris are selected
* @author weishu fun flashModulesSequentially(
* @date 2023/1/1. uris: List<Uri>,
*/ onStdout: (String) -> Unit,
onStderr: (String) -> Unit
): FlashResult {
for (uri in uris) {
flashModule(uri, onStdout, onStderr).apply {
if (code != 0) {
return FlashResult(code, err, showReboot)
}
}
}
return FlashResult(0, "", true)
}
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
@Destination<RootGraph> @Destination<RootGraph>
@@ -192,7 +209,7 @@ sealed class FlashIt : Parcelable {
data class FlashBoot(val boot: Uri? = null, val lkm: LkmSelection, val ota: Boolean) : data class FlashBoot(val boot: Uri? = null, val lkm: LkmSelection, val ota: Boolean) :
FlashIt() FlashIt()
data class FlashModules(val uri: List<Uri>) : FlashIt() data class FlashModules(val uris: List<Uri>) : FlashIt()
data object FlashRestore : FlashIt() data object FlashRestore : FlashIt()
@@ -213,7 +230,9 @@ fun flashIt(
onStderr onStderr
) )
is FlashIt.FlashModules -> flashModules(flashIt.uri, onStdout, onStderr) is FlashIt.FlashModules -> {
flashModulesSequentially(flashIt.uris, onStdout, onStderr)
}
FlashIt.FlashRestore -> restoreBoot(onStdout, onStderr) FlashIt.FlashRestore -> restoreBoot(onStdout, onStderr)

View File

@@ -36,6 +36,7 @@ import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.outlined.PlayArrow import androidx.compose.material.icons.outlined.PlayArrow
import androidx.compose.material.icons.outlined.Download import androidx.compose.material.icons.outlined.Download
import androidx.compose.material.icons.outlined.Delete import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Checkbox import androidx.compose.material3.Checkbox
@@ -56,6 +57,7 @@ import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarResult import androidx.compose.material3.SnackbarResult
import androidx.compose.material3.Switch import androidx.compose.material3.Switch
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.material3.rememberTopAppBarState import androidx.compose.material3.rememberTopAppBarState
@@ -104,6 +106,7 @@ import me.weishu.kernelsu.ui.util.hasMagisk
import me.weishu.kernelsu.ui.util.reboot import me.weishu.kernelsu.ui.util.reboot
import me.weishu.kernelsu.ui.util.toggleModule import me.weishu.kernelsu.ui.util.toggleModule
import me.weishu.kernelsu.ui.util.uninstallModule import me.weishu.kernelsu.ui.util.uninstallModule
import me.weishu.kernelsu.ui.util.getFileName
import me.weishu.kernelsu.ui.viewmodel.ModuleViewModel import me.weishu.kernelsu.ui.viewmodel.ModuleViewModel
import me.weishu.kernelsu.ui.webui.WebUIActivity import me.weishu.kernelsu.ui.webui.WebUIActivity
@@ -200,6 +203,12 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
floatingActionButton = { floatingActionButton = {
if (!hideInstallButton) { if (!hideInstallButton) {
val moduleInstall = stringResource(id = R.string.module_install) val moduleInstall = stringResource(id = R.string.module_install)
val confirmTitle = stringResource(R.string.module)
var zipUris by remember { mutableStateOf<List<Uri>>(emptyList()) }
val confirmDialog = rememberConfirmDialog(onConfirm = {
navigator.navigate(FlashScreenDestination(FlashIt.FlashModules(zipUris)))
viewModel.markNeedRefresh()
})
val selectZipLauncher = rememberLauncherForActivityResult( val selectZipLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult() contract = ActivityResultContracts.StartActivityForResult()
) { ) {
@@ -207,20 +216,38 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
return@rememberLauncherForActivityResult return@rememberLauncherForActivityResult
} }
val data = it.data ?: return@rememberLauncherForActivityResult val data = it.data ?: return@rememberLauncherForActivityResult
val uri = data.data ?: return@rememberLauncherForActivityResult val clipData = data.clipData
navigator.navigate(FlashScreenDestination(FlashIt.FlashModules(listOf(uri)))) val uris = mutableListOf<Uri>()
if (clipData != null) {
for (i in 0 until clipData.itemCount) {
clipData.getItemAt(i)?.uri?.let { uris.add(it) }
}
} else {
data.data?.let { uris.add(it) }
}
viewModel.markNeedRefresh() if (uris.size == 1) {
navigator.navigate(FlashScreenDestination(FlashIt.FlashModules(listOf(uris.first()))))
Log.i("ModuleScreen", "select zip result: ${it.data}") } else if (uris.size > 1) {
// multiple files selected
val moduleNames = uris.mapIndexed { index, uri -> "\n${index + 1}. ${uri.getFileName(context)}" }.joinToString("")
val confirmContent = context.getString(R.string.module_install_prompt_with_name, moduleNames)
zipUris = uris
confirmDialog.showConfirm(
title = confirmTitle,
content = confirmContent,
markdown = true
)
}
} }
ExtendedFloatingActionButton( ExtendedFloatingActionButton(
onClick = { onClick = {
// select the zip file to install // Select the zip files to install
val intent = Intent(Intent.ACTION_GET_CONTENT).apply { val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
type = "application/zip" type = "application/zip"
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
} }
selectZipLauncher.launch(intent) selectZipLauncher.launch(intent)
}, },
@@ -232,6 +259,7 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal), contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),
snackbarHost = { SnackbarHost(hostState = snackBarHost) } snackbarHost = { SnackbarHost(hostState = snackBarHost) }
) { innerPadding -> ) { innerPadding ->
when { when {
hasMagisk -> { hasMagisk -> {
Box( Box(

View File

@@ -191,20 +191,6 @@ fun flashModule(
} }
} }
fun flashModules(
uris: List<Uri>,
onStdout: (String) -> Unit,
onStderr: (String) -> Unit
): FlashResult {
for (uri in uris) {
val result = flashModule(uri, onStdout, onStderr)
if (result.code != 0) {
return result
}
}
return FlashResult(0, "", true)
}
fun runModuleAction( fun runModuleAction(
moduleId: String, onStdout: (String) -> Unit, onStderr: (String) -> Unit moduleId: String, onStdout: (String) -> Unit, onStderr: (String) -> Unit
): Boolean { ): Boolean {

View File

@@ -23,8 +23,10 @@
<string name="module_failed_to_disable">Failed to disable module: %s</string> <string name="module_failed_to_disable">Failed to disable module: %s</string>
<string name="module_empty">No module installed</string> <string name="module_empty">No module installed</string>
<string name="module">Module</string> <string name="module">Module</string>
<string name="module_install_prompt_with_name">The following modules will be installed: %1$s</string>
<string name="module_sort_action_first">Sort (Action first)</string> <string name="module_sort_action_first">Sort (Action first)</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string> <string name="module_sort_enabled_first">Sort (Enabled first)</string>
<string name="confirm">Confirm</string>
<string name="uninstall">Uninstall</string> <string name="uninstall">Uninstall</string>
<string name="module_install">Install</string> <string name="module_install">Install</string>
<string name="install">Install</string> <string name="install">Install</string>