Skip to content

Commit e790195

Browse files
authored
feat(contacts): persist display number and upsert contact metadata (#786)
Add displayNumber column to contact_mapping table (DB v17, AutoMigration). Switch from insert-only to upsert-all strategy in ContactCoordinator so contact name/photo metadata stays fresh. Format phone numbers via PhoneUtils for user-friendly display. Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent 0b6faaf commit e790195

5 files changed

Lines changed: 502 additions & 16 deletions

File tree

apps/flipcash/shared/contacts/src/main/kotlin/com/flipcash/app/contacts/ContactCoordinator.kt

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import androidx.lifecycle.ProcessLifecycleOwner
99
import com.flipcash.app.contacts.device.DeviceContact
1010
import com.flipcash.app.contacts.device.PickedContactData
1111
import com.flipcash.app.contacts.device.ScopeAwareContactReader
12+
import com.flipcash.app.phone.PhoneUtils
1213
import com.flipcash.app.contacts.sync.ContactChecksum
1314
import com.flipcash.app.persistence.FlipcashDatabase
1415
import com.flipcash.app.persistence.entities.ContactMappingEntity
@@ -52,6 +53,7 @@ class ContactCoordinator @Inject constructor(
5253
private val resolverController: ResolverController,
5354
private val networkObserver: NetworkConnectivityListener,
5455
private val contactReader: ScopeAwareContactReader,
56+
private val phoneUtils: PhoneUtils,
5557
) : SessionListener, DefaultLifecycleObserver {
5658

5759
companion object {
@@ -157,6 +159,7 @@ class ContactCoordinator @Inject constructor(
157159
androidContactId = mapping.androidContactId,
158160
displayName = mapping.displayName,
159161
photoUri = mapping.photoUri,
162+
displayNumber = mapping.displayNumber,
160163
)
161164
}
162165
val flipcashE164s = mappings.filter { it.isOnFlipcash }.map { it.e164 }.toSet()
@@ -202,26 +205,26 @@ class ContactCoordinator @Inject constructor(
202205
val adds = newE164s - existingE164s
203206
val removes = existingE164s - newE164s
204207

205-
// 4. Persist new mappings
206-
if (adds.isNotEmpty()) {
207-
val newEntities = adds.mapNotNull { e164 ->
208-
deviceContacts[e164]?.let { contact ->
209-
ContactMappingEntity(
210-
e164 = contact.e164,
211-
androidContactId = contact.androidContactId,
212-
displayName = contact.displayName,
213-
photoUri = contact.photoUri,
214-
)
215-
}
216-
}
217-
dao.upsertMappings(newEntities)
208+
// 4. Persist all mappings (upsert fixes metadata staleness for name/photo changes)
209+
val allEntities = deviceContacts.values.map { contact ->
210+
ContactMappingEntity(
211+
e164 = contact.e164,
212+
androidContactId = contact.androidContactId,
213+
displayName = contact.displayName,
214+
photoUri = contact.photoUri,
215+
displayNumber = phoneUtils.formatNumber(contact.e164),
216+
)
218217
}
218+
dao.upsertMappings(allEntities)
219219
if (removes.isNotEmpty()) {
220220
dao.deleteMappings(removes.toList())
221221
}
222222

223-
// Update in-memory contacts
224-
_state.update { it.copy(contacts = deviceContacts) }
223+
// Update in-memory contacts with displayNumber
224+
val enrichedContacts = deviceContacts.mapValues { (_, contact) ->
225+
contact.copy(displayNumber = phoneUtils.formatNumber(contact.e164))
226+
}
227+
_state.update { it.copy(contacts = enrichedContacts) }
225228

226229
// 5. CheckSync with server
227230
val syncState = dao.getSyncState()

apps/flipcash/shared/contacts/src/main/kotlin/com/flipcash/app/contacts/device/DeviceContactReader.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.flipcash.app.contacts.device
22

3+
import com.flipcash.app.phone.PhoneUtils
4+
35
interface DeviceContactReader {
46
suspend fun readAll(): Result<Map<String, DeviceContact>>
57
}
@@ -9,6 +11,7 @@ data class DeviceContact(
911
val androidContactId: Long,
1012
val displayName: String,
1113
val photoUri: String?,
14+
val displayNumber: String = "",
1215
)
1316

1417
data class PickedContactData(

0 commit comments

Comments
 (0)