fix: send ui
This commit is contained in:
@@ -126,6 +126,11 @@ val EnHomeStrings = AppStrings(
|
||||
resolving = "Resolving…",
|
||||
sendingPayment = "Sending payment…",
|
||||
|
||||
// ── SendScreen — paying ───────────────────────────────────────────────────
|
||||
paymentTakingLong = "This is taking longer than usual",
|
||||
paymentTakingLongDetail = "Your payment is still on its way. This may be a hold invoice that settles when the recipient is ready. You'll get a notification when it completes — you can safely leave this screen.",
|
||||
dismissPayment = "Dismiss",
|
||||
|
||||
// ── SendScreen — payment sent ─────────────────────────────────────────────
|
||||
paymentSent = "Payment sent!",
|
||||
amountSats = { sats -> "$sats sats" },
|
||||
|
||||
@@ -126,6 +126,11 @@ val EsHomeStrings = AppStrings(
|
||||
resolving = "Resolviendo…",
|
||||
sendingPayment = "Enviando pago…",
|
||||
|
||||
// ── SendScreen — paying ───────────────────────────────────────────────────
|
||||
paymentTakingLong = "Esto está tardando más de lo habitual",
|
||||
paymentTakingLongDetail = "Tu pago sigue en camino. Es posible que sea una factura hold que se liquidará cuando el destinatario esté listo. Recibirás una notificación cuando se complete — puedes salir de esta pantalla con seguridad.",
|
||||
dismissPayment = "Salir",
|
||||
|
||||
// ── SendScreen — payment sent ─────────────────────────────────────────────
|
||||
paymentSent = "¡Pago enviado!",
|
||||
amountSats = { sats -> "$sats sats" },
|
||||
|
||||
@@ -126,6 +126,12 @@ val EuStrings = AppStrings(
|
||||
resolving = "Ebazten…",
|
||||
sendingPayment = "Ordainketa bidaltzen…",
|
||||
|
||||
// ── SendScreen — paying ───────────────────────────────────────────────────
|
||||
paymentTakingLong = "Ohikoa baino gehiago ari da irauten",
|
||||
paymentTakingLongDetail = "Zure ordainketa bidean dago oraindik. Baliteke atxikitako faktura bat izatea, hartzaileak prest dagoenean kitatzekoa. Jakinarazpen bat jasoko duzu burutzen denean — pantaila hau segurtasunez utzi dezakezu.",
|
||||
dismissPayment = "Utzi",
|
||||
|
||||
|
||||
// ── SendScreen — payment sent ─────────────────────────────────────────────
|
||||
paymentSent = "Ordainketa bidalita!",
|
||||
amountSats = { sats -> "$sats sat" },
|
||||
|
||||
@@ -135,6 +135,11 @@ data class AppStrings(
|
||||
val resolving : String,
|
||||
val sendingPayment : String,
|
||||
|
||||
// ── SendScreen — paying ───────────────────────────────────────────────────
|
||||
val paymentTakingLong : String,
|
||||
val paymentTakingLongDetail: String,
|
||||
val dismissPayment : String,
|
||||
|
||||
// ── SendScreen — payment sent ─────────────────────────────────────────────
|
||||
val paymentSent : String,
|
||||
val amountSats : (sats: Long) -> String,
|
||||
|
||||
@@ -6,8 +6,10 @@ import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.CheckCircle
|
||||
import androidx.compose.material.icons.filled.ContentPaste
|
||||
import androidx.compose.material.icons.filled.Nfc
|
||||
import androidx.compose.material.icons.outlined.HourglassTop
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -28,10 +30,13 @@ import com.bitcointxoko.gudariwallet.ui.NfcOfferState
|
||||
import com.bitcointxoko.gudariwallet.ui.SendState
|
||||
import com.bitcointxoko.gudariwallet.ui.WalletViewModel
|
||||
import com.bitcointxoko.gudariwallet.ui.nfc.NfcViewModel
|
||||
import com.bitcointxoko.gudariwallet.ui.receive.AmountDisplay
|
||||
import com.bitcointxoko.gudariwallet.util.SendInputDetector
|
||||
import com.bitcointxoko.gudariwallet.util.feePpm
|
||||
import com.bitcointxoko.gudariwallet.util.fiatLabel
|
||||
import com.bitcointxoko.gudariwallet.util.formatFiat
|
||||
import com.bitcointxoko.gudariwallet.util.satsToFiat
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
@@ -89,25 +94,9 @@ fun SendScreen(
|
||||
text = strings.send, // ← "Send"
|
||||
style = MaterialTheme.typography.headlineSmall
|
||||
)
|
||||
}
|
||||
|
||||
// NFC indicator — only visible in Idle/Error, lights up when offer pending
|
||||
if (sendState is SendState.Idle || sendState is SendState.Error) {
|
||||
FilledTonalIconButton(
|
||||
onClick = { /* passive indicator */ },
|
||||
modifier = Modifier.size(40.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Nfc,
|
||||
contentDescription = strings.tapNfcHint, // ← "Tap NFC device to receive invoice"
|
||||
tint = if (nfcOffer is NfcOfferState.Detected)
|
||||
MaterialTheme.colorScheme.primary
|
||||
else
|
||||
MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Spacer(Modifier.height(16.dp))
|
||||
|
||||
if (sendState !is SendState.PaymentSent) {
|
||||
OutlinedTextField(
|
||||
@@ -206,42 +195,60 @@ fun SendScreen(
|
||||
}
|
||||
|
||||
is SendState.Paying -> {
|
||||
var slowPayment by remember { mutableStateOf(false) }
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
delay(10_000L)
|
||||
slowPayment = true
|
||||
}
|
||||
|
||||
Spacer(Modifier.height(16.dp))
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
if (slowPayment) {
|
||||
// Slow path — replace spinner with explanatory text
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.HourglassTop,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.size(32.dp)
|
||||
)
|
||||
Spacer(Modifier.height(12.dp))
|
||||
Text(
|
||||
text = strings.paymentTakingLong, // "This is taking longer than usual"
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
Spacer(Modifier.height(8.dp))
|
||||
Text(
|
||||
text = strings.paymentTakingLongDetail,
|
||||
// "Your payment is still on its way. This may be a hold invoice
|
||||
// that settles when the recipient is ready. You'll get a
|
||||
// notification when it completes — you can safely leave this screen."
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
Spacer(Modifier.height(20.dp))
|
||||
OutlinedButton(
|
||||
onClick = { vm.resetSendState(); input = "" },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(strings.dismissPayment) // "Dismiss"
|
||||
}
|
||||
} else {
|
||||
// Fast path — normal spinner
|
||||
CircularProgressIndicator()
|
||||
Spacer(Modifier.height(8.dp))
|
||||
Text(strings.sendingPayment) // ← "Sending payment…"
|
||||
Text(strings.sendingPayment) // "Sending payment…"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is SendState.PaymentSent -> {
|
||||
Spacer(Modifier.height(32.dp))
|
||||
Text(
|
||||
text = "✓",
|
||||
style = MaterialTheme.typography.displayLarge,
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
Spacer(Modifier.height(8.dp))
|
||||
Text(
|
||||
text = strings.paymentSent, // ← "Payment sent!"
|
||||
style = MaterialTheme.typography.headlineSmall
|
||||
)
|
||||
Spacer(Modifier.height(4.dp))
|
||||
Text(
|
||||
text = strings.amountSats(state.amountSats), // ← "X sats"
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
val fiatAmount = if (fiatRate != null && fiatCurrency != null) {
|
||||
satsToFiat(state.amountSats, fiatRate)
|
||||
} else null
|
||||
if (fiatAmount != null && fiatCurrency != null) {
|
||||
Text(
|
||||
text = strings.fiatEquivalent( // ← "≈ X.XX EUR"
|
||||
formatFiat(fiatAmount, fiatCurrency)
|
||||
),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
}
|
||||
Spacer(Modifier.height(4.dp))
|
||||
val fiatLabel = fiatLabel(state.amountSats, fiatRate, fiatCurrency)
|
||||
val ppm = if (state.feeSats != null && state.feeSats != 0L) {
|
||||
feePpm(
|
||||
amountMsat = state.amountSats * 1_000L,
|
||||
@@ -256,13 +263,33 @@ fun SendScreen(
|
||||
strings.routingFee(state.feeSats, ppmSuffix) // ← "Routing fee: X sats (Y ppm)"
|
||||
}
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.CheckCircle,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.size(72.dp)
|
||||
)
|
||||
Spacer(Modifier.height(16.dp))
|
||||
Text(
|
||||
text = strings.paymentSent, // ← "Payment sent!"
|
||||
style = MaterialTheme.typography.headlineSmall
|
||||
)
|
||||
Spacer(Modifier.height(8.dp))
|
||||
AmountDisplay(amountSats = state.amountSats, fiatLabel = fiatLabel)
|
||||
Spacer(Modifier.height(4.dp))
|
||||
Text(
|
||||
text = feeText,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
Spacer(Modifier.height(32.dp))
|
||||
OutlinedButton(
|
||||
Button(
|
||||
onClick = {
|
||||
val record = state.pendingRecord
|
||||
if (record != null) {
|
||||
@@ -272,12 +299,13 @@ fun SendScreen(
|
||||
enabled = state.pendingRecord != null,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) { Text(strings.details) } // ← "Details"
|
||||
Spacer(Modifier.height(8.dp))
|
||||
Button(
|
||||
Spacer(Modifier.height(32.dp))
|
||||
TextButton(
|
||||
onClick = { vm.resetSendState(); input = "" },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) { Text(strings.sendAnother) } // ← "Send Another"
|
||||
}
|
||||
}
|
||||
|
||||
is SendState.Error -> {
|
||||
Spacer(Modifier.height(8.dp))
|
||||
|
||||
Reference in New Issue
Block a user