refactor
This commit is contained in:
Generated
+1
@@ -6,6 +6,7 @@
|
|||||||
<w>Tink</w>
|
<w>Tink</w>
|
||||||
<w>amboss</w>
|
<w>amboss</w>
|
||||||
<w>hkdf</w>
|
<w>hkdf</w>
|
||||||
|
<w>inflight</w>
|
||||||
<w>lnbc</w>
|
<w>lnbc</w>
|
||||||
<w>lnbits</w>
|
<w>lnbits</w>
|
||||||
<w>lnurlp</w>
|
<w>lnurlp</w>
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.bitcointxoko.gudariwallet.ui
|
|||||||
|
|
||||||
import android.content.ClipData
|
import android.content.ClipData
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.util.Log
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
@@ -32,7 +31,7 @@ import androidx.core.net.toUri
|
|||||||
import com.bitcointxoko.gudariwallet.api.PaymentRecord
|
import com.bitcointxoko.gudariwallet.api.PaymentRecord
|
||||||
import com.bitcointxoko.gudariwallet.ui.theme.semanticColors
|
import com.bitcointxoko.gudariwallet.ui.theme.semanticColors
|
||||||
import com.bitcointxoko.gudariwallet.util.feePpm
|
import com.bitcointxoko.gudariwallet.util.feePpm
|
||||||
import com.bitcointxoko.gudariwallet.util.formatFiatForSats // ← new import
|
import com.bitcointxoko.gudariwallet.util.formatFiatForSats
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
// ── List screen ──────────────────────────────────────────────────────────────
|
// ── List screen ──────────────────────────────────────────────────────────────
|
||||||
@@ -156,6 +155,21 @@ fun HistoryScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Payment color helpers ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private fun isPendingStatus(status: String): Boolean =
|
||||||
|
status.lowercase() in setOf("pending", "in_flight", "inflight")
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun paymentAmountColor(status: String, isOutgoing: Boolean): Color {
|
||||||
|
val semantic = semanticColors()
|
||||||
|
return when {
|
||||||
|
isPendingStatus(status) -> MaterialTheme.colorScheme.onSurfaceVariant // muted
|
||||||
|
isOutgoing -> MaterialTheme.colorScheme.onSurface // neutral
|
||||||
|
else -> semantic.success // green
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ── Single row ───────────────────────────────────────────────────────────────
|
// ── Single row ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -168,16 +182,8 @@ private fun PaymentRow(
|
|||||||
val semantic = semanticColors()
|
val semantic = semanticColors()
|
||||||
|
|
||||||
// ── Pending detection ────────────────────────────────────────────────────
|
// ── Pending detection ────────────────────────────────────────────────────
|
||||||
val isPending = payment.status.lowercase() in setOf("pending", "in_flight", "inflight")
|
val isPending = isPendingStatus(payment.status)
|
||||||
|
val amountColor = paymentAmountColor(payment.status, payment.isOutgoing)
|
||||||
// bitcoin.design: green for received, neutral for sent, muted for pending.
|
|
||||||
val amountColor = when {
|
|
||||||
isPending -> MaterialTheme.colorScheme.onSurfaceVariant
|
|
||||||
payment.isOutgoing -> MaterialTheme.colorScheme.onSurface
|
|
||||||
else -> semantic.success
|
|
||||||
}
|
|
||||||
|
|
||||||
val amountPrefix = if (payment.isOutgoing) "−" else "+"
|
|
||||||
val icon = if (payment.isOutgoing) Icons.Default.ArrowUpward
|
val icon = if (payment.isOutgoing) Icons.Default.ArrowUpward
|
||||||
else Icons.Default.ArrowDownward
|
else Icons.Default.ArrowDownward
|
||||||
|
|
||||||
@@ -235,29 +241,15 @@ private fun PaymentRow(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Spacer(Modifier.width(12.dp))
|
Spacer(Modifier.width(12.dp))
|
||||||
|
AmountWithFiatColumn(
|
||||||
// Right: sats (primary) + fiat (secondary) — right-aligned
|
amountSat = payment.amountSat,
|
||||||
Column(horizontalAlignment = Alignment.End) {
|
isOutgoing = payment.isOutgoing,
|
||||||
Text(
|
amountColor = amountColor,
|
||||||
text = "$amountPrefix${payment.amountSat} sats",
|
fiatLine = fiatLine
|
||||||
style = MaterialTheme.typography.bodyMedium.copy(
|
)
|
||||||
fontFamily = FontFamily.Monospace
|
|
||||||
),
|
|
||||||
color = amountColor
|
|
||||||
)
|
|
||||||
if (fiatLine != null) {
|
|
||||||
Spacer(Modifier.height(1.dp))
|
|
||||||
Text(
|
|
||||||
text = fiatLine,
|
|
||||||
style = MaterialTheme.typography.bodySmall,
|
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.75f)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ── Detail screen ────────────────────────────────────────────────────────────
|
// ── Detail screen ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@@ -354,13 +346,8 @@ private fun PaymentDetailContent(
|
|||||||
fiatSatsPerUnit : Double?, // ← new
|
fiatSatsPerUnit : Double?, // ← new
|
||||||
modifier : Modifier = Modifier
|
modifier : Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val isPending = payment.status.lowercase() in setOf("pending", "in_flight", "inflight")
|
val isPending = isPendingStatus(payment.status)
|
||||||
val semantic = semanticColors()
|
val amountColor = paymentAmountColor(payment.status, payment.isOutgoing)
|
||||||
val amountColor = when {
|
|
||||||
isPending -> MaterialTheme.colorScheme.onSurfaceVariant // muted
|
|
||||||
payment.isOutgoing -> MaterialTheme.colorScheme.onSurface // neutral
|
|
||||||
else -> semantic.success // green
|
|
||||||
}
|
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val clipboard = LocalClipboard.current
|
val clipboard = LocalClipboard.current
|
||||||
@@ -407,24 +394,14 @@ private fun PaymentDetailContent(
|
|||||||
modifier = Modifier.size(36.dp)
|
modifier = Modifier.size(36.dp)
|
||||||
)
|
)
|
||||||
Spacer(Modifier.height(8.dp))
|
Spacer(Modifier.height(8.dp))
|
||||||
|
AmountWithFiatColumn(
|
||||||
// Primary: sats
|
amountSat = payment.amountSat,
|
||||||
Text(
|
isOutgoing = payment.isOutgoing,
|
||||||
text = "${if (payment.isOutgoing) "−" else "+"}${payment.amountSat} sats",
|
amountColor = amountColor,
|
||||||
style = MaterialTheme.typography.headlineLarge,
|
fiatLine = heroFiat,
|
||||||
color = amountColor
|
style = MaterialTheme.typography.headlineLarge,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
)
|
)
|
||||||
|
|
||||||
// Secondary: fiat equivalent
|
|
||||||
if (heroFiat != null) {
|
|
||||||
Spacer(Modifier.height(4.dp))
|
|
||||||
Text(
|
|
||||||
text = "≈ $heroFiat",
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.75f)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fee line (with fiat if available)
|
// Fee line (with fiat if available)
|
||||||
if (payment.feeSat > 0) {
|
if (payment.feeSat > 0) {
|
||||||
val ppm = feePpm(
|
val ppm = feePpm(
|
||||||
@@ -433,7 +410,7 @@ private fun PaymentDetailContent(
|
|||||||
)
|
)
|
||||||
val feeLabel = buildString {
|
val feeLabel = buildString {
|
||||||
append("Fee: ${payment.feeSat} sats")
|
append("Fee: ${payment.feeSat} sats")
|
||||||
if (feeFiat != null) append(" (≈ $feeFiat)")
|
if (feeFiat != null) append(" ($feeFiat)")
|
||||||
if (ppm != null) append(" · $ppm ppm")
|
if (ppm != null) append(" · $ppm ppm")
|
||||||
}
|
}
|
||||||
Spacer(Modifier.height(4.dp))
|
Spacer(Modifier.height(4.dp))
|
||||||
@@ -520,13 +497,7 @@ private fun PaymentDetailContent(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
if (!payment.bolt11.isNullOrBlank()) {
|
||||||
}
|
|
||||||
|
|
||||||
// ── BOLT11 invoice ───────────────────────────────────────────────────
|
|
||||||
if (!payment.bolt11.isNullOrBlank()) {
|
|
||||||
item {
|
|
||||||
DetailSection(title = "Invoice") {
|
|
||||||
DetailRow(
|
DetailRow(
|
||||||
label = "BOLT11",
|
label = "BOLT11",
|
||||||
value = payment.bolt11,
|
value = payment.bolt11,
|
||||||
@@ -542,8 +513,6 @@ private fun PaymentDetailContent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── Reusable section wrapper ─────────────────────────────────────────────────
|
// ── Reusable section wrapper ─────────────────────────────────────────────────
|
||||||
// (unchanged — kept for completeness)
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun DetailSection(
|
private fun DetailSection(
|
||||||
title : String,
|
title : String,
|
||||||
@@ -563,8 +532,6 @@ private fun DetailSection(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── Single label/value row ───────────────────────────────────────────────────
|
// ── Single label/value row ───────────────────────────────────────────────────
|
||||||
// (unchanged)
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun DetailRow(
|
private fun DetailRow(
|
||||||
label : String,
|
label : String,
|
||||||
@@ -625,8 +592,6 @@ private fun DetailRow(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── Status chip ──────────────────────────────────────────────────────────────
|
// ── Status chip ──────────────────────────────────────────────────────────────
|
||||||
// (unchanged)
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun StatusChip(status: String) {
|
private fun StatusChip(status: String) {
|
||||||
val semantic = semanticColors()
|
val semantic = semanticColors()
|
||||||
@@ -675,3 +640,30 @@ private fun formatTimestamp(time: String): String {
|
|||||||
.format(odt)
|
.format(odt)
|
||||||
}.getOrDefault(time)
|
}.getOrDefault(time)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun AmountWithFiatColumn(
|
||||||
|
amountSat : Long,
|
||||||
|
isOutgoing : Boolean,
|
||||||
|
amountColor : Color,
|
||||||
|
fiatLine : String?,
|
||||||
|
style : androidx.compose.ui.text.TextStyle = MaterialTheme.typography.bodyMedium,
|
||||||
|
horizontalAlignment: Alignment.Horizontal = Alignment.End
|
||||||
|
) {
|
||||||
|
val prefix = if (isOutgoing) "−" else "+"
|
||||||
|
Column(horizontalAlignment = horizontalAlignment) {
|
||||||
|
Text(
|
||||||
|
text = "$prefix$amountSat sats",
|
||||||
|
style = style.copy(fontFamily = FontFamily.Monospace),
|
||||||
|
color = amountColor
|
||||||
|
)
|
||||||
|
if (fiatLine != null) {
|
||||||
|
Spacer(Modifier.height(if (horizontalAlignment == Alignment.CenterHorizontally) 4.dp else 1.dp))
|
||||||
|
Text(
|
||||||
|
text = fiatLine,
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.75f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package com.bitcointxoko.gudariwallet.ui
|
|||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.foundation.combinedClickable
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
|
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
@@ -10,14 +11,11 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.animation.core.animateFloatAsState
|
|
||||||
import androidx.compose.animation.core.tween
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Visibility
|
import androidx.compose.material.icons.filled.Visibility
|
||||||
import androidx.compose.material.icons.filled.VisibilityOff
|
import androidx.compose.material.icons.filled.VisibilityOff
|
||||||
import androidx.compose.ui.draw.alpha
|
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.material.icons.filled.ArrowDropDown
|
import androidx.compose.material.icons.filled.ArrowDropDown
|
||||||
@@ -29,7 +27,7 @@ import androidx.compose.foundation.text.KeyboardOptions
|
|||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.platform.LocalFocusManager
|
import androidx.compose.ui.platform.LocalFocusManager
|
||||||
import com.bitcointxoko.gudariwallet.util.formatFiat
|
import com.bitcointxoko.gudariwallet.util.formatFiat
|
||||||
import kotlinx.coroutines.delay
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -43,18 +41,6 @@ fun HomeTab(
|
|||||||
|
|
||||||
val balanceHidden by vm.balanceHidden.collectAsState()
|
val balanceHidden by vm.balanceHidden.collectAsState()
|
||||||
|
|
||||||
var eyeVisible by remember { mutableStateOf(false) }
|
|
||||||
LaunchedEffect(balanceHidden) {
|
|
||||||
eyeVisible = true
|
|
||||||
delay(1_500)
|
|
||||||
eyeVisible = false
|
|
||||||
}
|
|
||||||
val eyeAlpha by animateFloatAsState(
|
|
||||||
targetValue = if (eyeVisible) 1f else 0f,
|
|
||||||
animationSpec = tween(durationMillis = 400),
|
|
||||||
label = "eyeAlpha"
|
|
||||||
)
|
|
||||||
|
|
||||||
val isRefreshing = balanceState is BalanceState.Loading
|
val isRefreshing = balanceState is BalanceState.Loading
|
||||||
|| (balanceState as? BalanceState.Success)?.isRefreshing == true
|
|| (balanceState as? BalanceState.Success)?.isRefreshing == true
|
||||||
|
|
||||||
@@ -96,9 +82,7 @@ fun HomeTab(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically
|
||||||
horizontalArrangement = Arrangement.Center,
|
|
||||||
modifier = Modifier.fillMaxWidth()
|
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = if (balanceHidden)
|
imageVector = if (balanceHidden)
|
||||||
@@ -109,14 +93,15 @@ fun HomeTab(
|
|||||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(20.dp)
|
.size(20.dp)
|
||||||
.alpha(eyeAlpha)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(Modifier.width(8.dp))
|
Spacer(Modifier.width(8.dp))
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = if (balanceHidden) "••••••" else "${s.sats}",
|
text = if (balanceHidden) "••••••" else formatSats(s.sats),
|
||||||
style = MaterialTheme.typography.displayLarge,
|
style = MaterialTheme.typography.displayLarge.copy(
|
||||||
|
fontFamily = FontFamily.Monospace
|
||||||
|
),
|
||||||
color = if (balanceHidden)
|
color = if (balanceHidden)
|
||||||
MaterialTheme.colorScheme.onSurface.copy(alpha = 0.35f)
|
MaterialTheme.colorScheme.onSurface.copy(alpha = 0.35f)
|
||||||
else
|
else
|
||||||
@@ -124,74 +109,93 @@ fun HomeTab(
|
|||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
softWrap = false,
|
softWrap = false,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f, fill = false)
|
.widthIn(max = 280.dp)
|
||||||
.clickable(
|
.combinedClickable(
|
||||||
onClick = { vm.toggleBalanceVisibility() },
|
onClick = { if (!balanceHidden) vm.toggleBalanceVisibility() },
|
||||||
onClickLabel = if (balanceHidden) "Reveal balance" else "Hide balance",
|
onClickLabel = if (balanceHidden) null else "Hide balance",
|
||||||
|
onLongClick = { if (balanceHidden) vm.toggleBalanceVisibility() },
|
||||||
|
onLongClickLabel = if (balanceHidden) "Reveal balance" else null,
|
||||||
indication = null,
|
indication = null,
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(Modifier.width(8.dp))
|
Spacer(Modifier.width(8.dp))
|
||||||
Spacer(Modifier.size(20.dp))
|
Text(
|
||||||
|
text = "sats",
|
||||||
|
style = MaterialTheme.typography.titleMedium.copy(
|
||||||
|
fontFamily = FontFamily.Monospace
|
||||||
|
),
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
|
Spacer(Modifier.width(8.dp))
|
||||||
}
|
}
|
||||||
Text(
|
|
||||||
text = "sats",
|
|
||||||
style = MaterialTheme.typography.titleMedium,
|
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
|
||||||
)
|
|
||||||
Spacer(Modifier.height(2.dp))
|
Spacer(Modifier.height(2.dp))
|
||||||
Row(
|
val currency = selectedCurrency
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
if (currency != null) {
|
||||||
horizontalArrangement = Arrangement.Center
|
// ── Fiat amount + tappable currency code ──────────────────────────
|
||||||
) {
|
|
||||||
if (s.fiatAmount != null && s.fiatCurrency != null) {
|
|
||||||
Text(
|
|
||||||
text = if (balanceHidden) "≈ ••••"
|
|
||||||
else "≈ ${formatFiat(s.fiatAmount, s.fiatCurrency)}",
|
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
|
||||||
color = if (balanceHidden)
|
|
||||||
MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.35f)
|
|
||||||
else
|
|
||||||
MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.75f),
|
|
||||||
maxLines = 1,
|
|
||||||
softWrap = false
|
|
||||||
)
|
|
||||||
Spacer(Modifier.width(2.dp))
|
|
||||||
}
|
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
modifier = Modifier
|
horizontalArrangement = Arrangement.Center
|
||||||
.clickable(
|
|
||||||
onClick = { showCurrencyPicker = true },
|
|
||||||
onClickLabel = "Change currency",
|
|
||||||
indication = null,
|
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
|
||||||
)
|
|
||||||
.padding(start = 0.dp, end = 4.dp, top = 4.dp, bottom = 4.dp)
|
|
||||||
) {
|
) {
|
||||||
Text(
|
if (s.fiatAmount != null && s.fiatCurrency != null) {
|
||||||
text = selectedCurrency ?: "—",
|
Text(
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
text = if (balanceHidden) "••••"
|
||||||
color = if (selectedCurrency != null)
|
else formatFiat(s.fiatAmount, s.fiatCurrency),
|
||||||
MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.75f)
|
style = MaterialTheme.typography.bodyMedium.copy(
|
||||||
else
|
fontFamily = FontFamily.Monospace
|
||||||
MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.4f)
|
),
|
||||||
)
|
color = if (balanceHidden)
|
||||||
// Triangle only shown when null — signals "tap to set a currency"
|
MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.35f)
|
||||||
if (selectedCurrency == null) {
|
else
|
||||||
|
MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.75f),
|
||||||
|
maxLines = 1,
|
||||||
|
softWrap = false
|
||||||
|
)
|
||||||
|
Spacer(Modifier.width(4.dp))
|
||||||
|
}
|
||||||
|
// Currency code — always shown when a currency is selected, tappable to change
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier
|
||||||
|
.clickable(
|
||||||
|
onClick = { showCurrencyPicker = true },
|
||||||
|
onClickLabel = "Change currency",
|
||||||
|
indication = null,
|
||||||
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
|
)
|
||||||
|
.padding(horizontal = 4.dp, vertical = 4.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = currency,
|
||||||
|
style = MaterialTheme.typography.bodyMedium.copy(
|
||||||
|
fontFamily = FontFamily.Monospace
|
||||||
|
),
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.75f)
|
||||||
|
)
|
||||||
Spacer(Modifier.width(2.dp))
|
Spacer(Modifier.width(2.dp))
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Filled.ArrowDropDown,
|
imageVector = Icons.Filled.ArrowDropDown,
|
||||||
contentDescription = "Change currency",
|
contentDescription = "Change currency",
|
||||||
tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.4f),
|
tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f),
|
||||||
modifier = Modifier.size(14.dp)
|
modifier = Modifier.size(14.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// ── No currency selected — ghost prompt ───────────────────────────
|
||||||
|
TextButton(
|
||||||
|
onClick = { showCurrencyPicker = true },
|
||||||
|
contentPadding = PaddingValues(horizontal = 8.dp, vertical = 2.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "+ Show fiat",
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.45f)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Spacer(Modifier.height(8.dp))
|
Spacer(Modifier.height(8.dp))
|
||||||
|
|
||||||
if (!s.isRefreshing) {
|
if (!s.isRefreshing) {
|
||||||
@@ -231,8 +235,10 @@ fun HomeTab(
|
|||||||
is BalanceState.Error -> {
|
is BalanceState.Error -> {
|
||||||
if (s.staleSats != null) {
|
if (s.staleSats != null) {
|
||||||
Text(
|
Text(
|
||||||
text = if (balanceHidden) "••••••" else "${s.staleSats}",
|
text = if (balanceHidden) "••••••" else formatSats(s.staleSats),
|
||||||
style = MaterialTheme.typography.displayLarge,
|
style = MaterialTheme.typography.displayLarge.copy(
|
||||||
|
fontFamily = FontFamily.Monospace
|
||||||
|
),
|
||||||
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.4f)
|
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.4f)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
@@ -264,6 +270,9 @@ fun HomeTab(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun formatSats(sats: Long): String =
|
||||||
|
"%,d".format(sats).replace(',', ' ')
|
||||||
|
|
||||||
private fun formatLastUpdated(epochMs: Long): String {
|
private fun formatLastUpdated(epochMs: Long): String {
|
||||||
val ageMs = System.currentTimeMillis() - epochMs
|
val ageMs = System.currentTimeMillis() - epochMs
|
||||||
return when {
|
return when {
|
||||||
|
|||||||
Reference in New Issue
Block a user