diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/ExecuteModuleAction.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/ExecuteModuleAction.kt index 4e8bda0f..b3a51821 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/ExecuteModuleAction.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/ExecuteModuleAction.kt @@ -1,15 +1,22 @@ package com.rifsxd.ksunext.ui.screen import android.os.Environment +import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.safeDrawing +import androidx.compose.foundation.layout.only import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Save import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExtendedFloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme @@ -49,12 +56,18 @@ import java.util.Locale @Destination fun ExecuteModuleActionScreen(navigator: DestinationsNavigator, moduleId: String) { var text by rememberSaveable { mutableStateOf("") } - var tempText : String + var tempText: String val logContent = rememberSaveable { StringBuilder() } val snackBarHost = LocalSnackbarHost.current val scope = rememberCoroutineScope() val scrollState = rememberScrollState() var actionResult: Boolean + var isActionRunning by rememberSaveable { mutableStateOf(true) } + + BackHandler(enabled = isActionRunning) { + // Disable back button if action is running + // TODO: Disable Destination Navbar to evade hang on destonation change caused by runModuleAction() in ui.util.KsuCli, users shoudln't get out of actionScreen if action is running + } LaunchedEffect(Unit) { if (text.isNotEmpty()) { @@ -79,29 +92,41 @@ fun ExecuteModuleActionScreen(navigator: DestinationsNavigator, moduleId: String actionResult = it } } - if (actionResult) navigator.popBackStack() + isActionRunning = false } Scaffold( topBar = { TopBar( - onBack = { - navigator.popBackStack() - }, + isActionRunning = isActionRunning, onSave = { - scope.launch { - val format = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.getDefault()) - val date = format.format(Date()) - val file = File( - Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), - "KernelSU_Next_module_action_log_${date}.log" - ) - file.writeText(logContent.toString()) - snackBarHost.showSnackbar("Log saved to ${file.absolutePath}") + if (!isActionRunning) { + scope.launch { + val format = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.getDefault()) + val date = format.format(Date()) + val file = File( + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), + "KernelSU_Next_module_action_log_${date}.log" + ) + file.writeText(logContent.toString()) + snackBarHost.showSnackbar("Log saved to ${file.absolutePath}") + } } } ) }, + floatingActionButton = { + if (!isActionRunning) { + ExtendedFloatingActionButton( + text = { Text("Go Back") }, + icon = { Icon(Icons.Filled.Close, contentDescription = "Back") }, + onClick = { + navigator.popBackStack() + } + ) + } + }, + contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal), snackbarHost = { SnackbarHost(snackBarHost) } ) { innerPadding -> KeyEventBlocker { @@ -129,16 +154,14 @@ fun ExecuteModuleActionScreen(navigator: DestinationsNavigator, moduleId: String @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun TopBar(onBack: () -> Unit = {}, onSave: () -> Unit = {}) { +private fun TopBar(isActionRunning: Boolean, onSave: () -> Unit = {}) { TopAppBar( title = { Text(stringResource(R.string.action)) }, - navigationIcon = { - IconButton( - onClick = onBack - ) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) } - }, actions = { - IconButton(onClick = onSave) { + IconButton( + onClick = onSave, + enabled = !isActionRunning + ) { Icon( imageVector = Icons.Filled.Save, contentDescription = stringResource(id = R.string.save_log), @@ -146,4 +169,4 @@ private fun TopBar(onBack: () -> Unit = {}, onSave: () -> Unit = {}) { } } ) -} \ No newline at end of file +} diff --git a/manager/app/src/main/res/values-in/strings.xml b/manager/app/src/main/res/values-in/strings.xml index 6d0b9894..0f551990 100644 --- a/manager/app/src/main/res/values-in/strings.xml +++ b/manager/app/src/main/res/values-in/strings.xml @@ -100,6 +100,7 @@ Mulai mengunduh: %s Tersedia versi terbaru %s, Klik untuk membarui. Jalankan + Menutup Paksa berhenti Mulai ulang Gagal membarui aturan SELinux pada: %s 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 7d4fd88d..7fae83f1 100644 --- a/manager/app/src/main/res/values-zh-rCN/strings.xml +++ b/manager/app/src/main/res/values-zh-rCN/strings.xml @@ -100,6 +100,7 @@ 开始下载: %s 发现新版本:%s,点击升级。 启动 + 关闭 强制停止 重新启动 为:%s 更新SELinux规则失败 diff --git a/manager/app/src/main/res/values/strings.xml b/manager/app/src/main/res/values/strings.xml index 9130d1c5..83634881 100644 --- a/manager/app/src/main/res/values/strings.xml +++ b/manager/app/src/main/res/values/strings.xml @@ -101,6 +101,7 @@ Start downloading: %s New version %s is available, click to upgrade. Launch + Close Force stop Restart Failed to update SELinux rules for: %s diff --git a/manager/gradlew b/manager/gradlew old mode 100644 new mode 100755