Small UI improvements
This commit is contained in:
parent
9106fc48b8
commit
6794d3a833
|
|
@ -41,7 +41,7 @@ fun SearchAppBar(
|
||||||
val focusRequester = remember { FocusRequester() }
|
val focusRequester = remember { FocusRequester() }
|
||||||
var onSearch by remember { mutableStateOf(false) }
|
var onSearch by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
LaunchedEffect(onSearch) {
|
LaunchedEffect(Unit) {
|
||||||
if (onSearch) focusRequester.requestFocus()
|
if (onSearch) focusRequester.requestFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,11 +72,10 @@ private val listener: (Int, Int) -> Unit = { _, grantResult ->
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun ShizukuCard() {
|
private fun ShizukuCard() {
|
||||||
val key = remember { true }
|
LaunchedEffect(Unit) {
|
||||||
LaunchedEffect(key) {
|
|
||||||
Shizuku.addRequestPermissionResultListener(listener)
|
Shizuku.addRequestPermissionResultListener(listener)
|
||||||
}
|
}
|
||||||
DisposableEffect(key) {
|
DisposableEffect(Unit) {
|
||||||
onDispose {
|
onDispose {
|
||||||
Shizuku.removeRequestPermissionResultListener(listener)
|
Shizuku.removeRequestPermissionResultListener(listener)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import android.content.ClipboardManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.PackageInstaller
|
import android.content.pm.PackageInstaller
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.compose.animation.animateContentSize
|
import androidx.compose.animation.animateContentSize
|
||||||
import androidx.compose.animation.core.Spring
|
import androidx.compose.animation.core.Spring
|
||||||
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 kotlinx.coroutines.launch
|
||||||
import org.lsposed.lspatch.Patcher
|
import org.lsposed.lspatch.Patcher
|
||||||
import org.lsposed.lspatch.R
|
import org.lsposed.lspatch.R
|
||||||
import org.lsposed.lspatch.TAG
|
|
||||||
import org.lsposed.lspatch.lspApp
|
import org.lsposed.lspatch.lspApp
|
||||||
import org.lsposed.lspatch.ui.component.SelectionColumn
|
import org.lsposed.lspatch.ui.component.SelectionColumn
|
||||||
import org.lsposed.lspatch.ui.component.ShimmerAnimation
|
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.lspatch.util.ShizukuApi
|
||||||
import org.lsposed.patch.util.Logger
|
import org.lsposed.patch.util.Logger
|
||||||
|
|
||||||
|
private const val TAG = "NewPatchPage"
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun NewPatchPage(entry: NavBackStackEntry) {
|
fun NewPatchPage(entry: NavBackStackEntry) {
|
||||||
|
|
@ -57,27 +59,29 @@ fun NewPatchPage(entry: NavBackStackEntry) {
|
||||||
val navController = LocalNavController.current
|
val navController = LocalNavController.current
|
||||||
val lifecycleOwner = LocalLifecycleOwner.current
|
val lifecycleOwner = LocalLifecycleOwner.current
|
||||||
val isCancelled by entry.observeState<Boolean>("isCancelled")
|
val isCancelled by entry.observeState<Boolean>("isCancelled")
|
||||||
entry.savedStateHandle.getLiveData<AppInfo>("appInfo").observe(lifecycleOwner) {
|
LaunchedEffect(Unit) {
|
||||||
viewModel.patchApp = it
|
entry.savedStateHandle.getLiveData<AppInfo>("appInfo").observe(lifecycleOwner) {
|
||||||
|
viewModel.configurePatch(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(TAG, "NewPatchPage: ${viewModel.patchState}")
|
Log.d(TAG, "PatchState: ${viewModel.patchState}")
|
||||||
if (viewModel.patchState == PatchState.SELECTING) {
|
if (viewModel.patchState == PatchState.SELECTING) {
|
||||||
when {
|
LaunchedEffect(Unit) {
|
||||||
isCancelled == true -> {
|
if (isCancelled == true) navController.popBackStack()
|
||||||
LaunchedEffect(viewModel) { navController.popBackStack() }
|
else navController.navigate(PageList.SelectApps.name + "/false")
|
||||||
return
|
|
||||||
}
|
|
||||||
viewModel.patchApp != null -> {
|
|
||||||
LaunchedEffect(viewModel) { viewModel.configurePatch() }
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
LaunchedEffect(viewModel) { navController.navigate(PageList.SelectApps.name + "/false") }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Scaffold(
|
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 = {
|
floatingActionButton = {
|
||||||
if (viewModel.patchState == PatchState.CONFIGURING) {
|
if (viewModel.patchState == PatchState.CONFIGURING) {
|
||||||
ConfiguringFab()
|
ConfiguringFab()
|
||||||
|
|
@ -85,8 +89,10 @@ fun NewPatchPage(entry: NavBackStackEntry) {
|
||||||
}
|
}
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
if (viewModel.patchState == PatchState.CONFIGURING) {
|
if (viewModel.patchState == PatchState.CONFIGURING) {
|
||||||
entry.savedStateHandle.getLiveData<SnapshotStateList<AppInfo>>("selected", SnapshotStateList()).observe(lifecycleOwner) {
|
LaunchedEffect(Unit) {
|
||||||
viewModel.embeddedModules = it
|
entry.savedStateHandle.getLiveData<SnapshotStateList<AppInfo>>("selected", SnapshotStateList()).observe(lifecycleOwner) {
|
||||||
|
viewModel.embeddedModules = it
|
||||||
|
}
|
||||||
}
|
}
|
||||||
PatchOptionsBody(Modifier.padding(innerPadding))
|
PatchOptionsBody(Modifier.padding(innerPadding))
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -97,21 +103,14 @@ fun NewPatchPage(entry: NavBackStackEntry) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun TopBar(patchApp: AppInfo) {
|
private fun ConfiguringTopBar(onBackClick: () -> Unit) {
|
||||||
SmallTopAppBar(
|
SmallTopAppBar(
|
||||||
title = {
|
title = { Text(stringResource(R.string.page_new_patch)) },
|
||||||
Column {
|
navigationIcon = {
|
||||||
Text(
|
IconButton(
|
||||||
text = patchApp.label,
|
onClick = onBackClick,
|
||||||
style = MaterialTheme.typography.headlineSmall,
|
content = { Icon(Icons.Outlined.ArrowBack, null) }
|
||||||
modifier = Modifier.padding(horizontal = 24.dp)
|
)
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = patchApp.app.packageName,
|
|
||||||
style = MaterialTheme.typography.bodyLarge,
|
|
||||||
modifier = Modifier.padding(horizontal = 24.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -141,6 +140,16 @@ private fun PatchOptionsBody(modifier: Modifier) {
|
||||||
val navController = LocalNavController.current
|
val navController = LocalNavController.current
|
||||||
|
|
||||||
Column(modifier.verticalScroll(rememberScrollState())) {
|
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(
|
||||||
text = stringResource(R.string.patch_mode),
|
text = stringResource(R.string.patch_mode),
|
||||||
style = MaterialTheme.typography.titleLarge,
|
style = MaterialTheme.typography.titleLarge,
|
||||||
|
|
@ -263,7 +272,7 @@ private fun DoPatchBody(modifier: Modifier) {
|
||||||
val logs = remember { mutableStateListOf<Pair<Int, String>>() }
|
val logs = remember { mutableStateListOf<Pair<Int, String>>() }
|
||||||
val logger = remember { PatchLogger(logs) }
|
val logger = remember { PatchLogger(logs) }
|
||||||
|
|
||||||
LaunchedEffect(viewModel) {
|
LaunchedEffect(Unit) {
|
||||||
try {
|
try {
|
||||||
Patcher.patch(context, logger, viewModel.patchOptions)
|
Patcher.patch(context, logger, viewModel.patchOptions)
|
||||||
viewModel.finishPatch()
|
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 =
|
val shellBoxMaxHeight =
|
||||||
if (viewModel.patchState == PatchState.PATCHING) maxHeight
|
if (viewModel.patchState == PatchState.PATCHING) maxHeight
|
||||||
else maxHeight - ButtonDefaults.MinHeight - 12.dp
|
else maxHeight - ButtonDefaults.MinHeight - 12.dp
|
||||||
|
|
@ -318,13 +327,14 @@ private fun DoPatchBody(modifier: Modifier) {
|
||||||
}
|
}
|
||||||
|
|
||||||
when (viewModel.patchState) {
|
when (viewModel.patchState) {
|
||||||
|
PatchState.PATCHING -> BackHandler {}
|
||||||
PatchState.FINISHED -> {
|
PatchState.FINISHED -> {
|
||||||
val shizukuUnavailable = stringResource(R.string.shizuku_unavailable)
|
val shizukuUnavailable = stringResource(R.string.shizuku_unavailable)
|
||||||
val installSuccessfully = stringResource(R.string.patch_install_successfully)
|
val installSuccessfully = stringResource(R.string.patch_install_successfully)
|
||||||
val installFailed = stringResource(R.string.patch_install_failed)
|
val installFailed = stringResource(R.string.patch_install_failed)
|
||||||
val copyError = stringResource(R.string.patch_copy_error)
|
val copyError = stringResource(R.string.patch_copy_error)
|
||||||
var installing by rememberSaveable { mutableStateOf(false) }
|
var installing by rememberSaveable { mutableStateOf(false) }
|
||||||
if (installing) InstallDialog(viewModel.patchApp!!) { status, message ->
|
if (installing) InstallDialog(viewModel.patchApp) { status, message ->
|
||||||
scope.launch {
|
scope.launch {
|
||||||
installing = false
|
installing = false
|
||||||
if (status == PackageInstaller.STATUS_SUCCESS) {
|
if (status == PackageInstaller.STATUS_SUCCESS) {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ class NewPatchViewModel : ViewModel() {
|
||||||
|
|
||||||
var patchState by mutableStateOf(PatchState.SELECTING)
|
var patchState by mutableStateOf(PatchState.SELECTING)
|
||||||
private set
|
private set
|
||||||
var patchApp by mutableStateOf<AppInfo?>(null)
|
|
||||||
|
|
||||||
var useManager by mutableStateOf(true)
|
var useManager by mutableStateOf(true)
|
||||||
var debuggable by mutableStateOf(false)
|
var debuggable by mutableStateOf(false)
|
||||||
|
|
@ -24,17 +23,20 @@ class NewPatchViewModel : ViewModel() {
|
||||||
var sign = mutableStateListOf(false, true)
|
var sign = mutableStateListOf(false, true)
|
||||||
var sigBypassLevel by mutableStateOf(2)
|
var sigBypassLevel by mutableStateOf(2)
|
||||||
|
|
||||||
|
lateinit var patchApp: AppInfo
|
||||||
|
private set
|
||||||
lateinit var embeddedModules: SnapshotStateList<AppInfo>
|
lateinit var embeddedModules: SnapshotStateList<AppInfo>
|
||||||
lateinit var patchOptions: Patcher.Options
|
lateinit var patchOptions: Patcher.Options
|
||||||
|
|
||||||
fun configurePatch() {
|
fun configurePatch(app: AppInfo) {
|
||||||
|
patchApp = app
|
||||||
patchState = PatchState.CONFIGURING
|
patchState = PatchState.CONFIGURING
|
||||||
}
|
}
|
||||||
|
|
||||||
fun submitPatch() {
|
fun submitPatch() {
|
||||||
if (useManager) embeddedModules.clear()
|
if (useManager) embeddedModules.clear()
|
||||||
patchOptions = Patcher.Options(
|
patchOptions = Patcher.Options(
|
||||||
apkPaths = listOf(patchApp!!.app.sourceDir) + (patchApp!!.app.splitSourceDirs ?: emptyArray()),
|
apkPaths = listOf(patchApp.app.sourceDir) + (patchApp.app.splitSourceDirs ?: emptyArray()),
|
||||||
debuggable = debuggable,
|
debuggable = debuggable,
|
||||||
sigbypassLevel = sigBypassLevel,
|
sigbypassLevel = sigBypassLevel,
|
||||||
v1 = sign[0], v2 = sign[1],
|
v1 = sign[0], v2 = sign[1],
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue