Updated on 2026-08-14
This commit is contained in:
parent
6256f4ed23
commit
68297064be
19 changed files with 80 additions and 158 deletions
|
|
@ -42,7 +42,6 @@ internal class ContactsBlockModel @Inject constructor(
|
|||
combine(
|
||||
params.queryFlow.flatMapLatest { query ->
|
||||
getVerifiedContactsInteractor.getVerifiedContacts(query = query, userWalletId = null)
|
||||
.map { verified -> verified.map { it.contact } }
|
||||
},
|
||||
getWalletsUseCase.invokeAsMap(isOnlyMultiCurrency = false, filterLocked = true),
|
||||
) { contacts, wallets -> contacts to wallets.values.toList() }
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import com.tangem.core.decompose.model.Model
|
|||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.domain.addressbook.interactor.GetVerifiedContactsInteractor
|
||||
import com.tangem.domain.addressbook.model.VerifiedContact
|
||||
import com.tangem.domain.addressbook.model.Contact
|
||||
import com.tangem.domain.addressbook.usecase.SyncAddressBooksUseCase
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
|
@ -63,7 +63,7 @@ internal class AddressBookListModel @Inject constructor(
|
|||
private val searchActive = MutableStateFlow(value = false)
|
||||
private val selectedWalletId = MutableStateFlow<String?>(value = null)
|
||||
|
||||
private val allContacts: SharedFlow<List<VerifiedContact>> =
|
||||
private val allContacts: SharedFlow<List<Contact>> =
|
||||
getVerifiedContactsInteractor.getVerifiedContacts(query = "", userWalletId = null)
|
||||
.shareIn(modelScope, SharingStarted.Lazily, replay = 1)
|
||||
|
||||
|
|
@ -179,8 +179,8 @@ internal class AddressBookListModel @Inject constructor(
|
|||
}
|
||||
|
||||
private data class ListInputs(
|
||||
val allContacts: List<VerifiedContact>,
|
||||
val matchedContacts: List<VerifiedContact>,
|
||||
val allContacts: List<Contact>,
|
||||
val matchedContacts: List<Contact>,
|
||||
val query: String,
|
||||
val selectedWalletId: String?,
|
||||
val wallets: Map<UserWalletId, UserWallet>,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import com.tangem.core.ui.R
|
|||
import com.tangem.core.ui.ds2.search.TangemSearch
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.addressbook.model.VerifiedContact
|
||||
import com.tangem.domain.addressbook.model.Contact
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.features.addressbook.MatchedContact
|
||||
|
|
@ -23,8 +23,8 @@ import kotlinx.collections.immutable.toImmutableList
|
|||
@Suppress("LongParameterList")
|
||||
internal class UpdateAddressBookListContentTransformer(
|
||||
wallets: Map<UserWalletId, UserWallet>,
|
||||
private val allContacts: List<VerifiedContact>,
|
||||
private val matchedContacts: List<VerifiedContact>,
|
||||
private val allContacts: List<Contact>,
|
||||
private val matchedContacts: List<Contact>,
|
||||
private val mode: AddressBookRoute.ListMode,
|
||||
private val selectedWalletId: String?,
|
||||
private val query: String,
|
||||
|
|
@ -73,14 +73,14 @@ internal class UpdateAddressBookListContentTransformer(
|
|||
DefaultContactConverter(onContactClick).convertList(matchedContacts)
|
||||
is AddressBookRoute.ListMode.Selector ->
|
||||
SelectorContactConverter(onPickContact)
|
||||
.convertList(ContactMatcher.match(matchedContacts.map { it.contact }, mode.networkId))
|
||||
.convertList(ContactMatcher.match(matchedContacts, mode.networkId))
|
||||
}
|
||||
|
||||
/** Wallets that own at least one contact (respecting the network filter in selector mode) — drives chip visibility. */
|
||||
private fun totalWalletIds(): Set<String> = when (val mode = mode) {
|
||||
AddressBookRoute.ListMode.Default -> allContacts.mapTo(mutableSetOf()) { it.contact.walletId.stringValue }
|
||||
AddressBookRoute.ListMode.Default -> allContacts.mapTo(mutableSetOf()) { it.walletId.stringValue }
|
||||
is AddressBookRoute.ListMode.Selector ->
|
||||
ContactMatcher.match(allContacts.map { it.contact }, mode.networkId).mapTo(mutableSetOf()) { it.walletId }
|
||||
ContactMatcher.match(allContacts, mode.networkId).mapTo(mutableSetOf()) { it.walletId }
|
||||
}
|
||||
|
||||
private fun contentMode(): ContentMode = when (mode) {
|
||||
|
|
|
|||
|
|
@ -1,30 +1,29 @@
|
|||
package com.tangem.features.addressbook.list.state.transformers.converter
|
||||
|
||||
import com.tangem.common.ui.account.AccountIconUM
|
||||
import com.tangem.domain.addressbook.model.VerifiedContact
|
||||
import com.tangem.domain.addressbook.model.Contact
|
||||
import com.tangem.domain.models.account.CryptoPortfolioIcon
|
||||
import com.tangem.features.addressbook.list.ui.state.ContactUM
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
internal class DefaultContactConverter(
|
||||
private val onContactClick: (String) -> Unit,
|
||||
) : Converter<VerifiedContact, ContactUM> {
|
||||
) : Converter<Contact, ContactUM> {
|
||||
|
||||
override fun convert(value: VerifiedContact): ContactUM {
|
||||
val contact = value.contact
|
||||
val name = contact.name.value
|
||||
override fun convert(value: Contact): ContactUM {
|
||||
val name = value.name.value
|
||||
return ContactUM(
|
||||
id = contact.id.value,
|
||||
walletId = contact.walletId.stringValue,
|
||||
id = value.id.value,
|
||||
walletId = value.walletId.stringValue,
|
||||
name = name,
|
||||
icon = AccountIconUM.CryptoPortfolio(
|
||||
value = CryptoPortfolioIcon.Icon.entries.firstOrNull { it.name == contact.icon }
|
||||
value = CryptoPortfolioIcon.Icon.entries.firstOrNull { it.name == value.icon }
|
||||
?: CryptoPortfolioIcon.Icon.Letter,
|
||||
color = CryptoPortfolioIcon.Color.entries.firstOrNull { it.name == contact.iconColor }
|
||||
color = CryptoPortfolioIcon.Color.entries.firstOrNull { it.name == value.iconColor }
|
||||
?: CryptoPortfolioIcon.Color.Azure,
|
||||
),
|
||||
networkAddressCount = contact.addresses.size,
|
||||
onClick = { onContactClick(contact.id.value) },
|
||||
networkAddressCount = value.addresses.size,
|
||||
onClick = { onContactClick(value.id.value) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,6 @@ import com.tangem.domain.addressbook.model.*
|
|||
import com.tangem.domain.addressbook.usecase.SyncAddressBooksUseCase
|
||||
import com.tangem.domain.models.account.CryptoPortfolioIcon
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
import com.tangem.features.addressbook.AddressBookContactsBlockComponent
|
||||
|
|
@ -48,7 +47,7 @@ internal class ContactsBlockModelTest {
|
|||
fun resetMocks() {
|
||||
clearMocks(getVerifiedContactsInteractor, getWalletsUseCase, analyticsSender)
|
||||
every { getWalletsUseCase.invokeAsMap(isOnlyMultiCurrency = false, filterLocked = true) } returns
|
||||
flowOf(linkedMapOf<UserWalletId, UserWallet>())
|
||||
flowOf(linkedMapOf())
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
|
|
@ -61,7 +60,7 @@ internal class ContactsBlockModelTest {
|
|||
fun `GIVEN matching contacts WHEN block populated THEN SendFlowWidgetShown sent once`() = runTest {
|
||||
// Arrange
|
||||
every { getVerifiedContactsInteractor.getVerifiedContacts(query = any(), userWalletId = null) } returns
|
||||
flowOf(listOf(verified(id = "1"), verified(id = "2")))
|
||||
flowOf(listOf(contact(id = "1"), contact(id = "2")))
|
||||
|
||||
// Act
|
||||
createModel(testScope = this)
|
||||
|
|
@ -91,7 +90,7 @@ internal class ContactsBlockModelTest {
|
|||
// Arrange
|
||||
var clicked: MatchedContact? = null
|
||||
every { getVerifiedContactsInteractor.getVerifiedContacts(query = any(), userWalletId = null) } returns
|
||||
flowOf(listOf(verified(id = "42")))
|
||||
flowOf(listOf(contact(id = "42")))
|
||||
val model = createModel(testScope = this, onContactClick = { clicked = it })
|
||||
advanceUntilIdle()
|
||||
|
||||
|
|
@ -103,9 +102,6 @@ internal class ContactsBlockModelTest {
|
|||
assertThat(clicked?.contactId).isEqualTo("42")
|
||||
}
|
||||
|
||||
private fun verified(id: String): VerifiedContact =
|
||||
VerifiedContact(contact = contact(id = id), invalidEntries = emptyList())
|
||||
|
||||
private fun contact(id: String): Contact = Contact(
|
||||
id = ContactId(id),
|
||||
walletId = UserWalletId("a"),
|
||||
|
|
|
|||
|
|
@ -205,26 +205,23 @@ internal class AddressBookListModelTest {
|
|||
verify(exactly = 1) { analyticsSender.sendContactSelectedInSend(contactId = "42", scope = any()) }
|
||||
}
|
||||
|
||||
private fun verifiedContact(id: String, name: String): VerifiedContact = VerifiedContact(
|
||||
contact = Contact(
|
||||
id = ContactId(id),
|
||||
walletId = UserWalletId("a"),
|
||||
name = ContactName(name).getOrNull()!!,
|
||||
icon = "",
|
||||
iconColor = CryptoPortfolioIcon.Color.Azure.name,
|
||||
createdAt = TIMESTAMP,
|
||||
updatedAt = TIMESTAMP,
|
||||
addresses = listOf(
|
||||
AddressEntry(
|
||||
id = AddressEntryId("e-$id"),
|
||||
address = "0xABC",
|
||||
networkId = Network.RawID("ethereum"),
|
||||
memo = null,
|
||||
signature = "sig",
|
||||
),
|
||||
private fun verifiedContact(id: String, name: String): Contact = Contact(
|
||||
id = ContactId(id),
|
||||
walletId = UserWalletId("a"),
|
||||
name = ContactName(name).getOrNull()!!,
|
||||
icon = "",
|
||||
iconColor = CryptoPortfolioIcon.Color.Azure.name,
|
||||
createdAt = TIMESTAMP,
|
||||
updatedAt = TIMESTAMP,
|
||||
addresses = listOf(
|
||||
AddressEntry(
|
||||
id = AddressEntryId("e-$id"),
|
||||
address = "0xABC",
|
||||
networkId = Network.RawID("ethereum"),
|
||||
memo = null,
|
||||
signature = "sig",
|
||||
),
|
||||
),
|
||||
invalidEntries = emptyList(),
|
||||
)
|
||||
|
||||
private fun createModel(
|
||||
|
|
|
|||
|
|
@ -133,8 +133,8 @@ internal class UpdateAddressBookListContentTransformerTest {
|
|||
}
|
||||
|
||||
private fun transform(
|
||||
allContacts: List<VerifiedContact>,
|
||||
matchedContacts: List<VerifiedContact>,
|
||||
allContacts: List<Contact>,
|
||||
matchedContacts: List<Contact>,
|
||||
selectedWalletId: String? = null,
|
||||
query: String = "",
|
||||
): AddressBookListUM = UpdateAddressBookListContentTransformer(
|
||||
|
|
@ -156,25 +156,22 @@ internal class UpdateAddressBookListContentTransformerTest {
|
|||
private fun wallet(id: String, name: String): UserWallet =
|
||||
MockUserWalletFactory.create().copy(walletId = UserWalletId(stringValue = id), name = name)
|
||||
|
||||
private fun verified(walletId: String, name: String): VerifiedContact = VerifiedContact(
|
||||
contact = Contact(
|
||||
id = ContactId(name + walletId),
|
||||
walletId = UserWalletId(stringValue = walletId),
|
||||
name = requireNotNull(ContactName(name).getOrNull()) { "invalid test name" },
|
||||
icon = "",
|
||||
iconColor = "Azure",
|
||||
createdAt = "2026-06-10T14:30:00.000Z",
|
||||
updatedAt = "2026-06-10T14:30:00.000Z",
|
||||
addresses = listOf(
|
||||
AddressEntry(
|
||||
id = AddressEntryId(name),
|
||||
address = "addr-$name",
|
||||
networkId = Network.RawID("ethereum"),
|
||||
memo = null,
|
||||
signature = "sig",
|
||||
),
|
||||
private fun verified(walletId: String, name: String): Contact = Contact(
|
||||
id = ContactId(name + walletId),
|
||||
walletId = UserWalletId(stringValue = walletId),
|
||||
name = requireNotNull(ContactName(name).getOrNull()) { "invalid test name" },
|
||||
icon = "",
|
||||
iconColor = "Azure",
|
||||
createdAt = "2026-06-10T14:30:00.000Z",
|
||||
updatedAt = "2026-06-10T14:30:00.000Z",
|
||||
addresses = listOf(
|
||||
AddressEntry(
|
||||
id = AddressEntryId(name),
|
||||
address = "addr-$name",
|
||||
networkId = Network.RawID("ethereum"),
|
||||
memo = null,
|
||||
signature = "sig",
|
||||
),
|
||||
),
|
||||
invalidEntries = emptyList(),
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue