Fix UI bugs
This commit is contained in:
parent
a9b27b1427
commit
d7b3b4cb6b
|
|
@ -10,6 +10,7 @@ import androidx.compose.runtime.*
|
|||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavGraph.Companion.findStartDestination
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
|
|
@ -18,7 +19,7 @@ import org.lsposed.lspatch.ui.page.PageList
|
|||
import org.lsposed.lspatch.ui.theme.LSPTheme
|
||||
import org.lsposed.lspatch.ui.util.LocalNavController
|
||||
import org.lsposed.lspatch.ui.util.LocalSnackbarHost
|
||||
import org.lsposed.lspatch.ui.util.currentRoute
|
||||
import org.lsposed.lspatch.ui.util.navigateWithState
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
|
||||
|
|
@ -27,7 +28,6 @@ class MainActivity : ComponentActivity() {
|
|||
super.onCreate(savedInstanceState)
|
||||
setContent {
|
||||
val navController = rememberAnimatedNavController()
|
||||
val currentRoute = navController.currentRoute
|
||||
var mainPage by rememberSaveable { mutableStateOf(PageList.Home) }
|
||||
|
||||
LSPTheme {
|
||||
|
|
@ -39,12 +39,9 @@ class MainActivity : ComponentActivity() {
|
|||
Scaffold(
|
||||
bottomBar = {
|
||||
MainNavigationBar(mainPage) {
|
||||
if (mainPage == it) return@MainNavigationBar
|
||||
mainPage = it
|
||||
navController.navigate(it.name) {
|
||||
currentRoute?.let { route ->
|
||||
popUpTo(route) { inclusive = true }
|
||||
}
|
||||
}
|
||||
navController.navigateWithState(it.name)
|
||||
}
|
||||
},
|
||||
snackbarHost = { SnackbarHost(snackbarHostState) }
|
||||
|
|
@ -64,12 +61,8 @@ private fun MainNavHost(navController: NavHostController, modifier: Modifier) {
|
|||
startDestination = PageList.Home.name,
|
||||
modifier = modifier
|
||||
) {
|
||||
PageList.values().forEach { page ->
|
||||
val sb = StringBuilder(page.name)
|
||||
if (page.arguments.isNotEmpty()) {
|
||||
sb.append(page.arguments.joinToString(",", "?") { "${it.name}={${it.name}}" })
|
||||
}
|
||||
composable(route = sb.toString(), arguments = page.arguments, content = page.body)
|
||||
for (page in PageList.values()) {
|
||||
composable(route = page.route, arguments = page.arguments, content = page.body)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,12 +23,10 @@ import androidx.compose.material.icons.Icons
|
|||
import androidx.compose.material.icons.outlined.*
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.snapshots.SnapshotStateList
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
|
|
@ -38,7 +36,6 @@ import androidx.lifecycle.viewmodel.compose.viewModel
|
|||
import androidx.navigation.NavBackStackEntry
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.lsposed.lspatch.Patcher
|
||||
import org.lsposed.lspatch.R
|
||||
import org.lsposed.lspatch.lspApp
|
||||
import org.lsposed.lspatch.ui.component.SelectionColumn
|
||||
|
|
@ -51,7 +48,6 @@ import org.lsposed.lspatch.ui.viewmodel.NewPatchViewModel.PatchState
|
|||
import org.lsposed.lspatch.util.LSPPackageManager
|
||||
import org.lsposed.lspatch.util.LSPPackageManager.AppInfo
|
||||
import org.lsposed.lspatch.util.ShizukuApi
|
||||
import org.lsposed.patch.util.Logger
|
||||
import java.io.File
|
||||
|
||||
private const val TAG = "NewPatchPage"
|
||||
|
|
@ -64,12 +60,6 @@ fun NewPatchPage(from: String, entry: NavBackStackEntry) {
|
|||
val navController = LocalNavController.current
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
val isCancelled by entry.observeState<Boolean>("isCancelled")
|
||||
LaunchedEffect(Unit) {
|
||||
lspApp.tmpApkDir.listFiles()?.forEach(File::delete)
|
||||
entry.savedStateHandle.getLiveData<AppInfo>("appInfo").observe(lifecycleOwner) {
|
||||
viewModel.configurePatch(it)
|
||||
}
|
||||
}
|
||||
|
||||
Log.d(TAG, "PatchState: ${viewModel.patchState}")
|
||||
if (viewModel.patchState == PatchState.SELECTING) {
|
||||
|
|
@ -90,10 +80,16 @@ fun NewPatchPage(from: String, entry: NavBackStackEntry) {
|
|||
}
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
lspApp.tmpApkDir.listFiles()?.forEach(File::delete)
|
||||
if (isCancelled == true) navController.popBackStack()
|
||||
else when (from) {
|
||||
"storage" -> storageLauncher.launch(arrayOf("application/vnd.android.package-archive"))
|
||||
"applist" -> navController.navigate(PageList.SelectApps.name + "?multiSelect=false")
|
||||
"applist" -> {
|
||||
entry.savedStateHandle.getLiveData<AppInfo>("appInfo").observe(lifecycleOwner) {
|
||||
viewModel.configurePatch(it)
|
||||
}
|
||||
navController.navigate(PageList.SelectApps.name + "?multiSelect=false")
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -268,44 +264,16 @@ private fun PatchOptionsBody(modifier: Modifier) {
|
|||
}
|
||||
}
|
||||
|
||||
private class PatchLogger(private val logs: MutableList<Pair<Int, String>>) : Logger() {
|
||||
override fun d(msg: String) {
|
||||
if (verbose) {
|
||||
Log.d(TAG, msg)
|
||||
logs += Log.DEBUG to msg
|
||||
}
|
||||
}
|
||||
|
||||
override fun i(msg: String) {
|
||||
Log.i(TAG, msg)
|
||||
logs += Log.INFO to msg
|
||||
}
|
||||
|
||||
override fun e(msg: String) {
|
||||
Log.e(TAG, msg)
|
||||
logs += Log.ERROR to msg
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DoPatchBody(modifier: Modifier) {
|
||||
val viewModel = viewModel<NewPatchViewModel>()
|
||||
val snackbarHost = LocalSnackbarHost.current
|
||||
val navController = LocalNavController.current
|
||||
val scope = rememberCoroutineScope()
|
||||
val logs = remember { mutableStateListOf<Pair<Int, String>>() }
|
||||
val logger = remember { PatchLogger(logs) }
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
try {
|
||||
Patcher.patch(logger, viewModel.patchOptions)
|
||||
viewModel.finishPatch()
|
||||
} catch (t: Throwable) {
|
||||
logger.e(t.message.orEmpty())
|
||||
logger.e(t.stackTraceToString())
|
||||
viewModel.failPatch()
|
||||
} finally {
|
||||
lspApp.tmpApkDir.listFiles()?.forEach(File::delete)
|
||||
if (viewModel.logs.isEmpty()) {
|
||||
viewModel.launchPatch()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -333,7 +301,7 @@ private fun DoPatchBody(modifier: Modifier) {
|
|||
.background(brush)
|
||||
.padding(horizontal = 24.dp, vertical = 18.dp)
|
||||
) {
|
||||
items(logs) {
|
||||
items(viewModel.logs) {
|
||||
when (it.first) {
|
||||
Log.DEBUG -> Text(text = it.second)
|
||||
Log.INFO -> Text(text = it.second)
|
||||
|
|
@ -357,7 +325,7 @@ private fun DoPatchBody(modifier: Modifier) {
|
|||
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) }
|
||||
var installing by remember { mutableStateOf(false) }
|
||||
if (installing) InstallDialog(viewModel.patchApp) { status, message ->
|
||||
scope.launch {
|
||||
LSPPackageManager.fetchAppList()
|
||||
|
|
@ -408,7 +376,7 @@ private fun DoPatchBody(modifier: Modifier) {
|
|||
modifier = Modifier.weight(1f),
|
||||
onClick = {
|
||||
val cm = lspApp.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
cm.setPrimaryClip(ClipData.newPlainText("LSPatch", logs.joinToString { it.second + "\n" }))
|
||||
cm.setPrimaryClip(ClipData.newPlainText("LSPatch", viewModel.logs.joinToString { it.second + "\n" }))
|
||||
},
|
||||
content = { Text(stringResource(R.string.patch_copy_error)) }
|
||||
)
|
||||
|
|
|
|||
|
|
@ -66,4 +66,11 @@ enum class PageList(
|
|||
NewPatch -> stringResource(R.string.page_new_patch)
|
||||
SelectApps -> stringResource(R.string.page_select_apps)
|
||||
}
|
||||
|
||||
val route = buildString {
|
||||
append(name)
|
||||
if (arguments.isNotEmpty()) {
|
||||
append(arguments.joinToString(",", "?") { "${it.name}={${it.name}}" })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,27 +5,18 @@ import androidx.compose.runtime.livedata.observeAsState
|
|||
import androidx.navigation.NavBackStackEntry
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavGraph.Companion.findStartDestination
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
|
||||
val NavController.currentRoute: String?
|
||||
@Composable get() = currentBackStackEntryAsState().value?.destination?.route
|
||||
|
||||
val NavController.startRoute: String?
|
||||
get() = graph.findStartDestination().route
|
||||
|
||||
fun <T> NavBackStackEntry.setState(key: String, value: T?) {
|
||||
savedStateHandle.getLiveData<T>(key).value = value
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun <T> NavBackStackEntry.observeState(key: String, initial: T? = null) = savedStateHandle.getLiveData(key, initial).observeAsState()
|
||||
fun <T> NavBackStackEntry.observeState(key: String, initial: T? = null) =
|
||||
savedStateHandle.getLiveData(key, initial).observeAsState()
|
||||
|
||||
@Composable
|
||||
fun NavController.isAtStartRoute(): Boolean = currentRoute == startRoute
|
||||
|
||||
fun NavController.navigateWithState(route: String?) {
|
||||
navigate(route.toString()) {
|
||||
popUpTo(startRoute.toString()) {
|
||||
fun NavController.navigateWithState(route: String) {
|
||||
navigate(route) {
|
||||
popUpTo(graph.findStartDestination().id) {
|
||||
saveState = true
|
||||
}
|
||||
launchSingleTop = true
|
||||
|
|
|
|||
|
|
@ -1,13 +1,21 @@
|
|||
package org.lsposed.lspatch.ui.viewmodel
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.snapshots.SnapshotStateList
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.lsposed.lspatch.Patcher
|
||||
import org.lsposed.lspatch.lspApp
|
||||
import org.lsposed.lspatch.util.LSPPackageManager.AppInfo
|
||||
import org.lsposed.patch.util.Logger
|
||||
import java.io.File
|
||||
|
||||
private const val TAG = "NewPatchViewModel"
|
||||
|
||||
class NewPatchViewModel : ViewModel() {
|
||||
|
||||
|
|
@ -21,7 +29,7 @@ class NewPatchViewModel : ViewModel() {
|
|||
var useManager by mutableStateOf(true)
|
||||
var debuggable by mutableStateOf(false)
|
||||
var overrideVersionCode by mutableStateOf(false)
|
||||
var sign = mutableStateListOf(false, true)
|
||||
val sign = mutableStateListOf(false, true)
|
||||
var sigBypassLevel by mutableStateOf(2)
|
||||
|
||||
lateinit var patchApp: AppInfo
|
||||
|
|
@ -30,12 +38,34 @@ class NewPatchViewModel : ViewModel() {
|
|||
lateinit var patchOptions: Patcher.Options
|
||||
private set
|
||||
|
||||
val logs = mutableStateListOf<Pair<Int, String>>()
|
||||
private val logger = object : Logger() {
|
||||
override fun d(msg: String) {
|
||||
if (verbose) {
|
||||
Log.d(TAG, msg)
|
||||
logs += Log.DEBUG to msg
|
||||
}
|
||||
}
|
||||
|
||||
override fun i(msg: String) {
|
||||
Log.i(TAG, msg)
|
||||
logs += Log.INFO to msg
|
||||
}
|
||||
|
||||
override fun e(msg: String) {
|
||||
Log.e(TAG, msg)
|
||||
logs += Log.ERROR to msg
|
||||
}
|
||||
}
|
||||
|
||||
fun configurePatch(app: AppInfo) {
|
||||
Log.d(TAG, "Configuring patch for ${app.app.packageName}")
|
||||
patchApp = app
|
||||
patchState = PatchState.CONFIGURING
|
||||
}
|
||||
|
||||
fun submitPatch() {
|
||||
Log.d(TAG, "Submit patch")
|
||||
if (useManager) embeddedModules.clear()
|
||||
patchOptions = Patcher.Options(
|
||||
apkPaths = listOf(patchApp.app.sourceDir) + (patchApp.app.splitSourceDirs ?: emptyArray()),
|
||||
|
|
@ -50,11 +80,19 @@ class NewPatchViewModel : ViewModel() {
|
|||
patchState = PatchState.PATCHING
|
||||
}
|
||||
|
||||
fun finishPatch() {
|
||||
patchState = PatchState.FINISHED
|
||||
fun launchPatch() {
|
||||
logger.i("Launch patch")
|
||||
viewModelScope.launch {
|
||||
patchState = try {
|
||||
Patcher.patch(logger, patchOptions)
|
||||
PatchState.FINISHED
|
||||
} catch (t: Throwable) {
|
||||
logger.e(t.message.orEmpty())
|
||||
logger.e(t.stackTraceToString())
|
||||
PatchState.ERROR
|
||||
} finally {
|
||||
lspApp.tmpApkDir.listFiles()?.forEach(File::delete)
|
||||
}
|
||||
}
|
||||
|
||||
fun failPatch() {
|
||||
patchState = PatchState.ERROR
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue