diff --git a/manager/app/src/main/java/me/weishu/kernelsu/ui/MainActivity.kt b/manager/app/src/main/java/me/weishu/kernelsu/ui/MainActivity.kt index 5737c524a940..171d4d7e9b5c 100644 --- a/manager/app/src/main/java/me/weishu/kernelsu/ui/MainActivity.kt +++ b/manager/app/src/main/java/me/weishu/kernelsu/ui/MainActivity.kt @@ -34,8 +34,10 @@ import androidx.compose.ui.unit.dp import androidx.navigation.NavBackStackEntry import androidx.navigation.NavHostController import androidx.navigation.compose.rememberNavController +import androidx.navigation.compose.currentBackStackEntryAsState import com.ramcosta.composedestinations.DestinationsNavHost import com.ramcosta.composedestinations.animations.NavHostAnimatedDestinationStyle +import com.ramcosta.composedestinations.generated.destinations.ExecuteModuleActionScreenDestination import com.ramcosta.composedestinations.generated.NavGraphs import com.ramcosta.composedestinations.utils.isRouteOnBackStackAsState import com.ramcosta.composedestinations.utils.rememberDestinationsNavigator @@ -46,6 +48,7 @@ import me.weishu.kernelsu.ui.theme.KernelSUTheme import me.weishu.kernelsu.ui.util.LocalSnackbarHost import me.weishu.kernelsu.ui.util.rootAvailable import me.weishu.kernelsu.ui.util.install +import me.weishu.kernelsu.ui.util.* class MainActivity : ComponentActivity() { @@ -66,8 +69,19 @@ class MainActivity : ComponentActivity() { KernelSUTheme { val navController = rememberNavController() val snackBarHostState = remember { SnackbarHostState() } + val currentDestination = navController.currentBackStackEntryAsState()?.value?.destination + + val showBottomBar = when (currentDestination?.route) { + ExecuteModuleActionScreenDestination.route -> false // Hide for ExecuteModuleActionScreen + else -> true + } + Scaffold( - bottomBar = { BottomBar(navController) }, + bottomBar = { + if (showBottomBar) { + BottomBar(navController) + } + }, contentWindowInsets = WindowInsets(0, 0, 0, 0) ) { innerPadding -> CompositionLocalProvider( diff --git a/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/ExecuteModuleAction.kt b/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/ExecuteModuleAction.kt index 93b06a0ca514..cde274f9fba8 100644 --- a/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/ExecuteModuleAction.kt +++ b/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/ExecuteModuleAction.kt @@ -1,15 +1,22 @@ package me.weishu.kernelsu.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,17 @@ 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 + } LaunchedEffect(Unit) { if (text.isNotEmpty()) { @@ -79,29 +91,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_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(text = stringResource(R.string.close)) }, + icon = { Icon(Icons.Filled.Close, contentDescription = null) }, + onClick = { + navigator.popBackStack() + } + ) + } + }, + contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal), snackbarHost = { SnackbarHost(snackBarHost) } ) { innerPadding -> KeyEventBlocker { @@ -129,16 +153,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),