Updated on 2026-08-14

This commit is contained in:
Tangem 2025-03-03 10:43:56 +05:00
parent 1266ffce6a
commit 0a767ba435
11 changed files with 127 additions and 23 deletions

View file

@ -188,6 +188,8 @@ dependencies {
implementation(projects.features.stories.impl)
implementation(projects.features.txhistory.api)
implementation(projects.features.txhistory.impl)
implementation(projects.features.nft.api)
implementation(projects.features.nft.impl)
/** AndroidX libraries */
implementation(deps.androidx.core.ktx)

View file

@ -121,7 +121,7 @@ object PreferencesKeys {
val SEED_FIRST_NOTIFICATION_SHOW_TIME by lazy { longPreferencesKey("seedFirstNotificationTime") }
val WALLETS_WITH_NFT_ENABLED_KEY by lazy { stringSetPreferencesKey(name = "walletsWithNftEnabled") }
val WALLETS_NFT_ENABLED_STATES_KEY by lazy { stringPreferencesKey(name = "walletsNftEnabledStates") }
fun getShouldShowStoriesKey(storyId: String) = booleanPreferencesKey("shouldShowStories_$storyId")

View file

@ -11,6 +11,7 @@ import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.datasource.local.preferences.PreferencesKeys.SEED_FIRST_NOTIFICATION_SHOW_TIME
import com.tangem.datasource.local.preferences.utils.get
import com.tangem.datasource.local.preferences.utils.getObjectMap
import com.tangem.datasource.local.preferences.utils.getSyncOrDefault
import com.tangem.datasource.local.preferences.utils.store
import com.tangem.datasource.local.userwallet.UserWalletsStore
@ -205,21 +206,27 @@ internal class DefaultWalletsRepository(
override fun nftEnabledStatus(userWalletId: UserWalletId): Flow<Boolean> {
return appPreferencesStore
.get(key = PreferencesKeys.WALLETS_WITH_NFT_ENABLED_KEY, default = emptySet())
.map { it.contains(userWalletId.stringValue) }
.getObjectMap<Boolean>(PreferencesKeys.WALLETS_NFT_ENABLED_STATES_KEY)
.map { !it.contains(userWalletId.stringValue) || it[userWalletId.stringValue] == true }
}
override suspend fun enableNFT(userWalletId: UserWalletId) {
appPreferencesStore.editData {
val added = it[PreferencesKeys.WALLETS_WITH_NFT_ENABLED_KEY].orEmpty()
it[PreferencesKeys.WALLETS_WITH_NFT_ENABLED_KEY] = added + userWalletId.stringValue
it.setObjectMap(
PreferencesKeys.WALLETS_NFT_ENABLED_STATES_KEY,
it.getObjectMap<Boolean>(PreferencesKeys.WALLETS_NFT_ENABLED_STATES_KEY)
.plus(userWalletId.stringValue to true),
)
}
}
override suspend fun disableNFT(userWalletId: UserWalletId) {
appPreferencesStore.editData {
val added = it[PreferencesKeys.WALLETS_WITH_NFT_ENABLED_KEY].orEmpty()
it[PreferencesKeys.WALLETS_WITH_NFT_ENABLED_KEY] = added - userWalletId.stringValue
it.setObjectMap(
PreferencesKeys.WALLETS_NFT_ENABLED_STATES_KEY,
it.getObjectMap<Boolean>(PreferencesKeys.WALLETS_NFT_ENABLED_STATES_KEY)
.plus(userWalletId.stringValue to false),
)
}
}
}

View file

@ -32,8 +32,8 @@ dependencies {
/** Tangem libraries */
implementation(projects.libs.tangemSdkApi)
implementation(deps.tangem.card.core)
implementation(deps.tangem.card.android) {
implementation(tangemDeps.card.core)
implementation(tangemDeps.card.android) {
exclude(module = "joda-time")
}

View file

@ -16,6 +16,7 @@ dependencies {
/* Project - API */
implementation(projects.features.walletSettings.api)
implementation(projects.features.manageTokens.api)
implementation(projects.features.nft.api)
/* Project - Core */
implementation(projects.core.decompose)

View file

@ -23,6 +23,9 @@ internal class PreviewWalletSettingsComponent : WalletSettingsComponent {
isReferralAvailable = true,
isLinkMoreCardsAvailable = true,
isRenameWalletAvailable = false,
isNFTFeatureEnabled = true,
isNFTEnabled = true,
onCheckedNFTChange = {},
renameWallet = {},
forgetWallet = {},
onLinkMoreCardsClick = {},

View file

@ -16,6 +16,13 @@ internal sealed class WalletSettingsItemUM {
val blocks: ImmutableList<BlockUM>,
) : WalletSettingsItemUM()
data class WithSwitch(
override val id: String,
val title: TextReference,
val isChecked: Boolean,
val onCheckedChange: (Boolean) -> Unit,
) : WalletSettingsItemUM()
data class WithText(
override val id: String,
val title: TextReference,

View file

@ -21,6 +21,7 @@ import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.redux.LegacyAction
import com.tangem.domain.redux.ReduxStateHolder
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.repository.WalletsRepository
import com.tangem.domain.wallets.usecase.DeleteWalletUseCase
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsSyncUseCase
@ -31,6 +32,7 @@ import com.tangem.feature.walletsettings.entity.WalletSettingsItemUM
import com.tangem.feature.walletsettings.entity.WalletSettingsUM
import com.tangem.feature.walletsettings.impl.R
import com.tangem.feature.walletsettings.utils.ItemsBuilder
import com.tangem.features.nft.NFTFeatureToggles
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.persistentListOf
@ -53,6 +55,8 @@ internal class WalletSettingsModel @Inject constructor(
private val analyticsContextProxy: AnalyticsContextProxy,
private val reduxStateHolder: ReduxStateHolder,
private val getShouldSaveUserWalletsSyncUseCase: ShouldSaveUserWalletsSyncUseCase,
private val walletsRepository: WalletsRepository,
private val nftFeatureToggles: NFTFeatureToggles,
) : Model() {
val params: WalletSettingsComponent.Params = paramsContainer.require()
@ -68,11 +72,19 @@ internal class WalletSettingsModel @Inject constructor(
init {
getWalletUseCase.invokeFlow(params.userWalletId)
.distinctUntilChanged()
.onEach { maybeWallet ->
val wallet = maybeWallet.getOrNull() ?: return@onEach
.combine(walletsRepository.nftEnabledStatus(params.userWalletId)) { maybeWallet, nftEnabled ->
val wallet = maybeWallet.getOrNull() ?: return@combine
val isRenameWalletAvailable = getShouldSaveUserWalletsSyncUseCase()
state.update { value ->
value.copy(items = buildItems(wallet, dialogNavigation, isRenameWalletAvailable))
value.copy(
items = buildItems(
userWallet = wallet,
dialogNavigation = dialogNavigation,
isRenameWalletAvailable = isRenameWalletAvailable,
isNFTFeatureEnabled = nftFeatureToggles.isNFTEnabled,
isNFTEnabled = nftEnabled,
),
)
}
}
.launchIn(modelScope)
@ -82,6 +94,8 @@ internal class WalletSettingsModel @Inject constructor(
userWallet: UserWallet,
dialogNavigation: SlotNavigation<DialogConfig>,
isRenameWalletAvailable: Boolean,
isNFTFeatureEnabled: Boolean,
isNFTEnabled: Boolean,
): PersistentList<WalletSettingsItemUM> = itemsBuilder.buildItems(
userWalletId = userWallet.walletId,
userWalletName = userWallet.name,
@ -90,6 +104,11 @@ internal class WalletSettingsModel @Inject constructor(
isManageTokensAvailable = userWallet.isMultiCurrency,
isRenameWalletAvailable = isRenameWalletAvailable,
renameWallet = { openRenameWalletDialog(userWallet, dialogNavigation) },
isNFTFeatureEnabled = isNFTFeatureEnabled,
isNFTEnabled = isNFTEnabled,
onCheckedNFTChange = { isChecked ->
onCheckedNFTChange(isChecked)
},
forgetWallet = {
val message = DialogMessage(
message = resourceReference(R.string.user_wallet_list_delete_prompt),
@ -151,4 +170,14 @@ internal class WalletSettingsModel @Inject constructor(
router.push(AppRoute.OnboardingWallet())
}
private fun onCheckedNFTChange(isChecked: Boolean) {
modelScope.launch {
if (isChecked) {
walletsRepository.enableNFT(params.userWalletId)
} else {
walletsRepository.disableNFT(params.userWalletId)
}
}
}
}

View file

@ -14,6 +14,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.components.TangemSwitch
import com.tangem.core.ui.components.appbar.TangemTopAppBar
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
import com.tangem.core.ui.components.block.BlockCard
@ -96,6 +97,10 @@ private fun Content(state: WalletSettingsUM, modifier: Modifier = Modifier) {
modifier = itemModifier,
model = item,
)
is WalletSettingsItemUM.WithSwitch -> SwitchBlock(
modifier = itemModifier,
model = item,
)
}
}
}
@ -165,6 +170,34 @@ private fun TextBlock(model: WalletSettingsItemUM.WithText, modifier: Modifier =
}
}
@Composable
private fun SwitchBlock(model: WalletSettingsItemUM.WithSwitch, modifier: Modifier = Modifier) {
BlockCard(
modifier = modifier.fillMaxWidth(),
enabled = model.isChecked,
) {
Row(
modifier = Modifier.padding(all = TangemTheme.dimens.spacing12),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12, Alignment.Start),
) {
Text(
modifier = Modifier.weight(1f),
text = model.title.resolveReference(),
style = TangemTheme.typography.subtitle1,
color = TangemTheme.colors.text.primary1,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
TangemSwitch(
checked = model.isChecked,
onCheckedChange = model.onCheckedChange,
)
}
}
}
// region Preview
@Composable
@Preview(showBackground = true, widthDp = 360)

View file

@ -31,20 +31,31 @@ internal class ItemsBuilder @Inject constructor(
isReferralAvailable: Boolean,
isManageTokensAvailable: Boolean,
isRenameWalletAvailable: Boolean,
isNFTFeatureEnabled: Boolean,
isNFTEnabled: Boolean,
onCheckedNFTChange: (Boolean) -> Unit,
forgetWallet: () -> Unit,
renameWallet: () -> Unit,
onLinkMoreCardsClick: () -> Unit,
): PersistentList<WalletSettingsItemUM> = persistentListOf(
buildNameItem(userWalletName, isRenameWalletAvailable, renameWallet),
buildCardItem(
userWalletId = userWalletId,
isLinkMoreCardsAvailable = isLinkMoreCardsAvailable,
isReferralAvailable = isReferralAvailable,
isManageTokensAvailable = isManageTokensAvailable,
onLinkMoreCardsClick = onLinkMoreCardsClick,
),
buildForgetItem(forgetWallet),
)
): PersistentList<WalletSettingsItemUM> = persistentListOf<WalletSettingsItemUM>()
.add(buildNameItem(userWalletName, isRenameWalletAvailable, renameWallet))
.run {
if (isNFTFeatureEnabled) {
add(buildNFTItem(isNFTEnabled, onCheckedNFTChange))
} else {
this
}
}
.add(
buildCardItem(
userWalletId = userWalletId,
isLinkMoreCardsAvailable = isLinkMoreCardsAvailable,
isReferralAvailable = isReferralAvailable,
isManageTokensAvailable = isManageTokensAvailable,
onLinkMoreCardsClick = onLinkMoreCardsClick,
),
)
.add(buildForgetItem(forgetWallet))
private fun buildNameItem(walletName: String, isRenameWalletAvailable: Boolean, renameWallet: () -> Unit) =
WalletSettingsItemUM.WithText(
@ -55,6 +66,14 @@ internal class ItemsBuilder @Inject constructor(
onClick = renameWallet,
)
private fun buildNFTItem(isNFTEnabled: Boolean, onCheckedNFTChange: (Boolean) -> Unit) =
WalletSettingsItemUM.WithSwitch(
id = "nft",
title = resourceReference(id = R.string.details_nft_title),
isChecked = isNFTEnabled,
onCheckedChange = onCheckedNFTChange,
)
private fun buildCardItem(
userWalletId: UserWalletId,
isLinkMoreCardsAvailable: Boolean,

View file

@ -227,6 +227,9 @@ include(":features:stories:impl")
include(":features:txhistory:api")
include(":features:txhistory:impl")
include(":features:nft:api")
include(":features:nft:impl")
// endregion Feature modules
// region Domain modules