manager: Enhance Flash module handling

- Module screen for batch installation

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
This commit is contained in:
ShirkNeko
2025-05-19 14:07:40 +08:00
parent b587216b5e
commit 4ff46a4911
2 changed files with 33 additions and 4 deletions

View File

@@ -24,6 +24,7 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.dropUnlessResumed
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.generated.destinations.FlashScreenDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
import kotlinx.coroutines.Dispatchers
@@ -33,6 +34,7 @@ import kotlinx.parcelize.Parcelize
import com.sukisu.ultra.ui.component.KeyEventBlocker
import com.sukisu.ultra.ui.util.*
import com.sukisu.ultra.R
import com.sukisu.ultra.ui.theme.CardConfig
import java.io.File
import java.text.SimpleDateFormat
import java.util.*
@@ -80,6 +82,16 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
text += "\n\n\n"
showFloatAction = true
}
if (flashIt is FlashIt.FlashModules && flashIt.currentIndex < flashIt.uris.size - 1) {
val nextFlashIt = flashIt.copy(
currentIndex = flashIt.currentIndex + 1
)
scope.launch {
kotlinx.coroutines.delay(500)
navigator.navigate(FlashScreenDestination(nextFlashIt))
}
}
}, onStdout = {
tempText = "$it\n"
if (tempText.startsWith("[H[J")) { // clear command
@@ -166,6 +178,7 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
sealed class FlashIt : Parcelable {
data class FlashBoot(val boot: Uri? = null, val lkm: LkmSelection, val ota: Boolean) : FlashIt()
data class FlashModule(val uri: Uri) : FlashIt()
data class FlashModules(val uris: List<Uri>, val currentIndex: Int = 0) : FlashIt()
data object FlashRestore : FlashIt()
data object FlashUninstall : FlashIt()
}
@@ -186,6 +199,17 @@ fun flashIt(
onStderr
)
is FlashIt.FlashModule -> flashModule(flashIt.uri, onFinish, onStdout, onStderr)
is FlashIt.FlashModules -> {
if (flashIt.uris.isEmpty() || flashIt.currentIndex >= flashIt.uris.size) {
onFinish(false, 0)
return
}
val currentUri = flashIt.uris[flashIt.currentIndex]
onStdout("Installing module ${flashIt.currentIndex + 1} of ${flashIt.uris.size}")
flashModule(currentUri, onFinish, onStdout, onStderr)
}
FlashIt.FlashRestore -> restoreBoot(onFinish, onStdout, onStderr)
FlashIt.FlashUninstall -> uninstallPermanently(onFinish, onStdout, onStderr)
}
@@ -199,6 +223,9 @@ private fun TopBar(
onSave: () -> Unit = {},
scrollBehavior: TopAppBarScrollBehavior? = null
) {
val cardColor = MaterialTheme.colorScheme.surfaceVariant
val cardAlpha = CardConfig.cardAlpha
TopAppBar(
title = {
Text(
@@ -216,6 +243,10 @@ private fun TopBar(
onClick = onBack
) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) }
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = cardColor.copy(alpha = cardAlpha),
scrolledContainerColor = cardColor.copy(alpha = cardAlpha)
),
actions = {
IconButton(onClick = onSave) {
Icon(

View File

@@ -97,7 +97,7 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
val clipData = data.clipData
if (clipData != null) {
// 处理多选结果
val selectedModules = mutableSetOf<Uri>()
val selectedModules = mutableListOf<Uri>()
val selectedModuleNames = mutableMapOf<Uri, String>()
suspend fun processUri(uri: Uri) {
@@ -146,9 +146,7 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
if (confirmResult == ConfirmResult.Confirmed) {
// 批量安装模块
selectedModules.forEach { uri ->
navigator.navigate(FlashScreenDestination(FlashIt.FlashModule(uri)))
}
navigator.navigate(FlashScreenDestination(FlashIt.FlashModules(selectedModules)))
viewModel.markNeedRefresh()
}
} else {