From 6794d3a83338dff2ca10a1d2e782c90ffd321d83 Mon Sep 17 00:00:00 2001 From: Nullptr <52071314+Dr-TSNG@users.noreply.github.com> Date: Fri, 6 May 2022 15:52:44 +0800 Subject: [PATCH] Small UI improvements --- .../lsposed/lspatch/ui/component/SearchBar.kt | 2 +- .../org/lsposed/lspatch/ui/page/HomePage.kt | 5 +- .../lsposed/lspatch/ui/page/NewPatchPage.kt | 80 +++++++++++-------- .../lspatch/ui/viewmodel/NewPatchViewModel.kt | 8 +- 4 files changed, 53 insertions(+), 42 deletions(-) diff --git a/manager/src/main/java/org/lsposed/lspatch/ui/component/SearchBar.kt b/manager/src/main/java/org/lsposed/lspatch/ui/component/SearchBar.kt index b70faf9..15f4b89 100644 --- a/manager/src/main/java/org/lsposed/lspatch/ui/component/SearchBar.kt +++ b/manager/src/main/java/org/lsposed/lspatch/ui/component/SearchBar.kt @@ -41,7 +41,7 @@ fun SearchAppBar( val focusRequester = remember { FocusRequester() } var onSearch by remember { mutableStateOf(false) } - LaunchedEffect(onSearch) { + LaunchedEffect(Unit) { if (onSearch) focusRequester.requestFocus() } diff --git a/manager/src/main/java/org/lsposed/lspatch/ui/page/HomePage.kt b/manager/src/main/java/org/lsposed/lspatch/ui/page/HomePage.kt index bb9d469..b9fd957 100644 --- a/manager/src/main/java/org/lsposed/lspatch/ui/page/HomePage.kt +++ b/manager/src/main/java/org/lsposed/lspatch/ui/page/HomePage.kt @@ -72,11 +72,10 @@ private val listener: (Int, Int) -> Unit = { _, grantResult -> @OptIn(ExperimentalMaterial3Api::class) @Composable private fun ShizukuCard() { - val key = remember { true } - LaunchedEffect(key) { + LaunchedEffect(Unit) { Shizuku.addRequestPermissionResultListener(listener) } - DisposableEffect(key) { + DisposableEffect(Unit) { onDispose { Shizuku.removeRequestPermissionResultListener(listener) } diff --git a/manager/src/main/java/org/lsposed/lspatch/ui/page/NewPatchPage.kt b/manager/src/main/java/org/lsposed/lspatch/ui/page/NewPatchPage.kt index 560c26b..82a4435 100644 --- a/manager/src/main/java/org/lsposed/lspatch/ui/page/NewPatchPage.kt +++ b/manager/src/main/java/org/lsposed/lspatch/ui/page/NewPatchPage.kt @@ -5,6 +5,7 @@ import android.content.ClipboardManager import android.content.Context import android.content.pm.PackageInstaller import android.util.Log +import androidx.activity.compose.BackHandler import androidx.compose.animation.animateContentSize import androidx.compose.animation.core.Spring import androidx.compose.animation.core.spring @@ -36,7 +37,6 @@ import androidx.navigation.NavBackStackEntry import kotlinx.coroutines.launch import org.lsposed.lspatch.Patcher import org.lsposed.lspatch.R -import org.lsposed.lspatch.TAG import org.lsposed.lspatch.lspApp import org.lsposed.lspatch.ui.component.SelectionColumn import org.lsposed.lspatch.ui.component.ShimmerAnimation @@ -50,6 +50,8 @@ import org.lsposed.lspatch.util.LSPPackageInstaller import org.lsposed.lspatch.util.ShizukuApi import org.lsposed.patch.util.Logger +private const val TAG = "NewPatchPage" + @OptIn(ExperimentalMaterial3Api::class) @Composable fun NewPatchPage(entry: NavBackStackEntry) { @@ -57,27 +59,29 @@ fun NewPatchPage(entry: NavBackStackEntry) { val navController = LocalNavController.current val lifecycleOwner = LocalLifecycleOwner.current val isCancelled by entry.observeState("isCancelled") - entry.savedStateHandle.getLiveData("appInfo").observe(lifecycleOwner) { - viewModel.patchApp = it + LaunchedEffect(Unit) { + entry.savedStateHandle.getLiveData("appInfo").observe(lifecycleOwner) { + viewModel.configurePatch(it) + } } - Log.d(TAG, "NewPatchPage: ${viewModel.patchState}") + Log.d(TAG, "PatchState: ${viewModel.patchState}") if (viewModel.patchState == PatchState.SELECTING) { - when { - isCancelled == true -> { - LaunchedEffect(viewModel) { navController.popBackStack() } - return - } - viewModel.patchApp != null -> { - LaunchedEffect(viewModel) { viewModel.configurePatch() } - } - else -> { - LaunchedEffect(viewModel) { navController.navigate(PageList.SelectApps.name + "/false") } - } + LaunchedEffect(Unit) { + if (isCancelled == true) navController.popBackStack() + else navController.navigate(PageList.SelectApps.name + "/false") } } else { Scaffold( - topBar = { TopBar(viewModel.patchApp!!) }, + topBar = { + when (viewModel.patchState) { + PatchState.CONFIGURING -> ConfiguringTopBar { navController.popBackStack() } + PatchState.PATCHING, + PatchState.FINISHED, + PatchState.ERROR -> CenterAlignedTopAppBar(title = { Text(viewModel.patchApp.app.packageName) }) + else -> Unit + } + }, floatingActionButton = { if (viewModel.patchState == PatchState.CONFIGURING) { ConfiguringFab() @@ -85,8 +89,10 @@ fun NewPatchPage(entry: NavBackStackEntry) { } ) { innerPadding -> if (viewModel.patchState == PatchState.CONFIGURING) { - entry.savedStateHandle.getLiveData>("selected", SnapshotStateList()).observe(lifecycleOwner) { - viewModel.embeddedModules = it + LaunchedEffect(Unit) { + entry.savedStateHandle.getLiveData>("selected", SnapshotStateList()).observe(lifecycleOwner) { + viewModel.embeddedModules = it + } } PatchOptionsBody(Modifier.padding(innerPadding)) } else { @@ -97,21 +103,14 @@ fun NewPatchPage(entry: NavBackStackEntry) { } @Composable -private fun TopBar(patchApp: AppInfo) { +private fun ConfiguringTopBar(onBackClick: () -> Unit) { SmallTopAppBar( - title = { - Column { - Text( - text = patchApp.label, - style = MaterialTheme.typography.headlineSmall, - modifier = Modifier.padding(horizontal = 24.dp) - ) - Text( - text = patchApp.app.packageName, - style = MaterialTheme.typography.bodyLarge, - modifier = Modifier.padding(horizontal = 24.dp) - ) - } + title = { Text(stringResource(R.string.page_new_patch)) }, + navigationIcon = { + IconButton( + onClick = onBackClick, + content = { Icon(Icons.Outlined.ArrowBack, null) } + ) } ) } @@ -141,6 +140,16 @@ private fun PatchOptionsBody(modifier: Modifier) { val navController = LocalNavController.current Column(modifier.verticalScroll(rememberScrollState())) { + Text( + text = viewModel.patchApp.label, + style = MaterialTheme.typography.headlineSmall, + modifier = Modifier.padding(horizontal = 24.dp) + ) + Text( + text = viewModel.patchApp.app.packageName, + style = MaterialTheme.typography.bodyLarge, + modifier = Modifier.padding(horizontal = 24.dp) + ) Text( text = stringResource(R.string.patch_mode), style = MaterialTheme.typography.titleLarge, @@ -263,7 +272,7 @@ private fun DoPatchBody(modifier: Modifier) { val logs = remember { mutableStateListOf>() } val logger = remember { PatchLogger(logs) } - LaunchedEffect(viewModel) { + LaunchedEffect(Unit) { try { Patcher.patch(context, logger, viewModel.patchOptions) viewModel.finishPatch() @@ -276,7 +285,7 @@ private fun DoPatchBody(modifier: Modifier) { } } - BoxWithConstraints(modifier.padding(24.dp)) { + BoxWithConstraints(modifier.padding(start = 24.dp, end = 24.dp, bottom = 24.dp)) { val shellBoxMaxHeight = if (viewModel.patchState == PatchState.PATCHING) maxHeight else maxHeight - ButtonDefaults.MinHeight - 12.dp @@ -318,13 +327,14 @@ private fun DoPatchBody(modifier: Modifier) { } when (viewModel.patchState) { + PatchState.PATCHING -> BackHandler {} PatchState.FINISHED -> { val shizukuUnavailable = stringResource(R.string.shizuku_unavailable) val installSuccessfully = stringResource(R.string.patch_install_successfully) val installFailed = stringResource(R.string.patch_install_failed) val copyError = stringResource(R.string.patch_copy_error) var installing by rememberSaveable { mutableStateOf(false) } - if (installing) InstallDialog(viewModel.patchApp!!) { status, message -> + if (installing) InstallDialog(viewModel.patchApp) { status, message -> scope.launch { installing = false if (status == PackageInstaller.STATUS_SUCCESS) { diff --git a/manager/src/main/java/org/lsposed/lspatch/ui/viewmodel/NewPatchViewModel.kt b/manager/src/main/java/org/lsposed/lspatch/ui/viewmodel/NewPatchViewModel.kt index e2bb48b..4c7f12f 100644 --- a/manager/src/main/java/org/lsposed/lspatch/ui/viewmodel/NewPatchViewModel.kt +++ b/manager/src/main/java/org/lsposed/lspatch/ui/viewmodel/NewPatchViewModel.kt @@ -16,7 +16,6 @@ class NewPatchViewModel : ViewModel() { var patchState by mutableStateOf(PatchState.SELECTING) private set - var patchApp by mutableStateOf(null) var useManager by mutableStateOf(true) var debuggable by mutableStateOf(false) @@ -24,17 +23,20 @@ class NewPatchViewModel : ViewModel() { var sign = mutableStateListOf(false, true) var sigBypassLevel by mutableStateOf(2) + lateinit var patchApp: AppInfo + private set lateinit var embeddedModules: SnapshotStateList lateinit var patchOptions: Patcher.Options - fun configurePatch() { + fun configurePatch(app: AppInfo) { + patchApp = app patchState = PatchState.CONFIGURING } fun submitPatch() { if (useManager) embeddedModules.clear() patchOptions = Patcher.Options( - apkPaths = listOf(patchApp!!.app.sourceDir) + (patchApp!!.app.splitSourceDirs ?: emptyArray()), + apkPaths = listOf(patchApp.app.sourceDir) + (patchApp.app.splitSourceDirs ?: emptyArray()), debuggable = debuggable, sigbypassLevel = sigBypassLevel, v1 = sign[0], v2 = sign[1],