feat: add Public chip to onchain wallet card

The onchain wallet's Taproot address is derived from the account's Nostr
pubkey, so anyone with the npub can see its balance and transaction
history on-chain. Surface that fact directly on the card with a tappable
"(i) Public" chip that opens a dialog explaining the privacy implication
and recommending private (non-Nostr) channels for funding and draining.
This commit is contained in:
Claude
2026-05-20 16:39:34 +00:00
parent baf043343d
commit fc8f057e3e
2 changed files with 64 additions and 0 deletions
@@ -35,6 +35,7 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card import androidx.compose.material3.Card
@@ -43,6 +44,7 @@ import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@@ -180,6 +182,8 @@ private fun HeaderRow(
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.SemiBold, fontWeight = FontWeight.SemiBold,
) )
Spacer(modifier = Modifier.width(8.dp))
PublicChip()
} }
Spacer(modifier = Modifier.height(4.dp)) Spacer(modifier = Modifier.height(4.dp))
Text( Text(
@@ -193,6 +197,65 @@ private fun HeaderRow(
} }
} }
@Composable
private fun PublicChip() {
var showDialog by remember { mutableStateOf(false) }
val onSurfaceVariant = MaterialTheme.colorScheme.onSurfaceVariant
Row(
modifier =
Modifier
.clip(RoundedCornerShape(8.dp))
.background(onSurfaceVariant.copy(alpha = 0.12f))
.clickable { showDialog = true }
.padding(horizontal = 6.dp, vertical = 2.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
symbol = MaterialSymbols.Info,
contentDescription = null,
tint = onSurfaceVariant,
modifier = Modifier.size(12.dp),
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = "Public",
style = MaterialTheme.typography.labelSmall,
color = onSurfaceVariant,
fontWeight = FontWeight.Medium,
)
}
if (showDialog) {
AlertDialog(
onDismissRequest = { showDialog = false },
icon = {
Icon(
symbol = MaterialSymbols.Info,
contentDescription = null,
modifier = Modifier.size(24.dp),
)
},
title = { Text("This wallet is public") },
text = {
Text(
"Your Taproot address is derived from your Nostr public key, " +
"so anyone who knows your npub can see this wallet's balance " +
"and transaction history on the blockchain.\n\n" +
"To preserve your privacy, use private channels — not Nostr " +
"events — when funding or draining this wallet, and avoid " +
"linking deposits or withdrawals to identifiable activity.",
)
},
confirmButton = {
TextButton(onClick = { showDialog = false }) {
Text("Got it")
}
},
)
}
}
@Composable @Composable
private fun BitcoinChip(orange: Color) { private fun BitcoinChip(orange: Color) {
Box( Box(
@@ -129,6 +129,7 @@ object MaterialSymbols {
val HourglassEmpty = MaterialSymbol("\uE88B") val HourglassEmpty = MaterialSymbol("\uE88B")
val HourglassTop = MaterialSymbol("\uEA5B") val HourglassTop = MaterialSymbol("\uEA5B")
val Image = MaterialSymbol("\uE3F4") val Image = MaterialSymbol("\uE3F4")
val Info = MaterialSymbol("\uE88E")
val Key = MaterialSymbol("\uE73C") val Key = MaterialSymbol("\uE73C")
val KeyboardArrowDown = MaterialSymbol("\uE313") val KeyboardArrowDown = MaterialSymbol("\uE313")
val KeyboardArrowUp = MaterialSymbol("\uE316") val KeyboardArrowUp = MaterialSymbol("\uE316")