diff --git a/manager/app/src/main/java/com/sukisu/ultra/flash/KernelFlash.kt b/manager/app/src/main/java/com/sukisu/ultra/flash/KernelFlash.kt
index 85bff66f..343c265f 100644
--- a/manager/app/src/main/java/com/sukisu/ultra/flash/KernelFlash.kt
+++ b/manager/app/src/main/java/com/sukisu/ultra/flash/KernelFlash.kt
@@ -354,7 +354,7 @@ fun HorizonKernelFlashProgress(state: FlashState) {
Surface(
modifier = Modifier
.fillMaxWidth()
- .heightIn(max = 150.dp)
+ .heightIn(max = 230.dp)
.padding(vertical = 4.dp),
color = MaterialTheme.colorScheme.surface,
tonalElevation = 1.dp,
diff --git a/manager/app/src/main/java/com/sukisu/ultra/ui/screen/Install.kt b/manager/app/src/main/java/com/sukisu/ultra/ui/screen/Install.kt
index faad2c2b..1758922f 100644
--- a/manager/app/src/main/java/com/sukisu/ultra/ui/screen/Install.kt
+++ b/manager/app/src/main/java/com/sukisu/ultra/ui/screen/Install.kt
@@ -21,6 +21,7 @@ import androidx.compose.foundation.selection.toggleable
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
+import androidx.compose.material.icons.filled.AutoFixHigh
import androidx.compose.material.icons.filled.FileUpload
import androidx.compose.material3.*
import androidx.compose.runtime.*
@@ -335,8 +336,16 @@ private fun SelectInstallMethod(onSelected: (InstallMethod) -> Unit = {}) {
if (it.resultCode == Activity.RESULT_OK) {
it.data?.data?.let { uri ->
val option = when (currentSelectingMethod) {
- is InstallMethod.SelectFile -> InstallMethod.SelectFile(uri, summary = selectFileTip)
- is InstallMethod.HorizonKernel -> InstallMethod.HorizonKernel(uri, summary = horizonKernelSummary)
+ is InstallMethod.SelectFile -> InstallMethod.SelectFile(
+ uri,
+ summary = selectFileTip
+ )
+
+ is InstallMethod.HorizonKernel -> InstallMethod.HorizonKernel(
+ uri,
+ summary = horizonKernelSummary
+ )
+
else -> null
}
option?.let {
@@ -364,57 +373,136 @@ private fun SelectInstallMethod(onSelected: (InstallMethod) -> Unit = {}) {
is InstallMethod.SelectFile, is InstallMethod.HorizonKernel -> {
selectImageLauncher.launch(Intent(Intent.ACTION_GET_CONTENT).apply {
type = "application/*"
- putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("application/octet-stream", "application/zip"))
+ putExtra(
+ Intent.EXTRA_MIME_TYPES,
+ arrayOf("application/octet-stream", "application/zip")
+ )
})
}
+
is InstallMethod.DirectInstall -> {
selectedOption = option
onSelected(option)
}
+
is InstallMethod.DirectInstallToInactiveSlot -> {
confirmDialog.showConfirm(dialogTitle, dialogContent)
}
}
}
+ var LKMExpanded by remember { mutableStateOf(false) }
+ var GKIExpanded by remember { mutableStateOf(false) }
+
Column {
- radioOptions.forEach { option ->
- val interactionSource = remember { MutableInteractionSource() }
- Row(
- verticalAlignment = Alignment.CenterVertically,
- modifier = Modifier
- .fillMaxWidth()
- .toggleable(
- value = option.javaClass == selectedOption?.javaClass,
- onValueChange = { onClick(option) },
- role = Role.RadioButton,
- indication = LocalIndication.current,
- interactionSource = interactionSource
- )
+ ListItem(
+ leadingContent = { Icon(Icons.Filled.AutoFixHigh, null) },
+ headlineContent = { Text(stringResource(R.string.Lkm_install_methods)) },
+ modifier = Modifier.clickable {
+ LKMExpanded = !LKMExpanded
+ }
+ )
+ radioOptions.take(3).forEach { option ->
+ AnimatedVisibility(
+ visible = LKMExpanded,
+ modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
) {
- RadioButton(
- selected = option.javaClass == selectedOption?.javaClass,
- onClick = { onClick(option) },
- interactionSource = interactionSource
- )
- Column(
- modifier = Modifier.padding(vertical = 12.dp)
- ) {
- Text(
- text = stringResource(id = option.label),
- fontSize = MaterialTheme.typography.titleMedium.fontSize,
- fontFamily = MaterialTheme.typography.titleMedium.fontFamily,
- fontStyle = MaterialTheme.typography.titleMedium.fontStyle
- )
- option.summary?.let {
- Text(
- text = it,
- fontSize = MaterialTheme.typography.bodySmall.fontSize,
- fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
- fontStyle = MaterialTheme.typography.bodySmall.fontStyle
+ Column {
+ val interactionSource = remember { MutableInteractionSource() }
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier
+ .fillMaxWidth()
+ .toggleable(
+ value = option.javaClass == selectedOption?.javaClass,
+ onValueChange = { onClick(option) },
+ role = Role.RadioButton,
+ indication = LocalIndication.current,
+ interactionSource = interactionSource
+ )
+ ) {
+ RadioButton(
+ selected = option.javaClass == selectedOption?.javaClass,
+ onClick = { onClick(option) },
+ interactionSource = interactionSource
)
+ Column(
+ modifier = Modifier.padding(vertical = 12.dp)
+ ) {
+ Text(
+ text = stringResource(id = option.label),
+ fontSize = MaterialTheme.typography.titleMedium.fontSize,
+ fontFamily = MaterialTheme.typography.titleMedium.fontFamily,
+ fontStyle = MaterialTheme.typography.titleMedium.fontStyle
+ )
+ option.summary?.let {
+ Text(
+ text = it,
+ fontSize = MaterialTheme.typography.bodySmall.fontSize,
+ fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
+ fontStyle = MaterialTheme.typography.bodySmall.fontStyle
+ )
+ }
+ }
}
}
+ Spacer(modifier = Modifier.height(8.dp))
+ }
+ }
+ }
+ Column {
+ ListItem(
+ leadingContent = { Icon(Icons.Filled.FileUpload, null) },
+ headlineContent = { Text(stringResource(R.string.GKI_install_methods)) },
+ modifier = Modifier.clickable {
+ GKIExpanded = !GKIExpanded
+ }
+ )
+ AnimatedVisibility(
+ visible = GKIExpanded,
+ modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
+ ) {
+ Column {
+ radioOptions.drop(3).forEach { option ->
+ val interactionSource = remember { MutableInteractionSource() }
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier
+ .fillMaxWidth()
+ .toggleable(
+ value = option.javaClass == selectedOption?.javaClass,
+ onValueChange = { onClick(option) },
+ role = Role.RadioButton,
+ indication = LocalIndication.current,
+ interactionSource = interactionSource
+ )
+ ) {
+ RadioButton(
+ selected = option.javaClass == selectedOption?.javaClass,
+ onClick = { onClick(option) },
+ interactionSource = interactionSource
+ )
+ Column(
+ modifier = Modifier.padding(vertical = 12.dp)
+ ) {
+ Text(
+ text = stringResource(id = option.label),
+ fontSize = MaterialTheme.typography.titleMedium.fontSize,
+ fontFamily = MaterialTheme.typography.titleMedium.fontFamily,
+ fontStyle = MaterialTheme.typography.titleMedium.fontStyle
+ )
+ option.summary?.let {
+ Text(
+ text = it,
+ fontSize = MaterialTheme.typography.bodySmall.fontSize,
+ fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
+ fontStyle = MaterialTheme.typography.bodySmall.fontStyle
+ )
+ }
+ }
+ }
+ Spacer(modifier = Modifier.height(8.dp))
+ }
}
}
}
@@ -522,11 +610,6 @@ private fun TopBar(
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null)
}
},
- actions = {
- IconButton(onClick = onLkmUpload) {
- Icon(Icons.Filled.FileUpload, contentDescription = null)
- }
- },
windowInsets = WindowInsets.safeDrawing.only(
WindowInsetsSides.Top + WindowInsetsSides.Horizontal
),
diff --git a/manager/app/src/main/res/values-zh-rCN/strings.xml b/manager/app/src/main/res/values-zh-rCN/strings.xml
index 40de3327..6f9e2c8b 100644
--- a/manager/app/src/main/res/values-zh-rCN/strings.xml
+++ b/manager/app/src/main/res/values-zh-rCN/strings.xml
@@ -117,7 +117,7 @@
启用 WebView 调试
可用于调试 WebUI 。请仅在需要时启用。
直接安装(推荐)
- 选择一个文件
+ 选择一个需要修补的镜像
安装到未使用的槽位(OTA 后)
将在重启后强制切换到另一个槽位!\n注意只能在 OTA 更新完成后的重启之前使用。\n确认?
下一步
@@ -284,12 +284,15 @@
A槽位
B槽位
已选择槽位: %1$s
-
- 复制失败
- 未知错误
获取原有槽位
设置指定槽位
恢复默认槽位
当前槽位:%1$s
+
+ 复制失败
+ 未知错误
刷写失败
+
+ LKM修补/安装
+ GKI安装
diff --git a/manager/app/src/main/res/values/strings.xml b/manager/app/src/main/res/values/strings.xml
index 2e7f51dd..382f6b9a 100644
--- a/manager/app/src/main/res/values/strings.xml
+++ b/manager/app/src/main/res/values/strings.xml
@@ -118,7 +118,7 @@
Enable WebView debugging
Can be used to debug WebUI. Please enable only when needed.
Direct install (Recommended)
- Select a file
+ Select a mirror that needs to be patched
Install to inactive slot (After OTA)
Your device will be **FORCED** to boot to the current inactive slot after a reboot!\nOnly use this option after OTA is done.\nContinue?
Next
@@ -288,12 +288,15 @@
Slot A
Slot B
Selected slot: %1$s
-
- Copy failed
- Unknown error
Getting the original slot
Setting the specified slot
Restore Default Slot
Current Slot:%1$s
+
+ Copy failed
+ Unknown error
Flash failed
+
+ LKM repair/installation
+ GKI installation