feat: add Public Key to node key status dialog

This commit is contained in:
andrekir 2024-12-05 19:45:34 -03:00
parent 94dc3dead1
commit 746f155a99
2 changed files with 127 additions and 7 deletions

View file

@ -170,6 +170,7 @@ fun NodeItem(
NodeKeyStatusIcon(
hasPKC = thatNode.hasPKC,
mismatchKey = thatNode.mismatchKey,
publicKey = thatNode.user.publicKey,
modifier = Modifier.size(32.dp)
)
Text(

View file

@ -17,8 +17,25 @@
package com.geeksville.mesh.ui.components
import android.util.Base64
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.ContentAlpha
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.KeyOff
import androidx.compose.material.icons.filled.Lock
@ -27,17 +44,83 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import com.geeksville.mesh.R
import com.geeksville.mesh.model.Channel
import com.geeksville.mesh.ui.theme.AppTheme
import com.google.protobuf.ByteString
@Composable
private fun KeyStatusDialog(
@StringRes title: Int,
@StringRes text: Int,
key: ByteString?,
onDismiss: () -> Unit = {}
) = Dialog(
onDismissRequest = onDismiss,
) {
Surface(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(16.dp),
color = MaterialTheme.colors.background
) {
LazyColumn(
contentPadding = PaddingValues(horizontal = 24.dp, vertical = 16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
item {
Text(
text = stringResource(id = title),
color = MaterialTheme.colors.onBackground.copy(alpha = ContentAlpha.high),
textAlign = TextAlign.Center,
)
Spacer(Modifier.height(16.dp))
Text(
text = stringResource(id = text),
color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.medium),
textAlign = TextAlign.Center,
)
Spacer(Modifier.height(16.dp))
if (key != null && title == R.string.encryption_pkc) {
val keyString = Base64.encodeToString(key.toByteArray(), Base64.NO_WRAP)
SelectionContainer {
Text(
text = "Public Key: $keyString",
textAlign = TextAlign.Center,
)
}
Spacer(Modifier.height(16.dp))
}
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.End,
) {
TextButton(
onClick = onDismiss,
colors = ButtonDefaults.textButtonColors(
contentColor = MaterialTheme.colors.onSurface,
),
) { Text(text = stringResource(id = R.string.close)) }
}
}
}
}
}
@Composable
fun NodeKeyStatusIcon(
hasPKC: Boolean,
mismatchKey: Boolean,
publicKey: ByteString? = null,
modifier: Modifier = Modifier,
) {
var showEncryptionDialog by remember { mutableStateOf(false) }
@ -47,13 +130,13 @@ fun NodeKeyStatusIcon(
hasPKC -> R.string.encryption_pkc to R.string.encryption_pkc_text
else -> R.string.encryption_psk to R.string.encryption_psk_text
}
SimpleAlertDialog(title, text) { showEncryptionDialog = false }
KeyStatusDialog(title, text, publicKey) { showEncryptionDialog = false }
}
val (icon, tint) = when {
mismatchKey -> rememberVectorPainter(Icons.Default.KeyOff) to Color.Red
hasPKC -> rememberVectorPainter(Icons.Default.Lock) to Color(color = 0xFF30C047)
else -> painterResource(R.drawable.ic_lock_open_right_24) to Color(color = 0xFFFEC30A)
mismatchKey -> Icons.Default.KeyOff to Color.Red
hasPKC -> Icons.Default.Lock to Color(color = 0xFF30C047)
else -> ImageVector.vectorResource(R.drawable.ic_lock_open_right_24) to Color(color = 0xFFFEC30A)
}
IconButton(
@ -61,7 +144,7 @@ fun NodeKeyStatusIcon(
modifier = modifier,
) {
Icon(
painter = icon,
imageVector = icon,
contentDescription = stringResource(
id = when {
mismatchKey -> R.string.encryption_error
@ -73,3 +156,39 @@ fun NodeKeyStatusIcon(
)
}
}
@PreviewLightDark
@Composable
private fun KeyStatusDialogErrorPreview() {
AppTheme {
KeyStatusDialog(
title = R.string.encryption_error,
text = R.string.encryption_error_text,
key = null,
)
}
}
@PreviewLightDark
@Composable
private fun KeyStatusDialogPkcPreview() {
AppTheme {
KeyStatusDialog(
title = R.string.encryption_pkc,
text = R.string.encryption_pkc_text,
key = Channel.getRandomKey(),
)
}
}
@PreviewLightDark
@Composable
private fun KeyStatusDialogPskPreview() {
AppTheme {
KeyStatusDialog(
title = R.string.encryption_psk,
text = R.string.encryption_psk_text,
key = null,
)
}
}