ksud: added module restore cmd, replaced pkg id for debug and uninstall manager and changed banner

manager: implement restore module UI
This commit is contained in:
Rifat Azad
2024-12-19 17:33:20 +06:00
parent 9911795aa3
commit adf3920caa
7 changed files with 116 additions and 39 deletions

View File

@@ -31,10 +31,8 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.selection.toggleable
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.Wysiwyg
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.outlined.PlayArrow
import androidx.compose.material.icons.outlined.Download
import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material.icons.filled.*
import androidx.compose.material.icons.outlined.*
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
@@ -101,6 +99,7 @@ import com.rifsxd.ksunext.ui.util.hasMagisk
import com.rifsxd.ksunext.ui.util.reboot
import com.rifsxd.ksunext.ui.util.toggleModule
import com.rifsxd.ksunext.ui.util.uninstallModule
import com.rifsxd.ksunext.ui.util.restoreModule
import com.rifsxd.ksunext.ui.viewmodel.ModuleViewModel
import com.rifsxd.ksunext.ui.webui.WebUIActivity
import okhttp3.OkHttpClient
@@ -255,13 +254,17 @@ private fun ModuleList(
val failedEnable = stringResource(R.string.module_failed_to_enable)
val failedDisable = stringResource(R.string.module_failed_to_disable)
val failedUninstall = stringResource(R.string.module_uninstall_failed)
val failedRestore = stringResource(R.string.module_restore_failed)
val successUninstall = stringResource(R.string.module_uninstall_success)
val successRestore = stringResource(R.string.module_restore_success)
val reboot = stringResource(R.string.reboot)
val rebootToApply = stringResource(R.string.reboot_to_apply)
val moduleStr = stringResource(R.string.module)
val uninstall = stringResource(R.string.uninstall)
val restore = stringResource(R.string.restore)
val cancel = stringResource(android.R.string.cancel)
val moduleUninstallConfirm = stringResource(R.string.module_uninstall_confirm)
val moduleRestoreConfirm = stringResource(R.string.module_restore_confirm)
val updateText = stringResource(R.string.module_update)
val changelogText = stringResource(R.string.module_changelog)
val downloadingText = stringResource(R.string.module_downloading)
@@ -375,6 +378,33 @@ private fun ModuleList(
reboot()
}
}
suspend fun onModuleRestore(module: ModuleViewModel.ModuleInfo) {
val confirmResult = confirmDialog.awaitConfirm(
moduleStr,
content = moduleRestoreConfirm.format(module.name),
confirm = restore,
dismiss = cancel
)
if (confirmResult != ConfirmResult.Confirmed) {
return
}
val success = loadingDialog.withLoading {
withContext(Dispatchers.IO) {
restoreModule(module.id)
}
}
if (success) {
viewModel.fetchModuleList()
}
val message = if (success) {
successRestore.format(module.name)
} else {
failedRestore.format(module.name)
}
}
PullToRefreshBox(
modifier = boxModifier,
onRefresh = {
@@ -427,6 +457,9 @@ private fun ModuleList(
onUninstall = {
scope.launch { onModuleUninstall(module) }
},
onRestore = {
scope.launch { onModuleRestore(module) }
},
onCheckChanged = {
scope.launch {
val success = loadingDialog.withLoading {
@@ -486,6 +519,7 @@ fun ModuleItem(
isChecked: Boolean,
updateUrl: String,
onUninstall: (ModuleViewModel.ModuleInfo) -> Unit,
onRestore: (ModuleViewModel.ModuleInfo) -> Unit,
onCheckChanged: (Boolean) -> Unit,
onUpdate: (ModuleViewModel.ModuleInfo) -> Unit,
onClick: (ModuleViewModel.ModuleInfo) -> Unit
@@ -576,29 +610,28 @@ fun ModuleItem(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
if (module.hasActionScript) {
FilledTonalButton(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
onClick = {
navigator.navigate(ExecuteModuleActionScreenDestination(module.id))
viewModel.markNeedRefresh()
navigator.navigate(ExecuteModuleActionScreenDestination(module.id))
viewModel.markNeedRefresh()
},
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.PlayArrow,
contentDescription = null
)
if (!module.hasWebUi && updateUrl.isEmpty()) {
if (!module.hasWebUi && updateUrl.isEmpty()) {
Text(
modifier = Modifier.padding(start = 7.dp),
modifier = Modifier.padding(start = 7.dp),
text = stringResource(R.string.action),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize
)
}
}
}
Spacer(modifier = Modifier.weight(0.1f, true))
@@ -612,16 +645,16 @@ fun ModuleItem(
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
modifier = Modifier.size(20.dp),
imageVector = Icons.AutoMirrored.Outlined.Wysiwyg,
contentDescription = null
)
if (!module.hasActionScript && updateUrl.isEmpty()) {
Text(
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.open)
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.open)
)
}
}
@@ -636,43 +669,61 @@ fun ModuleItem(
shape = ButtonDefaults.textShape,
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Download,
contentDescription = null
)
if (!module.hasActionScript || !module.hasWebUi) {
)
if (!module.hasActionScript || !module.hasWebUi) {
Text(
modifier = Modifier.padding(start = 7.dp),
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.module_update)
)
}
}
}
Spacer(modifier = Modifier.weight(0.1f, true))
}
FilledTonalButton(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
enabled = !module.remove,
onClick = { onUninstall(module) },
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Delete,
contentDescription = null
)
if (!module.hasActionScript && !module.hasWebUi && updateUrl.isEmpty()) {
Text(
modifier = Modifier.padding(start = 7.dp),
if (module.remove) {
FilledTonalButton(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
onClick = { onRestore(module) },
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Restore,
contentDescription = null
)
Text(
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.restore)
)
}
} else {
FilledTonalButton(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
enabled = true,
onClick = { onUninstall(module) },
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Delete,
contentDescription = null
)
Text(
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.uninstall)
)
}
}
}
}
}
@@ -696,5 +747,5 @@ fun ModuleItemPreview() {
hasWebUi = false,
hasActionScript = false
)
ModuleItem(EmptyDestinationsNavigator, module, true, "", {}, {}, {}, {})
ModuleItem(EmptyDestinationsNavigator, module, true, "", {}, {}, {}, {}, {})
}

View File

@@ -142,6 +142,13 @@ fun uninstallModule(id: String): Boolean {
return result
}
fun restoreModule(id: String): Boolean {
val cmd = "module restore $id"
val result = execKsud(cmd, true)
Log.i(TAG, "restore module $id result: $result")
return result
}
private fun flashWithIO(
cmd: String,
onStdout: (String) -> Unit,

View File

@@ -27,6 +27,7 @@
<string name="confirm_module_installation">Confirm Installation</string>
<string name="module_install_prompt_with_name">Do you want to continue installing this module?\nModule: %1$s</string>
<string name="uninstall">Uninstall</string>
<string name="restore">Restore</string>
<string name="module_install">Install</string>
<string name="install">Install</string>
<string name="reboot">Reboot</string>
@@ -40,6 +41,9 @@
<string name="module_uninstall_confirm">Are you sure you want to uninstall module %s?</string>
<string name="module_uninstall_success">%s uninstalled</string>
<string name="module_uninstall_failed">Failed to uninstall: %s</string>
<string name="module_restore_confirm">Are you sure you want to restore module %s?</string>
<string name="module_restore_success">%s restoreed</string>
<string name="module_restore_failed">Failed to restore: %s</string>
<string name="module_version">Version</string>
<string name="module_author">Author</string>
<string name="refresh">Refresh</string>