From e65bf8538bd23adfa4b32e71bbcb55c9072f23a6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 22 Jun 2026 14:11:36 +0200 Subject: [PATCH] Updated on 2026-08-14 --- .../send/send/DefaultSendComponent.kt | 24 +++++---------- .../send/sendnft/DefaultNFTSendComponent.kt | 23 +++++---------- .../destination/model/SendDestinationModel.kt | 29 ++++--------------- .../model/converter/ContactIconConverter.kt | 15 ++++++++++ .../SendDestinationContactTransformer.kt | 7 +++++ 5 files changed, 43 insertions(+), 55 deletions(-) create mode 100644 features/send/impl/src/main/java/com/tangem/features/send/subcomponents/destination/model/converter/ContactIconConverter.kt diff --git a/features/send/impl/src/main/java/com/tangem/features/send/send/DefaultSendComponent.kt b/features/send/impl/src/main/java/com/tangem/features/send/send/DefaultSendComponent.kt index bae3465d9b..cda575b53c 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/send/DefaultSendComponent.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/send/DefaultSendComponent.kt @@ -28,25 +28,22 @@ import com.tangem.core.ui.decompose.ComposableContentComponent import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.res.TangemTheme import com.tangem.domain.models.account.derivationIndex -import com.tangem.features.addressbook.AddressBookContactsBlockComponent -import com.tangem.features.addressbook.AddressBookFeatureToggles -import com.tangem.features.addressbook.AddressSelectorComponent import com.tangem.features.send.api.FeeSelectorBlockComponent import com.tangem.features.send.api.SendComponent import com.tangem.features.send.api.analytics.CommonSendAnalyticEvents +import com.tangem.features.send.api.subcomponents.destination.SendDestinationComponent import com.tangem.features.send.api.subcomponents.destination.SendDestinationComponentParams import com.tangem.features.send.api.subcomponents.destination.entity.DestinationUM import com.tangem.features.send.common.CommonSendRoute import com.tangem.features.send.common.ui.SendContent import com.tangem.features.send.common.ui.state.ConfirmUM +import com.tangem.features.send.impl.R import com.tangem.features.send.send.confirm.SendConfirmComponent import com.tangem.features.send.send.model.SendModel import com.tangem.features.send.send.success.SendConfirmSuccessComponent import com.tangem.features.send.subcomponents.amount.SendAmountComponent import com.tangem.features.send.subcomponents.amount.SendAmountComponentParams import com.tangem.features.send.subcomponents.destination.DefaultSendDestinationBlockComponent -import com.tangem.features.send.subcomponents.destination.DefaultSendDestinationComponent -import com.tangem.features.send.impl.R import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject @@ -55,15 +52,13 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.launch -@Suppress("LargeClass", "LongParameterList") +@Suppress("LargeClass") internal class DefaultSendComponent @AssistedInject constructor( @Assisted appComponentContext: AppComponentContext, @Assisted private val params: SendComponent.Params, private val analyticsEventHandler: AnalyticsEventHandler, private val feeSelectorComponentFactory: FeeSelectorBlockComponent.Factory, - private val contactsBlockFactory: AddressBookContactsBlockComponent.Factory, - private val addressSelectorFactory: AddressSelectorComponent.Factory, - private val addressBookFeatureToggles: AddressBookFeatureToggles, + private val sendDestinationComponentFactory: SendDestinationComponent.Factory, ) : SendComponent, AppComponentContext by appComponentContext { private val stackNavigation = StackNavigation() @@ -128,7 +123,7 @@ internal class DefaultSendComponent @AssistedInject constructor( ) activeComponent.updateState(model.uiState.value.amountUM) } - is DefaultSendDestinationComponent -> { + is SendDestinationComponent -> { analyticsEventHandler.send( CommonSendAnalyticEvents.AddressScreenOpened( categoryName = model.analyticCategoryName, @@ -168,9 +163,9 @@ internal class DefaultSendComponent @AssistedInject constructor( is CommonSendRoute.ConfirmSuccess -> getConfirmSuccessComponent(factoryContext) } - private fun getDestinationComponent(factoryContext: AppComponentContext): DefaultSendDestinationComponent = - DefaultSendDestinationComponent( - appComponentContext = factoryContext, + private fun getDestinationComponent(factoryContext: AppComponentContext): SendDestinationComponent = + sendDestinationComponentFactory.create( + context = factoryContext, params = SendDestinationComponentParams.DestinationParams( state = model.uiState.value.destinationUM, currentRoute = model.currentRoute.filterIsInstance(), @@ -182,9 +177,6 @@ internal class DefaultSendComponent @AssistedInject constructor( cryptoCurrency = params.currency, callback = model, ), - addressBookFeatureToggles = addressBookFeatureToggles, - contactsBlockFactory = contactsBlockFactory, - addressSelectorFactory = addressSelectorFactory, ) private fun getAmountComponent(factoryContext: AppComponentContext): ComposableContentComponent { diff --git a/features/send/impl/src/main/java/com/tangem/features/send/sendnft/DefaultNFTSendComponent.kt b/features/send/impl/src/main/java/com/tangem/features/send/sendnft/DefaultNFTSendComponent.kt index abce364a1b..e06f11e545 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/sendnft/DefaultNFTSendComponent.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/sendnft/DefaultNFTSendComponent.kt @@ -18,36 +18,30 @@ import com.tangem.core.decompose.model.getOrCreateModel import com.tangem.core.decompose.navigation.inner.InnerRouter import com.tangem.core.ui.decompose.ComposableContentComponent import com.tangem.core.ui.extensions.resourceReference -import com.tangem.features.addressbook.AddressBookContactsBlockComponent -import com.tangem.features.addressbook.AddressBookFeatureToggles -import com.tangem.features.addressbook.AddressSelectorComponent import com.tangem.features.send.api.NFTSendComponent import com.tangem.features.send.api.analytics.CommonSendAnalyticEvents +import com.tangem.features.send.api.subcomponents.destination.SendDestinationComponent import com.tangem.features.send.api.subcomponents.destination.SendDestinationComponentParams import com.tangem.features.send.common.CommonSendRoute import com.tangem.features.send.common.ui.SendContent import com.tangem.features.send.common.ui.state.ConfirmUM +import com.tangem.features.send.impl.R import com.tangem.features.send.sendnft.confirm.NFTSendConfirmComponent import com.tangem.features.send.sendnft.model.NFTSendModel import com.tangem.features.send.sendnft.success.NFTSendSuccessComponent -import com.tangem.features.send.subcomponents.destination.DefaultSendDestinationComponent -import com.tangem.features.send.impl.R import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.launch -@Suppress("LongParameterList") internal class DefaultNFTSendComponent @AssistedInject constructor( @Assisted appComponentContext: AppComponentContext, @Assisted private val params: NFTSendComponent.Params, private val nftSendConfirmComponentFactory: NFTSendConfirmComponent.Factory, private val nftSendSuccessComponentFactory: NFTSendSuccessComponent.Factory, private val analyticsEventHandler: AnalyticsEventHandler, - private val contactsBlockFactory: AddressBookContactsBlockComponent.Factory, - private val addressSelectorFactory: AddressSelectorComponent.Factory, - private val addressBookFeatureToggles: AddressBookFeatureToggles, + private val sendDestinationComponentFactory: SendDestinationComponent.Factory, ) : NFTSendComponent, AppComponentContext by appComponentContext { private val stackNavigation = StackNavigation() @@ -103,7 +97,7 @@ internal class DefaultNFTSendComponent @AssistedInject constructor( activeComponent.updateState(model.uiState.value) } } - is DefaultSendDestinationComponent -> { + is SendDestinationComponent -> { analyticsEventHandler.send( CommonSendAnalyticEvents.AddressScreenOpened( categoryName = analyticsCategoryName, @@ -138,9 +132,9 @@ internal class DefaultNFTSendComponent @AssistedInject constructor( else -> getStubComponent() } - private fun getDestinationComponent(factoryContext: AppComponentContext): DefaultSendDestinationComponent = - DefaultSendDestinationComponent( - appComponentContext = factoryContext, + private fun getDestinationComponent(factoryContext: AppComponentContext): SendDestinationComponent = + sendDestinationComponentFactory.create( + context = factoryContext, params = SendDestinationComponentParams.DestinationParams( state = model.uiState.value.destinationUM, currentRoute = model.currentRouteFlow.filterIsInstance(), @@ -152,9 +146,6 @@ internal class DefaultNFTSendComponent @AssistedInject constructor( cryptoCurrency = model.cryptoCurrency, callback = model, ), - addressBookFeatureToggles = addressBookFeatureToggles, - contactsBlockFactory = contactsBlockFactory, - addressSelectorFactory = addressSelectorFactory, ) private fun getConfirmComponent(factoryContext: AppComponentContext) = nftSendConfirmComponentFactory.create( diff --git a/features/send/impl/src/main/java/com/tangem/features/send/subcomponents/destination/model/SendDestinationModel.kt b/features/send/impl/src/main/java/com/tangem/features/send/subcomponents/destination/model/SendDestinationModel.kt index 0056c9c2ff..d493255dca 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/subcomponents/destination/model/SendDestinationModel.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/subcomponents/destination/model/SendDestinationModel.kt @@ -8,7 +8,6 @@ import com.arkivanov.decompose.router.slot.activate import com.arkivanov.decompose.router.slot.dismiss import com.tangem.common.routing.AppRoute import com.tangem.common.routing.entity.AddressBookOpenMode -import com.tangem.common.ui.account.AccountIconUM import com.tangem.common.ui.navigationButtons.NavigationButton import com.tangem.common.ui.navigationButtons.NavigationUM import com.tangem.core.analytics.api.AnalyticsEventHandler @@ -24,7 +23,6 @@ import com.tangem.domain.addressbook.model.Contact import com.tangem.domain.addressbook.usecase.GetContactsUseCase import com.tangem.domain.feedback.SendBackupProblemEmailUseCase import com.tangem.domain.models.account.AccountStatus -import com.tangem.domain.models.account.CryptoPortfolioIcon import com.tangem.domain.models.account.PaymentAccountStatusValue import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.CryptoCurrencyAddress @@ -160,9 +158,7 @@ internal class SendDestinationModel @Inject constructor( .onEach { val content = uiState.value as? DestinationUM.Content ?: return@onEach if (content.addressTextField.contactName != null) { - _uiState.update(SendDestinationContactTransformer(contactName = null, contactIcon = null)) - _uiState.update(SendDestinationAddressTransformer(address = "", isPasted = false)) - validate(address = "", memo = content.memoTextField?.value) + _uiState.update(SendDestinationContactTransformer(contact = null)) } } .launchIn(modelScope) @@ -478,32 +474,19 @@ internal class SendDestinationModel @Inject constructor( private fun recognizeContact(type: EnterAddressSource?, isValidAddress: Boolean, address: String) { if (type == null || type == EnterAddressSource.Contact) return - val recognized = if (isValidAddress) findContactByAddress(address) else null - _uiState.update(SendDestinationContactTransformer(recognized?.name, recognized?.icon)) + val contact = if (isValidAddress) findContactByAddress(address) else null + _uiState.update(SendDestinationContactTransformer(contact)) } - private fun findContactByAddress(address: String): RecognizedContact? { + private fun findContactByAddress(address: String): Contact? { val networkId = cryptoCurrency.network.rawId - contacts.value.forEach { contact -> - val isMatch = contact.addressEntries.any { entry -> + return contacts.value.firstOrNull { contact -> + contact.addressEntries.any { entry -> entry.networkId.value == networkId && entry.address.equals(address, ignoreCase = true) } - if (isMatch) { - return RecognizedContact( - name = contact.name.value, - // TODO([REDACTED_TASK_KEY]): take the color from the domain Contact once the data layer stores it. - icon = AccountIconUM.CryptoPortfolio( - value = CryptoPortfolioIcon.Icon.Letter, - color = CryptoPortfolioIcon.Color.Azure, - ), - ) - } } - return null } - private data class RecognizedContact(val name: String, val icon: AccountIconUM.CryptoPortfolio) - private fun autoNextFromRecipient(type: EnterAddressSource, isValidAddress: Boolean, isValidMemo: Boolean) { if (type.isAutoNext && isValidAddress && isValidMemo) { saveResult() diff --git a/features/send/impl/src/main/java/com/tangem/features/send/subcomponents/destination/model/converter/ContactIconConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/subcomponents/destination/model/converter/ContactIconConverter.kt new file mode 100644 index 0000000000..7aab52ca2e --- /dev/null +++ b/features/send/impl/src/main/java/com/tangem/features/send/subcomponents/destination/model/converter/ContactIconConverter.kt @@ -0,0 +1,15 @@ +package com.tangem.features.send.subcomponents.destination.model.converter + +import com.tangem.common.ui.account.AccountIconUM +import com.tangem.domain.addressbook.model.Contact +import com.tangem.domain.models.account.CryptoPortfolioIcon +import com.tangem.utils.converter.Converter + +internal object ContactIconConverter : Converter { + + override fun convert(value: Contact): AccountIconUM.CryptoPortfolio = AccountIconUM.CryptoPortfolio( + value = CryptoPortfolioIcon.Icon.Letter, + color = CryptoPortfolioIcon.Color.entries.firstOrNull { it.name == value.iconColor } + ?: CryptoPortfolioIcon.Color.Azure, + ) +} \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/subcomponents/destination/model/transformers/SendDestinationContactTransformer.kt b/features/send/impl/src/main/java/com/tangem/features/send/subcomponents/destination/model/transformers/SendDestinationContactTransformer.kt index 1dd67091a4..802a0a8a04 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/subcomponents/destination/model/transformers/SendDestinationContactTransformer.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/subcomponents/destination/model/transformers/SendDestinationContactTransformer.kt @@ -1,7 +1,9 @@ package com.tangem.features.send.subcomponents.destination.model.transformers import com.tangem.common.ui.account.AccountIconUM +import com.tangem.domain.addressbook.model.Contact import com.tangem.features.send.api.subcomponents.destination.entity.DestinationUM +import com.tangem.features.send.subcomponents.destination.model.converter.ContactIconConverter import com.tangem.utils.transformer.Transformer internal class SendDestinationContactTransformer( @@ -9,6 +11,11 @@ internal class SendDestinationContactTransformer( private val contactIcon: AccountIconUM.CryptoPortfolio?, ) : Transformer { + constructor(contact: Contact?) : this( + contactName = contact?.name?.value, + contactIcon = contact?.let(ContactIconConverter::convert), + ) + override fun transform(prevState: DestinationUM): DestinationUM { val state = prevState as? DestinationUM.Content ?: return prevState