diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/EditBase64Preference.kt b/app/src/main/java/com/geeksville/mesh/ui/components/EditBase64Preference.kt index 3a2f1cdc..1275b1ca 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/EditBase64Preference.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/EditBase64Preference.kt @@ -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) + } + ) + } } }, ) diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/EditListPreference.kt b/app/src/main/java/com/geeksville/mesh/ui/components/EditListPreference.kt index 5f7e08e0..09ffa413 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/EditListPreference.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/EditListPreference.kt @@ -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 EditListPreference( @@ -50,9 +51,29 @@ inline fun 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 if (value is Int) EditTextPreference( title = "${index + 1}/$maxCount", @@ -64,21 +85,21 @@ inline fun 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 + 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 @@ -109,21 +130,7 @@ inline fun 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 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}") } diff --git a/app/src/main/java/com/geeksville/mesh/ui/components/config/SecurityConfigItemList.kt b/app/src/main/java/com/geeksville/mesh/ui/components/config/SecurityConfigItemList.kt index 0ec62933..ef5beac5 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/components/config/SecurityConfigItemList.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/components/config/SecurityConfigItemList.kt @@ -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) } }, )