Updated on 2026-08-14

This commit is contained in:
Tangem 2026-04-14 14:50:40 +04:00
parent aa03d39dc0
commit 49bd0090ff
18 changed files with 300 additions and 88 deletions

View file

@ -13,6 +13,10 @@ android {
namespace = "com.tangem.data.settings"
}
tasks.withType<Test>().configureEach {
useJUnitPlatform()
}
dependencies {
implementation(projects.core.datasource)
@ -28,6 +32,11 @@ dependencies {
kapt(deps.hilt.kapt)
// endregion
// region Test
testImplementation(projects.test.core)
testRuntimeOnly(deps.test.junit5.engine)
// endregion
// region Others dependencies
implementation(deps.jodatime)
implementation(deps.kotlin.coroutines)

View file

@ -0,0 +1,56 @@
package com.tangem.data.settings
import androidx.datastore.preferences.core.booleanPreferencesKey
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.utils.get
import com.tangem.domain.settings.HotWalletRestrictionManager
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.stateIn
/**
* Development implementation of [HotWalletRestrictionManager].
*
* Reads and writes the restriction state from [AppPreferencesStore],
* allowing testers to toggle it via the Tester Menu.
* The preference [Flow] is converted to a [StateFlow] on construction,
* so [isCreationEnabledSync] can be called from non-suspending contexts.
* Defaults to `true` (restriction enabled) when no value is stored.
*/
internal class DevHotWalletRestrictionManager(
private val appPreferencesStore: AppPreferencesStore,
dispatchers: CoroutineDispatcherProvider,
) : HotWalletRestrictionManager {
private val isCreationEnabledState: StateFlow<Boolean> =
appPreferencesStore
.get(key = IS_HOT_WALLET_CREATION_RESTRICTION_ENABLED_KEY, default = true)
.stateIn(
scope = CoroutineScope(dispatchers.io + SupervisorJob()),
started = SharingStarted.Eagerly,
initialValue = true,
)
override fun isCreationEnabled(): StateFlow<Boolean> = isCreationEnabledState
override fun isCreationEnabledSync(): Boolean = isCreationEnabledState.value
override suspend fun toggleCreationEnabled() {
appPreferencesStore.editData { preferences ->
val isEnabled = preferences.getOrDefault(
key = IS_HOT_WALLET_CREATION_RESTRICTION_ENABLED_KEY,
default = true,
)
preferences[IS_HOT_WALLET_CREATION_RESTRICTION_ENABLED_KEY] = !isEnabled
}
}
private companion object {
val IS_HOT_WALLET_CREATION_RESTRICTION_ENABLED_KEY =
booleanPreferencesKey(name = "isHotWalletCreationRestrictionEnabled")
}
}

View file

@ -0,0 +1,21 @@
package com.tangem.data.settings
import com.tangem.domain.settings.HotWalletRestrictionManager
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
/**
* Production implementation of [HotWalletRestrictionManager].
*
* Hot wallet creation restriction is always enabled in production builds
* users must scan a physical Tangem card to add a wallet.
* [toggleCreationEnabled] is a no-op since the restriction cannot be changed at runtime.
*/
internal class ProdHotWalletRestrictionManager : HotWalletRestrictionManager {
private val state: StateFlow<Boolean> = MutableStateFlow(true)
override fun isCreationEnabled(): StateFlow<Boolean> = state
override fun isCreationEnabledSync(): Boolean = true
override suspend fun toggleCreationEnabled() = Unit
}

View file

@ -1,12 +1,16 @@
package com.tangem.data.settings.di
import android.content.Context
import com.tangem.data.settings.BuildConfig
import com.tangem.data.settings.DefaultAppRatingRepository
import com.tangem.data.settings.DefaultPermissionRepository
import com.tangem.data.settings.DefaultSettingsRepository
import com.tangem.data.settings.DevHotWalletRestrictionManager
import com.tangem.data.settings.ProdHotWalletRestrictionManager
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.local.logs.AppLogsStore
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.domain.settings.HotWalletRestrictionManager
import com.tangem.domain.settings.repositories.AppRatingRepository
import com.tangem.domain.settings.repositories.PermissionRepository
import com.tangem.domain.settings.repositories.SettingsRepository
@ -55,4 +59,17 @@ internal object SettingsDataModule {
context = context,
)
}
@Provides
@Singleton
fun provideHotWalletRestrictionManager(
appPreferencesStore: AppPreferencesStore,
dispatchers: CoroutineDispatcherProvider,
): HotWalletRestrictionManager {
return if (BuildConfig.TESTER_MENU_ENABLED) {
DevHotWalletRestrictionManager(appPreferencesStore, dispatchers)
} else {
ProdHotWalletRestrictionManager()
}
}
}

View file

@ -0,0 +1,99 @@
package com.tangem.data.settings
import androidx.datastore.preferences.core.Preferences
import com.google.common.truth.Truth.assertThat
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.utils.get
import com.tangem.test.core.getEmittedValues
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkStatic
import io.mockk.unmockkStatic
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class DevHotWalletRestrictionManagerTest {
private val appPreferencesStore = mockk<AppPreferencesStore>(relaxed = true)
private val dispatchers: CoroutineDispatcherProvider = TestingCoroutineDispatcherProvider()
@BeforeEach
fun setup() {
mockkStatic("com.tangem.datasource.local.preferences.utils.PreferencesDataStoreExtKt")
}
@AfterEach
fun tearDown() {
unmockkStatic("com.tangem.datasource.local.preferences.utils.PreferencesDataStoreExtKt")
}
@Test
fun `GIVEN preference is true WHEN isCreationEnabled THEN emits true`() = runTest {
every {
appPreferencesStore.get(key = any<Preferences.Key<Boolean>>(), default = true)
} returns flowOf(true)
val manager = DevHotWalletRestrictionManager(appPreferencesStore, dispatchers)
val emitted = getEmittedValues(manager.isCreationEnabled())
assertThat(emitted).containsExactly(true)
}
@Test
fun `GIVEN preference is false WHEN isCreationEnabled THEN emits false`() = runTest {
every {
appPreferencesStore.get(key = any<Preferences.Key<Boolean>>(), default = true)
} returns flowOf(false)
val manager = DevHotWalletRestrictionManager(appPreferencesStore, dispatchers)
val emitted = getEmittedValues(manager.isCreationEnabled())
assertThat(emitted).containsExactly(false)
}
@Test
fun `GIVEN preference Flow emits true WHEN isCreationEnabledSync THEN returns cached true`() = runTest {
every {
appPreferencesStore.get(key = any<Preferences.Key<Boolean>>(), default = true)
} returns flowOf(true)
val manager = DevHotWalletRestrictionManager(appPreferencesStore, dispatchers)
assertThat(manager.isCreationEnabledSync()).isTrue()
}
@Test
fun `GIVEN preference Flow emits false WHEN isCreationEnabledSync THEN returns cached false`() = runTest {
every {
appPreferencesStore.get(key = any<Preferences.Key<Boolean>>(), default = true)
} returns flowOf(false)
val manager = DevHotWalletRestrictionManager(appPreferencesStore, dispatchers)
assertThat(manager.isCreationEnabledSync()).isFalse()
}
@Test
fun `WHEN toggleCreationEnabled THEN opens editData transaction`() = runTest {
every {
appPreferencesStore.get(key = any<Preferences.Key<Boolean>>(), default = true)
} returns flowOf(true)
coEvery { appPreferencesStore.editData(any()) } returns mockk(relaxed = true)
val manager = DevHotWalletRestrictionManager(appPreferencesStore, dispatchers)
manager.toggleCreationEnabled()
coVerify { appPreferencesStore.editData(any()) }
}
}

View file

@ -0,0 +1,31 @@
package com.tangem.data.settings
import com.google.common.truth.Truth.assertThat
import com.tangem.test.core.getEmittedValues
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class ProdHotWalletRestrictionManagerTest {
private val manager = ProdHotWalletRestrictionManager()
@Test
fun `WHEN isCreationEnabled THEN always emits true`() = runTest {
val emitted = getEmittedValues(manager.isCreationEnabled())
assertThat(emitted).containsExactly(true)
}
@Test
fun `WHEN isCreationEnabledSync THEN returns true`() = runTest {
assertThat(manager.isCreationEnabledSync()).isTrue()
}
@Test
fun `WHEN toggleCreationEnabled THEN isCreationEnabledSync still returns true`() = runTest {
manager.toggleCreationEnabled()
assertThat(manager.isCreationEnabledSync()).isTrue()
}
}

View file

@ -0,0 +1,21 @@
package com.tangem.domain.settings
import kotlinx.coroutines.flow.StateFlow
/**
* Manages the hot wallet creation restriction setting.
*
* When the restriction is enabled, users are forced to scan a physical Tangem card
* instead of being able to create a new software (hot) wallet.
*/
interface HotWalletRestrictionManager {
/** Observes the current restriction state as a [StateFlow]. */
fun isCreationEnabled(): StateFlow<Boolean>
/** Returns the latest cached restriction state synchronously. */
fun isCreationEnabledSync(): Boolean
/** Toggles the restriction state. No-op in production. */
suspend fun toggleCreationEnabled()
}

View file

@ -19,7 +19,6 @@ dependencies {
implementation(projects.features.disclaimer.api)
implementation(projects.features.tester.api)
implementation(projects.features.createWalletSelection.api)
implementation(projects.features.hotWallet.api)
implementation(projects.features.tangempay.details.api)
/* Project - Core */
@ -49,6 +48,7 @@ dependencies {
implementation(projects.domain.balanceHiding)
implementation(projects.domain.balanceHiding.models)
implementation(projects.domain.legacy)
implementation(projects.domain.settings)
implementation(projects.domain.visa)
/* SDK */

View file

@ -6,13 +6,15 @@ import com.tangem.core.decompose.navigation.DummyRouter
import com.tangem.core.navigation.url.DummyUrlOpener
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.settings.HotWalletRestrictionManager
import com.tangem.features.details.component.DetailsComponent
import com.tangem.features.details.entity.DetailsFooterUM
import com.tangem.features.details.entity.DetailsUM
import com.tangem.features.details.ui.DetailsScreen
import com.tangem.features.details.utils.ItemsBuilder
import com.tangem.features.details.utils.SocialsBuilder
import com.tangem.features.hotwallet.HotWalletFeatureToggles
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.runBlocking
internal class PreviewDetailsComponent : DetailsComponent {
@ -20,9 +22,10 @@ internal class PreviewDetailsComponent : DetailsComponent {
private val previewBlocks = runBlocking {
ItemsBuilder(
router = DummyRouter(),
hotWalletFeatureToggles = object : HotWalletFeatureToggles {
override val isWalletCreationRestrictionEnabled: Boolean = true
override val isAssetsDiscoveryEnabled: Boolean = true
hotWalletRestrictionManager = object : HotWalletRestrictionManager {
override fun isCreationEnabled(): StateFlow<Boolean> = MutableStateFlow(true)
override fun isCreationEnabledSync(): Boolean = true
override suspend fun toggleCreationEnabled() = Unit
},
).buildAll(
isWalletConnectAvailable = true,

View file

@ -19,8 +19,8 @@ import com.tangem.domain.wallets.usecase.UnlockWalletUseCase
import com.tangem.features.details.entity.UserWalletListUM
import com.tangem.features.details.entity.WalletReorderUM
import com.tangem.features.details.impl.R
import com.tangem.domain.settings.HotWalletRestrictionManager
import com.tangem.features.details.utils.UserWalletSaver
import com.tangem.features.hotwallet.HotWalletFeatureToggles
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
import com.tangem.features.wallet.utils.UserWalletsFetcher
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
@ -40,7 +40,7 @@ internal class UserWalletListModel @Inject constructor(
private val messageSender: UiMessageSender,
override val dispatchers: CoroutineDispatcherProvider,
private val userWalletSaver: UserWalletSaver,
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
private val hotWalletRestrictionManager: HotWalletRestrictionManager,
private val unlockWalletUseCase: UnlockWalletUseCase,
private val analyticsEventHandler: AnalyticsEventHandler,
private val walletFeatureToggles: WalletFeatureToggles,
@ -48,6 +48,8 @@ internal class UserWalletListModel @Inject constructor(
) : Model() {
private val isWalletSavingInProgress: MutableStateFlow<Boolean> = MutableStateFlow(value = false)
private val isWalletCreationRestrictionEnabled: StateFlow<Boolean> =
hotWalletRestrictionManager.isCreationEnabled()
private val userWalletsFetcher = userWalletsFetcherFactory.create(
messageSender = messageSender,
onlyMultiCurrency = false,
@ -101,7 +103,7 @@ internal class UserWalletListModel @Inject constructor(
private fun onAddNewWalletClick() {
analyticsEventHandler.send(SignIn.ButtonAddWallet(AnalyticsParam.ScreensSources.Settings))
if (hotWalletFeatureToggles.isWalletCreationRestrictionEnabled) {
if (isWalletCreationRestrictionEnabled.value) {
withProgress(isWalletSavingInProgress) {
userWalletSaver.scanAndSaveUserWallet(modelScope)
}

View file

@ -6,9 +6,9 @@ import com.tangem.core.decompose.navigation.Router
import com.tangem.core.ui.components.block.model.BlockUM
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.settings.HotWalletRestrictionManager
import com.tangem.features.details.entity.DetailsItemUM
import com.tangem.features.details.impl.R
import com.tangem.features.hotwallet.HotWalletFeatureToggles
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
@ -20,7 +20,7 @@ private const val TANGEM_PAY_ITEM_ID = "get_tangem_pay"
@ModelScoped
internal class ItemsBuilder @Inject constructor(
private val router: Router,
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
private val hotWalletRestrictionManager: HotWalletRestrictionManager,
) {
@Suppress("LongParameterList")
@ -36,7 +36,7 @@ internal class ItemsBuilder @Inject constructor(
buildWalletConnectBlock(isWalletConnectAvailable, userWalletId)?.let(::add)
buildUserWalletListBlock().let(::add)
if (hotWalletFeatureToggles.isWalletCreationRestrictionEnabled && hasAnyMobileWallet) {
if (hotWalletRestrictionManager.isCreationEnabledSync() && hasAnyMobileWallet) {
DetailsItemUM.UnderSectionText(
id = "only_one_mobile_wallet_explanation",
text = resourceReference(R.string.only_one_mobile_wallet_explanation),

View file

@ -31,8 +31,6 @@ dependencies {
/** Domain modules */
implementation(projects.domain.account)
implementation(projects.domain.appTheme)
implementation(projects.domain.appTheme.models)
implementation(projects.domain.card)
implementation(projects.domain.feedback)
implementation(projects.domain.markets.models)
@ -42,6 +40,7 @@ dependencies {
implementation(projects.domain.wallets.models)
implementation(projects.domain.wallets)
implementation(projects.domain.feedback.models)
implementation(projects.domain.settings)
implementation(projects.data.common)

View file

@ -1,23 +1,23 @@
package com.tangem.feature.tester.presentation.actions
import androidx.compose.runtime.Immutable
import com.tangem.domain.apptheme.model.AppThemeMode
import java.io.File
internal data class TesterActionsContentState(
val hideAllCurrenciesUM: HideAllCurrenciesUM,
val toggleAppThemeUM: ToggleAppThemeUM,
val toggleHotWalletRestrictionUM: ToggleHotWalletRestrictionUM,
val shareLogsUM: ShareLogsUM,
val onBackClick: () -> Unit,
) {
@Immutable
sealed class HideAllCurrenciesUM {
data class Clickable(val onClick: () -> Unit) : HideAllCurrenciesUM()
data object Progress : HideAllCurrenciesUM()
}
data class ToggleAppThemeUM(
val currentAppTheme: AppThemeMode,
data class ToggleHotWalletRestrictionUM(
val isEnabled: Boolean,
val onClick: () -> Unit,
)

View file

@ -22,10 +22,9 @@ import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.utils.findActivity
import com.tangem.domain.apptheme.model.AppThemeMode
import com.tangem.feature.tester.impl.R
import com.tangem.feature.tester.presentation.actions.TesterActionsContentState.HideAllCurrenciesUM
import com.tangem.feature.tester.presentation.actions.TesterActionsContentState.ToggleAppThemeUM
import com.tangem.feature.tester.presentation.actions.TesterActionsContentState.ToggleHotWalletRestrictionUM
import com.tangem.utils.logging.TangemLogger
import java.io.File
@ -57,10 +56,11 @@ internal fun TesterActionsScreen(state: TesterActionsContentState, modifier: Mod
}
item {
val config = state.toggleAppThemeUM
val config = state.toggleHotWalletRestrictionUM
val statusText = if (config.isEnabled) "ON" else "OFF"
TesterActionItem(
name = stringResourceSafe(id = R.string.toggle_app_theme, config.currentAppTheme.name),
name = stringResourceSafe(id = R.string.toggle_hot_wallet_restriction, statusText),
onClick = config.onClick,
)
}
@ -125,7 +125,7 @@ private fun TesterActionsScreenSample(modifier: Modifier = Modifier) {
TesterActionsScreen(
state = TesterActionsContentState(
hideAllCurrenciesUM = HideAllCurrenciesUM.Clickable {},
toggleAppThemeUM = ToggleAppThemeUM(AppThemeMode.DEFAULT) {},
toggleHotWalletRestrictionUM = ToggleHotWalletRestrictionUM(isEnabled = true) {},
shareLogsUM = TesterActionsContentState.ShareLogsUM(file = null),
onBackClick = {},
),

View file

@ -5,31 +5,25 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import arrow.core.getOrElse
import com.tangem.data.common.account.WalletAccountsSaver
import com.tangem.domain.apptheme.ChangeAppThemeModeUseCase
import com.tangem.domain.apptheme.GetAppThemeModeUseCase
import com.tangem.domain.apptheme.model.AppThemeMode
import com.tangem.domain.common.wallets.UserWalletsListRepository
import com.tangem.domain.feedback.repository.FeedbackRepository
import com.tangem.domain.settings.HotWalletRestrictionManager
import com.tangem.feature.tester.presentation.actions.TesterActionsContentState.HideAllCurrenciesUM
import com.tangem.feature.tester.presentation.actions.TesterActionsContentState.ToggleAppThemeUM
import com.tangem.feature.tester.presentation.actions.TesterActionsContentState.ToggleHotWalletRestrictionUM
import com.tangem.feature.tester.presentation.navigation.InnerTesterRouter
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import com.tangem.utils.logging.TangemLogger
import javax.inject.Inject
@HiltViewModel
internal class TesterActionsViewModel @Inject constructor(
private val changeAppThemeModeUseCase: ChangeAppThemeModeUseCase,
private val getAppThemeModeUseCase: GetAppThemeModeUseCase,
private val feedbackRepository: FeedbackRepository,
private val userWalletsListRepository: UserWalletsListRepository,
private val walletAccountsSaver: WalletAccountsSaver,
private val hotWalletRestrictionManager: HotWalletRestrictionManager,
) : ViewModel() {
var uiState: TesterActionsContentState by mutableStateOf(initialState)
@ -38,16 +32,16 @@ internal class TesterActionsViewModel @Inject constructor(
private val initialState: TesterActionsContentState
get() = TesterActionsContentState(
hideAllCurrenciesUM = HideAllCurrenciesUM.Clickable(this::hideAllCurrencies),
toggleAppThemeUM = ToggleAppThemeUM(
currentAppTheme = AppThemeMode.DEFAULT,
onClick = this::toggleAppTheme,
toggleHotWalletRestrictionUM = ToggleHotWalletRestrictionUM(
isEnabled = hotWalletRestrictionManager.isCreationEnabledSync(),
onClick = this::toggleHotWalletRestriction,
),
shareLogsUM = TesterActionsContentState.ShareLogsUM(file = feedbackRepository.getLogFile()),
onBackClick = { /* no-op */ },
)
init {
bootstrapAppThemeModeUpdates()
bootstrapHotWalletRestrictionUpdates()
}
fun setupNavigation(router: InnerTesterRouter) {
@ -78,57 +72,16 @@ internal class TesterActionsViewModel @Inject constructor(
)
}
private fun toggleAppTheme() = viewModelScope.launch {
val currentAppThemeMode = uiState.toggleAppThemeUM.currentAppTheme
val newAppThemeMode = when (currentAppThemeMode) {
AppThemeMode.FORCE_DARK -> AppThemeMode.FORCE_LIGHT
AppThemeMode.FORCE_LIGHT -> AppThemeMode.FOLLOW_SYSTEM
AppThemeMode.FOLLOW_SYSTEM -> AppThemeMode.FORCE_DARK
}
TangemLogger.d(
"""
Change app theme mode
|- Current theme mode: $currentAppThemeMode
|- New theme mode: $newAppThemeMode
""".trimIndent(),
)
changeAppThemeModeUseCase(newAppThemeMode).onLeft { error ->
TangemLogger.e(
"""
Unable to change app theme mode
|- Error: $error
""".trimIndent(),
)
}
private fun toggleHotWalletRestriction() = viewModelScope.launch {
hotWalletRestrictionManager.toggleCreationEnabled()
}
private fun bootstrapAppThemeModeUpdates() {
getAppThemeModeUseCase()
.distinctUntilChanged()
.onEach { maybeAppThemeMode ->
TangemLogger.d(
"""
Current app theme mode updated
|- Previous app theme mode: ${uiState.toggleAppThemeUM.currentAppTheme}
|- New app theme mode: $maybeAppThemeMode
""".trimIndent(),
)
private fun bootstrapHotWalletRestrictionUpdates() {
hotWalletRestrictionManager.isCreationEnabled()
.onEach { isEnabled ->
uiState = uiState.copy(
toggleAppThemeUM = uiState.toggleAppThemeUM.copy(
currentAppTheme = maybeAppThemeMode.getOrElse { error ->
TangemLogger.e(
"""
Unable to get current app theme mode, using default
|- Default theme mode: ${AppThemeMode.DEFAULT}
|- Error: $error
""".trimIndent(),
)
AppThemeMode.DEFAULT
},
toggleHotWalletRestrictionUM = uiState.toggleHotWalletRestrictionUM.copy(
isEnabled = isEnabled,
),
)
}

View file

@ -11,10 +11,10 @@
<string name="environment_toggles" translatable="false">Environment toggles</string>
<string name="tester_actions" translatable="false">Tester actions</string>
<string name="hide_all_currencies" translatable="false">Hide all currencies</string>
<string name="toggle_app_theme" translatable="false">Toggle app theme - %s</string>
<string name="excluded_blockchains" translatable="false">Excluded blockchains</string>
<string name="excluded_blockchains_search_placeholder" translatable="false">Filter by name or symbol</string>
<string name="blockchain_providers" translatable="false">Blockchain providers</string>
<string name="toggle_hot_wallet_restriction" translatable="false">Hot wallet creation restriction - %s</string>
<string name="share_logs" translatable="false">Share logs</string>
<string name="test_push" translatable="false">Test push</string>
<string name="accounts" translatable="false">Accounts</string>

View file

@ -14,7 +14,6 @@ android {
dependencies {
implementation(projects.features.welcome.api)
implementation(projects.features.wallet.api)
implementation(projects.features.hotWallet.api)
/** Core */
implementation(projects.core.configToggles)

View file

@ -23,11 +23,11 @@ import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.models.wallet.isLocked
import com.tangem.domain.settings.CanUseBiometryUseCase
import com.tangem.domain.settings.HotWalletRestrictionManager
import com.tangem.domain.wallets.builder.ColdUserWalletBuilder
import com.tangem.domain.wallets.repository.WalletsRepository
import com.tangem.domain.wallets.usecase.NonBiometricUnlockWalletUseCase
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
import com.tangem.features.hotwallet.HotWalletFeatureToggles
import com.tangem.features.wallet.utils.UserWalletsFetcher
import com.tangem.features.welcome.impl.ui.state.WelcomeUM
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
@ -54,7 +54,7 @@ internal class WelcomeModel @Inject constructor(
private val trackingContextProxy: TrackingContextProxy,
private val analyticsEventHandler: AnalyticsEventHandler,
userWalletsFetcherFactory: UserWalletsFetcher.Factory,
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
private val hotWalletRestrictionManager: HotWalletRestrictionManager,
private val scanCardProcessor: ScanCardProcessor,
private val messageSender: UiMessageSender,
) : Model() {
@ -90,6 +90,8 @@ internal class WelcomeModel @Inject constructor(
private val walletsFetcherJobHolder = JobHolder()
private val wallets = MutableStateFlow<ImmutableList<UserWalletItemUM>>(persistentListOf())
private var routedOut = false
private val isWalletCreationRestrictionEnabled: StateFlow<Boolean> =
hotWalletRestrictionManager.isCreationEnabled()
init {
modelScope.launch {
@ -181,7 +183,7 @@ internal class WelcomeModel @Inject constructor(
private fun addWalletClick() {
analyticsEventHandler.send(SignIn.ButtonAddWallet(AnalyticsParam.ScreensSources.SignIn))
if (hotWalletFeatureToggles.isWalletCreationRestrictionEnabled) {
if (isWalletCreationRestrictionEnabled.value) {
scanCard()
} else {
router.push(AppRoute.CreateWalletSelection)