manager: optimize uid/gid panel

This commit is contained in:
weishu
2023-06-04 23:07:42 +08:00
parent ef8da39d34
commit 887f02e742

View File

@@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowDropDown import androidx.compose.material.icons.filled.ArrowDropDown
@@ -29,11 +30,15 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
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.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.text.isDigitsOnly
import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState
import com.maxkeppeler.sheets.list.ListDialog import com.maxkeppeler.sheets.list.ListDialog
import com.maxkeppeler.sheets.list.models.ListOption import com.maxkeppeler.sheets.list.models.ListOption
@@ -43,7 +48,7 @@ import me.weishu.kernelsu.R
import me.weishu.kernelsu.profile.Capabilities import me.weishu.kernelsu.profile.Capabilities
import me.weishu.kernelsu.profile.Groups import me.weishu.kernelsu.profile.Groups
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
@Composable @Composable
fun RootProfileConfig( fun RootProfileConfig(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@@ -114,55 +119,22 @@ fun RootProfileConfig(
} }
}) })
ListItem(headlineContent = { UidPanel(uid = profile.uid, label = "uid", onUidChange = {
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
label = { Text("uid") },
value = profile.uid.toString(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
onValueChange = {
if (it.isNotEmpty()) {
it.filter { symbol ->
symbol.isDigit()
}.let { filtered ->
filtered.ifEmpty { "0" }
}.let { value ->
onProfileChange( onProfileChange(
profile.copy( profile.copy(
uid = value.toInt(), uid = it,
rootUseDefault = false rootUseDefault = false
) )
) )
}
}
}
)
}) })
ListItem(headlineContent = { UidPanel(uid = profile.gid, label = "gid", onUidChange = {
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
label = { Text("gid") },
value = profile.gid.toString(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
onValueChange = {
if (it.isNotEmpty()) {
it.filter { symbol ->
symbol.isDigit()
}.let { filtered ->
filtered.ifEmpty { "0" }
}.let { value ->
onProfileChange( onProfileChange(
profile.copy( profile.copy(
gid = value.toInt(), gid = it,
rootUseDefault = false rootUseDefault = false
) )
) )
}
}
}
)
}) })
val selectedGroups = profile.groups.ifEmpty { listOf(0) }.let { e -> val selectedGroups = profile.groups.ifEmpty { listOf(0) }.let { e ->
@@ -179,13 +151,10 @@ fun RootProfileConfig(
) )
} }
val selectedCaps = profile.capabilities.ifEmpty { val selectedCaps = profile.capabilities.mapNotNull { e ->
Capabilities.values().toList() Capabilities.values().find { it.cap == e }
}.let { e ->
e.mapNotNull { cap ->
Capabilities.values().find { it.cap == cap }
}
} }
CapsPanel(selectedCaps) { CapsPanel(selectedCaps) {
onProfileChange( onProfileChange(
profile.copy( profile.copy(
@@ -272,7 +241,7 @@ fun GroupsPanel(selected: List<Groups>, closeSelection: (selection: List<Groups>
@OptIn(ExperimentalLayoutApi::class) @OptIn(ExperimentalLayoutApi::class)
@Composable @Composable
fun CapsPanel( fun CapsPanel(
selected: List<Capabilities>, selected: Collection<Capabilities>,
closeSelection: (selection: List<Capabilities>) -> Unit closeSelection: (selection: List<Capabilities>) -> Unit
) { ) {
@@ -329,6 +298,47 @@ fun CapsPanel(
} }
} }
@OptIn(ExperimentalComposeUiApi::class)
@Composable
private fun UidPanel(uid: Int, label: String, onUidChange: (Int) -> Unit) {
ListItem(headlineContent = {
var isError by remember {
mutableStateOf(false)
}
var lastValidUid by remember {
mutableStateOf(uid)
}
val keyboardController = LocalSoftwareKeyboardController.current
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
label = { Text(label) },
value = uid.toString(),
isError = isError,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(onDone = {
keyboardController?.hide()
}),
onValueChange = {
val valid = isTextValidUid(it)
val targetUid = if (valid) it.toInt() else lastValidUid
if (valid) {
lastValidUid = it.toInt()
}
onUidChange(targetUid)
isError = !valid
}
)
})
}
@Preview @Preview
@Composable @Composable
private fun RootProfileConfigPreview() { private fun RootProfileConfigPreview() {
@@ -337,3 +347,7 @@ private fun RootProfileConfigPreview() {
profile = it profile = it
} }
} }
private fun isTextValidUid(text: String): Boolean {
return text.isNotEmpty() && text.isDigitsOnly() && text.toInt() >= 0 && text.toInt() <= Int.MAX_VALUE
}