manager: Add context menu for app profile

This commit is contained in:
weishu
2023-07-01 12:01:56 +08:00
parent b308a368d3
commit a10d2651c1
3 changed files with 81 additions and 9 deletions

View File

@@ -3,7 +3,9 @@ package me.weishu.kernelsu.ui.screen
import android.util.Log import android.util.Log
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.compose.animation.Crossfade import androidx.compose.animation.Crossfade
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
@@ -20,6 +22,8 @@ import androidx.compose.material.icons.filled.ArrowDropDown
import androidx.compose.material.icons.filled.ArrowDropUp import androidx.compose.material.icons.filled.ArrowDropUp
import androidx.compose.material.icons.filled.Security import androidx.compose.material.icons.filled.Security
import androidx.compose.material3.Divider import androidx.compose.material3.Divider
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExposedDropdownMenuBox import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.FilterChip import androidx.compose.material3.FilterChip
@@ -54,6 +58,9 @@ import me.weishu.kernelsu.ui.component.SwitchItem
import me.weishu.kernelsu.ui.component.profile.AppProfileConfig import me.weishu.kernelsu.ui.component.profile.AppProfileConfig
import me.weishu.kernelsu.ui.component.profile.RootProfileConfig import me.weishu.kernelsu.ui.component.profile.RootProfileConfig
import me.weishu.kernelsu.ui.util.LocalSnackbarHost import me.weishu.kernelsu.ui.util.LocalSnackbarHost
import me.weishu.kernelsu.ui.util.forceStopApp
import me.weishu.kernelsu.ui.util.launchApp
import me.weishu.kernelsu.ui.util.restartApp
import me.weishu.kernelsu.ui.viewmodel.SuperUserViewModel import me.weishu.kernelsu.ui.viewmodel.SuperUserViewModel
/** /**
@@ -77,10 +84,8 @@ fun AppProfileScreen(
mutableStateOf(Natives.getAppProfile(packageName, appInfo.uid)) mutableStateOf(Natives.getAppProfile(packageName, appInfo.uid))
} }
Log.i("mylog", "profile: $profile")
Scaffold( Scaffold(
topBar = { TopBar { navigator.popBackStack() } } topBar = { TopBar { navigator.popBackStack() } },
) { paddingValues -> ) { paddingValues ->
AppProfileInner( AppProfileInner(
modifier = Modifier modifier = Modifier
@@ -128,11 +133,13 @@ private fun AppProfileInner(
val isRootGranted = profile.allowSu val isRootGranted = profile.allowSu
Column(modifier = modifier) { Column(modifier = modifier) {
ListItem( AppMenuBox(packageName) {
headlineContent = { Text(appLabel) }, ListItem(
supportingContent = { Text(packageName) }, headlineContent = { Text(appLabel) },
leadingContent = appIcon, supportingContent = { Text(packageName) },
) leadingContent = appIcon,
)
}
SwitchItem( SwitchItem(
icon = Icons.Filled.Security, icon = Icons.Filled.Security,
@@ -291,6 +298,51 @@ private fun ProfileBox(
}) })
} }
@Composable
private fun AppMenuBox(packageName: String, content: @Composable () -> Unit) {
var expanded by remember { mutableStateOf(false) }
Box {
Box(modifier = Modifier.clickable {
expanded = true
}) {
content()
}
DropdownMenu(
expanded = expanded,
onDismissRequest = {
expanded = false
},
) {
DropdownMenuItem(
text = { Text(stringResource(id = R.string.launch_app)) },
onClick = {
expanded = false
launchApp(packageName)
},
)
DropdownMenuItem(
text = { Text(stringResource(id = R.string.force_stop_app)) },
onClick = {
expanded = false
forceStopApp(packageName)
},
)
DropdownMenuItem(
text = { Text(stringResource(id = R.string.restart_app)) },
onClick = {
expanded = false
restartApp(packageName)
},
)
}
}
}
@Preview @Preview
@Composable @Composable
private fun AppProfilePreview() { private fun AppProfilePreview() {

View File

@@ -9,7 +9,6 @@ import com.topjohnwu.superuser.ShellUtils
import me.weishu.kernelsu.BuildConfig import me.weishu.kernelsu.BuildConfig
import me.weishu.kernelsu.Natives import me.weishu.kernelsu.Natives
import me.weishu.kernelsu.ksuApp import me.weishu.kernelsu.ksuApp
import me.weishu.kernelsu.ui.viewmodel.ModuleViewModel
import org.json.JSONArray import org.json.JSONArray
import java.io.File import java.io.File
@@ -150,4 +149,22 @@ fun isSepolicyValid(rules: String?): Boolean {
val result = val result =
shell.newJob().add("ksud sepolicy check '$rules'").to(ArrayList(), null).exec() shell.newJob().add("ksud sepolicy check '$rules'").to(ArrayList(), null).exec()
return result.isSuccess return result.isSuccess
}
fun forceStopApp(packageName: String) {
val shell = getRootShell()
val result = shell.newJob().add("am force-stop $packageName").exec()
Log.i(TAG, "force stop $packageName result: $result")
}
fun launchApp(packageName: String) {
val shell = getRootShell()
val result = shell.newJob().add("monkey -p $packageName -c android.intent.category.LAUNCHER 1").exec()
Log.i(TAG, "launch $packageName result: $result")
}
fun restartApp(packageName: String) {
forceStopApp(packageName)
launchApp(packageName)
} }

View File

@@ -80,4 +80,7 @@
<string name="module_downloading">Downloading module: %s</string> <string name="module_downloading">Downloading module: %s</string>
<string name="module_start_downloading">Start downloading: %s</string> <string name="module_start_downloading">Start downloading: %s</string>
<string name="new_version_available">New version: %s is available, click to download</string> <string name="new_version_available">New version: %s is available, click to download</string>
<string name="launch_app">Launch</string>
<string name="force_stop_app">Force Stop</string>
<string name="restart_app">Restart</string>
</resources> </resources>