From cb9961608c15e2ef80c4708cb95c8c792a0640f7 Mon Sep 17 00:00:00 2001 From: rasputin Date: Wed, 3 Jun 2026 22:36:27 +0200 Subject: [PATCH] fix: payment detail not loading on filter or search when not in memory --- .../gudariwallet/ui/WalletScreen.kt | 17 +++++++------ .../gudariwallet/ui/WalletViewModel.kt | 1 - .../gudariwallet/ui/history/HistoryScreen.kt | 10 -------- .../ui/history/HistoryViewModel.kt | 24 +++++++++---------- .../ui/history/PaymentDetailDelegate.kt | 3 +-- .../gudariwallet/ui/history/PaymentRow.kt | 3 +-- 6 files changed, 21 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/WalletScreen.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/WalletScreen.kt index b62b51e..e42da35 100644 --- a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/WalletScreen.kt +++ b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/WalletScreen.kt @@ -72,7 +72,7 @@ sealed class TabItem(val route: String, val label: String, val icon: ImageVector private const val ROUTE_HOME = "home" private const val ROUTE_SCANNER = "scanner" private const val ROUTE_HISTORY = "history" -private const val ROUTE_PAYMENT_DETAIL = "payment_detail/{paymentHash}" +private const val ROUTE_PAYMENT_DETAIL = "payment_detail/{checkingId}" @Composable fun WalletScreen( @@ -317,7 +317,7 @@ fun WalletScreen( navController.popBackStack(ROUTE_HOME, inclusive = false) }, onPaymentClick = { payment -> - navController.navigate("payment_detail/${payment.paymentHash}") + navController.navigate("payment_detail/${payment.checkingId}") } ) } @@ -325,13 +325,12 @@ fun WalletScreen( // Payment detail — back → history (natural back stack) composable( route = ROUTE_PAYMENT_DETAIL, - arguments = listOf(navArgument("paymentHash") { type = NavType.StringType }) + arguments = listOf(navArgument("checkingId") { type = NavType.StringType }) ) { backStackEntry -> - val paymentHash = backStackEntry.arguments?.getString("paymentHash") ?: "" - val historyState by historyVm.state.collectAsState() - val payment = (historyState as? HistoryState.Success) - ?.payments - ?.firstOrNull { it.paymentHash == paymentHash } + val checkingId = backStackEntry.arguments?.getString("checkingId") ?: "" + // val historyState by historyVm.state.collectAsState() + val historyState by historyVm.filteredState.collectAsState() + val payment = historyVm.findPayment(checkingId) if (payment != null) { PaymentDetailScreen( @@ -340,7 +339,7 @@ fun WalletScreen( onBack = { navController.popBackStack() } ) } else { - LaunchedEffect(paymentHash) { historyVm.refresh() } + LaunchedEffect(checkingId) { historyVm.refresh() } Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/WalletViewModel.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/WalletViewModel.kt index 6d8c2f4..9013018 100644 --- a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/WalletViewModel.kt +++ b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/WalletViewModel.kt @@ -7,7 +7,6 @@ import com.bitcointxoko.gudariwallet.api.LnurlScanResponse import com.bitcointxoko.gudariwallet.data.NodeAliasRepository import com.bitcointxoko.gudariwallet.data.PaymentCacheRepository import com.bitcointxoko.gudariwallet.data.WalletRepository -import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/history/HistoryScreen.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/history/HistoryScreen.kt index bf7dde2..0b28a0a 100644 --- a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/history/HistoryScreen.kt +++ b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/history/HistoryScreen.kt @@ -57,17 +57,10 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalClipboard import androidx.compose.ui.unit.dp import com.bitcointxoko.gudariwallet.api.PaymentRecord -import com.bitcointxoko.gudariwallet.ui.history.DatePreset -import com.bitcointxoko.gudariwallet.ui.history.DirectionFilter import com.bitcointxoko.gudariwallet.ui.HistoryState -import com.bitcointxoko.gudariwallet.ui.history.HistoryViewModel -import com.bitcointxoko.gudariwallet.ui.history.PaymentFilter -import com.bitcointxoko.gudariwallet.ui.history.StatusFilter -import com.bitcointxoko.gudariwallet.ui.history.isActive import kotlinx.coroutines.launch // ── List screen ────────────────────────────────────────────────────────────── - @OptIn(ExperimentalMaterial3Api::class) @Composable fun HistoryScreen( @@ -265,7 +258,6 @@ fun HistoryScreen( } } } - // ── Sheets (outside Scaffold so they overlay correctly) ────────────────── if (filterSheetVisible) { FilterBottomSheet( @@ -292,7 +284,6 @@ fun HistoryScreen( } // ── Search bar ─────────────────────────────────────────────────────────────── - @Composable private fun SearchBar( query : String, @@ -357,7 +348,6 @@ private fun SearchBar( } // ── Active filter chips ────────────────────────────────────────────────────── - @OptIn(ExperimentalMaterial3Api::class) @Composable private fun ActiveFilterChips( diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/history/HistoryViewModel.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/history/HistoryViewModel.kt index 7063c28..931a15a 100644 --- a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/history/HistoryViewModel.kt +++ b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/history/HistoryViewModel.kt @@ -22,6 +22,8 @@ import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +private const val TAG = "HistoryViewModel" + @OptIn(FlowPreview::class) class HistoryViewModel( private val repo : WalletRepository, @@ -30,7 +32,6 @@ class HistoryViewModel( val fiatCurrency : StateFlow, val fiatSatsPerUnit : StateFlow ) : ViewModel() { - // ── Sync manager (owns _state, currentOffset, loadJob, sync loop) ───────── private val syncManager: PaymentSyncManager = PaymentSyncManager( repo = repo, @@ -38,7 +39,6 @@ class HistoryViewModel( scope = viewModelScope, onNewPayments = { payments -> enricher.enrich(payments) } ) - private val enricher: PaymentEnricher = PaymentEnricher( repo = repo, aliasRepo = aliasRepo, @@ -48,9 +48,7 @@ class HistoryViewModel( syncManager.updateEnrichedPayment(paymentHash, pubkey, alias) } ) - val state: StateFlow = syncManager.state - fun refresh() = syncManager.refresh() fun loadMore() = syncManager.loadMore( filteredCanLoadMore = { (filteredState.value as? HistoryState.Success)?.canLoadMore == true } @@ -63,10 +61,8 @@ class HistoryViewModel( scope = viewModelScope ) val detailState: StateFlow = detailDelegate.state - fun loadDetail(checkingId: String, record: PaymentRecord? = null) = detailDelegate.load(checkingId, record) - fun clearDetail() = detailDelegate.clear() // ── Filter state ────────────────────────────────────────────────────────── @@ -101,11 +97,18 @@ class HistoryViewModel( val (min, max) = preset.toEpochSecondRange() // ← delegate to PaymentFilter.kt setDateFilter(min, max, preset) } - fun clearDateFilter() { _filter.update { it.copy(minCreatedAt = null, maxCreatedAt = null, datePreset = null) } } + fun findPayment(checkingId: String): PaymentRecord? { + val fromFiltered = (filteredState.value as? HistoryState.Success) + ?.payments?.firstOrNull { it.checkingId == checkingId } + if (fromFiltered != null) return fromFiltered + return (state.value as? HistoryState.Success) + ?.payments?.firstOrNull { it.checkingId == checkingId } + } + // ── Room-backed query results ────────────────────────────────────────────── private val _roomResults = MutableStateFlow?>(null) @@ -165,7 +168,6 @@ class HistoryViewModel( } } } - viewModelScope.launch { WalletNotificationService.paymentEvents.collect { event -> Log.d(TAG, "PAYMENTS [WS EVENT ] incoming event ${event.paymentHash} — refreshing list") @@ -173,10 +175,6 @@ class HistoryViewModel( } } } - - companion object { - private const val TAG = "HistoryViewModel" - } } // ── Factory ─────────────────────────────────────────────────────────────────── @@ -198,4 +196,4 @@ class HistoryViewModelFactory( fiatSatsPerUnit = fiatSatsPerUnit ) as T } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/history/PaymentDetailDelegate.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/history/PaymentDetailDelegate.kt index a406235..b113325 100644 --- a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/history/PaymentDetailDelegate.kt +++ b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/history/PaymentDetailDelegate.kt @@ -55,6 +55,5 @@ class PaymentDetailDelegate( } } } - fun clear() { _state.value = DetailState.Idle } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/history/PaymentRow.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/history/PaymentRow.kt index f855ef1..d264ddb 100644 --- a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/history/PaymentRow.kt +++ b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/history/PaymentRow.kt @@ -33,9 +33,8 @@ internal fun PaymentRow( fiatSatsPerUnit : Double?, onClick : () -> Unit ) { - val semantic = semanticColors() - val isPending = isPendingStatus(payment.status) + val semantic = semanticColors() val amountColor = paymentAmountColor(payment.status, payment.isOutgoing) val icon = if (payment.isOutgoing) Icons.Default.ArrowUpward else Icons.Default.ArrowDownward