Updated on 2026-08-14
This commit is contained in:
parent
587a0c8624
commit
88cf7ec1af
212 changed files with 1223 additions and 1128 deletions
|
|
@ -6,6 +6,7 @@ import com.tangem.domain.models.scan.ScanResponse
|
|||
import kotlinx.coroutines.CoroutineScope
|
||||
import org.rekotlin.Action
|
||||
|
||||
@Suppress("BooleanPropertyNaming")
|
||||
sealed class DetailsAction : Action {
|
||||
|
||||
data class PrepareScreen(
|
||||
|
|
@ -32,7 +33,7 @@ sealed class DetailsAction : Action {
|
|||
|
||||
data object EnrollBiometrics : AppSettings()
|
||||
data class BiometricsStatusChanged(
|
||||
val needEnrollBiometrics: Boolean,
|
||||
val isEnrollBiometricsNeeded: Boolean,
|
||||
) : AppSettings()
|
||||
|
||||
data class ChangeAppThemeMode(
|
||||
|
|
@ -40,7 +41,7 @@ sealed class DetailsAction : Action {
|
|||
) : AppSettings()
|
||||
|
||||
data class ChangeBalanceHiding(
|
||||
val hideBalance: Boolean,
|
||||
val shouldHideBalance: Boolean,
|
||||
) : AppSettings()
|
||||
|
||||
data class ChangeAppCurrency(
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ class DetailsMiddleware {
|
|||
changeAppThemeMode(action.appThemeMode)
|
||||
}
|
||||
is DetailsAction.AppSettings.ChangeBalanceHiding -> {
|
||||
changeBalanceHiding(action.hideBalance)
|
||||
changeBalanceHiding(action.shouldHideBalance)
|
||||
}
|
||||
is DetailsAction.AppSettings.ChangeAppCurrency -> {
|
||||
store.dispatch(GlobalAction.ChangeAppCurrency(action.currency))
|
||||
|
|
@ -153,9 +153,9 @@ class DetailsMiddleware {
|
|||
private suspend fun setBiometricLockForAllWallets() {
|
||||
val userWalletsListRepository = store.inject(DaggerGraphState::userWalletsListRepository)
|
||||
val userWallets = userWalletsListRepository.userWalletsSync()
|
||||
userWallets.forEach {
|
||||
userWallets.forEach { wallet ->
|
||||
userWalletsListRepository.setLock(
|
||||
userWalletId = it.walletId,
|
||||
userWalletId = wallet.walletId,
|
||||
lockMethod = LockMethod.Biometric,
|
||||
changeUnsecured = false,
|
||||
)
|
||||
|
|
@ -174,11 +174,11 @@ class DetailsMiddleware {
|
|||
deleteSavedAccessCodes()
|
||||
val userWalletsListRepository = store.inject(DaggerGraphState::userWalletsListRepository)
|
||||
val tangemHotSdk = store.inject(DaggerGraphState::tangemHotSdk)
|
||||
userWalletsListRepository.userWalletsSync().forEach {
|
||||
if (it is UserWallet.Hot) {
|
||||
userWalletsListRepository.userWalletsSync().forEach { wallet ->
|
||||
if (wallet is UserWallet.Hot) {
|
||||
userWalletsListRepository.saveWithoutLock(
|
||||
userWallet = it.copy(
|
||||
hotWalletId = tangemHotSdk.removeBiometryAuthIfPresented(it.hotWalletId),
|
||||
userWallet = wallet.copy(
|
||||
hotWalletId = tangemHotSdk.removeBiometryAuthIfPresented(wallet.hotWalletId),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -188,10 +188,10 @@ class DetailsMiddleware {
|
|||
private fun observeBiometricsStatusChanges(scope: CoroutineScope) {
|
||||
val needEnrollBiometricsFlow = flow {
|
||||
do {
|
||||
val needEnrollBiometrics = runCatching(tangemSdkManager::needEnrollBiometrics).getOrNull()
|
||||
val isEnrollBiometricsNeeded = runCatching(tangemSdkManager::needEnrollBiometrics).getOrNull()
|
||||
|
||||
if (needEnrollBiometrics != null) {
|
||||
emit(needEnrollBiometrics)
|
||||
if (isEnrollBiometricsNeeded != null) {
|
||||
emit(isEnrollBiometricsNeeded)
|
||||
}
|
||||
|
||||
delay(timeMillis = 200)
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ private fun handlePrivacyAction(action: DetailsAction.AppSettings, state: Detail
|
|||
)
|
||||
is DetailsAction.AppSettings.BiometricsStatusChanged -> state.copy(
|
||||
appSettingsState = state.appSettingsState.copy(
|
||||
needEnrollBiometrics = action.needEnrollBiometrics,
|
||||
needEnrollBiometrics = action.isEnrollBiometricsNeeded,
|
||||
),
|
||||
)
|
||||
is DetailsAction.AppSettings.ChangeAppThemeMode -> state.copy(
|
||||
|
|
@ -99,7 +99,7 @@ private fun handlePrivacyAction(action: DetailsAction.AppSettings, state: Detail
|
|||
)
|
||||
is DetailsAction.AppSettings.ChangeBalanceHiding -> state.copy(
|
||||
appSettingsState = state.appSettingsState.copy(
|
||||
isHidingEnabled = action.hideBalance,
|
||||
isHidingEnabled = action.shouldHideBalance,
|
||||
),
|
||||
)
|
||||
// state should be copied to avoid concurrent modifications from different sources
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ data class DetailsState(
|
|||
val appSettingsState: AppSettingsState = AppSettingsState(),
|
||||
) : StateType
|
||||
|
||||
@Suppress("BooleanPropertyNaming")
|
||||
data class AppSettingsState(
|
||||
@Deprecated("Delete after hot wallet release")
|
||||
val saveWallets: Boolean = false,
|
||||
|
|
|
|||
|
|
@ -341,16 +341,16 @@ private class AppCurrencySelectorStateProvider : CollectionPreviewParameterProvi
|
|||
.mapIndexed { index, s -> Currency(index.toString(), s) }
|
||||
.toPersistentList()
|
||||
|
||||
AppCurrencySelectorState.Loading(onBackClick = {}).let(::add)
|
||||
AppCurrencySelectorState.Default(
|
||||
add(AppCurrencySelectorState.Loading(onBackClick = {}))
|
||||
add(AppCurrencySelectorState.Default(
|
||||
selectedId = "0",
|
||||
items = items,
|
||||
scrollToSelected = consumedEvent(),
|
||||
onCurrencyClick = {},
|
||||
onBackClick = {},
|
||||
onTopBarActionClick = {},
|
||||
).let(::add)
|
||||
AppCurrencySelectorState.Search(
|
||||
))
|
||||
add(AppCurrencySelectorState.Search(
|
||||
selectedId = "0",
|
||||
items = items,
|
||||
scrollToSelected = consumedEvent(),
|
||||
|
|
@ -358,7 +358,7 @@ private class AppCurrencySelectorStateProvider : CollectionPreviewParameterProvi
|
|||
onBackClick = {},
|
||||
onSearchInputChange = {},
|
||||
onTopBarActionClick = {},
|
||||
).let(::add)
|
||||
))
|
||||
},
|
||||
)
|
||||
// endregion Preview
|
||||
|
|
@ -27,16 +27,16 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
@Composable
|
||||
internal fun AppSettingsScreen(state: AppSettingsScreenState, onBackClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||
SettingsScreensScaffold(
|
||||
onBackClick = onBackClick,
|
||||
modifier = modifier,
|
||||
titleRes = R.string.app_settings_title,
|
||||
addBottomInsets = false,
|
||||
content = {
|
||||
when (state) {
|
||||
is AppSettingsScreenState.Content -> AppSettings(state = state)
|
||||
is AppSettingsScreenState.Loading -> Unit
|
||||
}
|
||||
},
|
||||
titleRes = R.string.app_settings_title,
|
||||
onBackClick = onBackClick,
|
||||
addBottomInsets = false,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -103,10 +103,10 @@ private class AppSettingsScreenStateProvider : CollectionPreviewParameterProvide
|
|||
itemsFactory.createSelectThemeModeButton(AppThemeMode.DEFAULT, {}),
|
||||
)
|
||||
|
||||
AppSettingsScreenState.Content(
|
||||
add(AppSettingsScreenState.Content(
|
||||
items = items,
|
||||
dialog = null,
|
||||
).let(::add)
|
||||
))
|
||||
},
|
||||
)
|
||||
// endregion Preview
|
||||
|
|
@ -47,8 +47,8 @@ private class AlertDialogProvider : CollectionPreviewParameterProvider<Dialog.Al
|
|||
collection = buildList {
|
||||
val dialogsFactory = AppSettingsDialogsFactory()
|
||||
|
||||
dialogsFactory.createDeleteSavedAccessCodesAlert({}, {}).let(::add)
|
||||
dialogsFactory.createDeleteSavedWalletsAlert({}, {}).let(::add)
|
||||
add(dialogsFactory.createDeleteSavedAccessCodesAlert({}, {}))
|
||||
add(dialogsFactory.createDeleteSavedWalletsAlert({}, {}))
|
||||
},
|
||||
)
|
||||
// endregion Preview
|
||||
|
|
@ -64,10 +64,10 @@ private class ButtonItemProvider : CollectionPreviewParameterProvider<Item.Butto
|
|||
collection = buildList {
|
||||
val itemsFactory = AppSettingsItemsFactory()
|
||||
|
||||
itemsFactory.createSelectAppCurrencyButton(
|
||||
add(itemsFactory.createSelectAppCurrencyButton(
|
||||
currentAppCurrencyName = "US Dollar",
|
||||
onClick = { /* no-op */ },
|
||||
).let(::add)
|
||||
))
|
||||
},
|
||||
)
|
||||
// endregion Preview
|
||||
|
|
@ -71,9 +71,9 @@ private class CardItemProvider : CollectionPreviewParameterProvider<Item.Card>(
|
|||
collection = buildList {
|
||||
val itemsFactory = AppSettingsItemsFactory()
|
||||
|
||||
itemsFactory.createEnrollBiometricsCard(
|
||||
add(itemsFactory.createEnrollBiometricsCard(
|
||||
onClick = { /* no-op */ },
|
||||
).let(::add)
|
||||
))
|
||||
},
|
||||
)
|
||||
// endregion Preview
|
||||
|
|
@ -85,26 +85,26 @@ private class SwitchItemProvider : CollectionPreviewParameterProvider<Item.Switc
|
|||
collection = buildList {
|
||||
val itemsFactory = AppSettingsItemsFactory()
|
||||
|
||||
itemsFactory.createSaveAccessCodeSwitch(
|
||||
add(itemsFactory.createSaveAccessCodeSwitch(
|
||||
isChecked = true,
|
||||
isEnabled = true,
|
||||
onCheckedChange = { /* no-op */ },
|
||||
).let(::add)
|
||||
itemsFactory.createSaveAccessCodeSwitch(
|
||||
))
|
||||
add(itemsFactory.createSaveAccessCodeSwitch(
|
||||
isChecked = false,
|
||||
isEnabled = true,
|
||||
onCheckedChange = { /* no-op */ },
|
||||
).let(::add)
|
||||
itemsFactory.createSaveAccessCodeSwitch(
|
||||
))
|
||||
add(itemsFactory.createSaveAccessCodeSwitch(
|
||||
isChecked = true,
|
||||
isEnabled = false,
|
||||
onCheckedChange = { /* no-op */ },
|
||||
).let(::add)
|
||||
itemsFactory.createSaveAccessCodeSwitch(
|
||||
))
|
||||
add(itemsFactory.createSaveAccessCodeSwitch(
|
||||
isChecked = false,
|
||||
isEnabled = false,
|
||||
onCheckedChange = { /* no-op */ },
|
||||
).let(::add)
|
||||
))
|
||||
},
|
||||
)
|
||||
// endregion Preview
|
||||
|
|
@ -99,60 +99,76 @@ internal class AppSettingsModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun buildItems(state: AppSettingsState): ImmutableList<AppSettingsScreenState.Item> {
|
||||
val items = buildList {
|
||||
val items = buildList<AppSettingsScreenState.Item> {
|
||||
if (state.needEnrollBiometrics) {
|
||||
itemsFactory.createEnrollBiometricsCard(
|
||||
onClick = ::enrollBiometrics,
|
||||
).let(::add)
|
||||
add(
|
||||
itemsFactory.createEnrollBiometricsCard(
|
||||
onClick = ::enrollBiometrics,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
itemsFactory.createSelectAppCurrencyButton(
|
||||
currentAppCurrencyName = state.selectedAppCurrency.name,
|
||||
onClick = ::showAppCurrencySelector,
|
||||
).let(::add)
|
||||
add(
|
||||
itemsFactory.createSelectAppCurrencyButton(
|
||||
currentAppCurrencyName = state.selectedAppCurrency.name,
|
||||
onClick = ::showAppCurrencySelector,
|
||||
),
|
||||
)
|
||||
|
||||
if (hotWalletFeatureToggles.isHotWalletEnabled) {
|
||||
val canUseBiometrics = !state.needEnrollBiometrics && !state.isInProgress
|
||||
|
||||
itemsFactory.createUseBiometricsSwitch(
|
||||
isChecked = state.useBiometricAuthentication,
|
||||
isEnabled = canUseBiometrics,
|
||||
onCheckedChange = ::onBiometricAuthenticationToggled,
|
||||
).let(::add)
|
||||
add(
|
||||
itemsFactory.createUseBiometricsSwitch(
|
||||
isChecked = state.useBiometricAuthentication,
|
||||
isEnabled = canUseBiometrics,
|
||||
onCheckedChange = ::onBiometricAuthenticationToggled,
|
||||
),
|
||||
)
|
||||
|
||||
itemsFactory.createRequireAccessCodeSwitch(
|
||||
isChecked = state.requireAccessCode,
|
||||
isEnabled = canUseBiometrics && state.useBiometricAuthentication,
|
||||
onCheckedChange = ::onRequireAccessCodeToggled,
|
||||
).let(::add)
|
||||
add(
|
||||
itemsFactory.createRequireAccessCodeSwitch(
|
||||
isChecked = state.requireAccessCode,
|
||||
isEnabled = canUseBiometrics && state.useBiometricAuthentication,
|
||||
onCheckedChange = ::onRequireAccessCodeToggled,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
if (state.isBiometricsAvailable) {
|
||||
val canUseBiometrics = !state.needEnrollBiometrics && !state.isInProgress
|
||||
|
||||
itemsFactory.createSaveWalletsSwitch(
|
||||
isChecked = state.saveWallets,
|
||||
isEnabled = canUseBiometrics,
|
||||
onCheckedChange = ::onSaveWalletsToggled,
|
||||
).let(::add)
|
||||
add(
|
||||
itemsFactory.createSaveWalletsSwitch(
|
||||
isChecked = state.saveWallets,
|
||||
isEnabled = canUseBiometrics,
|
||||
onCheckedChange = ::onSaveWalletsToggled,
|
||||
),
|
||||
)
|
||||
|
||||
itemsFactory.createSaveAccessCodeSwitch(
|
||||
isChecked = state.saveAccessCodes,
|
||||
isEnabled = canUseBiometrics,
|
||||
onCheckedChange = ::onSaveAccessCodesToggled,
|
||||
).let(::add)
|
||||
add(
|
||||
itemsFactory.createSaveAccessCodeSwitch(
|
||||
isChecked = state.saveAccessCodes,
|
||||
isEnabled = canUseBiometrics,
|
||||
onCheckedChange = ::onSaveAccessCodesToggled,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
itemsFactory.createFlipToHideBalanceSwitch(
|
||||
isChecked = state.isHidingEnabled,
|
||||
isEnabled = true,
|
||||
onCheckedChange = ::onFlipToHideBalanceToggled,
|
||||
).let(::add)
|
||||
add(
|
||||
itemsFactory.createFlipToHideBalanceSwitch(
|
||||
isChecked = state.isHidingEnabled,
|
||||
isEnabled = true,
|
||||
onCheckedChange = ::onFlipToHideBalanceToggled,
|
||||
),
|
||||
)
|
||||
|
||||
itemsFactory.createSelectThemeModeButton(
|
||||
currentThemeMode = state.selectedThemeMode,
|
||||
onClick = { showThemeModeSelector(state.selectedThemeMode) },
|
||||
).let(::add)
|
||||
add(
|
||||
itemsFactory.createSelectThemeModeButton(
|
||||
currentThemeMode = state.selectedThemeMode,
|
||||
onClick = { showThemeModeSelector(state.selectedThemeMode) },
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
return items.toImmutableList()
|
||||
|
|
@ -280,7 +296,7 @@ internal class AppSettingsModel @Inject constructor(
|
|||
val param = AnalyticsParam.OnOffState(enable)
|
||||
analyticsEventHandler.send(Settings.AppSettings.HideBalanceChanged(param))
|
||||
|
||||
store.dispatch(DetailsAction.AppSettings.ChangeBalanceHiding(hideBalance = enable))
|
||||
store.dispatch(DetailsAction.AppSettings.ChangeBalanceHiding(shouldHideBalance = enable))
|
||||
}
|
||||
|
||||
private fun dismissDialog() {
|
||||
|
|
@ -290,10 +306,10 @@ internal class AppSettingsModel @Inject constructor(
|
|||
private fun bootstrapAppCurrencyUpdates() {
|
||||
appCurrencyRepository
|
||||
.getSelectedAppCurrency()
|
||||
.onEach {
|
||||
if (it.code == store.state.globalState.appCurrency.code) return@onEach
|
||||
.onEach { appCurrency ->
|
||||
if (appCurrency.code == store.state.globalState.appCurrency.code) return@onEach
|
||||
|
||||
store.dispatchWithMain(DetailsAction.AppSettings.ChangeAppCurrency(it))
|
||||
store.dispatchWithMain(DetailsAction.AppSettings.ChangeAppCurrency(appCurrency))
|
||||
}
|
||||
.launchIn(scope)
|
||||
.saveIn(appCurrencyUpdatesJobHolder)
|
||||
|
|
|
|||
|
|
@ -26,19 +26,19 @@ import com.tangem.wallet.R
|
|||
|
||||
@Composable
|
||||
internal fun CardSettingsScreen(state: CardSettingsScreenState, modifier: Modifier = Modifier) {
|
||||
val needReadCard = state.cardDetails == null
|
||||
val isCardReadingNeeded = state.cardDetails == null
|
||||
|
||||
SettingsScreensScaffold(
|
||||
onBackClick = state.onBackClick,
|
||||
modifier = modifier,
|
||||
titleRes = R.string.card_settings_title,
|
||||
content = {
|
||||
if (needReadCard) {
|
||||
if (isCardReadingNeeded) {
|
||||
CardSettingsReadCard(state.onScanCardClick)
|
||||
} else {
|
||||
CardSettings(state = state)
|
||||
}
|
||||
},
|
||||
titleRes = R.string.card_settings_title,
|
||||
onBackClick = state.onBackClick,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -123,8 +123,8 @@ private fun CardSettings(state: CardSettingsScreenState) {
|
|||
.fillMaxWidth()
|
||||
.testTag(DeviceSettingsScreenTestTags.LAZY_LIST),
|
||||
) {
|
||||
items(state.cardDetails) {
|
||||
val paddingBottom = when (it) {
|
||||
items(state.cardDetails) { cardInfo ->
|
||||
val paddingBottom = when (cardInfo) {
|
||||
is CardInfo.CardId, is CardInfo.Issuer -> TangemTheme.dimens.spacing12
|
||||
is CardInfo.SignedHashes -> TangemTheme.dimens.spacing14
|
||||
is CardInfo.SecurityMode -> TangemTheme.dimens.spacing16
|
||||
|
|
@ -132,7 +132,7 @@ private fun CardSettings(state: CardSettingsScreenState) {
|
|||
is CardInfo.AccessCodeRecovery -> TangemTheme.dimens.spacing16
|
||||
is CardInfo.ResetToFactorySettings -> TangemTheme.dimens.spacing28
|
||||
}
|
||||
val paddingTop = when (it) {
|
||||
val paddingTop = when (cardInfo) {
|
||||
is CardInfo.CardId -> TangemTheme.dimens.spacing0
|
||||
is CardInfo.Issuer -> TangemTheme.dimens.spacing12
|
||||
is CardInfo.SignedHashes -> TangemTheme.dimens.spacing12
|
||||
|
|
@ -145,8 +145,8 @@ private fun CardSettings(state: CardSettingsScreenState) {
|
|||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(
|
||||
enabled = it.clickable,
|
||||
onClick = { state.onElementClick(it) },
|
||||
enabled = cardInfo.isClickable,
|
||||
onClick = { state.onElementClick(cardInfo) },
|
||||
)
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing20,
|
||||
|
|
@ -155,25 +155,25 @@ private fun CardSettings(state: CardSettingsScreenState) {
|
|||
top = paddingTop,
|
||||
),
|
||||
) {
|
||||
val titleColor = if (it.clickable) {
|
||||
val titleColor = if (cardInfo.isClickable) {
|
||||
TangemTheme.colors.text.primary1
|
||||
} else {
|
||||
TangemTheme.colors.text.tertiary
|
||||
}
|
||||
val subtitleColor = if (it.clickable) {
|
||||
val subtitleColor = if (cardInfo.isClickable) {
|
||||
TangemTheme.colors.text.secondary
|
||||
} else {
|
||||
TangemTheme.colors.text.tertiary
|
||||
}
|
||||
Text(
|
||||
text = it.titleRes.resolveReference(),
|
||||
text = cardInfo.titleRes.resolveReference(),
|
||||
color = titleColor,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
modifier = Modifier.testTag(DeviceSettingsScreenTestTags.ITEM_TITLE),
|
||||
)
|
||||
Spacer(modifier = Modifier.size(TangemTheme.dimens.size4))
|
||||
Text(
|
||||
text = it.subtitle.resolveReference(),
|
||||
text = cardInfo.subtitle.resolveReference(),
|
||||
color = subtitleColor,
|
||||
style = TangemTheme.typography.body2,
|
||||
modifier = Modifier.testTag(DeviceSettingsScreenTestTags.ITEM_SUBTITLE),
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ internal data class CardSettingsScreenState(
|
|||
internal sealed class CardInfo(
|
||||
val titleRes: TextReference,
|
||||
val subtitle: TextReference,
|
||||
val clickable: Boolean = false,
|
||||
val isClickable: Boolean = false,
|
||||
) {
|
||||
class CardId(subtitle: String) : CardInfo(
|
||||
titleRes = TextReference.Res(R.string.details_row_title_cid),
|
||||
|
|
@ -38,29 +38,29 @@ internal sealed class CardInfo(
|
|||
class SecurityMode(securityOption: SecurityOption, clickable: Boolean) : CardInfo(
|
||||
titleRes = TextReference.Res(R.string.card_settings_security_mode),
|
||||
subtitle = TextReference.Res(securityOption.toTitleRes()),
|
||||
clickable = clickable,
|
||||
isClickable = clickable,
|
||||
)
|
||||
|
||||
data object ChangeAccessCode : CardInfo(
|
||||
titleRes = TextReference.Res(R.string.card_settings_change_access_code),
|
||||
subtitle = TextReference.Res(R.string.card_settings_change_access_code_footer),
|
||||
clickable = true,
|
||||
isClickable = true,
|
||||
)
|
||||
|
||||
class AccessCodeRecovery(val enabled: Boolean) : CardInfo(
|
||||
class AccessCodeRecovery(val isEnabled: Boolean) : CardInfo(
|
||||
titleRes = TextReference.Res(R.string.card_settings_access_code_recovery_title),
|
||||
subtitle = if (enabled) {
|
||||
subtitle = if (isEnabled) {
|
||||
TextReference.Res(R.string.common_enabled)
|
||||
} else {
|
||||
TextReference.Res(R.string.common_disabled)
|
||||
},
|
||||
clickable = true,
|
||||
isClickable = true,
|
||||
)
|
||||
|
||||
class ResetToFactorySettings(description: TextReference) : CardInfo(
|
||||
titleRes = TextReference.Res(R.string.card_settings_reset_card_to_factory),
|
||||
subtitle = description,
|
||||
clickable = true,
|
||||
isClickable = true,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ import com.tangem.wallet.R
|
|||
@Composable
|
||||
fun AccessCodeRecoveryScreen(state: AccessCodeRecoveryScreenState, onBackClick: () -> Unit) {
|
||||
SettingsScreensScaffold(
|
||||
content = { AccessCodeRecoveryOptions(state = state) },
|
||||
onBackClick = onBackClick,
|
||||
content = { AccessCodeRecoveryOptions(state = state) },
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -38,13 +38,13 @@ fun AccessCodeRecoveryOptions(state: AccessCodeRecoveryScreenState) {
|
|||
DetailsRadioButtonElement(
|
||||
title = stringResourceSafe(id = R.string.common_enabled),
|
||||
subtitle = stringResourceSafe(id = R.string.card_settings_access_code_recovery_enabled_description),
|
||||
selected = state.enabledSelection,
|
||||
isSelected = state.isEnabledSelection,
|
||||
onClick = { state.onOptionClick(true) },
|
||||
)
|
||||
DetailsRadioButtonElement(
|
||||
title = stringResourceSafe(id = R.string.common_disabled),
|
||||
subtitle = stringResourceSafe(id = R.string.card_settings_access_code_recovery_disabled_description),
|
||||
selected = !state.enabledSelection,
|
||||
isSelected = !state.isEnabledSelection,
|
||||
onClick = { state.onOptionClick(false) },
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
package com.tangem.tap.features.details.ui.cardsettings.coderecovery
|
||||
|
||||
/**
|
||||
* @property enabledOnCard Indicates whether access code recovery is enabled on the card
|
||||
* @property enabledSelection Represents the currently selected option in the app (not yet saved on the card)
|
||||
* @property isEnabledOnCard Indicates whether access code recovery is enabled on the card
|
||||
* @property isEnabledSelection Represents the currently selected option in the app (not yet saved on the card)
|
||||
* @property isSaveChangesEnabled Determines if the user is allowed to save their selection to the card
|
||||
* @property onSaveChangesClick Callback function called when the user wants to apply the selected option
|
||||
* @property onOptionClick Callback function called when the user selects an option
|
||||
* */
|
||||
data class AccessCodeRecoveryScreenState(
|
||||
val enabledOnCard: Boolean,
|
||||
val enabledSelection: Boolean,
|
||||
val isEnabledOnCard: Boolean,
|
||||
val isEnabledSelection: Boolean,
|
||||
val isSaveChangesEnabled: Boolean,
|
||||
val onSaveChangesClick: () -> Unit,
|
||||
val onOptionClick: (Boolean) -> Unit,
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ internal class AccessCodeRecoveryModel @Inject constructor(
|
|||
)
|
||||
|
||||
return AccessCodeRecoveryScreenState(
|
||||
enabledOnCard = isEnabled,
|
||||
enabledSelection = isEnabled,
|
||||
isEnabledOnCard = isEnabled,
|
||||
isEnabledSelection = isEnabled,
|
||||
isSaveChangesEnabled = false,
|
||||
onSaveChangesClick = ::saveChanges,
|
||||
onOptionClick = ::selectOption,
|
||||
|
|
@ -52,7 +52,7 @@ internal class AccessCodeRecoveryModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun saveChanges() = modelScope.launch {
|
||||
val isEnabled = screenState.value.enabledSelection
|
||||
val isEnabled = screenState.value.isEnabledSelection
|
||||
|
||||
tangemSdkManager
|
||||
.setAccessCodeRecoveryEnabled(scannedScanResponse.card.cardId, isEnabled)
|
||||
|
|
@ -78,10 +78,10 @@ internal class AccessCodeRecoveryModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun selectOption(isEnabled: Boolean) {
|
||||
screenState.update {
|
||||
it.copy(
|
||||
enabledSelection = isEnabled,
|
||||
isSaveChangesEnabled = isEnabled != it.enabledOnCard,
|
||||
screenState.update { state ->
|
||||
state.copy(
|
||||
isEnabledSelection = isEnabled,
|
||||
isSaveChangesEnabled = isEnabled != state.isEnabledOnCard,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,9 +23,9 @@ internal class CardSettingsInteractor @Inject constructor() {
|
|||
}
|
||||
|
||||
fun update(transform: (ScanResponse) -> ScanResponse) {
|
||||
_scannedScanResponse.update {
|
||||
requireNotNull(it)
|
||||
transform(it)
|
||||
_scannedScanResponse.update { scanResponse ->
|
||||
requireNotNull(scanResponse)
|
||||
transform(scanResponse)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ internal class CardSettingsModel @Inject constructor(
|
|||
|
||||
private val params = paramsContainer.require<CardSettingsComponent.Params>()
|
||||
|
||||
private var previousBiometricsRequestPolicy: Boolean = false
|
||||
private var isBiometricsRequestPolicyPrevious: Boolean = false
|
||||
|
||||
private val userWalletId = params.userWalletId
|
||||
|
||||
|
|
@ -77,13 +77,13 @@ internal class CardSettingsModel @Inject constructor(
|
|||
// Reset card scanned data
|
||||
cardSettingsInteractor.clear()
|
||||
// Restore the previous value of access code request policy
|
||||
cardSdkConfigRepository.isBiometricsRequestPolicy = previousBiometricsRequestPolicy
|
||||
cardSdkConfigRepository.isBiometricsRequestPolicy = isBiometricsRequestPolicyPrevious
|
||||
}
|
||||
|
||||
private fun updateAccessCodeRequestPolicy() {
|
||||
runBlocking {
|
||||
// !!!IMPORTANT!!!: Do not forget to restore the previous value in onCleared() method
|
||||
previousBiometricsRequestPolicy = cardSdkConfigRepository.isBiometricsRequestPolicy
|
||||
isBiometricsRequestPolicyPrevious = cardSdkConfigRepository.isBiometricsRequestPolicy
|
||||
|
||||
val userWallet = getUserWalletUseCase(userWalletId)
|
||||
.getOrElse { error("User wallet $userWalletId not found") }
|
||||
|
|
@ -135,34 +135,38 @@ internal class CardSettingsModel @Inject constructor(
|
|||
)
|
||||
val isResetCardAllowed = isResetToFactoryAllowedByCard(card, cardTypesResolver)
|
||||
|
||||
val cardDetails = buildList {
|
||||
CardInfo.CardId(cardId).let(::add)
|
||||
CardInfo.Issuer(card.issuer.name).let(::add)
|
||||
val cardDetails = buildList<CardInfo> {
|
||||
add(CardInfo.CardId(cardId))
|
||||
add(CardInfo.Issuer(card.issuer.name))
|
||||
|
||||
if (!cardTypesResolver.isTangemTwins()) {
|
||||
CardInfo.SignedHashes(card.signedHashesCount().toString()).let(::add)
|
||||
add(CardInfo.SignedHashes(card.signedHashesCount().toString()))
|
||||
}
|
||||
|
||||
CardInfo.SecurityMode(
|
||||
currentSecurityOption,
|
||||
clickable = allowedSecurityOptions.size > 1,
|
||||
).let(::add)
|
||||
add(
|
||||
CardInfo.SecurityMode(
|
||||
currentSecurityOption,
|
||||
clickable = allowedSecurityOptions.size > 1,
|
||||
),
|
||||
)
|
||||
|
||||
if (card.backupStatus?.isActive == true && card.isAccessCodeSet) {
|
||||
CardInfo.ChangeAccessCode.let(::add)
|
||||
add(CardInfo.ChangeAccessCode)
|
||||
}
|
||||
|
||||
if (isAccessCodeRecoveryAllowed(cardTypesResolver)) {
|
||||
CardInfo.AccessCodeRecovery(isAccessCodeRecoveryEnabled(cardTypesResolver, card)).let(::add)
|
||||
add(CardInfo.AccessCodeRecovery(isAccessCodeRecoveryEnabled(cardTypesResolver, card)))
|
||||
}
|
||||
|
||||
if (isResetCardAllowed) {
|
||||
CardInfo.ResetToFactorySettings(
|
||||
description = getResetToFactoryDescription(
|
||||
isActiveBackupStatus = card.backupStatus?.isActive == true,
|
||||
typesResolver = cardTypesResolver,
|
||||
add(
|
||||
CardInfo.ResetToFactorySettings(
|
||||
description = getResetToFactoryDescription(
|
||||
isActiveBackupStatus = card.backupStatus?.isActive == true,
|
||||
typesResolver = cardTypesResolver,
|
||||
),
|
||||
),
|
||||
).let(::add)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@ import com.tangem.wallet.R
|
|||
@Composable
|
||||
internal fun SettingsScreensScaffold(
|
||||
onBackClick: () -> Unit,
|
||||
content: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
@StringRes titleRes: Int? = null,
|
||||
snackbarHostState: SnackbarHostState = remember { SnackbarHostState() },
|
||||
addBottomInsets: Boolean = true,
|
||||
snackbarHostState: SnackbarHostState = remember { SnackbarHostState() },
|
||||
content: @Composable () -> Unit,
|
||||
fab: @Composable () -> Unit = {},
|
||||
) {
|
||||
val backgroundColor = TangemTheme.colors.background.secondary
|
||||
|
|
@ -129,18 +129,18 @@ internal fun DetailsMainButton(
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun DetailsRadioButtonElement(title: String, subtitle: String, selected: Boolean, onClick: () -> Unit) {
|
||||
internal fun DetailsRadioButtonElement(title: String, subtitle: String, isSelected: Boolean, onClick: () -> Unit) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.selectable(
|
||||
selected = selected,
|
||||
selected = isSelected,
|
||||
onClick = { onClick() },
|
||||
)
|
||||
.padding(start = 20.dp, end = 20.dp, top = 16.dp, bottom = 16.dp),
|
||||
) {
|
||||
RadioButton(
|
||||
selected = selected,
|
||||
selected = isSelected,
|
||||
onClick = null,
|
||||
modifier = Modifier.padding(end = 20.dp),
|
||||
colors = RadioButtonDefaults.colors(
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ internal fun isAccessCodeRecoveryAllowed(typeResolver: CardTypesResolver): Boole
|
|||
|
||||
internal fun isAccessCodeRecoveryEnabled(typeResolver: CardTypesResolver, card: CardDTO): Boolean =
|
||||
if (typeResolver.isWallet2()) {
|
||||
card.userSettings?.isUserCodeRecoveryAllowed ?: false
|
||||
card.userSettings?.isUserCodeRecoveryAllowed == true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
|
@ -27,11 +27,11 @@ import com.tangem.tap.features.details.ui.resetcard.ResetCardScreenState.Dialog
|
|||
@Composable
|
||||
internal fun ResetCardScreen(state: ResetCardScreenState, onBackClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||
SettingsScreensScaffold(
|
||||
onBackClick = onBackClick,
|
||||
modifier = modifier,
|
||||
content = {
|
||||
ResetCardView(state = state)
|
||||
},
|
||||
onBackClick = onBackClick,
|
||||
)
|
||||
|
||||
when (val dialog = state.dialog) {
|
||||
|
|
@ -65,7 +65,7 @@ private fun ResetCardView(state: ResetCardScreenState) {
|
|||
Conditions(state)
|
||||
DynamicSpacer(scrollState = scrollState)
|
||||
SpacerH16()
|
||||
ResetButton(enabled = state.resetButtonEnabled, onResetButtonClick = state.onResetButtonClick)
|
||||
ResetButton(enabled = state.isResetButtonEnabled, onResetButtonClick = state.onResetButtonClick)
|
||||
SpacerH16()
|
||||
}
|
||||
}
|
||||
|
|
@ -113,18 +113,18 @@ private fun Description(text: TextReference) {
|
|||
|
||||
@Composable
|
||||
private fun Conditions(state: ResetCardScreenState) {
|
||||
state.warningsToShow.forEach {
|
||||
when (it) {
|
||||
state.warningsToShow.forEach { warning ->
|
||||
when (warning) {
|
||||
ResetCardScreenState.WarningsToReset.LOST_WALLET_ACCESS -> {
|
||||
ConditionCheckBox(
|
||||
checkedState = state.acceptCondition1Checked,
|
||||
checkedState = state.isAcceptCondition1Checked,
|
||||
onCheckedChange = state.onAcceptCondition1ToggleClick,
|
||||
description = TextReference.Res(R.string.reset_card_to_factory_condition_1),
|
||||
)
|
||||
}
|
||||
ResetCardScreenState.WarningsToReset.LOST_PASSWORD_RESTORE -> {
|
||||
ConditionCheckBox(
|
||||
checkedState = state.acceptCondition2Checked,
|
||||
checkedState = state.isAcceptCondition2Checked,
|
||||
onCheckedChange = state.onAcceptCondition2ToggleClick,
|
||||
description = TextReference.Res(R.string.reset_card_to_factory_condition_2),
|
||||
)
|
||||
|
|
@ -238,12 +238,12 @@ private fun ResetCardScreenSample(modifier: Modifier = Modifier) {
|
|||
) {
|
||||
ResetCardScreen(
|
||||
state = ResetCardScreenState(
|
||||
resetButtonEnabled = true,
|
||||
showResetPasswordButton = false,
|
||||
isResetButtonEnabled = true,
|
||||
isResetPasswordButtonShown = false,
|
||||
warningsToShow = listOf(ResetCardScreenState.WarningsToReset.LOST_WALLET_ACCESS),
|
||||
descriptionText = TextReference.Res(R.string.reset_card_with_backup_to_factory_message),
|
||||
acceptCondition1Checked = false,
|
||||
acceptCondition2Checked = false,
|
||||
isAcceptCondition1Checked = false,
|
||||
isAcceptCondition2Checked = false,
|
||||
onAcceptCondition1ToggleClick = {},
|
||||
onAcceptCondition2ToggleClick = {},
|
||||
onResetButtonClick = {},
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ import com.tangem.tap.features.details.ui.cardsettings.TextReference
|
|||
import com.tangem.wallet.R
|
||||
|
||||
internal data class ResetCardScreenState(
|
||||
val resetButtonEnabled: Boolean,
|
||||
val isResetButtonEnabled: Boolean,
|
||||
val descriptionText: TextReference,
|
||||
val warningsToShow: List<WarningsToReset>,
|
||||
val showResetPasswordButton: Boolean,
|
||||
val acceptCondition1Checked: Boolean,
|
||||
val acceptCondition2Checked: Boolean,
|
||||
val isResetPasswordButtonShown: Boolean,
|
||||
val isAcceptCondition1Checked: Boolean,
|
||||
val isAcceptCondition2Checked: Boolean,
|
||||
val onAcceptCondition1ToggleClick: (Boolean) -> Unit,
|
||||
val onAcceptCondition2ToggleClick: (Boolean) -> Unit,
|
||||
val onResetButtonClick: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -97,15 +97,15 @@ internal class ResetCardModel @Inject constructor(
|
|||
}
|
||||
|
||||
return ResetCardScreenState(
|
||||
resetButtonEnabled = false,
|
||||
isResetButtonEnabled = false,
|
||||
descriptionText = getResetToFactoryDescription(
|
||||
isActiveBackupStatus = isActiveBackupPrimaryCard,
|
||||
typesResolver = currentCardTypesResolver,
|
||||
),
|
||||
warningsToShow = warningsToShow,
|
||||
showResetPasswordButton = shouldShowResetPasswordButton,
|
||||
acceptCondition1Checked = false,
|
||||
acceptCondition2Checked = false,
|
||||
isResetPasswordButtonShown = shouldShowResetPasswordButton,
|
||||
isAcceptCondition1Checked = false,
|
||||
isAcceptCondition2Checked = false,
|
||||
onAcceptCondition1ToggleClick = ::toggleFirstCondition,
|
||||
onAcceptCondition2ToggleClick = ::toggleSecondCondition,
|
||||
onResetButtonClick = { showDialog(ResetCardDialog.StartResetDialog) },
|
||||
|
|
@ -121,26 +121,26 @@ internal class ResetCardModel @Inject constructor(
|
|||
|
||||
private fun toggleFirstCondition(isAccepted: Boolean) {
|
||||
screenState.update { prevState ->
|
||||
val resetButtonEnabled = if (prevState.showResetPasswordButton) {
|
||||
isAccepted && prevState.acceptCondition2Checked
|
||||
val isResetButtonEnabled = if (prevState.isResetPasswordButtonShown) {
|
||||
isAccepted && prevState.isAcceptCondition2Checked
|
||||
} else {
|
||||
isAccepted
|
||||
}
|
||||
|
||||
prevState.copy(
|
||||
acceptCondition1Checked = isAccepted,
|
||||
resetButtonEnabled = resetButtonEnabled,
|
||||
isAcceptCondition1Checked = isAccepted,
|
||||
isResetButtonEnabled = isResetButtonEnabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleSecondCondition(isAccepted: Boolean) {
|
||||
screenState.update { prevState ->
|
||||
val resetButtonEnabled = prevState.acceptCondition1Checked && isAccepted
|
||||
val isResetButtonEnabled = prevState.isAcceptCondition1Checked && isAccepted
|
||||
|
||||
prevState.copy(
|
||||
acceptCondition2Checked = isAccepted,
|
||||
resetButtonEnabled = resetButtonEnabled,
|
||||
isAcceptCondition2Checked = isAccepted,
|
||||
isResetButtonEnabled = isResetButtonEnabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -183,14 +183,14 @@ internal class ResetCardModel @Inject constructor(
|
|||
modelScope.launch {
|
||||
resetCardUseCase(cardId = primaryCardId, params = currentUserCodeParams).onRight {
|
||||
deleteSavedAccessCodesUseCase(cardId = primaryCardId)
|
||||
val hasUserWallets = deleteWalletUseCase(userWalletId = currentUserWalletId).getOrElse {
|
||||
Timber.e("Unable to delete user wallet: $it")
|
||||
val hasUserWallets = deleteWalletUseCase(userWalletId = currentUserWalletId).getOrElse { error ->
|
||||
Timber.e("Unable to delete user wallet: $error")
|
||||
return@launch
|
||||
}
|
||||
|
||||
if (hasUserWallets) {
|
||||
val newSelectedWallet = getSelectedWalletSyncUseCase().getOrElse {
|
||||
error("Failed to get selected wallet: $it")
|
||||
val newSelectedWallet = getSelectedWalletSyncUseCase().getOrElse { error ->
|
||||
error("Failed to get selected wallet: $error")
|
||||
}
|
||||
|
||||
store.onUserWalletSelected(newSelectedWallet)
|
||||
|
|
@ -269,7 +269,7 @@ internal class ResetCardModel @Inject constructor(
|
|||
if (hotWalletFeatureToggles.isHotWalletEnabled) {
|
||||
store.dispatchNavigationAction { replaceAll(AppRoute.Home()) }
|
||||
} else {
|
||||
val isLocked = runCatching { userWalletsListManager.asLockable()?.isLockedSync }.isSuccess
|
||||
val isLocked = runCatching { userWalletsListManager.asLockable()?.isLocked }.isSuccess
|
||||
if (isLocked && userWalletsListManager.hasUserWallets) {
|
||||
store.dispatchNavigationAction { popTo<AppRoute.Welcome>() }
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ internal fun SecurityModeScreen(
|
|||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
SettingsScreensScaffold(
|
||||
onBackClick = onBackClick,
|
||||
modifier = modifier,
|
||||
content = { SecurityModeOptions(state = state) },
|
||||
// titleRes = R.string.card_settings_security_mode,
|
||||
onBackClick = onBackClick,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ private fun SecurityModeOptions(state: SecurityModeScreenState) {
|
|||
|
||||
@Composable
|
||||
private fun SecurityOption(option: SecurityOption, state: SecurityModeScreenState) {
|
||||
val selected = option == state.selectedSecurityMode
|
||||
val isSelected = option == state.selectedSecurityMode
|
||||
|
||||
val title = option.toTitleRes()
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ private fun SecurityOption(option: SecurityOption, state: SecurityModeScreenStat
|
|||
DetailsRadioButtonElement(
|
||||
title = stringResourceSafe(id = title),
|
||||
subtitle = stringResourceSafe(id = subtitle),
|
||||
selected = selected,
|
||||
isSelected = isSelected,
|
||||
onClick = { state.onNewModeSelected(option) },
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,9 +77,9 @@ internal class SecurityModeModel @Inject constructor(
|
|||
SecurityOption.AccessCode -> tangemSdkManager.setAccessCode(cardId)
|
||||
}
|
||||
|
||||
cardSettingsInteractor.update {
|
||||
it.copy(
|
||||
card = it.card.copy(
|
||||
cardSettingsInteractor.update { scanResponse ->
|
||||
scanResponse.copy(
|
||||
card = scanResponse.card.copy(
|
||||
isAccessCodeSet = selectedOption == SecurityOption.AccessCode,
|
||||
isPasscodeSet = selectedOption == SecurityOption.PassCode,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ internal class MainViewModel @Inject constructor(
|
|||
prepareSelectedWalletFeedback()
|
||||
|
||||
// await while initial route stack is initialized
|
||||
appRouterConfig.isInitialized.first { it }
|
||||
appRouterConfig.initializedState.first { it }
|
||||
|
||||
isSplashScreenShown = false
|
||||
}
|
||||
|
|
@ -179,11 +179,9 @@ internal class MainViewModel @Inject constructor(
|
|||
private fun prepareSelectedWalletFeedback() {
|
||||
getSelectedWalletUseCase.invoke()
|
||||
.mapLeft { emptyFlow<UserWallet>() }
|
||||
.onRight {
|
||||
it.distinctUntilChanged()
|
||||
.onEach { userWallet ->
|
||||
Analytics.setContext(userWallet)
|
||||
}
|
||||
.onRight { wallet ->
|
||||
wallet.distinctUntilChanged()
|
||||
.onEach { Analytics.setContext(it) }
|
||||
.flowOn(dispatchers.io)
|
||||
.launchIn(viewModelScope)
|
||||
}
|
||||
|
|
@ -208,7 +206,7 @@ internal class MainViewModel @Inject constructor(
|
|||
return MoonPayService(
|
||||
apiKey = environmentConfig.moonPayApiKey,
|
||||
secretKey = environmentConfig.moonPayApiSecretKey,
|
||||
logEnabled = LogConfig.network.moonPayService,
|
||||
isLogEnabled = LogConfig.network.moonPayService,
|
||||
userWalletProvider = { getSelectedWalletUseCase.sync().getOrNull() },
|
||||
)
|
||||
}
|
||||
|
|
@ -224,8 +222,8 @@ internal class MainViewModel @Inject constructor(
|
|||
.filter {
|
||||
it.isBalanceHidingNotificationEnabled && it.isBalanceHidden
|
||||
}
|
||||
.onEach {
|
||||
if (!it.isUpdateFromToast) {
|
||||
.onEach { settings ->
|
||||
if (!settings.isUpdateFromToast) {
|
||||
listenToFlipsUseCase.changeUpdateEnabled(false)
|
||||
|
||||
val message = BottomSheetMessage.invoke(
|
||||
|
|
@ -354,6 +352,7 @@ internal class MainViewModel @Inject constructor(
|
|||
listenToFlipsUseCase.changeUpdateEnabled(isUpdateEnabled = true)
|
||||
}
|
||||
|
||||
@Suppress("NullableToStringCall")
|
||||
private fun sendKeyboardIdentifierEvent() {
|
||||
viewModelScope.launch {
|
||||
val keyboardId = keyboardValidator.getKeyboardId()
|
||||
|
|
|
|||
|
|
@ -34,11 +34,11 @@ object OnboardingHelper {
|
|||
}
|
||||
|
||||
response.cardTypesResolver.isWallet2() || response.cardTypesResolver.isShibaWallet() -> {
|
||||
val emptyWallets = response.card.wallets.isEmpty()
|
||||
val activationInProgress = cardRepository.isActivationInProgress(cardId)
|
||||
val areWalletsEmpty = response.card.wallets.isEmpty()
|
||||
val isActivationInProgress = cardRepository.isActivationInProgress(cardId)
|
||||
val isNoBackup = response.card.backupStatus == CardDTO.BackupStatus.NoBackup &&
|
||||
!DemoHelper.isDemoCard(response)
|
||||
emptyWallets || activationInProgress || isNoBackup
|
||||
areWalletsEmpty || isActivationInProgress || isNoBackup
|
||||
}
|
||||
|
||||
response.card.wallets.isNotEmpty() -> cardRepository.isActivationInProgress(cardId)
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@ object TradeCryptoMiddleware {
|
|||
fiatCurrencyName = action.appCurrencyCode,
|
||||
walletAddress = networkAddress,
|
||||
isDarkTheme = MutableAppThemeModeHolder.isDarkThemeActive,
|
||||
)?.let {
|
||||
store.dispatchOpenUrl(it)
|
||||
)?.let { url ->
|
||||
store.dispatchOpenUrl(url)
|
||||
Analytics.send(Token.Withdraw.ScreenOpened())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,8 +72,8 @@ internal class WelcomeModel @Inject constructor(
|
|||
|
||||
this.state.update { prevState ->
|
||||
prevState.copy(
|
||||
showUnlockWithBiometricsProgress = state.isUnlockWithBiometricsInProgress,
|
||||
showUnlockWithCardProgress = state.isUnlockWithCardInProgress,
|
||||
isUnlockWithBiometricsProgressVisible = state.isUnlockWithBiometricsInProgress,
|
||||
isUnlockWithCardProgressVisible = state.isUnlockWithCardInProgress,
|
||||
warning = warning,
|
||||
error = state.error
|
||||
?.takeIf { !it.silent && warning == null }
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ internal sealed interface WelcomeAction : Action {
|
|||
object ProceedWithCard : WelcomeAction {
|
||||
object Success : WelcomeAction
|
||||
data class Error(val error: TangemError) : WelcomeAction
|
||||
data class ChangeProgress(val showProgress: Boolean) : WelcomeAction
|
||||
data class ChangeProgress(val isProgress: Boolean) : WelcomeAction
|
||||
}
|
||||
|
||||
object CloseError : WelcomeAction
|
||||
|
|
|
|||
|
|
@ -141,13 +141,13 @@ internal class WelcomeMiddleware {
|
|||
onSuccess = { scanResponse ->
|
||||
scope.launch { onCardScanned(scanResponse) }
|
||||
},
|
||||
onFailure = {
|
||||
when (it) {
|
||||
onFailure = { error ->
|
||||
when (error) {
|
||||
is TangemSdkError.ExceptionError -> {
|
||||
store.dispatchOnMain(WelcomeAction.ProceedWithCard.Success)
|
||||
}
|
||||
else -> {
|
||||
store.dispatchOnMain(WelcomeAction.ProceedWithCard.Error(it))
|
||||
store.dispatchOnMain(WelcomeAction.ProceedWithCard.Error(error))
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ internal object WelcomeReducer {
|
|||
isUnlockWithCardInProgress = false,
|
||||
)
|
||||
is WelcomeAction.ProceedWithCard.ChangeProgress -> state.copy(
|
||||
isUnlockWithCardInProgress = action.showProgress,
|
||||
isUnlockWithCardInProgress = action.isProgress,
|
||||
)
|
||||
is WelcomeAction.ProceedWithBiometrics.Success -> state.copy(isUnlockWithBiometricsInProgress = false)
|
||||
is WelcomeAction.ProceedWithCard.Success -> state.copy(isUnlockWithCardInProgress = false)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import com.tangem.tap.features.welcome.ui.model.WarningModel
|
|||
|
||||
internal data class WelcomeScreenState(
|
||||
val onPopBack: () -> Unit = {},
|
||||
val showUnlockWithBiometricsProgress: Boolean = false,
|
||||
val showUnlockWithCardProgress: Boolean = false,
|
||||
val isUnlockWithBiometricsProgressVisible: Boolean = false,
|
||||
val isUnlockWithCardProgressVisible: Boolean = false,
|
||||
val warning: WarningModel? = null,
|
||||
val error: TextReference? = null,
|
||||
val onUnlockClick: () -> Unit = {},
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@ internal fun WelcomeScreen(state: WelcomeScreenState, modifier: Modifier = Modif
|
|||
.systemBarsPadding(),
|
||||
) {
|
||||
WelcomeScreenContent(
|
||||
showUnlockProgress = state.showUnlockWithBiometricsProgress,
|
||||
showScanCardProgress = state.showUnlockWithCardProgress,
|
||||
showUnlockProgress = state.isUnlockWithBiometricsProgressVisible,
|
||||
showScanCardProgress = state.isUnlockWithCardProgressVisible,
|
||||
onUnlockClick = state.onUnlockClick,
|
||||
onScanCardClick = state.onScanCardClick,
|
||||
)
|
||||
|
|
@ -57,8 +57,8 @@ internal fun WelcomeScreen(state: WelcomeScreenState, modifier: Modifier = Modif
|
|||
WarningDialog(warning)
|
||||
|
||||
LaunchedEffect(errorMessage, state.onCloseError) {
|
||||
errorMessage?.let {
|
||||
snackbarHostState.showSnackbar(it)
|
||||
errorMessage?.let { message ->
|
||||
snackbarHostState.showSnackbar(message)
|
||||
state.onCloseError()
|
||||
}
|
||||
}
|
||||
|
|
@ -82,8 +82,8 @@ private class WelcomeComponentPreviewProvider : PreviewParameterProvider<Welcome
|
|||
PreviewWelcomeComponent(),
|
||||
PreviewWelcomeComponent(
|
||||
initialState = WelcomeScreenState(
|
||||
showUnlockWithBiometricsProgress = true,
|
||||
showUnlockWithCardProgress = true,
|
||||
isUnlockWithBiometricsProgressVisible = true,
|
||||
isUnlockWithCardProgressVisible = true,
|
||||
),
|
||||
),
|
||||
PreviewWelcomeComponent(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue