Updated on 2026-08-14
This commit is contained in:
commit
438126dc82
665 changed files with 16174 additions and 6245 deletions
|
|
@ -4,36 +4,28 @@ import androidx.compose.runtime.Stable
|
|||
import arrow.core.getOrElse
|
||||
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.AppRouter
|
||||
import com.tangem.common.routing.RoutingFeatureToggle
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.deeplink.DeepLinksRegistry
|
||||
import com.tangem.core.deeplink.global.ReferralDeepLink
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.nft.ObserveAndClearNFTCacheIfNeedUseCase
|
||||
import com.tangem.domain.settings.*
|
||||
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.RefreshMultiCurrencyWalletQuotesUseCase
|
||||
import com.tangem.domain.tokens.TokensFeatureToggles
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.isMultiCurrency
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.deeplink.WalletDeepLinksHandler
|
||||
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.SelectedWalletAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.OnrampStatusFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletNameMigrationUseCase
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.loaders.WalletScreenContentLoader
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.PushNotificationsBottomSheetConfig
|
||||
|
|
@ -47,9 +39,11 @@ import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvid
|
|||
import com.tangem.features.biometry.AskBiometryComponent
|
||||
import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
|
||||
import com.tangem.features.pushnotifications.api.utils.getPushPermissionOrNull
|
||||
import com.tangem.features.wallet.deeplink.WalletDeepLinkActionListener
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.coroutines.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.*
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
|
@ -73,7 +67,6 @@ internal class WalletModel @Inject constructor(
|
|||
private val isWalletsScrollPreviewEnabled: IsWalletsScrollPreviewEnabled,
|
||||
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
private val selectedWalletAnalyticsSender: SelectedWalletAnalyticsSender,
|
||||
private val walletDeepLinksHandler: WalletDeepLinksHandler,
|
||||
private val walletNameMigrationUseCase: WalletNameMigrationUseCase,
|
||||
private val refreshMultiCurrencyWalletQuotesUseCase: RefreshMultiCurrencyWalletQuotesUseCase,
|
||||
private val shouldAskPermissionUseCase: ShouldAskPermissionUseCase,
|
||||
|
|
@ -81,11 +74,11 @@ internal class WalletModel @Inject constructor(
|
|||
private val tokenListStore: MultiWalletTokenListStore,
|
||||
private val onrampStatusFactory: OnrampStatusFactory,
|
||||
private val analyticsEventsHandler: AnalyticsEventHandler,
|
||||
private val deepLinksRegistry: DeepLinksRegistry,
|
||||
private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase,
|
||||
private val appRouter: AppRouter,
|
||||
private val routingFeatureToggle: RoutingFeatureToggle,
|
||||
private val walletContentFetcher: WalletContentFetcher,
|
||||
private val tokensFeatureToggles: TokensFeatureToggles,
|
||||
private val observeAndClearNFTCacheIfNeedUseCase: ObserveAndClearNFTCacheIfNeedUseCase,
|
||||
private val walletDeepLinkActionListener: WalletDeepLinkActionListener,
|
||||
val screenLifecycleProvider: ScreenLifecycleProvider,
|
||||
val innerWalletRouter: InnerWalletRouter,
|
||||
) : Model() {
|
||||
|
|
@ -167,7 +160,16 @@ internal class WalletModel @Inject constructor(
|
|||
return innerWalletRouter.isWalletLastScreen() && shouldShowSaveWalletScreenUseCase() && canUseBiometryUseCase()
|
||||
}
|
||||
|
||||
private fun subscribeToUserWalletsUpdates() {
|
||||
private fun subscribeToUserWalletsUpdates() = channelFlow<Unit> {
|
||||
val firstWalletsUseCaseEmit = MutableStateFlow(false)
|
||||
suspend fun waitFirstWalletsUseCaseEmit() = firstWalletsUseCaseEmit.filter { it }.first()
|
||||
|
||||
// deepLinkActionFlow must wait for fist getWalletsUseCase() emit to correct handle Action.InitializeWallets
|
||||
walletDeepLinkActionListener.selectWalletFlow
|
||||
.onEach { waitFirstWalletsUseCaseEmit() }
|
||||
.onEach(::selectWalletById)
|
||||
.launchIn(this)
|
||||
|
||||
getWalletsUseCase()
|
||||
.conflate()
|
||||
.distinctUntilChanged()
|
||||
|
|
@ -178,10 +180,13 @@ internal class WalletModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
.onEach(::updateWallets)
|
||||
.flowOn(dispatchers.main)
|
||||
.launchIn(modelScope)
|
||||
.saveIn(walletsUpdateJobHolder)
|
||||
.onEach { firstWalletsUseCaseEmit.update { true } }
|
||||
.launchIn(this)
|
||||
awaitClose()
|
||||
}
|
||||
.flowOn(dispatchers.default)
|
||||
.launchIn(modelScope)
|
||||
.saveIn(walletsUpdateJobHolder)
|
||||
|
||||
private fun subscribeOnBalanceHiding() {
|
||||
getBalanceHidingSettingsUseCase()
|
||||
|
|
@ -226,12 +231,6 @@ internal class WalletModel @Inject constructor(
|
|||
selectedWalletAnalyticsSender.send(selectedWallet)
|
||||
}
|
||||
|
||||
if (!routingFeatureToggle.isDeepLinkNavigationEnabled) {
|
||||
// Registering here, because `WalletDeepLinksHandler` unregisters deeplink when scope is cancelled
|
||||
// This is temporary solution, will be removed with complete deeplink navigation overhaul
|
||||
addReferralDeepLink(selectedWallet)
|
||||
walletDeepLinksHandler.registerForWallet(scope = modelScope, userWallet = selectedWallet)
|
||||
}
|
||||
subscribeOnExpressTransactionsUpdates(selectedWallet)
|
||||
observeAndClearNFTCacheIfNeedUseCase(selectedWallet)
|
||||
}
|
||||
|
|
@ -240,18 +239,17 @@ internal class WalletModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun addReferralDeepLink(userWallet: UserWallet) {
|
||||
deepLinksRegistry.register(
|
||||
ReferralDeepLink(
|
||||
onReceive = {
|
||||
if (userWallet !is UserWallet.Cold || userWallet.cardTypesResolver.isTangemWallet()) {
|
||||
appRouter.push(
|
||||
AppRoute.ReferralProgram(userWalletId = userWallet.walletId),
|
||||
)
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
private fun selectWalletById(selectedWalletId: UserWalletId) {
|
||||
val currentWalletId = stateHolder.getSelectedWalletId()
|
||||
|
||||
if (currentWalletId == selectedWalletId) return
|
||||
|
||||
val currentIndex = stateHolder.getWalletIndexByWalletId(userWalletId = currentWalletId) ?: return
|
||||
val newIndex = stateHolder.getWalletIndexByWalletId(userWalletId = selectedWalletId) ?: return
|
||||
|
||||
scrollToWallet(prevIndex = currentIndex, newIndex = newIndex) {
|
||||
stateHolder.update { it.copy(selectedWalletIndex = newIndex) }
|
||||
}
|
||||
}
|
||||
|
||||
// We need to update the current wallet quotes if the application was in the background for more than 10 seconds
|
||||
|
|
@ -372,24 +370,28 @@ internal class WalletModel @Inject constructor(
|
|||
coroutineScope = modelScope,
|
||||
)
|
||||
|
||||
fetchIfSingleWallet(action.selectedWallet)
|
||||
fetchWalletContent(userWallet = action.selectedWallet)
|
||||
|
||||
val otherWallets = action.wallets.minus(action.selectedWallet)
|
||||
|
||||
if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
|
||||
otherWallets.onEach { userWallet ->
|
||||
modelScope.launch { walletContentFetcher(userWalletId = userWallet.walletId) }
|
||||
}
|
||||
}
|
||||
|
||||
if (action.wallets.size > 1 && isWalletsScrollPreviewEnabled()) {
|
||||
withContext(dispatchers.io) { delay(timeMillis = 1_800) }
|
||||
val direction = if (action.selectedWalletIndex == action.wallets.lastIndex) {
|
||||
Direction.RIGHT
|
||||
} else {
|
||||
Direction.LEFT
|
||||
}
|
||||
|
||||
walletEventSender.send(
|
||||
event = WalletEvent.DemonstrateWalletsScrollPreview(
|
||||
direction = if (action.selectedWalletIndex == action.wallets.lastIndex) {
|
||||
Direction.RIGHT
|
||||
} else {
|
||||
Direction.LEFT
|
||||
},
|
||||
),
|
||||
)
|
||||
demonstrateWalletsScrollPreview(direction = direction)
|
||||
}
|
||||
}
|
||||
|
||||
private fun reinitializeWallet(action: WalletsUpdateActionResolver.Action.ReinitializeWallet) {
|
||||
private suspend fun reinitializeWallet(action: WalletsUpdateActionResolver.Action.ReinitializeWallet) {
|
||||
walletScreenContentLoader.cancel(action.prevWalletId)
|
||||
tokenListStore.remove(action.prevWalletId)
|
||||
|
||||
|
|
@ -399,7 +401,7 @@ internal class WalletModel @Inject constructor(
|
|||
coroutineScope = modelScope,
|
||||
)
|
||||
|
||||
fetchIfSingleWallet(userWallet = action.selectedWallet)
|
||||
fetchWalletContent(userWallet = action.selectedWallet)
|
||||
|
||||
stateHolder.update(
|
||||
ReinitializeWalletTransformer(
|
||||
|
|
@ -411,14 +413,14 @@ internal class WalletModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun addWallet(action: WalletsUpdateActionResolver.Action.AddWallet) {
|
||||
private suspend fun addWallet(action: WalletsUpdateActionResolver.Action.AddWallet) {
|
||||
walletScreenContentLoader.load(
|
||||
userWallet = action.selectedWallet,
|
||||
clickIntents = clickIntents,
|
||||
coroutineScope = modelScope,
|
||||
)
|
||||
|
||||
fetchIfSingleWallet(userWallet = action.selectedWallet)
|
||||
fetchWalletContent(userWallet = action.selectedWallet)
|
||||
|
||||
stateHolder.update(
|
||||
AddWalletTransformer(
|
||||
|
|
@ -490,6 +492,16 @@ internal class WalletModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun demonstrateWalletsScrollPreview(direction: Direction) {
|
||||
modelScope.launch(dispatchers.mainImmediate) {
|
||||
delay(timeMillis = 1_800)
|
||||
|
||||
walletEventSender.send(
|
||||
event = WalletEvent.DemonstrateWalletsScrollPreview(direction = direction),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun scrollToWallet(prevIndex: Int, newIndex: Int, onConsume: () -> Unit = {}) {
|
||||
// Should not show scroll animation if WalletScreen isn't in the background.
|
||||
if (screenLifecycleProvider.isBackgroundState.value) {
|
||||
|
|
@ -517,6 +529,20 @@ internal class WalletModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun fetchWalletContent(userWallet: UserWallet) {
|
||||
if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
|
||||
/*
|
||||
* Updating the balance of the current wallet is an essential part of InitializationWallets,
|
||||
* so the coroutine is launched in the current context
|
||||
*/
|
||||
supervisorScope {
|
||||
launch { walletContentFetcher(userWalletId = userWallet.walletId) }
|
||||
}
|
||||
} else {
|
||||
fetchIfSingleWallet(userWallet = userWallet)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchIfSingleWallet(userWallet: UserWallet) {
|
||||
if (userWallet is UserWallet.Cold && userWallet.scanResponse.cardTypesResolver.isSingleWallet()) {
|
||||
modelScope.launch {
|
||||
|
|
|
|||
|
|
@ -10,20 +10,19 @@ import com.tangem.domain.settings.NeverToShowWalletsScrollPreview
|
|||
import com.tangem.domain.tokens.FetchCardTokenListUseCase
|
||||
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.FetchTokenListUseCase
|
||||
import com.tangem.domain.tokens.FetchTokenListUseCase.RefreshMode
|
||||
import com.tangem.domain.tokens.TokensFeatureToggles
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
|
||||
import com.tangem.domain.wallets.usecase.SelectWalletUseCase
|
||||
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.OnrampStatusFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletContentFetcher
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.unwrap
|
||||
import com.tangem.feature.wallet.presentation.wallet.loaders.WalletScreenContentLoader
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetRefreshStateTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTokenListErrorTransformer
|
||||
import com.tangem.features.onramp.OnrampFeatureToggles
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
|
|
@ -44,13 +43,13 @@ internal class WalletClickIntents @Inject constructor(
|
|||
private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
|
||||
private val selectWalletUseCase: SelectWalletUseCase,
|
||||
private val fetchTokenListUseCase: FetchTokenListUseCase,
|
||||
private val walletContentFetcher: WalletContentFetcher,
|
||||
private val tokensFeatureToggles: TokensFeatureToggles,
|
||||
private val fetchCardTokenListUseCase: FetchCardTokenListUseCase,
|
||||
private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val neverToShowWalletsScrollPreview: NeverToShowWalletsScrollPreview,
|
||||
private val rampStateManager: RampStateManager,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val onrampFeatureToggles: OnrampFeatureToggles,
|
||||
private val fetchHotCryptoUseCase: FetchHotCryptoUseCase,
|
||||
private val onrampStatusFactory: OnrampStatusFactory,
|
||||
) : BaseWalletClickIntents(),
|
||||
|
|
@ -88,6 +87,10 @@ internal class WalletClickIntents @Inject constructor(
|
|||
stateHolder.update { it.copy(selectedWalletIndex = index) }
|
||||
|
||||
maybeUserWallet.onRight {
|
||||
if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
|
||||
launch { walletContentFetcher(userWalletId = it.walletId) }
|
||||
}
|
||||
|
||||
walletScreenContentLoader.load(
|
||||
userWallet = it,
|
||||
clickIntents = this@WalletClickIntents,
|
||||
|
|
@ -127,36 +130,36 @@ internal class WalletClickIntents @Inject constructor(
|
|||
)
|
||||
|
||||
modelScope.launch {
|
||||
val maybeFetchResult = if (
|
||||
userWallet is UserWallet.Cold &&
|
||||
userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
|
||||
) {
|
||||
fetchCardTokenListUseCase(userWalletId = userWallet.walletId, refresh = true)
|
||||
if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
|
||||
walletContentFetcher(userWalletId = userWallet.walletId, forceUpdate = true)
|
||||
} else {
|
||||
fetchTokenListUseCase(userWalletId = userWallet.walletId, mode = RefreshMode.FULL)
|
||||
val isSingleWalletWithToken = userWallet is UserWallet.Cold &&
|
||||
userWallet.cardTypesResolver.isSingleWalletWithToken()
|
||||
|
||||
val maybeFetchResult = if (isSingleWalletWithToken) {
|
||||
fetchCardTokenListUseCase(userWalletId = userWallet.walletId, refresh = true)
|
||||
} else {
|
||||
fetchTokenListUseCase(userWalletId = userWallet.walletId)
|
||||
}
|
||||
|
||||
maybeFetchResult.onLeft {
|
||||
stateHolder.update(
|
||||
SetTokenListErrorTransformer(
|
||||
selectedWallet = userWallet,
|
||||
error = it,
|
||||
appCurrency = getSelectedAppCurrencyUseCase.unwrap(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
buildList {
|
||||
if (!onrampFeatureToggles.isFeatureEnabled) {
|
||||
async { rampStateManager.fetchBuyServiceData() }.let(::add)
|
||||
}
|
||||
|
||||
async { rampStateManager.fetchSellServiceData() }.let(::add)
|
||||
|
||||
async { fetchHotCryptoUseCase() }.let(::add)
|
||||
}
|
||||
.awaitAll()
|
||||
|
||||
maybeFetchResult.onLeft {
|
||||
stateHolder.update(
|
||||
SetTokenListErrorTransformer(
|
||||
selectedWallet = userWallet,
|
||||
error = it,
|
||||
appCurrency = getSelectedAppCurrencyUseCase.unwrap(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
stateHolder.update(
|
||||
SetRefreshStateTransformer(userWalletId = userWallet.walletId, isRefreshing = false),
|
||||
)
|
||||
|
|
@ -172,8 +175,13 @@ internal class WalletClickIntents @Inject constructor(
|
|||
SetRefreshStateTransformer(userWalletId = userWallet.walletId, isRefreshing = showRefreshState),
|
||||
)
|
||||
|
||||
modelScope.launch(dispatchers.main) {
|
||||
fetchCurrencyStatusUseCase(userWallet.walletId, refresh = true)
|
||||
modelScope.launch {
|
||||
if (tokensFeatureToggles.isWalletBalanceFetcherEnabled) {
|
||||
walletContentFetcher(userWalletId = userWallet.walletId, forceUpdate = true)
|
||||
} else {
|
||||
fetchCurrencyStatusUseCase(userWallet.walletId, refresh = true)
|
||||
}
|
||||
|
||||
onrampStatusFactory.updateOnrmapTransactionStatuses(userWallet)
|
||||
walletScreenContentLoader.load(
|
||||
userWallet = userWallet,
|
||||
|
|
|
|||
|
|
@ -61,7 +61,6 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTokensListState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.CloseBottomSheetTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSender
|
||||
import com.tangem.features.onramp.OnrampFeatureToggles
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
|
@ -129,7 +128,6 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
|
|||
private val shareManager: ShareManager,
|
||||
private val appRouter: AppRouter,
|
||||
private val rampStateManager: RampStateManager,
|
||||
private val onrampFeatureToggles: OnrampFeatureToggles,
|
||||
) : BaseWalletClickIntents(), WalletCurrencyActionsClickIntents {
|
||||
|
||||
override fun onSendClick(
|
||||
|
|
@ -345,28 +343,13 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
|
|||
|
||||
if (handleUnavailabilityReason(unavailabilityReason)) return
|
||||
|
||||
if (onrampFeatureToggles.isFeatureEnabled) {
|
||||
appRouter.push(
|
||||
AppRoute.Onramp(
|
||||
userWalletId = userWallet.walletId,
|
||||
currency = cryptoCurrencyStatus.currency,
|
||||
source = OnrampSource.TOKEN_LONG_TAP,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
showErrorIfDemoModeOrElse {
|
||||
modelScope.launch(dispatchers.main) {
|
||||
reduxStateHolder.dispatch(
|
||||
TradeCryptoAction.Buy(
|
||||
userWallet = userWallet,
|
||||
source = OnrampSource.TOKEN_LONG_TAP,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
appCurrencyCode = getSelectedAppCurrencyUseCase.unwrap().code,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
appRouter.push(
|
||||
AppRoute.Onramp(
|
||||
userWalletId = userWallet.walletId,
|
||||
currency = cryptoCurrencyStatus.currency,
|
||||
source = OnrampSource.TOKEN_LONG_TAP,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
override fun onSwapClick(
|
||||
|
|
@ -482,11 +465,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
|
|||
|
||||
override fun onMultiWalletBuyClick(userWalletId: UserWalletId, screenType: String) {
|
||||
onMultiWalletActionClick(
|
||||
statusFlow = if (onrampFeatureToggles.isFeatureEnabled) {
|
||||
rampStateManager.getExpressInitializationStatus(userWalletId)
|
||||
} else {
|
||||
rampStateManager.getBuyInitializationStatus()
|
||||
},
|
||||
statusFlow = rampStateManager.getExpressInitializationStatus(userWalletId),
|
||||
route = AppRoute.BuyCrypto(userWalletId = userWalletId),
|
||||
eventCreator = { MainScreenAnalyticsEvent.ButtonBuy(status = it, screenType = screenType) },
|
||||
)
|
||||
|
|
|
|||
|
|
@ -87,6 +87,8 @@ internal interface WalletWarningsClickIntents {
|
|||
fun onSeedPhraseSecondNotificationAccept()
|
||||
|
||||
fun onSeedPhraseSecondNotificationReject()
|
||||
|
||||
fun onFinishWalletActivationClick()
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
|
|
@ -371,6 +373,10 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun onFinishWalletActivationClick() {
|
||||
// TODO implement wallet activation process
|
||||
}
|
||||
|
||||
private suspend fun fetchCryptoCurrencies(userWalletId: UserWalletId, currencies: List<CryptoCurrency>) {
|
||||
coroutineScope {
|
||||
listOf(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
package com.tangem.feature.wallet.deeplink
|
||||
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.features.wallet.deeplink.WalletDeepLinkActionListener
|
||||
import com.tangem.features.wallet.deeplink.WalletDeepLinkActionTrigger
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
internal class DefaultWalletDeepLinkActionTrigger @Inject constructor() :
|
||||
WalletDeepLinkActionTrigger,
|
||||
WalletDeepLinkActionListener {
|
||||
|
||||
private val _selectWalletFlow = Channel<UserWalletId>()
|
||||
override val selectWalletFlow: Flow<UserWalletId>
|
||||
get() = _selectWalletFlow.receiveAsFlow()
|
||||
|
||||
override fun selectWallet(userWalletId: UserWalletId) {
|
||||
_selectWalletFlow.trySend(userWalletId)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
package com.tangem.feature.wallet.deeplink.di
|
||||
|
||||
import com.tangem.feature.wallet.deeplink.DefaultWalletDeepLinkActionTrigger
|
||||
import com.tangem.feature.wallet.deeplink.DefaultWalletDeepLinkHandler
|
||||
import com.tangem.features.wallet.deeplink.WalletDeepLinkActionListener
|
||||
import com.tangem.features.wallet.deeplink.WalletDeepLinkActionTrigger
|
||||
import com.tangem.features.wallet.deeplink.WalletDeepLinkHandler
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
|
|
@ -15,4 +18,12 @@ internal interface WalletDeepLinkModule {
|
|||
@Binds
|
||||
@Singleton
|
||||
fun bindWalletDeepLinkHandlerFactory(impl: DefaultWalletDeepLinkHandler.Factory): WalletDeepLinkHandler.Factory
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindWalletDeepLinkActionTrigger(impl: DefaultWalletDeepLinkActionTrigger): WalletDeepLinkActionTrigger
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindWalletDeepLinkActionListener(impl: DefaultWalletDeepLinkActionTrigger): WalletDeepLinkActionListener
|
||||
}
|
||||
|
|
@ -117,6 +117,7 @@ internal object WalletScreenPreviewData {
|
|||
buttons = persistentListOf(buyButton),
|
||||
warnings = persistentListOf(
|
||||
WalletNotification.Warning.SomeNetworksUnreachable,
|
||||
WalletNotification.FinishWalletActivation { },
|
||||
),
|
||||
bottomSheetConfig = null,
|
||||
tokensListState = textContentTokensState,
|
||||
|
|
|
|||
|
|
@ -1,94 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.deeplink
|
||||
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.deeplink.DeepLink
|
||||
import com.tangem.core.deeplink.DeepLinksRegistry
|
||||
import com.tangem.core.deeplink.global.BuyCurrencyDeepLink
|
||||
import com.tangem.core.deeplink.global.SellCurrencyDeepLink
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyUseCase
|
||||
import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.isMultiCurrency
|
||||
import com.tangem.features.onramp.OnrampFeatureToggles
|
||||
import com.tangem.utils.coroutines.launchOnCancellation
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class WalletDeepLinksHandler @Inject constructor(
|
||||
private val deepLinksRegistry: DeepLinksRegistry,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val getCryptoCurrencyUseCase: GetCryptoCurrencyUseCase,
|
||||
private val onrampFeatureToggles: OnrampFeatureToggles,
|
||||
private val router: AppRouter,
|
||||
) {
|
||||
|
||||
private var deepLinksMap = mutableMapOf<UserWalletId, List<DeepLink>>()
|
||||
|
||||
fun registerForWallet(scope: CoroutineScope, userWallet: UserWallet) {
|
||||
val deepLinks = deepLinksMap.getOrPut(userWallet.walletId) {
|
||||
getDeepLinks(userWallet, scope)
|
||||
}
|
||||
deepLinksRegistry.unregisterByIds(deepLinks.map { it.id })
|
||||
deepLinksRegistry.register(deepLinks = deepLinks)
|
||||
|
||||
// When navigation to another screen scope is Cancelled and deeplinks are hot handled
|
||||
scope.launchOnCancellation {
|
||||
deepLinksRegistry.unregister(deepLinks)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDeepLinks(userWallet: UserWallet, scope: CoroutineScope): List<DeepLink> {
|
||||
val sellCurrencyDeepLink = SellCurrencyDeepLink(
|
||||
onReceive = { data ->
|
||||
scope.launch {
|
||||
onSellCurrencyDeepLink(userWallet, data)
|
||||
}
|
||||
},
|
||||
shouldHandleDelayed = true,
|
||||
)
|
||||
|
||||
return buildList {
|
||||
add(sellCurrencyDeepLink)
|
||||
if (!onrampFeatureToggles.isFeatureEnabled && !userWallet.isMultiCurrency) {
|
||||
add(
|
||||
BuyCurrencyDeepLink(
|
||||
onReceive = {
|
||||
scope.launch { onBuyCurrencyDeepLink(userWallet) }
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun onSellCurrencyDeepLink(userWallet: UserWallet, data: SellCurrencyDeepLink.Data) {
|
||||
val cryptoCurrency = getCryptoCurrencyUseCase(userWallet, data.currencyId).getOrNull()
|
||||
|
||||
if (cryptoCurrency == null) {
|
||||
Timber.e("onSellCurrencyDeepLink cryptoCurrency is null")
|
||||
return
|
||||
}
|
||||
|
||||
val route = AppRoute.Send(
|
||||
currency = cryptoCurrency,
|
||||
userWalletId = userWallet.walletId,
|
||||
transactionId = data.transactionId,
|
||||
destinationAddress = data.depositWalletAddress,
|
||||
amount = data.baseCurrencyAmount,
|
||||
tag = data.depositWalletAddressTag,
|
||||
)
|
||||
|
||||
router.push(route)
|
||||
}
|
||||
|
||||
private suspend fun onBuyCurrencyDeepLink(userWallet: UserWallet) {
|
||||
val cryptoCurrency = getCryptoCurrencyUseCase(userWallet.walletId).getOrNull() ?: return
|
||||
analyticsEventHandler.send(TokenScreenAnalyticsEvent.Bought(cryptoCurrency.symbol))
|
||||
}
|
||||
}
|
||||
|
|
@ -61,6 +61,7 @@ internal class WalletWarningsAnalyticsSender @Inject constructor(
|
|||
is WalletNotification.Warning.NetworksUnreachable,
|
||||
is WalletNotification.UsedOutdatedData,
|
||||
is WalletNotification.UnlockVisaAccess,
|
||||
is WalletNotification.FinishWalletActivation,
|
||||
-> null
|
||||
is WalletNotification.Critical.SeedPhraseNotification -> MainScreen.NoticeSeedPhraseSupport
|
||||
is WalletNotification.Critical.SeedPhraseSecondNotification -> MainScreen.NoticeSeedPhraseSupportSecond
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
|
||||
addCriticalNotifications(userWallet, seedPhraseIssueStatus, clickIntents)
|
||||
|
||||
addFinishWalletActivationNotification(userWallet, clickIntents)
|
||||
|
||||
addReferralPromoNotification(cardTypesResolver, clickIntents, shouldShowReferralPromo)
|
||||
|
||||
addInformationalNotifications(cardTypesResolver, maybeTokenList, clickIntents)
|
||||
|
|
@ -259,6 +261,23 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
if (condition) add(element = element)
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotification>.addFinishWalletActivationNotification(
|
||||
userWallet: UserWallet,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
if (userWallet !is UserWallet.Hot) return
|
||||
|
||||
// TODO [REDACTED_TASK_KEY] set an actual value
|
||||
val shouldShowFinishActivation = false
|
||||
|
||||
addIf(
|
||||
element = WalletNotification.FinishWalletActivation(
|
||||
onFinishClick = clickIntents::onFinishWalletActivationClick,
|
||||
),
|
||||
condition = shouldShowFinishActivation,
|
||||
)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val MAX_REMAINING_SIGNATURES_COUNT = 10
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,21 +2,17 @@ package com.tangem.feature.wallet.presentation.wallet.domain
|
|||
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.features.nft.NFTFeatureToggles
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
|
||||
class IsWalletNFTEnabledSyncUseCase(
|
||||
private val walletsRepository: WalletsRepository,
|
||||
private val nftFeatureToggles: NFTFeatureToggles,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(userWalletId: UserWalletId): Boolean = if (nftFeatureToggles.isNFTEnabled) {
|
||||
walletsRepository
|
||||
.nftEnabledStatuses()
|
||||
suspend operator fun invoke(userWalletId: UserWalletId): Boolean {
|
||||
val isNFTEnabled = walletsRepository.nftEnabledStatuses()
|
||||
.firstOrNull()
|
||||
?.let { it[userWalletId] }
|
||||
?: false
|
||||
} else {
|
||||
false
|
||||
?.get(userWalletId)
|
||||
|
||||
return isNFTEnabled == true
|
||||
}
|
||||
}
|
||||
|
|
@ -39,10 +39,22 @@ internal object WalletAdditionalInfoFactory {
|
|||
wallet.resolveSingleCurrencyInfo(currencyAmount)
|
||||
}
|
||||
}
|
||||
is UserWallet.Hot -> TODO("[REDACTED_TASK_KEY]")
|
||||
is UserWallet.Hot -> wallet.resolveAdditionalInfo()
|
||||
}
|
||||
}
|
||||
|
||||
private fun UserWallet.Hot.resolveAdditionalInfo(): WalletAdditionalInfo {
|
||||
return WalletAdditionalInfo(
|
||||
hideable = false,
|
||||
content = TextReference.Res(R.string.hw_mobile_wallet) +
|
||||
when {
|
||||
isLocked -> DIVIDER + TextReference.Res(R.string.common_locked)
|
||||
backedUp.not() -> DIVIDER + TextReference.Res(R.string.hw_backup_no_backup)
|
||||
else -> TextReference.Str("")
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun UserWallet.Cold.resolveMultiCurrencyInfo(): WalletAdditionalInfo {
|
||||
return if (isLocked) {
|
||||
WalletAdditionalInfo(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,75 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.domain
|
||||
|
||||
import com.tangem.domain.tokens.wallet.WalletBalanceFetcher
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.JobHolder
|
||||
import com.tangem.utils.coroutines.saveInAndJoin
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.supervisorScope
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
* Wallet content fetcher
|
||||
*
|
||||
* @property walletBalanceFetcher fetcher for wallet balance
|
||||
* @property dispatchers dispatchers
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Singleton
|
||||
internal class WalletContentFetcher @Inject constructor(
|
||||
private val walletBalanceFetcher: WalletBalanceFetcher,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) {
|
||||
|
||||
private val fetchingJobMap = ConcurrentHashMap<UserWalletId, JobHolder>()
|
||||
private val mutex = Mutex()
|
||||
|
||||
suspend operator fun invoke(userWalletId: UserWalletId, forceUpdate: Boolean = false) = supervisorScope {
|
||||
withContext(dispatchers.default) {
|
||||
// Use mutex to ensure thread safety
|
||||
val jobHolder = mutex.withLock {
|
||||
val savedJobHolder = fetchingJobMap.getOrPut(key = userWalletId, defaultValue = ::JobHolder)
|
||||
|
||||
/*
|
||||
* If this is not a forced update and there is a saved job in the cache
|
||||
* (doesn't matter if it is active or not), then skip the update process.
|
||||
*/
|
||||
if (!forceUpdate && savedJobHolder != null && !savedJobHolder.isEmpty()) {
|
||||
Timber.d("Skip fetching for $userWalletId")
|
||||
|
||||
return@withContext
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is a forced update and there is already a job in the cache that is updating the balance,
|
||||
* then cancel the previous update.
|
||||
*/
|
||||
if (forceUpdate && savedJobHolder?.isActive == true) {
|
||||
Timber.d("Cancel old fetching for $userWalletId")
|
||||
|
||||
savedJobHolder.cancel()
|
||||
}
|
||||
|
||||
JobHolder().also { fetchingJobMap[userWalletId] = it }
|
||||
}
|
||||
|
||||
Timber.d("Start fetching for $userWalletId")
|
||||
|
||||
val maybeResult = launch {
|
||||
walletBalanceFetcher(params = WalletBalanceFetcher.Params(userWalletId = userWalletId))
|
||||
.onLeft(Timber::e)
|
||||
}
|
||||
.saveInAndJoin(jobHolder)
|
||||
|
||||
Timber.d("Finish fetching with result $maybeResult for $userWalletId")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -24,7 +24,11 @@ internal class WalletImageResolver @Inject constructor(
|
|||
/** Get a specified wallet [userWallet] image */
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
@DrawableRes
|
||||
fun resolve(userWallet: UserWallet.Cold): Int? {
|
||||
fun resolve(userWallet: UserWallet): Int? {
|
||||
if (userWallet !is UserWallet.Cold) {
|
||||
return null
|
||||
}
|
||||
|
||||
val cardTypesResolver = userWallet.scanResponse.cardTypesResolver
|
||||
|
||||
val cobrandImage = Wallet2CobrandImage.entries.firstOrNull {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ internal class WalletContentLoaderFactory @Inject constructor(
|
|||
userWallet is UserWallet.Cold && userWallet.scanResponse.cardTypesResolver.isVisaWallet() -> {
|
||||
visaWalletContentLoaderFactory.create(userWallet, clickIntents, isRefresh)
|
||||
}
|
||||
!userWallet.isMultiCurrency -> {
|
||||
userWallet is UserWallet.Cold && !userWallet.isMultiCurrency -> {
|
||||
singleWalletContentLoaderFactory.create(userWallet, clickIntents, isRefresh)
|
||||
}
|
||||
else -> null
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
||||
|
||||
import com.tangem.common.routing.RoutingFeatureToggle
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.deeplink.DeepLinksRegistry
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.nft.GetNFTCollectionsUseCase
|
||||
import com.tangem.domain.promo.GetStoryContentUseCase
|
||||
|
|
@ -21,11 +19,6 @@ import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenList
|
|||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.MultiWalletActionButtonsSubscriber
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.MultiWalletTokenListSubscriber
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.MultiWalletWarningsSubscriber
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.WalletSubscriber
|
||||
import com.tangem.features.nft.NFTFeatureToggles
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@ModelScoped
|
||||
|
|
@ -45,11 +38,8 @@ internal class MultiWalletContentLoader(
|
|||
private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase,
|
||||
private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase,
|
||||
private val getStoryContentUseCase: GetStoryContentUseCase,
|
||||
private val deepLinksRegistry: DeepLinksRegistry,
|
||||
private val nftFeatureToggles: NFTFeatureToggles,
|
||||
private val walletsRepository: WalletsRepository,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val routingFeatureToggle: RoutingFeatureToggle,
|
||||
) : WalletContentLoader(id = userWallet.walletId) {
|
||||
|
||||
override fun create(): List<WalletSubscriber> {
|
||||
|
|
@ -64,19 +54,17 @@ internal class MultiWalletContentLoader(
|
|||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
applyTokenListSortingUseCase = applyTokenListSortingUseCase,
|
||||
runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase,
|
||||
deepLinksRegistry = deepLinksRegistry,
|
||||
routingFeatureToggle = routingFeatureToggle,
|
||||
).let(::add)
|
||||
if (nftFeatureToggles.isNFTEnabled) {
|
||||
WalletNFTListSubscriber(
|
||||
userWallet = userWallet,
|
||||
getNFTCollectionsUseCase = getNFTCollectionsUseCase,
|
||||
stateHolder = stateHolder,
|
||||
walletsRepository = walletsRepository,
|
||||
clickIntents = clickIntents,
|
||||
currenciesRepository = currenciesRepository,
|
||||
).let(::add)
|
||||
}
|
||||
|
||||
WalletNFTListSubscriber(
|
||||
userWallet = userWallet,
|
||||
getNFTCollectionsUseCase = getNFTCollectionsUseCase,
|
||||
stateHolder = stateHolder,
|
||||
walletsRepository = walletsRepository,
|
||||
clickIntents = clickIntents,
|
||||
currenciesRepository = currenciesRepository,
|
||||
).let(::add)
|
||||
|
||||
MultiWalletWarningsSubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateHolder,
|
||||
|
|
@ -85,11 +73,13 @@ internal class MultiWalletContentLoader(
|
|||
walletWarningsAnalyticsSender = walletWarningsAnalyticsSender,
|
||||
walletWarningsSingleEventSender = walletWarningsSingleEventSender,
|
||||
).let(::add)
|
||||
|
||||
MultiWalletActionButtonsSubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateHolder,
|
||||
getStoryContentUseCase = getStoryContentUseCase,
|
||||
).let(::add)
|
||||
|
||||
WalletDropDownItemsSubscriber(
|
||||
stateHolder = stateHolder,
|
||||
shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
||||
|
||||
import com.tangem.common.routing.RoutingFeatureToggle
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.deeplink.DeepLinksRegistry
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.nft.GetNFTCollectionsUseCase
|
||||
import com.tangem.domain.promo.GetStoryContentUseCase
|
||||
|
|
@ -20,7 +18,6 @@ import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarnin
|
|||
import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.features.nft.NFTFeatureToggles
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
|
|
@ -38,11 +35,8 @@ internal class MultiWalletContentLoaderFactory @Inject constructor(
|
|||
private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase,
|
||||
private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase,
|
||||
private val getStoryContentUseCase: GetStoryContentUseCase,
|
||||
private val deepLinksRegistry: DeepLinksRegistry,
|
||||
private val nftFeatureToggles: NFTFeatureToggles,
|
||||
private val walletsRepository: WalletsRepository,
|
||||
private val getNFTCollectionsUseCase: GetNFTCollectionsUseCase,
|
||||
private val routingFeatureToggle: RoutingFeatureToggle,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
) {
|
||||
|
||||
|
|
@ -62,11 +56,8 @@ internal class MultiWalletContentLoaderFactory @Inject constructor(
|
|||
runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase,
|
||||
getStoryContentUseCase = getStoryContentUseCase,
|
||||
shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase,
|
||||
deepLinksRegistry = deepLinksRegistry,
|
||||
nftFeatureToggles = nftFeatureToggles,
|
||||
walletsRepository = walletsRepository,
|
||||
getNFTCollectionsUseCase = getNFTCollectionsUseCase,
|
||||
routingFeatureToggle = routingFeatureToggle,
|
||||
currenciesRepository = currenciesRepository,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import com.tangem.feature.wallet.presentation.wallet.subscribers.*
|
|||
|
||||
@Suppress("LongParameterList")
|
||||
internal class SingleWalletContentLoader(
|
||||
private val userWallet: UserWallet,
|
||||
private val userWallet: UserWallet.Cold,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val isRefresh: Boolean,
|
||||
private val stateHolder: WalletStateController,
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ internal class SingleWalletContentLoaderFactory @Inject constructor(
|
|||
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
|
||||
) {
|
||||
|
||||
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents, isRefresh: Boolean): WalletContentLoader {
|
||||
fun create(userWallet: UserWallet.Cold, clickIntents: WalletClickIntents, isRefresh: Boolean): WalletContentLoader {
|
||||
return SingleWalletContentLoader(
|
||||
userWallet = userWallet,
|
||||
clickIntents = clickIntents,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
||||
|
||||
import com.tangem.common.routing.RoutingFeatureToggle
|
||||
import com.tangem.core.deeplink.DeepLinksRegistry
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.promo.GetStoryContentUseCase
|
||||
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
|
||||
|
|
@ -19,7 +17,7 @@ import com.tangem.feature.wallet.presentation.wallet.subscribers.*
|
|||
|
||||
@Suppress("LongParameterList")
|
||||
internal class SingleWalletWithTokenContentLoader(
|
||||
private val userWallet: UserWallet,
|
||||
private val userWallet: UserWallet.Cold,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val stateHolder: WalletStateController,
|
||||
private val tokenListAnalyticsSender: TokenListAnalyticsSender,
|
||||
|
|
@ -32,8 +30,6 @@ internal class SingleWalletWithTokenContentLoader(
|
|||
private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase,
|
||||
private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase,
|
||||
private val getStoryContentUseCase: GetStoryContentUseCase,
|
||||
private val deepLinksRegistry: DeepLinksRegistry,
|
||||
private val routingFeatureToggle: RoutingFeatureToggle,
|
||||
) : WalletContentLoader(id = userWallet.walletId) {
|
||||
|
||||
override fun create(): List<WalletSubscriber> {
|
||||
|
|
@ -47,8 +43,6 @@ internal class SingleWalletWithTokenContentLoader(
|
|||
tokenListStore = tokenListStore,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase,
|
||||
deepLinksRegistry = deepLinksRegistry,
|
||||
routingFeatureToggle = routingFeatureToggle,
|
||||
).let(::add)
|
||||
MultiWalletWarningsSubscriber(
|
||||
userWallet = userWallet,
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
||||
|
||||
import com.tangem.common.routing.RoutingFeatureToggle
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.deeplink.DeepLinksRegistry
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.promo.GetStoryContentUseCase
|
||||
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender
|
||||
|
|
@ -15,7 +14,6 @@ import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarnin
|
|||
import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import javax.inject.Inject
|
||||
|
||||
// TODO: Refactor
|
||||
|
|
@ -33,11 +31,9 @@ internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor(
|
|||
private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase,
|
||||
private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase,
|
||||
private val getStoryContentUseCase: GetStoryContentUseCase,
|
||||
private val deepLinksRegistry: DeepLinksRegistry,
|
||||
private val routingFeatureToggle: RoutingFeatureToggle,
|
||||
) {
|
||||
|
||||
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): SingleWalletWithTokenContentLoader {
|
||||
fun create(userWallet: UserWallet.Cold, clickIntents: WalletClickIntents): SingleWalletWithTokenContentLoader {
|
||||
return SingleWalletWithTokenContentLoader(
|
||||
userWallet = userWallet,
|
||||
clickIntents = clickIntents,
|
||||
|
|
@ -52,8 +48,6 @@ internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor(
|
|||
runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase,
|
||||
getStoryContentUseCase = getStoryContentUseCase,
|
||||
shouldSaveUserWalletsUseCase = shouldSaveUserWalletsUseCase,
|
||||
deepLinksRegistry = deepLinksRegistry,
|
||||
routingFeatureToggle = routingFeatureToggle,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ import com.tangem.feature.wallet.presentation.wallet.subscribers.WalletSubscribe
|
|||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
|
||||
internal class VisaWalletContentLoader(
|
||||
private val userWallet: UserWallet,
|
||||
private val userWallet: UserWallet.Cold,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val isRefresh: Boolean,
|
||||
private val stateController: WalletStateController,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ internal class VisaWalletContentLoaderFactory @Inject constructor(
|
|||
private val getVisaTxHistoryUseCase: GetVisaTxHistoryUseCase,
|
||||
) {
|
||||
|
||||
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents, isRefresh: Boolean): WalletContentLoader {
|
||||
fun create(userWallet: UserWallet.Cold, clickIntents: WalletClickIntents, isRefresh: Boolean): WalletContentLoader {
|
||||
return VisaWalletContentLoader(
|
||||
userWallet = userWallet,
|
||||
clickIntents = clickIntents,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTopBarCon
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.CloseBottomSheetTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.OpenBottomSheetTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.WalletScreenStateTransformer
|
||||
import com.tangem.utils.extensions.indexOfFirstOrNull
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
|
@ -68,6 +69,10 @@ internal class WalletStateController @Inject constructor() {
|
|||
return with(value) { wallets[selectedWalletIndex].walletCardState.id }
|
||||
}
|
||||
|
||||
fun getWalletIndexByWalletId(userWalletId: UserWalletId): Int? {
|
||||
return with(value) { wallets.indexOfFirstOrNull { it.walletCardState.id == userWalletId } }
|
||||
}
|
||||
|
||||
fun showBottomSheet(
|
||||
content: TangemBottomSheetConfigContent,
|
||||
userWalletId: UserWalletId = getSelectedWalletId(),
|
||||
|
|
|
|||
|
|
@ -255,6 +255,20 @@ sealed class WalletNotification(val config: NotificationConfig) {
|
|||
),
|
||||
)
|
||||
|
||||
data class FinishWalletActivation(
|
||||
val onFinishClick: () -> Unit,
|
||||
) : WalletNotification(
|
||||
config = NotificationConfig(
|
||||
title = resourceReference(R.string.hw_activation_need_title),
|
||||
subtitle = resourceReference(R.string.hw_activation_need_description),
|
||||
iconResId = R.drawable.img_knight_shield_32,
|
||||
buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
|
||||
text = resourceReference(R.string.hw_activation_need_finish),
|
||||
onClick = onFinishClick,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
data class ReferralPromo(
|
||||
val onCloseClick: () -> Unit,
|
||||
val onClick: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
|||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.isLocked
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
|
|
@ -55,8 +54,6 @@ internal class InitializeWalletsTransformer(
|
|||
}
|
||||
|
||||
private fun createLockedState(userWallet: UserWallet): WalletState {
|
||||
userWallet.requireColdWallet()
|
||||
|
||||
return userWallet.createStateByWalletType(
|
||||
multiCurrencyCreator = {
|
||||
WalletState.MultiCurrency.Locked(
|
||||
|
|
@ -87,7 +84,7 @@ internal class InitializeWalletsTransformer(
|
|||
)
|
||||
}
|
||||
|
||||
private fun UserWallet.Cold.toLockedWalletCardState(): WalletCardState {
|
||||
private fun UserWallet.toLockedWalletCardState(): WalletCardState {
|
||||
return WalletCardState.LockedContent(
|
||||
id = walletId,
|
||||
title = name,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import com.tangem.domain.appcurrency.model.AppCurrency
|
|||
import com.tangem.domain.common.util.getCardsCount
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
|
|
@ -57,8 +56,6 @@ internal class SetTokenListErrorTransformer(
|
|||
}
|
||||
|
||||
private fun WalletCardState.toLoadedState(): WalletCardState {
|
||||
selectedWallet.requireColdWallet() // TODO [REDACTED_TASK_KEY]
|
||||
|
||||
return WalletCardState.Content(
|
||||
id = id,
|
||||
title = title,
|
||||
|
|
@ -68,7 +65,10 @@ internal class SetTokenListErrorTransformer(
|
|||
balance = BigDecimal.ZERO.format {
|
||||
fiat(fiatCurrencyCode = appCurrency.code, fiatCurrencySymbol = appCurrency.symbol)
|
||||
},
|
||||
cardCount = selectedWallet.getCardsCount(),
|
||||
cardCount = when (selectedWallet) {
|
||||
is UserWallet.Cold -> selectedWallet.getCardsCount()
|
||||
is UserWallet.Hot -> null
|
||||
},
|
||||
isZeroBalance = true,
|
||||
isBalanceFlickering = false,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
|||
import com.tangem.domain.visa.exception.RefreshTokenExpiredException
|
||||
import com.tangem.domain.visa.model.VisaCurrency
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.BalancesAndLimitsBlockState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAdditionalInfo
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
||||
|
|
@ -27,7 +26,7 @@ import org.joda.time.DateTime
|
|||
import org.joda.time.Days
|
||||
|
||||
internal class SetVisaInfoTransformer(
|
||||
private val userWallet: UserWallet,
|
||||
private val userWallet: UserWallet.Cold,
|
||||
private val maybeVisaCurrency: Either<Throwable, VisaCurrency>,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
) : TypedWalletStateTransformer<WalletState.Visa.Content>(
|
||||
|
|
@ -76,8 +75,6 @@ internal class SetVisaInfoTransformer(
|
|||
}
|
||||
|
||||
private fun getContentWalletCardState(prevState: WalletCardState, visaCurrency: VisaCurrency): WalletCardState {
|
||||
userWallet.requireColdWallet() // TODO [REDACTED_TASK_KEY]
|
||||
|
||||
return with(prevState) {
|
||||
WalletCardState.Content(
|
||||
id = id,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import com.tangem.domain.common.util.getCardsCount
|
|||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.tokens.model.TotalFiatBalance
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
|
@ -48,8 +47,6 @@ internal class MultiWalletCardStateConverter(
|
|||
}
|
||||
|
||||
private fun WalletCardState.toWalletCardState(fiatBalance: TotalFiatBalance.Loaded): WalletCardState {
|
||||
selectedWallet.requireColdWallet()
|
||||
|
||||
return WalletCardState.Content(
|
||||
id = id,
|
||||
title = title,
|
||||
|
|
@ -60,7 +57,10 @@ internal class MultiWalletCardStateConverter(
|
|||
fiat(fiatCurrencyCode = appCurrency.code, fiatCurrencySymbol = appCurrency.symbol)
|
||||
},
|
||||
isZeroBalance = fiatBalance.amount.isZero(),
|
||||
cardCount = selectedWallet.getCardsCount(),
|
||||
cardCount = when (selectedWallet) {
|
||||
is UserWallet.Cold -> selectedWallet.getCardsCount()
|
||||
is UserWallet.Hot -> null
|
||||
},
|
||||
isBalanceFlickering = fiatBalance.source == StatusSource.CACHE,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import com.tangem.domain.common.util.getCardsCount
|
|||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
||||
import com.tangem.utils.StringsSigns.DASH_SIGN
|
||||
|
|
@ -64,7 +63,10 @@ internal class SingleWalletCardStateConverter(
|
|||
imageResId = imageResId,
|
||||
dropDownItems = dropDownItems,
|
||||
balance = formatFiatAmount(status = status, appCurrency = appCurrency),
|
||||
cardCount = selectedWallet.requireColdWallet().getCardsCount(), // TODO [REDACTED_TASK_KEY]
|
||||
cardCount = when (selectedWallet) {
|
||||
is UserWallet.Cold -> selectedWallet.getCardsCount()
|
||||
is UserWallet.Hot -> null
|
||||
},
|
||||
isZeroBalance = status.fiatAmount?.isZero(),
|
||||
isBalanceFlickering = (status as? CryptoCurrencyStatus.Loaded)?.sources?.total == StatusSource.CACHE,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -4,14 +4,17 @@ import com.tangem.domain.common.util.cardTypesResolver
|
|||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
|
||||
internal inline fun UserWallet.Cold.createStateByWalletType(
|
||||
internal inline fun UserWallet.createStateByWalletType(
|
||||
multiCurrencyCreator: () -> WalletState.MultiCurrency,
|
||||
singleCurrencyCreator: () -> WalletState.SingleCurrency,
|
||||
visaWalletCreator: () -> WalletState.Visa,
|
||||
): WalletState = when {
|
||||
isVisaWallet() -> visaWalletCreator()
|
||||
isWalletWithTokens() -> multiCurrencyCreator()
|
||||
else -> singleCurrencyCreator()
|
||||
): WalletState = when (this) {
|
||||
is UserWallet.Cold -> when {
|
||||
isVisaWallet() -> visaWalletCreator()
|
||||
isWalletWithTokens() -> multiCurrencyCreator()
|
||||
else -> singleCurrencyCreator()
|
||||
}
|
||||
is UserWallet.Hot -> multiCurrencyCreator()
|
||||
}
|
||||
|
||||
private fun UserWallet.Cold.isWalletWithTokens(): Boolean {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
|||
import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
|
||||
|
|
@ -26,12 +25,35 @@ internal class WalletLoadingStateFactory(
|
|||
) {
|
||||
|
||||
fun create(userWallet: UserWallet): WalletState {
|
||||
userWallet.requireColdWallet()
|
||||
return when (userWallet) {
|
||||
is UserWallet.Cold -> {
|
||||
userWallet.createStateByWalletType(
|
||||
multiCurrencyCreator = { createLoadingMultiCurrencyContent(userWallet) },
|
||||
singleCurrencyCreator = { createLoadingSingleCurrencyContent(userWallet) },
|
||||
visaWalletCreator = { createLoadingVisaWalletContent(userWallet) },
|
||||
)
|
||||
}
|
||||
is UserWallet.Hot -> {
|
||||
createLoadingHotWalletContent(userWallet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return userWallet.createStateByWalletType(
|
||||
multiCurrencyCreator = { createLoadingMultiCurrencyContent(userWallet) },
|
||||
singleCurrencyCreator = { createLoadingSingleCurrencyContent(userWallet) },
|
||||
visaWalletCreator = { createLoadingVisaWalletContent(userWallet) },
|
||||
private fun createLoadingHotWalletContent(userWallet: UserWallet.Hot): WalletState.MultiCurrency.Content {
|
||||
return WalletState.MultiCurrency.Content(
|
||||
pullToRefreshConfig = createPullToRefreshConfig(),
|
||||
walletCardState = WalletCardState.Loading(
|
||||
id = userWallet.walletId,
|
||||
title = userWallet.name,
|
||||
additionalInfo = null, // TODO [REDACTED_TASK_KEY]
|
||||
imageResId = null, // TODO [REDACTED_TASK_KEY]
|
||||
dropDownItems = persistentListOf(),
|
||||
),
|
||||
buttons = createMultiWalletActions(userWallet),
|
||||
warnings = persistentListOf(),
|
||||
bottomSheetConfig = null,
|
||||
tokensListState = WalletTokensListState.ContentState.Loading,
|
||||
nftState = WalletNFTItemUM.Hidden,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -99,15 +121,21 @@ internal class WalletLoadingStateFactory(
|
|||
)
|
||||
}
|
||||
|
||||
private fun createMultiWalletActions(userWallet: UserWallet.Cold): PersistentList<WalletManageButton> {
|
||||
val isSingleWalletWithToken = userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
|
||||
private fun createMultiWalletActions(userWallet: UserWallet): PersistentList<WalletManageButton> {
|
||||
val isSingleWalletWithToken =
|
||||
userWallet is UserWallet.Cold && userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
|
||||
if (isSingleWalletWithToken) return persistentListOf()
|
||||
|
||||
return persistentListOf(
|
||||
WalletManageButton.Buy(
|
||||
enabled = true,
|
||||
dimContent = false,
|
||||
onClick = { clickIntents.onMultiWalletBuyClick(userWalletId = userWallet.walletId, WALLET_TYPE) },
|
||||
onClick = {
|
||||
clickIntents.onMultiWalletBuyClick(
|
||||
userWalletId = userWallet.walletId,
|
||||
WALLET_TYPE,
|
||||
)
|
||||
},
|
||||
),
|
||||
WalletManageButton.Swap(
|
||||
enabled = true,
|
||||
|
|
@ -124,14 +152,24 @@ internal class WalletLoadingStateFactory(
|
|||
|
||||
private fun createVisaDimmedButtons(): PersistentList<WalletManageButton> {
|
||||
return persistentListOf(
|
||||
WalletManageButton.Receive(enabled = true, dimContent = true, onClick = {}, onLongClick = null),
|
||||
WalletManageButton.Receive(
|
||||
enabled = true,
|
||||
dimContent = true,
|
||||
onClick = {},
|
||||
onLongClick = null,
|
||||
),
|
||||
WalletManageButton.Buy(enabled = true, dimContent = true, onClick = {}),
|
||||
)
|
||||
}
|
||||
|
||||
private fun createDimmedButtons(): PersistentList<WalletManageButton> {
|
||||
return persistentListOf(
|
||||
WalletManageButton.Receive(enabled = true, dimContent = true, onClick = {}, onLongClick = null),
|
||||
WalletManageButton.Receive(
|
||||
enabled = true,
|
||||
dimContent = true,
|
||||
onClick = {},
|
||||
onLongClick = null,
|
||||
),
|
||||
WalletManageButton.Send(enabled = true, dimContent = true, onClick = {}),
|
||||
WalletManageButton.Buy(enabled = true, dimContent = true, onClick = {}),
|
||||
WalletManageButton.Sell(enabled = true, dimContent = true, onClick = {}),
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.subscribers
|
||||
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.common.routing.RoutingFeatureToggle
|
||||
import com.tangem.core.deeplink.DeepLinksRegistry
|
||||
import com.tangem.core.deeplink.global.ReferralDeepLink
|
||||
import com.tangem.core.deeplink.global.SellCurrencyDeepLink
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.core.lce.Lce
|
||||
|
|
@ -39,8 +35,6 @@ internal abstract class BasicTokenListSubscriber(
|
|||
private val walletWithFundsChecker: WalletWithFundsChecker,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase,
|
||||
private val deepLinksRegistry: DeepLinksRegistry,
|
||||
private val routingFeatureToggle: RoutingFeatureToggle,
|
||||
) : WalletSubscriber() {
|
||||
|
||||
private val sendAnalyticsJobHolder = JobHolder()
|
||||
|
|
@ -48,6 +42,8 @@ internal abstract class BasicTokenListSubscriber(
|
|||
|
||||
protected abstract fun tokenListFlow(coroutineScope: CoroutineScope): LceFlow<TokenListError, TokenList>
|
||||
|
||||
protected abstract suspend fun onTokenListReceived(maybeTokenList: Lce<TokenListError, TokenList>)
|
||||
|
||||
override fun create(coroutineScope: CoroutineScope): Flow<*> {
|
||||
return combine(
|
||||
flow = tokenListFlow(coroutineScope)
|
||||
|
|
@ -114,21 +110,6 @@ internal abstract class BasicTokenListSubscriber(
|
|||
}
|
||||
}
|
||||
|
||||
protected open suspend fun onTokenListReceived(maybeTokenList: Lce<TokenListError, TokenList>) {
|
||||
if (!routingFeatureToggle.isDeepLinkNavigationEnabled) {
|
||||
/* no-op */
|
||||
// Handling sell deeplink requires full content in order to correctly open Send screen
|
||||
if (maybeTokenList.getOrNull(false) != null) {
|
||||
deepLinksRegistry.triggerDelayedDeeplink(deepLinkClass = SellCurrencyDeepLink::class.java)
|
||||
}
|
||||
// Handling referral deeplink requires only selected wallet to be loaded
|
||||
// This is temporary solution, will be removed with complete deeplink navigation overhaul
|
||||
if (maybeTokenList.getOrNull(true) != null) {
|
||||
deepLinksRegistry.triggerDelayedDeeplink(deepLinkClass = ReferralDeepLink::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun sendTokenListAnalytics(maybeTokenList: Lce<TokenListError, TokenList>) {
|
||||
val displayedState = stateHolder.getWalletStateIfSelected(userWallet.walletId)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.subscribers
|
||||
|
||||
import com.tangem.common.routing.RoutingFeatureToggle
|
||||
import com.tangem.core.deeplink.DeepLinksRegistry
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.core.lce.Lce
|
||||
import com.tangem.domain.core.lce.LceFlow
|
||||
|
|
@ -30,8 +28,6 @@ internal class MultiWalletTokenListSubscriber(
|
|||
walletWithFundsChecker: WalletWithFundsChecker,
|
||||
getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase,
|
||||
deepLinksRegistry: DeepLinksRegistry,
|
||||
routingFeatureToggle: RoutingFeatureToggle,
|
||||
) : BasicTokenListSubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateHolder,
|
||||
|
|
@ -40,8 +36,6 @@ internal class MultiWalletTokenListSubscriber(
|
|||
walletWithFundsChecker = walletWithFundsChecker,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase,
|
||||
deepLinksRegistry = deepLinksRegistry,
|
||||
routingFeatureToggle = routingFeatureToggle,
|
||||
) {
|
||||
|
||||
override fun tokenListFlow(coroutineScope: CoroutineScope): LceFlow<TokenListError, TokenList> {
|
||||
|
|
@ -52,7 +46,6 @@ internal class MultiWalletTokenListSubscriber(
|
|||
|
||||
override suspend fun onTokenListReceived(maybeTokenList: Lce<TokenListError, TokenList>) {
|
||||
updateSortingIfNeeded(maybeTokenList)
|
||||
super.onTokenListReceived(maybeTokenList)
|
||||
}
|
||||
|
||||
private suspend fun updateSortingIfNeeded(maybeTokenList: Lce<*, TokenList>) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.subscribers
|
||||
|
||||
import com.tangem.common.routing.RoutingFeatureToggle
|
||||
import com.tangem.core.deeplink.DeepLinksRegistry
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.core.lce.Lce
|
||||
import com.tangem.domain.core.lce.LceFlow
|
||||
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
|
|
@ -17,7 +16,7 @@ import kotlinx.coroutines.CoroutineScope
|
|||
|
||||
@Suppress("LongParameterList")
|
||||
internal class SingleWalletWithTokenListSubscriber(
|
||||
private val userWallet: UserWallet,
|
||||
private val userWallet: UserWallet.Cold,
|
||||
private val tokenListStore: MultiWalletTokenListStore,
|
||||
stateHolder: WalletStateController,
|
||||
clickIntents: WalletClickIntents,
|
||||
|
|
@ -25,8 +24,6 @@ internal class SingleWalletWithTokenListSubscriber(
|
|||
walletWithFundsChecker: WalletWithFundsChecker,
|
||||
getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase,
|
||||
deepLinksRegistry: DeepLinksRegistry,
|
||||
routingFeatureToggle: RoutingFeatureToggle,
|
||||
) : BasicTokenListSubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateHolder,
|
||||
|
|
@ -35,8 +32,6 @@ internal class SingleWalletWithTokenListSubscriber(
|
|||
walletWithFundsChecker = walletWithFundsChecker,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase,
|
||||
deepLinksRegistry = deepLinksRegistry,
|
||||
routingFeatureToggle = routingFeatureToggle,
|
||||
) {
|
||||
|
||||
override fun tokenListFlow(coroutineScope: CoroutineScope): LceFlow<TokenListError, TokenList> {
|
||||
|
|
@ -44,4 +39,6 @@ internal class SingleWalletWithTokenListSubscriber(
|
|||
|
||||
return tokenListStore.getOrThrow(userWallet.walletId)
|
||||
}
|
||||
|
||||
override suspend fun onTokenListReceived(maybeTokenList: Lce<TokenListError, TokenList>) = Unit
|
||||
}
|
||||
|
|
@ -13,7 +13,6 @@ import com.tangem.domain.txhistory.models.TxHistoryStateError
|
|||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.collectLatest
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
|
|
@ -32,7 +31,7 @@ typealias MaybeTxHistoryItems = Either<TxHistoryListError, Flow<PagingData<TxInf
|
|||
|
||||
@Suppress("LongParameterList")
|
||||
internal class TxHistorySubscriber(
|
||||
private val userWallet: UserWallet,
|
||||
private val userWallet: UserWallet.Cold,
|
||||
private val isRefresh: Boolean,
|
||||
private val stateHolder: WalletStateController,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
|
|
@ -97,7 +96,7 @@ internal class TxHistorySubscriber(
|
|||
)
|
||||
},
|
||||
ifRight = { itemsFlow ->
|
||||
val blockchain = userWallet.requireColdWallet().scanResponse.cardTypesResolver.getBlockchain()
|
||||
val blockchain = userWallet.scanResponse.cardTypesResolver.getBlockchain()
|
||||
val itemConverter = TxHistoryItemStateConverter(
|
||||
symbol = blockchain.currency,
|
||||
decimals = blockchain.decimals(),
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import kotlinx.coroutines.flow.map
|
|||
import timber.log.Timber
|
||||
|
||||
internal class VisaWalletSubscriber(
|
||||
private val userWallet: UserWallet,
|
||||
private val userWallet: UserWallet.Cold,
|
||||
private val stateController: WalletStateController,
|
||||
private val isRefresh: Boolean,
|
||||
private val getVisaCurrencyUseCase: GetVisaCurrencyUseCase,
|
||||
|
|
|
|||
|
|
@ -62,7 +62,8 @@ import com.tangem.core.ui.res.LocalMainBottomSheetColor
|
|||
import com.tangem.core.ui.res.LocalWindowSize
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.test.TestTags
|
||||
import com.tangem.core.ui.test.MainScreenTestTags
|
||||
import com.tangem.core.ui.test.MarketTooltipTestTags
|
||||
import com.tangem.core.ui.utils.lineTo
|
||||
import com.tangem.core.ui.utils.moveTo
|
||||
import com.tangem.core.ui.utils.toPx
|
||||
|
|
@ -178,7 +179,7 @@ private fun WalletContent(
|
|||
} ?: PaddingValues(bottom = TangemTheme.dimens.spacing92 + bottomBarHeight)
|
||||
|
||||
LazyColumn(
|
||||
modifier = Modifier.testTag(TestTags.MAIN_SCREEN),
|
||||
modifier = Modifier.testTag(MainScreenTestTags.SCREEN_CONTAINER),
|
||||
state = listState,
|
||||
contentPadding = contentPadding,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
|
|
@ -490,7 +491,9 @@ private fun MarketsTooltip(
|
|||
|
||||
val slideOffset = 40.dp.toPx()
|
||||
AnimatedVisibility(
|
||||
modifier = modifier.offset { IntOffset(x = 0, y = tooltipOffset.roundToPx()) },
|
||||
modifier = modifier
|
||||
.offset { IntOffset(x = 0, y = tooltipOffset.roundToPx()) }
|
||||
.testTag(MarketTooltipTestTags.CONTAINER),
|
||||
visible = visible,
|
||||
enter = slideIn(
|
||||
animationSpec = spring(
|
||||
|
|
|
|||
|
|
@ -20,11 +20,13 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.test.MainScreenTestTags
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.common.WalletCard
|
||||
|
|
@ -63,7 +65,9 @@ internal fun WalletsList(
|
|||
WalletCard(
|
||||
state = state,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
modifier = Modifier.width(itemWidth),
|
||||
modifier = Modifier
|
||||
.width(itemWidth)
|
||||
.testTag(MainScreenTestTags.WALLET_LIST_ITEM),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import androidx.compose.ui.layout.ContentScale
|
|||
import androidx.compose.ui.layout.onSizeChanged
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
|
|
@ -48,6 +49,7 @@ import com.tangem.core.ui.extensions.resolveReference
|
|||
import com.tangem.core.ui.res.TangemDimens
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.test.MainScreenTestTags
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletDropDownItems
|
||||
|
|
@ -278,7 +280,9 @@ private fun Balance(state: WalletCardState, isBalanceHidden: Boolean, modifier:
|
|||
when (state) {
|
||||
is WalletCardState.Content -> {
|
||||
ResizableText(
|
||||
modifier = Modifier.defaultMinSize(minHeight = TangemTheme.dimens.size32),
|
||||
modifier = Modifier
|
||||
.defaultMinSize(minHeight = TangemTheme.dimens.size32)
|
||||
.testTag(MainScreenTestTags.WALLET_BALANCE),
|
||||
text = balance,
|
||||
fontSizeRange = FontSizeRange(min = 16.sp, max = TangemTheme.typography.h2.fontSize),
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
|
|
|
|||
|
|
@ -9,8 +9,7 @@ import androidx.compose.ui.res.painterResource
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.test.TestTags.MAIN_SCREEN_MORE_BUTTON
|
||||
import com.tangem.core.ui.test.TestTags.MAIN_SCREEN_TOP_BAR
|
||||
import com.tangem.core.ui.test.MainScreenTestTags
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTopBarConfig
|
||||
|
|
@ -28,7 +27,7 @@ internal fun WalletTopBar(config: WalletTopBarConfig) {
|
|||
Icon(painter = painterResource(id = R.drawable.img_tangem_logo_90_24), contentDescription = null)
|
||||
},
|
||||
actions = {
|
||||
IconButton(onClick = config.onDetailsClick, modifier = Modifier.testTag(MAIN_SCREEN_MORE_BUTTON)) {
|
||||
IconButton(onClick = config.onDetailsClick, modifier = Modifier.testTag(MainScreenTestTags.MORE_BUTTON)) {
|
||||
Icon(painter = painterResource(id = R.drawable.ic_more_vertical_24), contentDescription = null)
|
||||
}
|
||||
},
|
||||
|
|
@ -38,7 +37,7 @@ internal fun WalletTopBar(config: WalletTopBarConfig) {
|
|||
actionIconContentColor = TangemTheme.colors.icon.primary1,
|
||||
),
|
||||
scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(),
|
||||
modifier = Modifier.testTag(MAIN_SCREEN_TOP_BAR),
|
||||
modifier = Modifier.testTag(MainScreenTestTags.TOP_BAR),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,13 +10,17 @@ import androidx.compose.material3.Icon
|
|||
import androidx.compose.material3.Text
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import com.tangem.core.ui.components.tokenlist.TokenListItem
|
||||
import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
|
||||
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.test.MainScreenTestTags
|
||||
import com.tangem.core.ui.utils.lazyListItemPosition
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTokensListState
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
@ -61,11 +65,14 @@ private fun LazyListScope.contentItems(
|
|||
TokenListItem(
|
||||
state = item,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
modifier = modifier.roundedShapeItemDecoration(
|
||||
currentIndex = index,
|
||||
lastIndex = items.lastIndex,
|
||||
backgroundColor = TangemTheme.colors.background.primary,
|
||||
),
|
||||
modifier = modifier
|
||||
.roundedShapeItemDecoration(
|
||||
currentIndex = index,
|
||||
lastIndex = items.lastIndex,
|
||||
backgroundColor = TangemTheme.colors.background.primary,
|
||||
)
|
||||
.testTag(MainScreenTestTags.TOKEN_LIST_ITEM)
|
||||
.semantics { lazyListItemPosition = index },
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import com.tangem.domain.balancehiding.BalanceHidingSettings
|
|||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.core.lce.Lce
|
||||
import com.tangem.domain.core.lce.lce
|
||||
import com.tangem.domain.core.utils.getOrElse
|
||||
import com.tangem.domain.core.utils.toLce
|
||||
import com.tangem.domain.models.ArtworkModel
|
||||
import com.tangem.domain.tokens.GetWalletTotalBalanceUseCase
|
||||
|
|
@ -22,12 +21,12 @@ import com.tangem.domain.tokens.model.TotalFiatBalance
|
|||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.isMultiCurrency
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.domain.wallets.usecase.GetCardImageUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.features.wallet.utils.UserWalletsFetcher
|
||||
import com.tangem.operations.attestation.ArtworkSize
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
|
@ -46,6 +45,7 @@ internal class DefaultUserWalletsFetcher @AssistedInject constructor(
|
|||
@Assisted private val messageSender: UiMessageSender,
|
||||
@Assisted private val onlyMultiCurrency: Boolean,
|
||||
private val getCardImageUseCase: GetCardImageUseCase,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
) : UserWalletsFetcher {
|
||||
|
||||
private var loadedArtworks: HashMap<UserWalletId, ArtworkModel> = hashMapOf()
|
||||
|
|
@ -54,7 +54,7 @@ internal class DefaultUserWalletsFetcher @AssistedInject constructor(
|
|||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override val userWallets: Flow<ImmutableList<UserWalletItemUM>> = walletsFlow.transformLatest { wallets ->
|
||||
val uiModels = UserWalletItemUMConverter(onClick = { onWalletClick(it) }).convertList(wallets)
|
||||
val uiModels = UserWalletItemUMConverter(onClick = onWalletClick).convertList(wallets)
|
||||
.toImmutableList()
|
||||
|
||||
emit(uiModels)
|
||||
|
|
@ -65,31 +65,31 @@ internal class DefaultUserWalletsFetcher @AssistedInject constructor(
|
|||
flow3 = getWalletTotalBalanceUseCase(wallets.map(UserWallet::walletId)).distinctUntilChanged(),
|
||||
flow4 = loadArtworks(wallets),
|
||||
) { maybeAppCurrency, balanceHidingSettings, maybeBalances, artworks ->
|
||||
val models = createUiModels(
|
||||
createUiModels(
|
||||
wallets = wallets,
|
||||
maybeAppCurrency = maybeAppCurrency,
|
||||
maybeBalances = maybeBalances,
|
||||
balanceHidingSettings = balanceHidingSettings,
|
||||
artworks = artworks,
|
||||
).getOrElse(
|
||||
ifLoading = { return@combine },
|
||||
ifError = {
|
||||
val message = resourceReference(R.string.common_unknown_error)
|
||||
messageSender.send(SnackbarMessage(message))
|
||||
|
||||
return@combine
|
||||
},
|
||||
)
|
||||
|
||||
emit(models)
|
||||
}.collect()
|
||||
}
|
||||
.collectLatest { lceItems: Lce<Error, ImmutableList<UserWalletItemUM>> ->
|
||||
when (lceItems) {
|
||||
is Lce.Content<ImmutableList<UserWalletItemUM>> -> emit(lceItems.content)
|
||||
is Lce.Error<Error> -> {
|
||||
val message = resourceReference(R.string.common_unknown_error)
|
||||
messageSender.send(SnackbarMessage(message))
|
||||
}
|
||||
is Lce.Loading<*> -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
.flowOn(dispatchers.default)
|
||||
|
||||
private fun loadArtworks(wallets: List<UserWallet>): Flow<HashMap<UserWalletId, ArtworkModel>> {
|
||||
return flow {
|
||||
emit(hashMapOf()) // emits right away so the transform doesn't wait for the images' loading to finish
|
||||
wallets.forEach { wallet ->
|
||||
wallet.requireColdWallet()
|
||||
wallets.filterIsInstance<UserWallet.Cold>().forEach { wallet ->
|
||||
val artwork = getCardImageUseCase(
|
||||
cardId = wallet.cardId,
|
||||
manufacturerName = wallet.scanResponse.card.manufacturer.name,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue