Updated on 2026-08-14
This commit is contained in:
parent
a13ace780e
commit
d42cb2a79e
30 changed files with 397 additions and 24 deletions
|
|
@ -9,6 +9,7 @@ import com.tangem.feature.stories.api.StoriesComponent
|
|||
import com.tangem.feature.usedesk.api.UsedeskComponent
|
||||
import com.tangem.feature.walletsettings.component.WalletSettingsComponent
|
||||
import com.tangem.features.account.AccountCreateEditComponent
|
||||
import com.tangem.features.commonfeatures.api.addfunds.AddFundsComponent
|
||||
import com.tangem.features.account.AccountDetailsComponent
|
||||
import com.tangem.features.account.ArchivedAccountListComponent
|
||||
import com.tangem.features.createwalletselection.CreateWalletSelectionComponent
|
||||
|
|
@ -111,6 +112,7 @@ internal class ChildFactory @Inject constructor(
|
|||
private val kycComponentFactory: KycComponent.Factory,
|
||||
private val yieldSupplyEntryComponentFactory: YieldSupplyEntryComponent.Factory,
|
||||
private val feedEntryComponentFactory: FeedEntryComponent.Factory,
|
||||
private val addFundsComponentFactory: AddFundsComponent.Factory,
|
||||
) {
|
||||
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
|
|
@ -227,6 +229,13 @@ internal class ChildFactory @Inject constructor(
|
|||
componentFactory = buyCryptoComponentFactory,
|
||||
)
|
||||
}
|
||||
is AppRoute.AddFunds -> {
|
||||
createComponentChild(
|
||||
context = context,
|
||||
params = AddFundsComponent.Params(userWalletId = route.userWalletId),
|
||||
componentFactory = addFundsComponentFactory,
|
||||
)
|
||||
}
|
||||
is AppRoute.SellCrypto -> {
|
||||
createComponentChild(
|
||||
context = context,
|
||||
|
|
|
|||
|
|
@ -58,6 +58,11 @@ sealed class AppRoute(val path: String) : Route {
|
|||
@Serializable
|
||||
data object Wallet : AppRoute(path = "/wallet")
|
||||
|
||||
@Serializable
|
||||
data class AddFunds(
|
||||
val userWalletId: UserWalletId,
|
||||
) : AppRoute(path = "/add_funds/${userWalletId.stringValue}")
|
||||
|
||||
@Serializable
|
||||
data class CurrencyDetails(
|
||||
val userWalletId: UserWalletId,
|
||||
|
|
|
|||
|
|
@ -74,5 +74,9 @@
|
|||
{
|
||||
"name": "TWI_1403_PUSH_NOTIFICATION_SETTINGS_ENABLED",
|
||||
"version": "undefined"
|
||||
},
|
||||
{
|
||||
"name": "AND_15310_ADD_FUNDS_STAGE1",
|
||||
"version": "undefined"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
package com.tangem.features.commonfeatures.api.addfunds
|
||||
|
||||
import com.tangem.core.decompose.factory.ComponentFactory
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
||||
interface AddFundsComponent : ComposableContentComponent {
|
||||
|
||||
data class Params(
|
||||
val userWalletId: UserWalletId,
|
||||
)
|
||||
|
||||
interface Factory : ComponentFactory<Params, AddFundsComponent>
|
||||
}
|
||||
|
|
@ -41,6 +41,11 @@ interface ChooseTokenBridge : ChooseTokenBridgeInternal {
|
|||
isShowMarketBlock = true,
|
||||
isShowPaymentAccount = true,
|
||||
)
|
||||
val AddFunds = Settings(
|
||||
title = resourceReference(R.string.swapping_to_title),
|
||||
isShowMarketBlock = true,
|
||||
isShowPaymentAccount = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
package com.tangem.features.commonfeatures.impl.addfunds
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.context.child
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemeRedesign
|
||||
import com.tangem.features.commonfeatures.api.addfunds.AddFundsComponent
|
||||
import com.tangem.features.commonfeatures.api.choosetoken.ChooseTokenComponent
|
||||
import com.tangem.features.commonfeatures.impl.R
|
||||
import com.tangem.features.commonfeatures.impl.addfunds.model.AddFundsModel
|
||||
import com.tangem.features.commonfeatures.impl.addtoportfolio.TokenActionsComponent
|
||||
import com.tangem.features.commonfeatures.impl.addtoportfolio.analytics.PortfolioAnalyticsEvent
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
internal class DefaultAddFundsComponent @AssistedInject constructor(
|
||||
@Assisted appComponentContext: AppComponentContext,
|
||||
@Assisted private val params: AddFundsComponent.Params,
|
||||
chooseTokenComponentFactory: ChooseTokenComponent.Factory,
|
||||
tokenActionsComponentFactory: TokenActionsComponent.Factory,
|
||||
) : AppComponentContext by appComponentContext, AddFundsComponent {
|
||||
|
||||
private val model: AddFundsModel = getOrCreateModel(params)
|
||||
|
||||
private val chooseTokenComponent: ChooseTokenComponent = chooseTokenComponentFactory.create(
|
||||
context = child(key = "addFundsChooseToken"),
|
||||
params = ChooseTokenComponent.Params(bridge = model.chooseTokenBridge),
|
||||
)
|
||||
|
||||
private val tokenActionsComponent: TokenActionsComponent = tokenActionsComponentFactory.create(
|
||||
context = child(key = "addFundsTokenActions"),
|
||||
params = TokenActionsComponent.Params(
|
||||
eventBuilder = PortfolioAnalyticsEvent.EventBuilder(
|
||||
tokenSymbol = "",
|
||||
source = ANALYTICS_SOURCE,
|
||||
category = ANALYTICS_CATEGORY,
|
||||
),
|
||||
data = model.tokenActionsData,
|
||||
callbacks = model,
|
||||
bottomAction = TokenActionsComponent.BottomAction.GoToToken,
|
||||
isRedesignForced = true,
|
||||
),
|
||||
)
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
chooseTokenComponent.Content(modifier)
|
||||
val isTokenActionsShown by model.isTokenActionsShown.collectAsStateWithLifecycle()
|
||||
if (isTokenActionsShown) {
|
||||
// force use redesign theme here according to the task requirements, will be reworked in the next release
|
||||
TangemThemeRedesign {
|
||||
TangemModalBottomSheet<TangemBottomSheetConfigContent.Empty>(
|
||||
config = TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
onDismissRequest = model::onTokenActionsDismiss,
|
||||
content = TangemBottomSheetConfigContent.Empty,
|
||||
),
|
||||
containerColor = TangemTheme.colors2.surface.level2,
|
||||
scrollableContent = true,
|
||||
title = {
|
||||
TangemModalBottomSheetTitle(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
title = resourceReference(R.string.common_get_token),
|
||||
endIconRes = R.drawable.ic_close_24,
|
||||
onEndClick = model::onTokenActionsDismiss,
|
||||
)
|
||||
},
|
||||
content = { _ ->
|
||||
Column(
|
||||
modifier = Modifier.padding(
|
||||
start = TangemTheme.dimens2.x4,
|
||||
top = TangemTheme.dimens2.x2,
|
||||
end = TangemTheme.dimens2.x4,
|
||||
bottom = TangemTheme.dimens2.x4,
|
||||
),
|
||||
) {
|
||||
tokenActionsComponent.Content(Modifier)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : AddFundsComponent.Factory {
|
||||
override fun create(context: AppComponentContext, params: AddFundsComponent.Params): DefaultAddFundsComponent
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val ANALYTICS_SOURCE = "AddFunds"
|
||||
const val ANALYTICS_CATEGORY = "Add Funds"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.features.commonfeatures.impl.addfunds.di
|
||||
|
||||
import com.tangem.features.commonfeatures.api.addfunds.AddFundsComponent
|
||||
import com.tangem.features.commonfeatures.impl.addfunds.DefaultAddFundsComponent
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface AddFundsComponentModule {
|
||||
|
||||
@Binds
|
||||
fun bindAddFundsComponentFactory(factory: DefaultAddFundsComponent.Factory): AddFundsComponent.Factory
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.tangem.features.commonfeatures.impl.addfunds.di
|
||||
|
||||
import com.tangem.core.decompose.di.ModelComponent
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.features.commonfeatures.impl.addfunds.model.AddFundsModel
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.multibindings.ClassKey
|
||||
import dagger.multibindings.IntoMap
|
||||
|
||||
@Module
|
||||
@InstallIn(ModelComponent::class)
|
||||
internal interface AddFundsModelModule {
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(AddFundsModel::class)
|
||||
fun addFundsModel(model: AddFundsModel): Model
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
package com.tangem.features.commonfeatures.impl.addfunds.model
|
||||
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.common.ui.markets.action.CryptoCurrencyData
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.domain.account.status.usecase.GetCryptoCurrencyActionsUseCaseV2
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.features.commonfeatures.api.addfunds.AddFundsComponent
|
||||
import com.tangem.features.commonfeatures.api.choosetoken.ChooseTokenAnalyticsPayload
|
||||
import com.tangem.features.commonfeatures.api.choosetoken.ChooseTokenBridge
|
||||
import com.tangem.features.commonfeatures.api.choosetoken.ChooseTokenResult
|
||||
import com.tangem.features.commonfeatures.impl.addtoportfolio.TokenActionsComponent
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@ModelScoped
|
||||
internal class AddFundsModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
chooseTokenBridgeFactory: ChooseTokenBridge.Factory,
|
||||
private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCaseV2,
|
||||
private val appRouter: AppRouter,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
) : Model(), TokenActionsComponent.Callbacks {
|
||||
|
||||
private val params = paramsContainer.require<AddFundsComponent.Params>()
|
||||
|
||||
val chooseTokenBridge: ChooseTokenBridge = chooseTokenBridgeFactory.create(
|
||||
modelScope = modelScope,
|
||||
settings = ChooseTokenBridge.Settings.AddFunds,
|
||||
analyticsPayload = setOf(
|
||||
ChooseTokenAnalyticsPayload.ScreensSources(SCREEN_SOURCE),
|
||||
),
|
||||
)
|
||||
|
||||
private val selectedToken = MutableStateFlow<ChooseTokenResult?>(null)
|
||||
|
||||
val isTokenActionsShown: StateFlow<Boolean> = selectedToken
|
||||
.map { it != null }
|
||||
.stateIn(modelScope, SharingStarted.Eagerly, initialValue = false)
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
val tokenActionsData: Flow<CryptoCurrencyData> = selectedToken
|
||||
.filterNotNull()
|
||||
.flatMapLatest { result ->
|
||||
val cryptoPortfolio = result.account as? AccountStatus.CryptoPortfolio
|
||||
?: return@flatMapLatest emptyFlow()
|
||||
getCryptoCurrencyActionsUseCase(
|
||||
accountId = cryptoPortfolio.account.accountId,
|
||||
currency = result.currency.currency,
|
||||
).map { actionsState ->
|
||||
CryptoCurrencyData(
|
||||
userWallet = result.wallet,
|
||||
status = result.currency,
|
||||
actions = actionsState.states,
|
||||
isAccountMode = false,
|
||||
account = cryptoPortfolio,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
chooseTokenBridge.selectWalletTab(params.userWalletId)
|
||||
observeBridge()
|
||||
}
|
||||
|
||||
override fun onBottomActionClick() {
|
||||
val result = selectedToken.value ?: return
|
||||
selectedToken.value = null
|
||||
appRouter.replaceCurrent(
|
||||
AppRoute.CurrencyDetails(
|
||||
userWalletId = result.wallet.walletId,
|
||||
currency = result.currency.currency,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fun onTokenActionsDismiss() {
|
||||
selectedToken.value = null
|
||||
}
|
||||
|
||||
private fun observeBridge() {
|
||||
modelScope.launch {
|
||||
chooseTokenBridge.onCurrencyChosen.receiveAsFlow().collect { result ->
|
||||
selectedToken.value = result
|
||||
}
|
||||
}
|
||||
modelScope.launch {
|
||||
chooseTokenBridge.onClose.receiveAsFlow().collect {
|
||||
appRouter.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val SCREEN_SOURCE = "AddFunds"
|
||||
}
|
||||
}
|
||||
|
|
@ -46,7 +46,7 @@ internal class TokenActionsComponent @AssistedInject constructor(
|
|||
val state = model.uiState.collectAsStateWithLifecycle()
|
||||
val bottomSheet by bottomSheetSlot.subscribeAsState()
|
||||
val tokenActionsUM = state.value ?: return
|
||||
if (LocalRedesignEnabled.current) {
|
||||
if (LocalRedesignEnabled.current || params.isRedesignForced) {
|
||||
TokenActionsContentV2(
|
||||
modifier = modifier,
|
||||
state = tokenActionsUM,
|
||||
|
|
@ -75,10 +75,14 @@ internal class TokenActionsComponent @AssistedInject constructor(
|
|||
val eventBuilder: PortfolioAnalyticsEvent.EventBuilder,
|
||||
val data: Flow<CryptoCurrencyData>,
|
||||
val callbacks: Callbacks,
|
||||
val bottomAction: BottomAction = BottomAction.Later,
|
||||
val isRedesignForced: Boolean = false,
|
||||
)
|
||||
|
||||
enum class BottomAction { Later, GoToToken }
|
||||
|
||||
interface Callbacks {
|
||||
fun onLaterClick()
|
||||
fun onBottomActionClick()
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
|
|
|
|||
|
|
@ -307,7 +307,7 @@ internal class AddToPortfolioModel @Inject constructor(
|
|||
.onEmpty { finishSuccessFlow(result) }
|
||||
.launchIn(this)
|
||||
|
||||
callbackDelegate.onLaterClick.receiveAsFlow().first()
|
||||
callbackDelegate.onChooseTokenBottomActionClick.receiveAsFlow().first()
|
||||
analyticsEventHandler.send(eventBuilder.getTokenLater())
|
||||
finishSuccessFlow(result)
|
||||
}
|
||||
|
|
@ -524,7 +524,7 @@ internal class AddToPortfolioCallbackDelegate @Inject constructor() :
|
|||
UserPortfolioComponent.Callbacks {
|
||||
|
||||
val onNetworkSelected = Channel<TokenMarketInfo.Network>()
|
||||
val onLaterClick = Channel<Unit>()
|
||||
val onChooseTokenBottomActionClick = Channel<Unit>()
|
||||
val onChangeNetworkClick = Channel<Unit>()
|
||||
val onChangePortfolioClick = Channel<Unit>()
|
||||
val onTokenAdded = Channel<CryptoCurrencyStatus>()
|
||||
|
|
@ -534,8 +534,8 @@ internal class AddToPortfolioCallbackDelegate @Inject constructor() :
|
|||
onNetworkSelected.trySend(network)
|
||||
}
|
||||
|
||||
override fun onLaterClick() {
|
||||
onLaterClick.trySend(Unit)
|
||||
override fun onBottomActionClick() {
|
||||
onChooseTokenBottomActionClick.trySend(Unit)
|
||||
}
|
||||
|
||||
override fun onChangeNetworkClick() {
|
||||
|
|
|
|||
|
|
@ -21,9 +21,12 @@ import com.tangem.core.ui.ds.badge.TangemBadgeShape
|
|||
import com.tangem.core.ui.ds.badge.TangemBadgeSize
|
||||
import com.tangem.core.ui.ds.badge.TangemBadgeUM
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.format.bigdecimal.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.commonfeatures.impl.R
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.usecase.GetWalletIconUseCase
|
||||
|
|
@ -48,7 +51,7 @@ internal class TokenActionsUiBuilder @Inject constructor(
|
|||
appCurrency: AppCurrency,
|
||||
isBalanceHidden: Boolean,
|
||||
): TokenActionsUM {
|
||||
return if (designFeatureToggles.isRedesignEnabled) {
|
||||
return if (designFeatureToggles.isRedesignEnabled || params.isRedesignForced) {
|
||||
buildV2(
|
||||
cryptoCurrencyData = cryptoCurrencyData,
|
||||
tokenActionsHandler = tokenActionsHandler,
|
||||
|
|
@ -85,8 +88,9 @@ internal class TokenActionsUiBuilder @Inject constructor(
|
|||
tokenActionsHandler = tokenActionsHandler,
|
||||
isRedesignEnabled = false,
|
||||
),
|
||||
onLaterClick = {
|
||||
params.callbacks.onLaterClick()
|
||||
bottomActionText = bottomActionText(params.bottomAction),
|
||||
onBottomActionClick = {
|
||||
params.callbacks.onBottomActionClick()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -115,14 +119,22 @@ internal class TokenActionsUiBuilder @Inject constructor(
|
|||
tokenActionsHandler = tokenActionsHandler,
|
||||
isRedesignEnabled = true,
|
||||
),
|
||||
onLaterClick = {
|
||||
params.callbacks.onLaterClick()
|
||||
bottomActionText = bottomActionText(params.bottomAction),
|
||||
onBottomActionClick = {
|
||||
params.callbacks.onBottomActionClick()
|
||||
},
|
||||
isBalancesHidden = isBalanceHidden,
|
||||
portfolioBadge = createPortfolioBadge(cryptoCurrencyData = cryptoCurrencyData),
|
||||
)
|
||||
}
|
||||
|
||||
private fun bottomActionText(action: TokenActionsComponent.BottomAction): TextReference {
|
||||
return when (action) {
|
||||
TokenActionsComponent.BottomAction.Later -> resourceReference(R.string.common_later)
|
||||
TokenActionsComponent.BottomAction.GoToToken -> resourceReference(R.string.common_go_to_token)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createPortfolioBadge(cryptoCurrencyData: CryptoCurrencyData): PortfolioBadgeUM {
|
||||
return if (cryptoCurrencyData.isAccountMode) {
|
||||
val icon = CryptoPortfolioIconConverter.convert(cryptoCurrencyData.account.account.icon)
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ import com.tangem.core.ui.components.token.TokenItem
|
|||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.haptic.TangemHapticEffect
|
||||
import com.tangem.core.ui.res.LocalHapticManager
|
||||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
|
|
@ -78,8 +77,8 @@ internal fun TokenActionsContent(state: TokenActionsUM, modifier: Modifier = Mod
|
|||
|
||||
SecondaryButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = stringResourceSafe(R.string.common_later),
|
||||
onClick = state.onLaterClick,
|
||||
text = state.bottomActionText.resolveReference(),
|
||||
onClick = state.onBottomActionClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -198,7 +197,8 @@ private class TokenActionsContentPreviewProvider : PreviewParameterProvider<Toke
|
|||
onQuickActionLongClick = {},
|
||||
),
|
||||
token = tokenState,
|
||||
onLaterClick = {},
|
||||
bottomActionText = stringReference("Later"),
|
||||
onBottomActionClick = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -78,8 +78,8 @@ internal fun TokenActionsContentV2(state: TokenActionsUM, modifier: Modifier = M
|
|||
CompositionLocalProvider(LocalHazeState provides rememberHazeState()) {
|
||||
SecondaryTangemButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onClick = state.onLaterClick,
|
||||
text = resourceReference(R.string.common_later),
|
||||
onClick = state.onBottomActionClick,
|
||||
text = state.bottomActionText,
|
||||
size = TangemButtonSize.X12,
|
||||
shape = TangemButtonShape.Rounded,
|
||||
)
|
||||
|
|
@ -234,7 +234,8 @@ private class TokenActionsContentPreviewProviderV2 : PreviewParameterProvider<To
|
|||
onQuickActionLongClick = {},
|
||||
),
|
||||
token = tokenState,
|
||||
onLaterClick = {},
|
||||
bottomActionText = resourceReference(R.string.common_later),
|
||||
onBottomActionClick = {},
|
||||
portfolioBadge = PortfolioBadgeUM.Wallet(
|
||||
name = stringReference("Wallet 2"),
|
||||
deviceIcon = DeviceIconUM.Stub(cardsCount = 2),
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ import com.tangem.core.ui.extensions.TextReference
|
|||
internal data class TokenActionsUM(
|
||||
val token: TokenItemState,
|
||||
val quickActions: QuickActions,
|
||||
val onLaterClick: () -> Unit,
|
||||
val bottomActionText: TextReference,
|
||||
val onBottomActionClick: () -> Unit,
|
||||
val isBalancesHidden: Boolean = false,
|
||||
val portfolioBadge: PortfolioBadgeUM = PortfolioBadgeUM.None,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,4 +8,6 @@ package com.tangem.features.wallet.featuretoggles
|
|||
interface WalletFeatureToggles {
|
||||
|
||||
val isAddAndManageTokensEnabled: Boolean
|
||||
|
||||
val isAddFundsStage1Enabled: Boolean
|
||||
}
|
||||
|
|
@ -63,6 +63,7 @@ import com.tangem.features.biometry.AskBiometryComponent
|
|||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsModelCallbacks
|
||||
import com.tangem.features.wallet.deeplink.WalletDeepLinkActionListener
|
||||
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.coroutines.*
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
|
|
@ -120,6 +121,7 @@ internal class WalletModel @Inject constructor(
|
|||
private val paymentAccountStatusFetcher: PaymentAccountStatusFetcher,
|
||||
private val uiMessageSender: UiMessageSender,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
private val walletFeatureToggles: WalletFeatureToggles,
|
||||
private val startAssetsDiscoveryUseCase: StartAssetsDiscoveryUseCase,
|
||||
val screenLifecycleProvider: ScreenLifecycleProvider,
|
||||
val innerWalletRouter: InnerWalletRouter,
|
||||
|
|
@ -544,6 +546,7 @@ internal class WalletModel @Inject constructor(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isAddFundsStage1Enabled = walletFeatureToggles.isAddFundsStage1Enabled,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -590,6 +593,7 @@ internal class WalletModel @Inject constructor(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isAddFundsStage1Enabled = walletFeatureToggles.isAddFundsStage1Enabled,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -611,6 +615,7 @@ internal class WalletModel @Inject constructor(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isAddFundsStage1Enabled = walletFeatureToggles.isAddFundsStage1Enabled,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -625,6 +630,7 @@ internal class WalletModel @Inject constructor(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isAddFundsStage1Enabled = walletFeatureToggles.isAddFundsStage1Enabled,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -686,6 +692,7 @@ internal class WalletModel @Inject constructor(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isAddFundsStage1Enabled = walletFeatureToggles.isAddFundsStage1Enabled,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.feature.wallet.child.wallet.model.intents
|
|||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.ui.DesignFeatureToggles
|
||||
import com.tangem.domain.exchange.RampStateManager
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.models.wallet.isLocked
|
||||
import com.tangem.domain.onramp.FetchHotCryptoUseCase
|
||||
import com.tangem.domain.settings.NeverToShowWalletsScrollPreview
|
||||
|
|
@ -114,6 +115,10 @@ internal class WalletClickIntents @Inject constructor(
|
|||
refreshSingleCurrencyContent(showRefreshState = true)
|
||||
}
|
||||
|
||||
fun onAddFundsClick(userWalletId: UserWalletId) {
|
||||
router.openAddFunds(userWalletId)
|
||||
}
|
||||
|
||||
private fun refreshMultiCurrencyContent(showRefreshState: Boolean) {
|
||||
val userWallet = getSelectedWalletSyncUseCase.unwrap() ?: return
|
||||
|
||||
|
|
|
|||
|
|
@ -11,4 +11,7 @@ internal class DefaultWalletFeatureToggles @Inject constructor(
|
|||
|
||||
override val isAddAndManageTokensEnabled: Boolean
|
||||
get() = featureToggles.isFeatureEnabled(FeatureToggles.ADD_AND_MANAGE_TOKENS_ENABLED)
|
||||
|
||||
override val isAddFundsStage1Enabled: Boolean
|
||||
get() = featureToggles.isFeatureEnabled(FeatureToggles.AND_15310_ADD_FUNDS_STAGE1)
|
||||
}
|
||||
|
|
@ -119,6 +119,10 @@ internal class DefaultWalletRouter @Inject constructor(
|
|||
router.push(AppRoute.Home())
|
||||
}
|
||||
|
||||
override fun openAddFunds(userWalletId: UserWalletId) {
|
||||
router.push(AppRoute.AddFunds(userWalletId = userWalletId))
|
||||
}
|
||||
|
||||
override fun isWalletLastScreen(): Boolean {
|
||||
return router.stack.lastOrNull() is AppRoute.Wallet
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,4 +117,7 @@ internal interface InnerWalletRouter {
|
|||
|
||||
/** Open network selection bottom sheet for multiple QR matches */
|
||||
fun openNetworkSelectionBottomSheet(target: QrSendTarget.Multiple)
|
||||
|
||||
/** Open Add Funds screen */
|
||||
fun openAddFunds(userWalletId: UserWalletId)
|
||||
}
|
||||
|
|
@ -51,6 +51,20 @@ internal sealed class WalletManageButton(val config: ActionButtonConfig) {
|
|||
),
|
||||
)
|
||||
|
||||
data class AddFunds(
|
||||
override val enabled: Boolean,
|
||||
override val dimContent: Boolean,
|
||||
override val onClick: () -> Unit,
|
||||
) : WalletManageButton(
|
||||
config = ActionButtonConfig(
|
||||
text = TextReference.Res(id = R.string.common_add_funds),
|
||||
iconResId = R.drawable.ic_plus_24,
|
||||
onClick = onClick,
|
||||
isEnabled = enabled,
|
||||
shouldDimContent = dimContent,
|
||||
),
|
||||
)
|
||||
|
||||
/**
|
||||
* Send
|
||||
*
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ internal class AddWalletTransformer(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
private val walletImageResolver: WalletImageResolver,
|
||||
private val getWalletIconUseCase: GetWalletIconUseCase,
|
||||
private val isAddFundsStage1Enabled: Boolean,
|
||||
) : WalletScreenStateTransformer {
|
||||
|
||||
private val walletLoadingStateFactory by lazy {
|
||||
|
|
@ -20,6 +21,7 @@ internal class AddWalletTransformer(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isAddFundsStage1Enabled = isAddFundsStage1Enabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ internal class InitializeWalletsTransformer(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
private val walletImageResolver: WalletImageResolver,
|
||||
private val getWalletIconUseCase: GetWalletIconUseCase,
|
||||
private val isAddFundsStage1Enabled: Boolean,
|
||||
) : WalletScreenStateTransformer {
|
||||
|
||||
private val walletLoadingStateFactory by lazy {
|
||||
|
|
@ -34,6 +35,7 @@ internal class InitializeWalletsTransformer(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isAddFundsStage1Enabled = isAddFundsStage1Enabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -147,8 +149,18 @@ internal class InitializeWalletsTransformer(
|
|||
userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
|
||||
if (isSingleWalletWithToken) return persistentListOf()
|
||||
|
||||
val firstButton = if (isAddFundsStage1Enabled) {
|
||||
WalletManageButton.AddFunds(
|
||||
enabled = false,
|
||||
dimContent = false,
|
||||
onClick = {},
|
||||
)
|
||||
} else {
|
||||
WalletManageButton.Buy(enabled = false, dimContent = false, onClick = {})
|
||||
}
|
||||
|
||||
return persistentListOf(
|
||||
WalletManageButton.Buy(enabled = false, dimContent = false, onClick = {}),
|
||||
firstButton,
|
||||
WalletManageButton.Swap(enabled = false, dimContent = false, onClick = {}),
|
||||
WalletManageButton.Sell(enabled = false, dimContent = false, onClick = {}),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ internal class ReinitializeNewWalletTransformer(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
private val walletImageResolver: WalletImageResolver,
|
||||
private val getWalletIconUseCase: GetWalletIconUseCase,
|
||||
private val isAddFundsStage1Enabled: Boolean,
|
||||
) : WalletScreenStateTransformer {
|
||||
|
||||
private val walletLoadingStateFactory by lazy {
|
||||
|
|
@ -31,6 +32,7 @@ internal class ReinitializeNewWalletTransformer(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isAddFundsStage1Enabled = isAddFundsStage1Enabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ internal class ReinitializeWalletTransformer(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
private val walletImageResolver: WalletImageResolver,
|
||||
private val getWalletIconUseCase: GetWalletIconUseCase,
|
||||
private val isAddFundsStage1Enabled: Boolean,
|
||||
) : WalletStateTransformer(userWalletId = userWallet.walletId) {
|
||||
|
||||
private val walletLoadingStateFactory by lazy {
|
||||
|
|
@ -27,6 +28,7 @@ internal class ReinitializeWalletTransformer(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isAddFundsStage1Enabled = isAddFundsStage1Enabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,10 +72,11 @@ internal class SetRefreshStateTransformer(
|
|||
private fun PersistentList<WalletManageButton>.toUpdatedState(): PersistentList<WalletManageButton> {
|
||||
val isButtonsEnabled = !isRefreshing
|
||||
|
||||
return mutate {
|
||||
it.mapNotNull { button ->
|
||||
return mutate { items ->
|
||||
items.mapNotNull { button ->
|
||||
when (button) {
|
||||
is WalletManageButton.Buy -> button.copy(enabled = isButtonsEnabled)
|
||||
is WalletManageButton.AddFunds -> button.copy(enabled = isButtonsEnabled)
|
||||
is WalletManageButton.Send -> button.copy(enabled = isButtonsEnabled)
|
||||
is WalletManageButton.Sell -> button.copy(enabled = isButtonsEnabled)
|
||||
is WalletManageButton.Receive -> button
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ internal class UnlockWalletTransformer(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
private val walletImageResolver: WalletImageResolver,
|
||||
private val getWalletIconUseCase: GetWalletIconUseCase,
|
||||
private val isAddFundsStage1Enabled: Boolean,
|
||||
) : WalletScreenStateTransformer {
|
||||
|
||||
private val walletLoadingStateFactory by lazy {
|
||||
|
|
@ -25,6 +26,7 @@ internal class UnlockWalletTransformer(
|
|||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
getWalletIconUseCase = getWalletIconUseCase,
|
||||
isAddFundsStage1Enabled = isAddFundsStage1Enabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ private fun WalletState.MultiCurrency.Content.changeAvailability(enabled: Boolea
|
|||
.map { action ->
|
||||
when (action) {
|
||||
is WalletManageButton.Buy -> action.copy(enabled = enabled)
|
||||
is WalletManageButton.AddFunds -> action.copy(enabled = enabled)
|
||||
is WalletManageButton.Sell -> action.copy(enabled = enabled)
|
||||
is WalletManageButton.Swap -> action.copy(enabled = enabled)
|
||||
else -> action
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ internal class WalletLoadingStateFactory(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
private val walletImageResolver: WalletImageResolver,
|
||||
private val getWalletIconUseCase: GetWalletIconUseCase,
|
||||
private val isAddFundsStage1Enabled: Boolean,
|
||||
) {
|
||||
|
||||
fun create(userWallet: UserWallet): WalletState {
|
||||
|
|
@ -149,7 +150,13 @@ internal class WalletLoadingStateFactory(
|
|||
userWallet is UserWallet.Cold && userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
|
||||
if (isSingleWalletWithToken) return persistentListOf()
|
||||
|
||||
return persistentListOf(
|
||||
val firstButton = if (isAddFundsStage1Enabled) {
|
||||
WalletManageButton.AddFunds(
|
||||
enabled = true,
|
||||
dimContent = false,
|
||||
onClick = { clickIntents.onAddFundsClick(userWallet.walletId) },
|
||||
)
|
||||
} else {
|
||||
WalletManageButton.Buy(
|
||||
enabled = true,
|
||||
dimContent = false,
|
||||
|
|
@ -159,7 +166,11 @@ internal class WalletLoadingStateFactory(
|
|||
WALLET_TYPE,
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
return persistentListOf(
|
||||
firstButton,
|
||||
WalletManageButton.Swap(
|
||||
enabled = true,
|
||||
dimContent = false,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue