kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
feat: add option for 3 admin keys in `SecurityConfig`
rodzic
ebe0aeec14
commit
0062d38c8b
|
@ -42,6 +42,7 @@ fun EditBase64Preference(
|
|||
onValueChange: (ByteString) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
onGenerateKey: (() -> Unit)? = null,
|
||||
trailingIcon: (@Composable () -> Unit)? = null,
|
||||
) {
|
||||
fun ByteString.encodeToString() = Base64.encodeToString(this.toByteArray(), Base64.NO_WRAP)
|
||||
fun String.toByteString() = Base64.decode(this, Base64.NO_WRAP).toByteString()
|
||||
|
@ -80,23 +81,30 @@ fun EditBase64Preference(
|
|||
),
|
||||
keyboardActions = keyboardActions,
|
||||
trailingIcon = {
|
||||
IconButton(
|
||||
onClick = {
|
||||
if (isError) {
|
||||
valueState = value.encodeToString()
|
||||
onValueChange(value)
|
||||
} else if (onGenerateKey != null && !isFocused) {
|
||||
onGenerateKey()
|
||||
}
|
||||
},
|
||||
enabled = enabled,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = icon ?: return@IconButton,
|
||||
contentDescription = description,
|
||||
tint = if (isError) MaterialTheme.colors.error
|
||||
else LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
|
||||
)
|
||||
if (trailingIcon != null) {
|
||||
trailingIcon()
|
||||
} else if (icon != null) {
|
||||
IconButton(
|
||||
onClick = {
|
||||
if (isError) {
|
||||
valueState = value.encodeToString()
|
||||
onValueChange(value)
|
||||
} else if (onGenerateKey != null && !isFocused) {
|
||||
onGenerateKey()
|
||||
}
|
||||
},
|
||||
enabled = enabled,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = description,
|
||||
tint = if (isError) {
|
||||
MaterialTheme.colors.error
|
||||
} else {
|
||||
LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
|
@ -31,6 +31,7 @@ import com.geeksville.mesh.ModuleConfigProtos.RemoteHardwarePinType
|
|||
import com.geeksville.mesh.R
|
||||
import com.geeksville.mesh.copy
|
||||
import com.geeksville.mesh.remoteHardwarePin
|
||||
import com.google.protobuf.ByteString
|
||||
|
||||
@Composable
|
||||
inline fun <reified T> EditListPreference(
|
||||
|
@ -50,9 +51,29 @@ inline fun <reified T> EditListPreference(
|
|||
modifier = modifier.padding(16.dp),
|
||||
text = title,
|
||||
style = MaterialTheme.typography.body2,
|
||||
color = if (!enabled) MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled) else Color.Unspecified,
|
||||
color = if (enabled) {
|
||||
Color.Unspecified
|
||||
} else {
|
||||
MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled)
|
||||
},
|
||||
)
|
||||
listState.forEachIndexed { index, value ->
|
||||
val trailingIcon = @Composable {
|
||||
IconButton(
|
||||
onClick = {
|
||||
focusManager.clearFocus()
|
||||
listState.removeAt(index)
|
||||
onValuesChanged(listState)
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.TwoTone.Close,
|
||||
contentDescription = stringResource(R.string.delete),
|
||||
modifier = Modifier.wrapContentSize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// handle lora.ignoreIncoming: List<Int>
|
||||
if (value is Int) EditTextPreference(
|
||||
title = "${index + 1}/$maxCount",
|
||||
|
@ -64,21 +85,21 @@ inline fun <reified T> EditListPreference(
|
|||
onValuesChanged(listState)
|
||||
},
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
trailingIcon = {
|
||||
IconButton(
|
||||
onClick = {
|
||||
focusManager.clearFocus()
|
||||
listState.removeAt(index)
|
||||
onValuesChanged(listState)
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
Icons.TwoTone.Close,
|
||||
stringResource(R.string.delete),
|
||||
modifier = Modifier.wrapContentSize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
trailingIcon = trailingIcon,
|
||||
)
|
||||
|
||||
// handle security.adminKey: List<ByteString>
|
||||
if (value is ByteString) EditBase64Preference(
|
||||
title = "${index + 1}/$maxCount",
|
||||
value = value,
|
||||
enabled = enabled,
|
||||
keyboardActions = keyboardActions,
|
||||
onValueChange = {
|
||||
listState[index] = it as T
|
||||
onValuesChanged(listState)
|
||||
},
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
trailingIcon = trailingIcon,
|
||||
)
|
||||
|
||||
// handle remoteHardware.availablePins: List<RemoteHardwarePin>
|
||||
|
@ -109,21 +130,7 @@ inline fun <reified T> EditListPreference(
|
|||
listState[index] = value.copy { name = it } as T
|
||||
onValuesChanged(listState)
|
||||
},
|
||||
trailingIcon = {
|
||||
IconButton(
|
||||
onClick = {
|
||||
focusManager.clearFocus()
|
||||
listState.removeAt(index)
|
||||
onValuesChanged(listState)
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
Icons.TwoTone.Close,
|
||||
stringResource(R.string.delete),
|
||||
modifier = Modifier.wrapContentSize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
trailingIcon = trailingIcon,
|
||||
)
|
||||
DropDownPreference(
|
||||
title = "Type",
|
||||
|
@ -145,6 +152,7 @@ inline fun <reified T> EditListPreference(
|
|||
// Add element based on the type T
|
||||
val newElement = when (T::class) {
|
||||
Int::class -> 0 as T
|
||||
ByteString::class -> ByteString.EMPTY as T
|
||||
RemoteHardwarePin::class -> remoteHardwarePin {} as T
|
||||
else -> throw IllegalArgumentException("Unsupported type: ${T::class}")
|
||||
}
|
||||
|
|
|
@ -15,10 +15,10 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import com.geeksville.mesh.ConfigProtos.Config.SecurityConfig
|
||||
import com.geeksville.mesh.copy
|
||||
import com.geeksville.mesh.ui.components.EditBase64Preference
|
||||
import com.geeksville.mesh.ui.components.EditListPreference
|
||||
import com.geeksville.mesh.ui.components.PreferenceCategory
|
||||
import com.geeksville.mesh.ui.components.PreferenceFooter
|
||||
import com.geeksville.mesh.ui.components.SwitchPreference
|
||||
import com.google.protobuf.ByteString
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
|
@ -64,17 +64,16 @@ fun SecurityConfigItemList(
|
|||
}
|
||||
|
||||
item {
|
||||
EditBase64Preference(
|
||||
EditListPreference(
|
||||
title = "Admin Key",
|
||||
value = securityInput.adminKeyList.firstOrNull() ?: ByteString.EMPTY,
|
||||
list = securityInput.adminKeyList,
|
||||
maxCount = 3,
|
||||
enabled = enabled,
|
||||
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
|
||||
onValueChange = {
|
||||
if (it.size() == 32) {
|
||||
securityInput = securityInput.copy {
|
||||
adminKey.clear()
|
||||
adminKey.add(it)
|
||||
}
|
||||
onValuesChanged = {
|
||||
securityInput = securityInput.copy {
|
||||
adminKey.clear()
|
||||
adminKey.addAll(it)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
Ładowanie…
Reference in New Issue