mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
feat: add Public Key to node key status dialog
This commit is contained in:
parent
94dc3dead1
commit
746f155a99
2 changed files with 127 additions and 7 deletions
|
|
@ -170,6 +170,7 @@ fun NodeItem(
|
|||
NodeKeyStatusIcon(
|
||||
hasPKC = thatNode.hasPKC,
|
||||
mismatchKey = thatNode.mismatchKey,
|
||||
publicKey = thatNode.user.publicKey,
|
||||
modifier = Modifier.size(32.dp)
|
||||
)
|
||||
Text(
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue