fix: spinner when loading details from successful send
This commit is contained in:
@@ -91,7 +91,8 @@ sealed class SendState {
|
||||
data class PaymentSent(
|
||||
val amountSats : Long,
|
||||
val feeSats : Long? = null,
|
||||
val paymentHash: String
|
||||
val paymentHash: String,
|
||||
val pendingRecord: PaymentRecord? = null
|
||||
) : SendState()
|
||||
data class Error(val message: String) : SendState()
|
||||
}
|
||||
|
||||
@@ -297,8 +297,8 @@ fun WalletScreen(
|
||||
SendScreen(
|
||||
vm = vm,
|
||||
nfcVm = nfcVm,
|
||||
onViewDetails = { checkingId ->
|
||||
historyVm.refresh()
|
||||
onViewDetails = { checkingId, record ->
|
||||
historyVm.primePayment(record)
|
||||
navController.navigate("payment_detail/$checkingId") {
|
||||
launchSingleTop = true
|
||||
}
|
||||
|
||||
@@ -39,6 +39,10 @@ class HistoryViewModel(
|
||||
scope = viewModelScope,
|
||||
onNewPayments = { payments -> enricher.enrich(payments) }
|
||||
)
|
||||
// ── Optimistic insert (called after a successful send) ─────────────────────
|
||||
fun primePayment(record: PaymentRecord) {
|
||||
syncManager.primePayment(record)
|
||||
}
|
||||
private val enricher: PaymentEnricher = PaymentEnricher(
|
||||
repo = repo,
|
||||
aliasRepo = aliasRepo,
|
||||
|
||||
@@ -192,4 +192,20 @@ class PaymentSyncManager(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// ── Optimistic insert ──────────────────────────────────────────────────────
|
||||
|
||||
fun primePayment(record: PaymentRecord) {
|
||||
val current = mutableState.value
|
||||
if (current is HistoryState.Success) {
|
||||
val already = current.payments.any { it.checkingId == record.checkingId }
|
||||
if (!already) {
|
||||
mutableState.value = current.copy(
|
||||
payments = listOf(record) + current.payments
|
||||
)
|
||||
}
|
||||
}
|
||||
// If state is Loading/Error (e.g. first launch), the next syncNewPayments()
|
||||
// will fetch the real record from the API — no action needed here.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.bitcointxoko.gudariwallet.api.PaymentRecord
|
||||
import com.bitcointxoko.gudariwallet.ui.BalanceState
|
||||
import com.bitcointxoko.gudariwallet.ui.NfcOfferState
|
||||
import com.bitcointxoko.gudariwallet.ui.SendState
|
||||
@@ -36,7 +37,7 @@ import kotlinx.coroutines.launch
|
||||
fun SendScreen(
|
||||
vm : WalletViewModel,
|
||||
nfcVm : NfcViewModel,
|
||||
onViewDetails: (paymentHash: String) -> Unit = {}
|
||||
onViewDetails: (paymentHash: String, record: PaymentRecord) -> Unit = { _, _ -> }
|
||||
) {
|
||||
val sendState : SendState by vm.sendState.collectAsStateWithLifecycle()
|
||||
var input by remember { mutableStateOf("") }
|
||||
@@ -244,7 +245,13 @@ fun SendScreen(
|
||||
)
|
||||
Spacer(Modifier.height(32.dp))
|
||||
OutlinedButton(
|
||||
onClick = { onViewDetails(state.paymentHash) },
|
||||
onClick = {
|
||||
val record = state.pendingRecord
|
||||
if (record != null) {
|
||||
onViewDetails(state.paymentHash, record)
|
||||
}
|
||||
},
|
||||
enabled = state.pendingRecord != null,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) { Text("Details") }
|
||||
Spacer(Modifier.height(8.dp))
|
||||
|
||||
@@ -5,6 +5,7 @@ import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.bitcointxoko.gudariwallet.api.LnurlScanResponse
|
||||
import com.bitcointxoko.gudariwallet.api.PaymentRecord
|
||||
import com.bitcointxoko.gudariwallet.api.RouteHintHop
|
||||
import com.bitcointxoko.gudariwallet.data.LnurlCacheRepository
|
||||
import com.bitcointxoko.gudariwallet.data.NodeAliasRepository
|
||||
@@ -65,6 +66,7 @@ class SendViewModel(
|
||||
|
||||
fun payBolt11(bolt11: String) {
|
||||
viewModelScope.launch {
|
||||
val decoded = _sendState.value as? SendState.Bolt11Decoded
|
||||
val amountSats = (_sendState.value as? SendState.Bolt11Decoded)?.amountSats ?: 0L
|
||||
_sendState.value = SendState.Paying
|
||||
runCatching { repo.payBolt11(bolt11) }
|
||||
@@ -73,9 +75,18 @@ class SendViewModel(
|
||||
repo.getPaymentDetail(response.paymentHash).details?.feeSat
|
||||
}.getOrNull()
|
||||
_sendState.value = SendState.PaymentSent(
|
||||
amountSats = amountSats,
|
||||
feeSats = feeSats,
|
||||
paymentHash = response.paymentHash
|
||||
amountSats = amountSats,
|
||||
feeSats = feeSats,
|
||||
paymentHash = response.paymentHash,
|
||||
pendingRecord = buildPendingRecord(
|
||||
paymentHash = response.paymentHash,
|
||||
amountSats = amountSats,
|
||||
feeSats = feeSats,
|
||||
bolt11 = decoded?.bolt11,
|
||||
memo = decoded?.memo,
|
||||
pubkey = decoded?.payee,
|
||||
alias = decoded?.nodeAlias
|
||||
)
|
||||
)
|
||||
balanceVm.refreshBalance()
|
||||
}
|
||||
@@ -230,9 +241,18 @@ class SendViewModel(
|
||||
repo.getPaymentDetail(paymentHash).details?.feeSat
|
||||
}.getOrNull()
|
||||
_sendState.value = SendState.PaymentSent(
|
||||
amountSats = state.amountSats,
|
||||
feeSats = feeSats,
|
||||
paymentHash = paymentHash
|
||||
amountSats = state.amountSats,
|
||||
feeSats = feeSats,
|
||||
paymentHash = paymentHash,
|
||||
pendingRecord = buildPendingRecord(
|
||||
paymentHash = paymentHash,
|
||||
amountSats = state.amountSats,
|
||||
feeSats = feeSats,
|
||||
bolt11 = state.bolt11,
|
||||
memo = state.memo,
|
||||
pubkey = state.payee,
|
||||
alias = state.nodeAlias
|
||||
)
|
||||
)
|
||||
balanceVm.refreshBalance()
|
||||
return@launch
|
||||
@@ -454,14 +474,31 @@ class SendViewModel(
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun recordPaymentSuccess(paymentHash: String, amountMsat: Long) {
|
||||
private suspend fun recordPaymentSuccess(
|
||||
paymentHash: String,
|
||||
amountMsat: Long,
|
||||
bolt11 : String? = null,
|
||||
memo : String? = null,
|
||||
pubkey : String? = null,
|
||||
alias : String? = null
|
||||
) {
|
||||
val feeSats = runCatching {
|
||||
repo.getPaymentDetail(paymentHash).details?.feeSat
|
||||
}.getOrNull()
|
||||
val amountSats = amountMsat / WalletConstants.MSAT_PER_SAT
|
||||
_sendState.value = SendState.PaymentSent(
|
||||
amountSats = amountMsat / WalletConstants.MSAT_PER_SAT,
|
||||
feeSats = feeSats,
|
||||
paymentHash = paymentHash
|
||||
amountSats = amountSats,
|
||||
feeSats = feeSats,
|
||||
paymentHash = paymentHash,
|
||||
pendingRecord = buildPendingRecord(
|
||||
paymentHash = paymentHash,
|
||||
amountSats = amountSats,
|
||||
feeSats = feeSats,
|
||||
bolt11 = bolt11,
|
||||
memo = memo,
|
||||
pubkey = pubkey,
|
||||
alias = alias
|
||||
)
|
||||
)
|
||||
balanceVm.refreshBalance()
|
||||
}
|
||||
@@ -551,4 +588,28 @@ class SendViewModel(
|
||||
key to value
|
||||
}.toMap()
|
||||
}
|
||||
|
||||
private fun buildPendingRecord(
|
||||
paymentHash: String,
|
||||
amountSats : Long,
|
||||
feeSats : Long?,
|
||||
bolt11 : String?,
|
||||
memo : String?,
|
||||
pubkey : String?,
|
||||
alias : String?
|
||||
): PaymentRecord = PaymentRecord(
|
||||
paymentHash = paymentHash,
|
||||
checkingId = paymentHash,
|
||||
amountMsat = -(amountSats * 1_000L), // negative = outgoing
|
||||
feeMsat = (feeSats ?: 0L) * 1_000L,
|
||||
memo = memo,
|
||||
time = (System.currentTimeMillis() / 1_000L).toString(),
|
||||
status = "complete",
|
||||
bolt11 = bolt11,
|
||||
pending = false,
|
||||
preimage = null,
|
||||
extra = null,
|
||||
pubkey = pubkey,
|
||||
alias = alias
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user