mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-11 16:57:39 +00:00
feat(cashu): reframe edit-wallet as mint editor; move Verify to suggestions
Adjusts the mint editor to the post-key-rotation reality and tidies its UI: - Settings hub: "Edit wallet details / Mints, nutzap key" row becomes "My mints / Add or remove the mints your wallet uses." The edit screen title changes from "Edit Cashu wallet" to "Edit mints". - The per-mint Verify button moves off the already-added mints list and into the Matching/Popular mints suggestion rows, sitting to the left of the + button, with the reachability result shown under each suggestion. Reuses the existing per-URL mintVerifications state. - Fixes the Mint URL placeholder wrapping onto two lines (and inflating the field height) by capping it to a single ellipsized line. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SXRAunSJS2dBx7B79qTMew
This commit is contained in:
+86
-71
@@ -65,6 +65,7 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.vitorpamplona.amethyst.R
|
||||
@@ -162,67 +163,27 @@ fun AddCashuWalletScreen(
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
val verifications by viewModel.mintVerifications.collectAsState()
|
||||
mints.forEachIndexed { index, mint ->
|
||||
val verifyState = verifications[mint.trim().trimEnd('/')]
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant),
|
||||
) {
|
||||
Column(modifier = Modifier.padding(horizontal = 12.dp, vertical = 4.dp)) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(
|
||||
text = mint,
|
||||
modifier = Modifier.weight(1f),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
Row(
|
||||
modifier = Modifier.padding(horizontal = 12.dp, vertical = 4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = mint,
|
||||
modifier = Modifier.weight(1f),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
)
|
||||
IconButton(onClick = { mints.removeAt(index) }) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.Delete,
|
||||
contentDescription = stringRes(R.string.cashu_remove_mint),
|
||||
modifier = Modifier.size(18.dp),
|
||||
tint = MaterialTheme.colorScheme.error,
|
||||
)
|
||||
OutlinedButton(
|
||||
onClick = { viewModel.verifyMint(mint) },
|
||||
enabled = verifyState !is MintPingState.Pinging,
|
||||
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 0.dp),
|
||||
modifier = Modifier.height(32.dp),
|
||||
) {
|
||||
if (verifyState is MintPingState.Pinging) {
|
||||
CircularProgressIndicator(modifier = Modifier.size(14.dp), strokeWidth = 2.dp)
|
||||
} else {
|
||||
Text(
|
||||
stringRes(R.string.cashu_verify),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
)
|
||||
}
|
||||
}
|
||||
IconButton(onClick = { mints.removeAt(index) }) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.Delete,
|
||||
contentDescription = stringRes(R.string.cashu_remove_mint),
|
||||
modifier = Modifier.size(18.dp),
|
||||
tint = MaterialTheme.colorScheme.error,
|
||||
)
|
||||
}
|
||||
}
|
||||
when (val vs = verifyState) {
|
||||
is MintPingState.Ok -> {
|
||||
Text(
|
||||
text =
|
||||
if (vs.name.isNullOrBlank()) {
|
||||
stringRes(R.string.cashu_mint_reachable)
|
||||
} else {
|
||||
stringRes(R.string.cashu_mint_reachable_named, vs.name)
|
||||
},
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.padding(bottom = 4.dp),
|
||||
)
|
||||
}
|
||||
is MintPingState.Failed -> {
|
||||
Text(
|
||||
text = stringRes(R.string.cashu_mint_unreachable, vs.message),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
modifier = Modifier.padding(bottom = 4.dp),
|
||||
)
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,7 +204,13 @@ fun AddCashuWalletScreen(
|
||||
viewModel.resetMintPing()
|
||||
},
|
||||
label = { Text(stringRes(R.string.cashu_mint_url)) },
|
||||
placeholder = { Text("https://mint.example.com") },
|
||||
placeholder = {
|
||||
Text(
|
||||
"https://mint.example.com",
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
},
|
||||
singleLine = true,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
@@ -318,10 +285,13 @@ fun AddCashuWalletScreen(
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
val verifications by viewModel.mintVerifications.collectAsState()
|
||||
MintSuggestionList(
|
||||
suggestions = suggestions,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
verifications = verifications,
|
||||
onVerify = { url -> viewModel.verifyMint(url) },
|
||||
onAdd = { entry ->
|
||||
val trimmed = entry.url.trim().trimEnd('/')
|
||||
if (trimmed.isNotEmpty() && trimmed !in mints) {
|
||||
@@ -465,9 +435,9 @@ private fun P2pkRadio(
|
||||
* Mint directory autocomplete rendered inline under the mint input.
|
||||
* Each row uses [MintDirectoryRow] so the user sees follower avatars
|
||||
* and recommendation counts the same way they would in a dedicated
|
||||
* picker. Each row carries a `+` button that adds the mint straight to
|
||||
* the wallet's mint list — the per-mint Verify button in that list lets
|
||||
* the user check reachability afterwards.
|
||||
* picker. Each row carries a small Verify button (to check the mint is
|
||||
* reachable) and, to its right, a `+` button that adds the mint straight
|
||||
* to the wallet's mint list. The verify result renders under the row.
|
||||
*
|
||||
* Rows are visually separated by an outlined surface and divider so
|
||||
* a long list reads as discrete entries instead of merging into a
|
||||
@@ -478,6 +448,8 @@ private fun MintSuggestionList(
|
||||
suggestions: List<CashuMintDirectoryEntry>,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: INav,
|
||||
verifications: Map<String, MintPingState>,
|
||||
onVerify: (String) -> Unit,
|
||||
onAdd: (CashuMintDirectoryEntry) -> Unit,
|
||||
) {
|
||||
OutlinedCard(
|
||||
@@ -490,18 +462,61 @@ private fun MintSuggestionList(
|
||||
if (index > 0) {
|
||||
HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant)
|
||||
}
|
||||
MintDirectoryRow(
|
||||
entry = entry,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
) {
|
||||
IconButton(onClick = { onAdd(entry) }) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.Add,
|
||||
contentDescription = stringRes(R.string.cashu_add_mint),
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
val verifyState = verifications[entry.url.trim().trimEnd('/')]
|
||||
Column {
|
||||
MintDirectoryRow(
|
||||
entry = entry,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
) {
|
||||
OutlinedButton(
|
||||
onClick = { onVerify(entry.url) },
|
||||
enabled = verifyState !is MintPingState.Pinging,
|
||||
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 0.dp),
|
||||
modifier = Modifier.height(32.dp),
|
||||
) {
|
||||
if (verifyState is MintPingState.Pinging) {
|
||||
CircularProgressIndicator(modifier = Modifier.size(14.dp), strokeWidth = 2.dp)
|
||||
} else {
|
||||
Text(
|
||||
stringRes(R.string.cashu_verify),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
)
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
IconButton(onClick = { onAdd(entry) }) {
|
||||
Icon(
|
||||
symbol = MaterialSymbols.Add,
|
||||
contentDescription = stringRes(R.string.cashu_add_mint),
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
when (val vs = verifyState) {
|
||||
is MintPingState.Ok -> {
|
||||
Text(
|
||||
text =
|
||||
if (vs.name.isNullOrBlank()) {
|
||||
stringRes(R.string.cashu_mint_reachable)
|
||||
} else {
|
||||
stringRes(R.string.cashu_mint_reachable_named, vs.name)
|
||||
},
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.padding(start = 12.dp, end = 12.dp, bottom = 8.dp),
|
||||
)
|
||||
}
|
||||
is MintPingState.Failed -> {
|
||||
Text(
|
||||
text = stringRes(R.string.cashu_mint_unreachable, vs.message),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
modifier = Modifier.padding(start = 12.dp, end = 12.dp, bottom = 8.dp),
|
||||
)
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -423,8 +423,8 @@ fun SettingsRowEditWalletPreview() {
|
||||
ThemeComparisonColumn {
|
||||
SettingsRow(
|
||||
icon = MaterialSymbols.Edit,
|
||||
title = "Edit wallet details",
|
||||
subtitle = "Mints, nutzap key",
|
||||
title = "My mints",
|
||||
subtitle = "Add or remove the mints your wallet uses.",
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2197,7 +2197,7 @@
|
||||
<string name="cashu_p2pk_autogen_warning_edit">Will invalidate any pending nutzaps locked to the current key.</string>
|
||||
<string name="cashu_p2pk_keep_current">Keep current key</string>
|
||||
<string name="cashu_p2pk_manual_label">P2PK private key (hex)</string>
|
||||
<string name="wallet_edit_cashu_title">Edit Cashu wallet</string>
|
||||
<string name="wallet_edit_cashu_title">Edit mints</string>
|
||||
<string name="wallet_save_changes">Save changes</string>
|
||||
<string name="cashu_mint_no_recs">No recommendations yet</string>
|
||||
<string name="cashu_mint_recommended_by">Recommended by</string>
|
||||
@@ -2227,8 +2227,8 @@
|
||||
<string name="cashu_history_incoming">Received</string>
|
||||
<string name="cashu_history_outgoing">Sent</string>
|
||||
<string name="cashu_settings_title">Cashu Wallet Settings</string>
|
||||
<string name="cashu_settings_edit_wallet">Edit wallet details</string>
|
||||
<string name="cashu_settings_edit_wallet_subtitle">Mints, nutzap key</string>
|
||||
<string name="cashu_settings_edit_wallet">My mints</string>
|
||||
<string name="cashu_settings_edit_wallet_subtitle">Add or remove the mints your wallet uses.</string>
|
||||
<string name="cashu_settings_my_recommendations">My mint recommendations</string>
|
||||
<string name="cashu_settings_recommendations_subtitle">Publicly vouch for mints you trust, and retract recommendations.</string>
|
||||
<string name="cashu_settings_no_recommendations">You haven\'t recommended any mints yet. Tap the thumbs-up next to a mint to publicly vouch for it.</string>
|
||||
|
||||
Reference in New Issue
Block a user