mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 11:05:59 +00:00
Fix crash in PackageChooser
Add 2 new user restriction items, close #124 Add User restriction editor Add Exit in settings
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
||||||
<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
|
<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
|
||||||
<uses-sdk tools:overrideLibrary="rikka.shizuku.provider,rikka.shizuku.api,rikka.shizuku.shared,rikka.shizuku.aidl"/>
|
<uses-sdk tools:overrideLibrary="rikka.shizuku.provider,rikka.shizuku.api,rikka.shizuku.shared,rikka.shizuku.aidl"/>
|
||||||
|
<uses-feature android:name="android.software.device_admin"/>
|
||||||
<application
|
<application
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
|
|||||||
@@ -207,6 +207,8 @@ import com.bintianqi.owndroid.dpm.UserInfoScreen
|
|||||||
import com.bintianqi.owndroid.dpm.UserOperation
|
import com.bintianqi.owndroid.dpm.UserOperation
|
||||||
import com.bintianqi.owndroid.dpm.UserOperationScreen
|
import com.bintianqi.owndroid.dpm.UserOperationScreen
|
||||||
import com.bintianqi.owndroid.dpm.UserRestriction
|
import com.bintianqi.owndroid.dpm.UserRestriction
|
||||||
|
import com.bintianqi.owndroid.dpm.UserRestrictionEditor
|
||||||
|
import com.bintianqi.owndroid.dpm.UserRestrictionEditorScreen
|
||||||
import com.bintianqi.owndroid.dpm.UserRestrictionOptions
|
import com.bintianqi.owndroid.dpm.UserRestrictionOptions
|
||||||
import com.bintianqi.owndroid.dpm.UserRestrictionOptionsScreen
|
import com.bintianqi.owndroid.dpm.UserRestrictionOptionsScreen
|
||||||
import com.bintianqi.owndroid.dpm.UserRestrictionScreen
|
import com.bintianqi.owndroid.dpm.UserRestrictionScreen
|
||||||
@@ -426,10 +428,13 @@ fun Home(vm: MyViewModel, onLock: () -> Unit) {
|
|||||||
composable<SetDefaultDialer> { SetDefaultDialerScreen(::navigateUp) }
|
composable<SetDefaultDialer> { SetDefaultDialerScreen(::navigateUp) }
|
||||||
|
|
||||||
composable<UserRestriction> {
|
composable<UserRestriction> {
|
||||||
UserRestrictionScreen(::navigateUp) { title, items ->
|
UserRestrictionScreen(::navigateUp) {
|
||||||
navigate(UserRestrictionOptions(title, items))
|
navigate(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
composable<UserRestrictionEditor> {
|
||||||
|
UserRestrictionEditorScreen(::navigateUp)
|
||||||
|
}
|
||||||
composable<UserRestrictionOptions>(mapOf(serializableNavTypePair<List<Restriction>>())) {
|
composable<UserRestrictionOptions>(mapOf(serializableNavTypePair<List<Restriction>>())) {
|
||||||
UserRestrictionOptionsScreen(it.toRoute(), ::navigateUp)
|
UserRestrictionOptionsScreen(it.toRoute(), ::navigateUp)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,10 +180,8 @@ fun AppChooserScreen(params: ApplicationsList, onChoosePackage: (String?) -> Uni
|
|||||||
}
|
}
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
LazyColumn(Modifier.fillMaxSize().padding(paddingValues)) {
|
LazyColumn(Modifier.fillMaxSize().padding(paddingValues)) {
|
||||||
stickyHeader {
|
if (progress < 1F) stickyHeader {
|
||||||
AnimatedVisibility(progress < 1F) {
|
LinearProgressIndicator({ progress }, Modifier.fillMaxWidth())
|
||||||
LinearProgressIndicator(progress = { progress }, modifier = Modifier.fillMaxWidth())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
items(filteredPackages, { it.name }) {
|
items(filteredPackages, { it.name }) {
|
||||||
Row(
|
Row(
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import androidx.compose.foundation.text.KeyboardActions
|
|||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Close
|
||||||
import androidx.compose.material.icons.filled.MoreVert
|
import androidx.compose.material.icons.filled.MoreVert
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.DropdownMenu
|
import androidx.compose.material3.DropdownMenu
|
||||||
@@ -67,6 +68,7 @@ import java.security.SecureRandom
|
|||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
@Serializable object Settings
|
@Serializable object Settings
|
||||||
|
|
||||||
@@ -105,6 +107,11 @@ fun SettingsScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
|||||||
Icon(painterResource(R.drawable.description_fill0), null)
|
Icon(painterResource(R.drawable.description_fill0), null)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
DropdownMenuItem(
|
||||||
|
{ Text(stringResource(R.string.exit)) },
|
||||||
|
{ exitProcess(0) },
|
||||||
|
leadingIcon = { Icon(Icons.Default.Close, null) }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -271,7 +271,8 @@ fun WorkModesScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
if ((privilege.device || privilege.profile) && !privilege.dhizuku) Row(
|
if ((privilege.device || privilege.profile) && !privilege.dhizuku) Row(
|
||||||
Modifier.padding(top = 20.dp).fillMaxWidth().clickable { onNavigate(DhizukuServerSettings) },
|
Modifier.padding(top = 20.dp).fillMaxWidth()
|
||||||
|
.clickable { onNavigate(DhizukuServerSettings) }.padding(vertical = 4.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Icon(painterResource(R.drawable.dhizuku_icon), null, Modifier.padding(8.dp).size(28.dp))
|
Icon(painterResource(R.drawable.dhizuku_icon), null, Modifier.padding(8.dp).size(28.dp))
|
||||||
|
|||||||
@@ -6,24 +6,67 @@ import android.os.UserManager
|
|||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.offset
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Add
|
||||||
|
import androidx.compose.material.icons.filled.Check
|
||||||
|
import androidx.compose.material.icons.filled.Edit
|
||||||
|
import androidx.compose.material.icons.outlined.Delete
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.LargeTopAppBar
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.MaterialTheme.colorScheme
|
||||||
|
import androidx.compose.material3.MaterialTheme.typography
|
||||||
|
import androidx.compose.material3.OutlinedTextField
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Switch
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TopAppBar
|
||||||
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateListOf
|
||||||
import androidx.compose.runtime.mutableStateMapOf
|
import androidx.compose.runtime.mutableStateMapOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import com.bintianqi.owndroid.HorizontalPadding
|
||||||
import com.bintianqi.owndroid.R
|
import com.bintianqi.owndroid.R
|
||||||
import com.bintianqi.owndroid.myPrivilege
|
import com.bintianqi.owndroid.myPrivilege
|
||||||
import com.bintianqi.owndroid.ui.FunctionItem
|
import com.bintianqi.owndroid.ui.FunctionItem
|
||||||
|
import com.bintianqi.owndroid.ui.MyLazyScaffold
|
||||||
import com.bintianqi.owndroid.ui.MyScaffold
|
import com.bintianqi.owndroid.ui.MyScaffold
|
||||||
|
import com.bintianqi.owndroid.ui.NavIcon
|
||||||
import com.bintianqi.owndroid.ui.SwitchItem
|
import com.bintianqi.owndroid.ui.SwitchItem
|
||||||
|
import com.bintianqi.owndroid.zhCN
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@@ -36,11 +79,37 @@ data class Restriction(
|
|||||||
|
|
||||||
@Serializable object UserRestriction
|
@Serializable object UserRestriction
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@RequiresApi(24)
|
@RequiresApi(24)
|
||||||
@Composable
|
@Composable
|
||||||
fun UserRestrictionScreen(onNavigateUp: () -> Unit, onNavigate: (Int, List<Restriction>) -> Unit) {
|
fun UserRestrictionScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
||||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||||
MyScaffold(R.string.user_restriction, onNavigateUp, 0.dp) {
|
val sb = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
||||||
|
fun navigateToOptions(title: Int, items: List<Restriction>) {
|
||||||
|
onNavigate(UserRestrictionOptions(title, items))
|
||||||
|
}
|
||||||
|
Scaffold(
|
||||||
|
Modifier.nestedScroll(sb.nestedScrollConnection),
|
||||||
|
topBar = {
|
||||||
|
LargeTopAppBar(
|
||||||
|
{ Text(stringResource(R.string.user_restriction)) },
|
||||||
|
navigationIcon = { NavIcon(onNavigateUp) },
|
||||||
|
actions = {
|
||||||
|
IconButton({ onNavigate(UserRestrictionEditor) }) {
|
||||||
|
Icon(Icons.Default.Edit, null)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scrollBehavior = sb
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { paddingValues ->
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(paddingValues)
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
.padding(bottom = 80.dp)
|
||||||
|
) {
|
||||||
Spacer(Modifier.padding(vertical = 2.dp))
|
Spacer(Modifier.padding(vertical = 2.dp))
|
||||||
Text(text = stringResource(R.string.switch_to_disable_feature), modifier = Modifier.padding(start = 16.dp))
|
Text(text = stringResource(R.string.switch_to_disable_feature), modifier = Modifier.padding(start = 16.dp))
|
||||||
if(privilege.profile) { Text(text = stringResource(R.string.profile_owner_is_restricted), modifier = Modifier.padding(start = 16.dp)) }
|
if(privilege.profile) { Text(text = stringResource(R.string.profile_owner_is_restricted), modifier = Modifier.padding(start = 16.dp)) }
|
||||||
@@ -49,22 +118,23 @@ fun UserRestrictionScreen(onNavigateUp: () -> Unit, onNavigate: (Int, List<Restr
|
|||||||
}
|
}
|
||||||
Spacer(Modifier.padding(vertical = 2.dp))
|
Spacer(Modifier.padding(vertical = 2.dp))
|
||||||
FunctionItem(R.string.network, icon = R.drawable.language_fill0) {
|
FunctionItem(R.string.network, icon = R.drawable.language_fill0) {
|
||||||
onNavigate(R.string.network, RestrictionData.internet)
|
navigateToOptions(R.string.network, RestrictionData.internet)
|
||||||
}
|
}
|
||||||
FunctionItem(R.string.connectivity, icon = R.drawable.devices_other_fill0) {
|
FunctionItem(R.string.connectivity, icon = R.drawable.devices_other_fill0) {
|
||||||
onNavigate(R.string.connectivity, RestrictionData.connectivity)
|
navigateToOptions(R.string.connectivity, RestrictionData.connectivity)
|
||||||
}
|
}
|
||||||
FunctionItem(R.string.applications, icon = R.drawable.apps_fill0) {
|
FunctionItem(R.string.applications, icon = R.drawable.apps_fill0) {
|
||||||
onNavigate(R.string.applications, RestrictionData.applications)
|
navigateToOptions(R.string.applications, RestrictionData.applications)
|
||||||
}
|
}
|
||||||
FunctionItem(R.string.users, icon = R.drawable.account_circle_fill0) {
|
FunctionItem(R.string.users, icon = R.drawable.account_circle_fill0) {
|
||||||
onNavigate(R.string.users, RestrictionData.users)
|
navigateToOptions(R.string.users, RestrictionData.users)
|
||||||
}
|
}
|
||||||
FunctionItem(R.string.media, icon = R.drawable.volume_up_fill0) {
|
FunctionItem(R.string.media, icon = R.drawable.volume_up_fill0) {
|
||||||
onNavigate(R.string.media, RestrictionData.media)
|
navigateToOptions(R.string.media, RestrictionData.media)
|
||||||
}
|
}
|
||||||
FunctionItem(R.string.other, icon = R.drawable.more_horiz_fill0) {
|
FunctionItem(R.string.other, icon = R.drawable.more_horiz_fill0) {
|
||||||
onNavigate(R.string.other, RestrictionData.other)
|
navigateToOptions(R.string.other, RestrictionData.other)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,10 +159,24 @@ fun UserRestrictionOptionsScreen(
|
|||||||
status.put(it.id, restrictions.getBoolean(it.id))
|
status.put(it.id, restrictions.getBoolean(it.id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MyScaffold(data.title, onNavigateUp, 0.dp) {
|
MyLazyScaffold(data.title, onNavigateUp) {
|
||||||
data.items.filter { Build.VERSION.SDK_INT >= it.requiresApi }.forEach { restriction ->
|
items(data.items.filter { Build.VERSION.SDK_INT >= it.requiresApi }) { restriction ->
|
||||||
SwitchItem(
|
Row(
|
||||||
restriction.name, restriction.id, restriction.icon, status[restriction.id] == true,
|
Modifier.fillMaxWidth().padding(15.dp, 6.dp),
|
||||||
|
Arrangement.SpaceBetween, Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Row(Modifier.fillMaxWidth(0.8F), verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Icon(painterResource(restriction.icon), null, Modifier.padding(start = 6.dp, end = 16.dp))
|
||||||
|
Column {
|
||||||
|
Text(stringResource(restriction.name), style = typography.titleMedium)
|
||||||
|
Text(
|
||||||
|
restriction.id, style = typography.bodyMedium,
|
||||||
|
color = colorScheme.onBackground.copy(alpha = 0.8F)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Switch(
|
||||||
|
status[restriction.id] == true,
|
||||||
{
|
{
|
||||||
if (it) {
|
if (it) {
|
||||||
dpm.addUserRestriction(receiver, restriction.id)
|
dpm.addUserRestriction(receiver, restriction.id)
|
||||||
@@ -100,10 +184,14 @@ fun UserRestrictionOptionsScreen(
|
|||||||
dpm.clearUserRestriction(receiver, restriction.id)
|
dpm.clearUserRestriction(receiver, restriction.id)
|
||||||
}
|
}
|
||||||
status[restriction.id] = dpm.getUserRestrictions(receiver).getBoolean(restriction.id)
|
status[restriction.id] = dpm.getUserRestrictions(receiver).getBoolean(restriction.id)
|
||||||
}, padding = true
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
item {
|
||||||
|
Spacer(Modifier.padding(vertical = 30.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("InlinedApi")
|
@Suppress("InlinedApi")
|
||||||
@@ -161,6 +249,8 @@ object RestrictionData {
|
|||||||
Restriction(UserManager.DISALLOW_ADD_USER, R.string.add_user, R.drawable.account_circle_fill0),
|
Restriction(UserManager.DISALLOW_ADD_USER, R.string.add_user, R.drawable.account_circle_fill0),
|
||||||
Restriction(UserManager.DISALLOW_REMOVE_USER, R.string.remove_user, R.drawable.account_circle_fill0),
|
Restriction(UserManager.DISALLOW_REMOVE_USER, R.string.remove_user, R.drawable.account_circle_fill0),
|
||||||
Restriction(UserManager.DISALLOW_USER_SWITCH, R.string.switch_user, R.drawable.account_circle_fill0, 28),
|
Restriction(UserManager.DISALLOW_USER_SWITCH, R.string.switch_user, R.drawable.account_circle_fill0, 28),
|
||||||
|
Restriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, R.string.create_work_profile, R.drawable.work_fill0, 26),
|
||||||
|
Restriction(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, R.string.delete_work_profile, R.drawable.delete_forever_fill0, 26),
|
||||||
Restriction(UserManager.DISALLOW_ADD_PRIVATE_PROFILE, R.string.create_private_space, R.drawable.lock_fill0, 35),
|
Restriction(UserManager.DISALLOW_ADD_PRIVATE_PROFILE, R.string.create_private_space, R.drawable.lock_fill0, 35),
|
||||||
Restriction(UserManager.DISALLOW_SET_USER_ICON, R.string.set_user_icon, R.drawable.account_circle_fill0, 24),
|
Restriction(UserManager.DISALLOW_SET_USER_ICON, R.string.set_user_icon, R.drawable.account_circle_fill0, 24),
|
||||||
Restriction(UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE, R.string.cross_profile_copy, R.drawable.content_paste_fill0),
|
Restriction(UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE, R.string.cross_profile_copy, R.drawable.content_paste_fill0),
|
||||||
@@ -187,3 +277,64 @@ object RestrictionData {
|
|||||||
)
|
)
|
||||||
fun getAllRestrictions() = internet + connectivity + media + applications + users + other
|
fun getAllRestrictions() = internet + connectivity + media + applications + users + other
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serializable object UserRestrictionEditor
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun UserRestrictionEditorScreen(onNavigateUp: () -> Unit) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val dpm = context.getDPM()
|
||||||
|
val receiver = context.getReceiver()
|
||||||
|
val list = remember { mutableStateListOf<String>() }
|
||||||
|
fun refresh() {
|
||||||
|
val restrictions = dpm.getUserRestrictions(receiver)
|
||||||
|
list.clear()
|
||||||
|
list.addAll(restrictions.keySet().filter { restrictions.getBoolean(it) })
|
||||||
|
}
|
||||||
|
LaunchedEffect(Unit) { refresh() }
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
TopAppBar(
|
||||||
|
title = { Text(stringResource(R.string.edit)) },
|
||||||
|
navigationIcon = { NavIcon(onNavigateUp) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { paddingValues ->
|
||||||
|
LazyColumn(Modifier.fillMaxSize().padding(paddingValues)) {
|
||||||
|
items(list, { it }) {
|
||||||
|
Row(
|
||||||
|
Modifier.fillMaxWidth().padding(HorizontalPadding, 2.dp).animateItem(),
|
||||||
|
Arrangement.SpaceBetween, Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(it)
|
||||||
|
IconButton({
|
||||||
|
dpm.clearUserRestriction(receiver, it)
|
||||||
|
refresh()
|
||||||
|
}) {
|
||||||
|
Icon(Icons.Outlined.Delete, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item {
|
||||||
|
var input by remember { mutableStateOf("") }
|
||||||
|
fun add() {
|
||||||
|
dpm.addUserRestriction(receiver, input)
|
||||||
|
refresh()
|
||||||
|
input = ""
|
||||||
|
}
|
||||||
|
OutlinedTextField(
|
||||||
|
input, { input = it }, Modifier.fillMaxWidth().padding(HorizontalPadding, 20.dp),
|
||||||
|
label = { Text("id") },
|
||||||
|
trailingIcon = {
|
||||||
|
IconButton(::add, enabled = input.isNotBlank()) {
|
||||||
|
Icon(Icons.Default.Add, null)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Ascii, imeAction = ImeAction.Done),
|
||||||
|
keyboardActions = KeyboardActions { add() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -68,6 +68,7 @@
|
|||||||
<string name="default_str">默认</string>
|
<string name="default_str">默认</string>
|
||||||
<string name="timeout">超时</string>
|
<string name="timeout">超时</string>
|
||||||
<string name="continue_str">继续</string>
|
<string name="continue_str">继续</string>
|
||||||
|
<string name="exit">退出</string>
|
||||||
|
|
||||||
<!--Permissions-->
|
<!--Permissions-->
|
||||||
<string name="profile_owner">Profile owner</string>
|
<string name="profile_owner">Profile owner</string>
|
||||||
|
|||||||
@@ -73,6 +73,7 @@
|
|||||||
<string name="default_str">Default</string>
|
<string name="default_str">Default</string>
|
||||||
<string name="timeout">Timeout</string>
|
<string name="timeout">Timeout</string>
|
||||||
<string name="continue_str">Continue</string>
|
<string name="continue_str">Continue</string>
|
||||||
|
<string name="exit">Exit</string>
|
||||||
|
|
||||||
<!--Permissions-->
|
<!--Permissions-->
|
||||||
<string name="profile_owner">Profile owner</string>
|
<string name="profile_owner">Profile owner</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user