feat: show contact name on payment rows

This commit is contained in:
2026-06-13 14:09:33 +02:00
parent f931405c90
commit f9991622b3
6 changed files with 35 additions and 3 deletions
@@ -137,4 +137,7 @@ class ContactRepository(app: Application) {
fun observePaymentIdsForContact(contactId: String): Flow<List<String>> = fun observePaymentIdsForContact(contactId: String): Flow<List<String>> =
dao.observePaymentIdsForContact(contactId) dao.observePaymentIdsForContact(contactId)
fun observeAllPaymentContactNames(): Flow<Map<String, String>> =
dao.observePaymentContactNames()
.map { list -> list.associate { it.checkingId to it.contactName } }
} }
@@ -98,4 +98,14 @@ interface ContactDao {
ORDER BY createdAt DESC ORDER BY createdAt DESC
""") """)
fun observePaymentIdsForContact(contactId: String): Flow<List<String>> fun observePaymentIdsForContact(contactId: String): Flow<List<String>>
// Returns all (checkingId, displayName) pairs that have a linked contact,
// so HistoryViewModel can build its lookup map in a single reactive query.
@Query("""
SELECT tcl.checkingId AS checkingId,
COALESCE(c.localAlias, c.displayName, c.name) AS contactName
FROM tx_contact_links tcl
INNER JOIN contacts c ON c.id = tcl.contactId
""")
fun observePaymentContactNames(): Flow<List<PaymentContactName>>
} }
@@ -0,0 +1,6 @@
package com.bitcointxoko.gudariwallet.data.db
data class PaymentContactName(
val checkingId : String,
val contactName : String
)
@@ -77,6 +77,7 @@ fun HistoryScreen(
val fiatSatsPerUnit by vm.fiatSatsPerUnit.collectAsState() val fiatSatsPerUnit by vm.fiatSatsPerUnit.collectAsState()
val availableTypes by vm.availableTypes.collectAsState() val availableTypes by vm.availableTypes.collectAsState()
val listState = rememberLazyListState() val listState = rememberLazyListState()
val contactNames by vm.contactNames.collectAsState()
var filterSheetVisible by rememberSaveable { mutableStateOf(false) } var filterSheetVisible by rememberSaveable { mutableStateOf(false) }
val dismissFilterSheet = { filterSheetVisible = false } val dismissFilterSheet = { filterSheetVisible = false }
@@ -234,6 +235,7 @@ fun HistoryScreen(
payment = payment, payment = payment,
fiatCurrency = fiatCurrency, fiatCurrency = fiatCurrency,
fiatSatsPerUnit = fiatSatsPerUnit, fiatSatsPerUnit = fiatSatsPerUnit,
contactName = contactNames[payment.checkingId],
onClick = { onPaymentClick(payment) } onClick = { onPaymentClick(payment) }
) )
HorizontalDivider( HorizontalDivider(
@@ -156,7 +156,16 @@ class HistoryViewModel(
else list.filter { it.extra?.tag in f.types } else list.filter { it.extra?.tag in f.types }
} }
// ── Contact name map ─────────────────────────────────────────────────────
// Maps checkingId → display name for any payment that has a linked contact.
// Rebuilt whenever the underlying tx_contact_links or contacts tables change.
val contactNames: StateFlow<Map<String, String>> =
contactRepo.observeAllPaymentContactNames()
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = emptyMap()
)
// ── Contact assignment ─────────────────────────────────────────────────── // ── Contact assignment ───────────────────────────────────────────────────
@@ -36,6 +36,7 @@ internal fun PaymentRow(
payment : PaymentRecord, payment : PaymentRecord,
fiatCurrency : String?, fiatCurrency : String?,
fiatSatsPerUnit : Double?, fiatSatsPerUnit : Double?,
contactName : String? = null,
onClick : () -> Unit onClick : () -> Unit
) { ) {
val strings = LocalAppStrings.current val strings = LocalAppStrings.current
@@ -70,8 +71,9 @@ internal fun PaymentRow(
Column(modifier = Modifier.weight(1f)) { Column(modifier = Modifier.weight(1f)) {
Text( Text(
text = payment.memo?.takeIf { it.isNotBlank() } text = contactName // ← contact name first
?: strings.history.paymentRowNoMemo, // ← "No memo" ?: payment.memo?.takeIf { it.isNotBlank() }
?: strings.history.paymentRowNoMemo,
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis