From 479a67f3be10382c9e814c8676505382b1b02be0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 22 Sep 2023 16:53:59 +0800 Subject: [PATCH] Updated on 2026-08-14 --- .../tangem/tap/di/domain/CardDomainModule.kt | 10 +++- .../tangem/datasource/di/CardDataModule.kt | 34 +++++++++++++ .../datasource/local/card/UsedCardInfo.kt | 8 +++ .../datasource/local/card/UsedCardsStore.kt | 21 ++++++++ .../core/KeylessDataStoreDecorator.kt | 27 +++------- data/card/build.gradle.kts | 1 + .../tangem/data/card/DefaultCardRepository.kt | 45 +++++++++++++++-- .../com/tangem/data/card/di/CardDataModule.kt | 5 +- .../domain/card/GetCardWasScannedUseCase.kt | 8 --- .../domain/card/SetCardWasScannedUseCase.kt | 8 +++ .../domain/card/WasCardScannedUseCase.kt | 9 ++++ .../domain/card/repository/CardRepository.kt | 6 ++- .../wallet/state/WalletAlertState.kt | 9 ++++ .../presentation/wallet/state/WalletEvent.kt | 2 + .../presentation/wallet/ui/WalletAlert.kt | 34 +++++++++++++ .../wallet/ui/WalletEventEffect.kt | 7 +++ .../presentation/wallet/ui/WalletScreen.kt | 13 +++-- .../WalletNotificationsListFactory.kt | 50 ++++++++++++------- .../wallet/viewmodels/WalletViewModel.kt | 21 ++++++-- 19 files changed, 257 insertions(+), 61 deletions(-) create mode 100644 core/datasource/src/main/java/com/tangem/datasource/di/CardDataModule.kt create mode 100644 core/datasource/src/main/java/com/tangem/datasource/local/card/UsedCardInfo.kt create mode 100644 core/datasource/src/main/java/com/tangem/datasource/local/card/UsedCardsStore.kt delete mode 100644 domain/card/src/main/kotlin/com/tangem/domain/card/GetCardWasScannedUseCase.kt create mode 100644 domain/card/src/main/kotlin/com/tangem/domain/card/SetCardWasScannedUseCase.kt create mode 100644 domain/card/src/main/kotlin/com/tangem/domain/card/WasCardScannedUseCase.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletAlertState.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletAlert.kt diff --git a/app/src/main/java/com/tangem/tap/di/domain/CardDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/CardDomainModule.kt index 1cee11bdbc..4f41cea873 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/CardDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/CardDomainModule.kt @@ -43,8 +43,14 @@ internal object CardDomainModule { @Provides @ViewModelScoped - fun provideGetCardWasScannedUseCase(cardRepository: CardRepository): GetCardWasScannedUseCase { - return GetCardWasScannedUseCase(cardRepository = cardRepository) + fun provideWasWalletAlreadySignedHashesConfirmedUseCase(cardRepository: CardRepository): WasCardScannedUseCase { + return WasCardScannedUseCase(cardRepository = cardRepository) + } + + @Provides + @ViewModelScoped + fun provideSetCardWasScannedUseCase(cardRepository: CardRepository): SetCardWasScannedUseCase { + return SetCardWasScannedUseCase(cardRepository = cardRepository) } @Provides diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/CardDataModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/CardDataModule.kt new file mode 100644 index 0000000000..9855d09182 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/di/CardDataModule.kt @@ -0,0 +1,34 @@ +package com.tangem.datasource.di + +import android.content.Context +import com.squareup.moshi.Moshi +import com.squareup.moshi.Types +import com.tangem.datasource.local.card.DefaultUsedCardsStore +import com.tangem.datasource.local.card.UsedCardInfo +import com.tangem.datasource.local.card.UsedCardsStore +import com.tangem.datasource.local.datastore.SharedPreferencesDataStore +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +internal object CardDataModule { + + @Provides + @Singleton + fun provideUsedCardsStore(@ApplicationContext context: Context, @NetworkMoshi moshi: Moshi): UsedCardsStore { + return DefaultUsedCardsStore( + store = SharedPreferencesDataStore( + preferencesName = "tapPrefs", + context = context, + adapter = moshi.adapter( + Types.newParameterizedType(List::class.java, UsedCardInfo::class.java), + ), + ), + ) + } +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/card/UsedCardInfo.kt b/core/datasource/src/main/java/com/tangem/datasource/local/card/UsedCardInfo.kt new file mode 100644 index 0000000000..0f619b1eec --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/local/card/UsedCardInfo.kt @@ -0,0 +1,8 @@ +package com.tangem.datasource.local.card + +data class UsedCardInfo( + val cardId: String, + val isScanned: Boolean = false, + val isActivationStarted: Boolean = false, + val isActivationFinished: Boolean = false, +) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/card/UsedCardsStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/card/UsedCardsStore.kt new file mode 100644 index 0000000000..0d54995dbb --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/local/card/UsedCardsStore.kt @@ -0,0 +1,21 @@ +package com.tangem.datasource.local.card + +import com.tangem.datasource.local.datastore.SharedPreferencesDataStore +import com.tangem.datasource.local.datastore.core.KeylessDataStoreDecorator +import kotlinx.coroutines.flow.Flow + +interface UsedCardsStore { + + fun get(): Flow> + + suspend fun getSyncOrNull(): List? + + suspend fun store(item: List) +} + +internal class DefaultUsedCardsStore( + store: SharedPreferencesDataStore>, +) : UsedCardsStore, KeylessDataStoreDecorator>( + wrappedDataStore = store, + key = "usedCardsInfo_v2", +) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/datastore/core/KeylessDataStoreDecorator.kt b/core/datasource/src/main/java/com/tangem/datasource/local/datastore/core/KeylessDataStoreDecorator.kt index 6010c456b5..fd8f6b333c 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/datastore/core/KeylessDataStoreDecorator.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/datastore/core/KeylessDataStoreDecorator.kt @@ -1,32 +1,21 @@ package com.tangem.datasource.local.datastore.core -import kotlinx.coroutines.flow.Flow - internal abstract class KeylessDataStoreDecorator( wrappedDataStore: StringKeyDataStore, -) : StringKeyDataStoreDecorator(wrappedDataStore) { + private val key: String = DEFAULT_STRING_KEY, +) : StringKeyDataStoreDecorator(wrappedDataStore) { - override fun provideStringKey(key: Unit): String { - return STRING_KEY - } + override fun provideStringKey(key: String) = key - open fun get(): Flow { - return get(Unit) - } + open fun get() = get(key) - open suspend fun getSyncOrNull(): Value? { - return getSyncOrNull(Unit) - } + open suspend fun getSyncOrNull() = getSyncOrNull(key) - open suspend fun store(item: Value) { - store(Unit, item) - } + open suspend fun store(item: Value) = store(key, item) - open suspend fun isEmpty(): Boolean { - return getSyncOrNull() == null - } + open suspend fun isEmpty() = getSyncOrNull() == null private companion object { - const val STRING_KEY = "key" + const val DEFAULT_STRING_KEY = "key" } } \ No newline at end of file diff --git a/data/card/build.gradle.kts b/data/card/build.gradle.kts index 0999cc6959..c7a692bd7e 100644 --- a/data/card/build.gradle.kts +++ b/data/card/build.gradle.kts @@ -17,6 +17,7 @@ dependencies { implementation(deps.tangem.card.android) implementation(deps.tangem.card.core) + implementation(projects.core.datasource) implementation(projects.core.utils) implementation(projects.data.source.preferences) diff --git a/data/card/src/main/java/com/tangem/data/card/DefaultCardRepository.kt b/data/card/src/main/java/com/tangem/data/card/DefaultCardRepository.kt index b1bc033cb1..4c2cb66af4 100644 --- a/data/card/src/main/java/com/tangem/data/card/DefaultCardRepository.kt +++ b/data/card/src/main/java/com/tangem/data/card/DefaultCardRepository.kt @@ -1,16 +1,53 @@ package com.tangem.data.card -import com.tangem.data.source.preferences.PreferencesDataSource +import com.tangem.datasource.local.card.UsedCardInfo +import com.tangem.datasource.local.card.UsedCardsStore import com.tangem.domain.card.repository.CardRepository import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.channelFlow +import kotlinx.coroutines.launch import kotlinx.coroutines.withContext internal class DefaultCardRepository( - private val preferencesDataSource: PreferencesDataSource, + private val usedCardsStore: UsedCardsStore, private val dispatchers: CoroutineDispatcherProvider, ) : CardRepository { - override suspend fun wasCardScanned(cardId: String): Boolean { - return withContext(dispatchers.io) { preferencesDataSource.usedCardsPrefStorage.wasScanned(cardId) } + override fun wasCardScanned(cardId: String): Flow { + return channelFlow { + launch(dispatchers.io) { + usedCardsStore.get() + .collect { savedCards -> + send(element = savedCards.any { it.cardId == cardId }) + } + } + + withContext(dispatchers.io) { + if (usedCardsStore.getSyncOrNull() == null) { + send(element = false) + } + } + } + } + + override suspend fun setCardWasScanned(cardId: String) { + withContext(dispatchers.io) { + usedCardsStore.store( + item = usedCardsStore.getSyncOrNull() + ?.updateCard(cardId) + ?: listOf(UsedCardInfo(cardId = cardId, isScanned = true)), + ) + } + } + + private fun List.updateCard(cardId: String): List { + return map { cardInfo -> + if (cardInfo.cardId == cardId) { + cardInfo.copy(isScanned = true) + } else { + cardInfo + } + } } } \ No newline at end of file diff --git a/data/card/src/main/java/com/tangem/data/card/di/CardDataModule.kt b/data/card/src/main/java/com/tangem/data/card/di/CardDataModule.kt index b5edf95c45..0c2cfdecbf 100644 --- a/data/card/src/main/java/com/tangem/data/card/di/CardDataModule.kt +++ b/data/card/src/main/java/com/tangem/data/card/di/CardDataModule.kt @@ -4,6 +4,7 @@ import com.tangem.data.card.DefaultCardRepository import com.tangem.data.card.DefaultCardSdkConfigRepository import com.tangem.data.card.sdk.CardSdkProvider import com.tangem.data.source.preferences.PreferencesDataSource +import com.tangem.datasource.local.card.UsedCardsStore import com.tangem.domain.card.repository.CardRepository import com.tangem.domain.card.repository.CardSdkConfigRepository import com.tangem.utils.coroutines.CoroutineDispatcherProvider @@ -32,9 +33,9 @@ internal object CardDataModule { @Provides @Singleton fun provideCardRepository( - preferencesDataSource: PreferencesDataSource, + usedCardsStore: UsedCardsStore, dispatchers: CoroutineDispatcherProvider, ): CardRepository { - return DefaultCardRepository(preferencesDataSource = preferencesDataSource, dispatchers = dispatchers) + return DefaultCardRepository(usedCardsStore = usedCardsStore, dispatchers = dispatchers) } } \ No newline at end of file diff --git a/domain/card/src/main/kotlin/com/tangem/domain/card/GetCardWasScannedUseCase.kt b/domain/card/src/main/kotlin/com/tangem/domain/card/GetCardWasScannedUseCase.kt deleted file mode 100644 index 91c077997d..0000000000 --- a/domain/card/src/main/kotlin/com/tangem/domain/card/GetCardWasScannedUseCase.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.tangem.domain.card - -import com.tangem.domain.card.repository.CardRepository - -class GetCardWasScannedUseCase(private val cardRepository: CardRepository) { - - suspend operator fun invoke(cardId: String): Boolean = cardRepository.wasCardScanned(cardId) -} \ No newline at end of file diff --git a/domain/card/src/main/kotlin/com/tangem/domain/card/SetCardWasScannedUseCase.kt b/domain/card/src/main/kotlin/com/tangem/domain/card/SetCardWasScannedUseCase.kt new file mode 100644 index 0000000000..9cd5449cb0 --- /dev/null +++ b/domain/card/src/main/kotlin/com/tangem/domain/card/SetCardWasScannedUseCase.kt @@ -0,0 +1,8 @@ +package com.tangem.domain.card + +import com.tangem.domain.card.repository.CardRepository + +class SetCardWasScannedUseCase(private val cardRepository: CardRepository) { + + suspend operator fun invoke(cardId: String) = cardRepository.setCardWasScanned(cardId) +} \ No newline at end of file diff --git a/domain/card/src/main/kotlin/com/tangem/domain/card/WasCardScannedUseCase.kt b/domain/card/src/main/kotlin/com/tangem/domain/card/WasCardScannedUseCase.kt new file mode 100644 index 0000000000..5d8e288f3c --- /dev/null +++ b/domain/card/src/main/kotlin/com/tangem/domain/card/WasCardScannedUseCase.kt @@ -0,0 +1,9 @@ +package com.tangem.domain.card + +import com.tangem.domain.card.repository.CardRepository +import kotlinx.coroutines.flow.Flow + +class WasCardScannedUseCase(private val cardRepository: CardRepository) { + + operator fun invoke(cardId: String): Flow = cardRepository.wasCardScanned(cardId) +} \ No newline at end of file diff --git a/domain/card/src/main/kotlin/com/tangem/domain/card/repository/CardRepository.kt b/domain/card/src/main/kotlin/com/tangem/domain/card/repository/CardRepository.kt index 40ac6ec968..27bb1657ab 100644 --- a/domain/card/src/main/kotlin/com/tangem/domain/card/repository/CardRepository.kt +++ b/domain/card/src/main/kotlin/com/tangem/domain/card/repository/CardRepository.kt @@ -1,6 +1,10 @@ package com.tangem.domain.card.repository +import kotlinx.coroutines.flow.Flow + interface CardRepository { - suspend fun wasCardScanned(cardId: String): Boolean + fun wasCardScanned(cardId: String): Flow + + suspend fun setCardWasScanned(cardId: String) } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletAlertState.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletAlertState.kt new file mode 100644 index 0000000000..4bcdd07368 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletAlertState.kt @@ -0,0 +1,9 @@ +package com.tangem.feature.wallet.presentation.wallet.state + +import androidx.compose.runtime.Immutable + +@Immutable +internal sealed class WalletAlertState { + + data class WalletAlreadySignedHashes(val onUnderstandClick: () -> Unit) : WalletAlertState() +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletEvent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletEvent.kt index 1c1ccaaceb..8b7d294ae4 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletEvent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletEvent.kt @@ -13,4 +13,6 @@ internal sealed class WalletEvent { data class ShowToast(val text: TextReference) : WalletEvent() data class CopyAddress(val address: String) : WalletEvent() + + data class ShowWalletAlreadySignedHashesMessage(val onUnderstandClick: () -> Unit) : WalletEvent() } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletAlert.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletAlert.kt new file mode 100644 index 0000000000..5b5a6a7e5e --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletAlert.kt @@ -0,0 +1,34 @@ +package com.tangem.feature.wallet.presentation.wallet.ui + +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import com.tangem.core.ui.components.BasicDialog +import com.tangem.core.ui.components.DialogButton +import com.tangem.feature.wallet.impl.R +import com.tangem.feature.wallet.presentation.wallet.state.WalletAlertState + +@Composable +internal fun WalletAlert(config: WalletAlertState, onDismiss: () -> Unit) { + when (config) { + is WalletAlertState.WalletAlreadySignedHashes -> { + WalletAlreadySignedHashesAlert(config = config, onDismiss = onDismiss) + } + } +} + +@Composable +private fun WalletAlreadySignedHashesAlert(config: WalletAlertState.WalletAlreadySignedHashes, onDismiss: () -> Unit) { + BasicDialog( + message = stringResource(id = R.string.alert_signed_hashes_message), + confirmButton = DialogButton( + title = stringResource(id = R.string.common_understand), + onClick = { + config.onUnderstandClick() + onDismiss() + }, + ), + onDismissDialog = onDismiss, + title = stringResource(id = R.string.warning_important_security_info, "\u26A0"), + dismissButton = DialogButton(title = stringResource(id = R.string.common_cancel), onClick = onDismiss), + ) +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletEventEffect.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletEventEffect.kt index 914ae8de38..b667aa10ad 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletEventEffect.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletEventEffect.kt @@ -10,6 +10,7 @@ import androidx.compose.ui.text.AnnotatedString import com.tangem.core.ui.event.EventEffect import com.tangem.core.ui.event.StateEvent import com.tangem.core.ui.extensions.resolveReference +import com.tangem.feature.wallet.presentation.wallet.state.WalletAlertState import com.tangem.feature.wallet.presentation.wallet.state.WalletEvent @Composable @@ -18,6 +19,7 @@ internal fun WalletEventEffect( snackbarHostState: SnackbarHostState, event: StateEvent, onAutoScrollSet: () -> Unit, + onAlertConfigSet: (WalletAlertState) -> Unit, ) { val context = LocalContext.current val resources = LocalContext.current.resources @@ -39,6 +41,11 @@ internal fun WalletEventEffect( is WalletEvent.CopyAddress -> { clipboardManager.setText(AnnotatedString(value.address)) } + is WalletEvent.ShowWalletAlreadySignedHashesMessage -> { + onAlertConfigSet( + WalletAlertState.WalletAlreadySignedHashes(onUnderstandClick = value.onUnderstandClick), + ) + } } }, ) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt index 3f8672679f..bacaea655a 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt @@ -12,10 +12,7 @@ import androidx.compose.material3.FabPosition import androidx.compose.material3.Scaffold import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.State -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource @@ -30,6 +27,7 @@ import com.tangem.core.ui.components.transactions.state.TxHistoryState import com.tangem.core.ui.res.TangemTheme import com.tangem.feature.wallet.impl.R import com.tangem.feature.wallet.presentation.common.WalletPreviewData +import com.tangem.feature.wallet.presentation.wallet.state.WalletAlertState import com.tangem.feature.wallet.presentation.wallet.state.WalletMultiCurrencyState import com.tangem.feature.wallet.presentation.wallet.state.WalletSingleCurrencyState import com.tangem.feature.wallet.presentation.wallet.state.WalletState @@ -72,12 +70,19 @@ internal fun WalletScreen(state: WalletState) { onAutoScrollReset = { isAutoScroll.value = false }, ) + var alertConfig by remember { mutableStateOf(value = null) } + WalletEventEffect( walletsListState = walletsListState, snackbarHostState = snackbarHostState, event = state.event, onAutoScrollSet = { isAutoScroll.value = true }, + onAlertConfigSet = { alertConfig = it }, ) + + alertConfig?.let { + WalletAlert(config = it, onDismiss = { alertConfig = null }) + } } is WalletState.Initial -> Unit } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletNotificationsListFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletNotificationsListFactory.kt index 4935e3ac1b..21de9b5e10 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletNotificationsListFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletNotificationsListFactory.kt @@ -1,6 +1,6 @@ package com.tangem.feature.wallet.presentation.wallet.viewmodels -import com.tangem.domain.card.GetCardWasScannedUseCase +import com.tangem.domain.card.WasCardScannedUseCase import com.tangem.domain.common.CardTypesResolver import com.tangem.domain.demo.IsDemoCardUseCase import com.tangem.domain.settings.IsUserAlreadyRateAppUseCase @@ -10,14 +10,16 @@ import com.tangem.feature.wallet.presentation.wallet.state.components.WalletNoti import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.map +import kotlin.collections.count /** * Wallet notifications list factory * * @property isDemoCardUseCase use case that check if card is demo * @property isUserAlreadyRateAppUseCase use case that check if card is user already rate app - * @property getCardWasScannedUseCase use case that check if card was scanned + * @property wasCardScannedUseCase use case that check if card was scanned * @property clickIntents screen click intents * [REDACTED_AUTHOR] @@ -25,7 +27,7 @@ import kotlinx.coroutines.flow.flow internal class WalletNotificationsListFactory( private val isDemoCardUseCase: IsDemoCardUseCase, private val isUserAlreadyRateAppUseCase: IsUserAlreadyRateAppUseCase, - private val getCardWasScannedUseCase: GetCardWasScannedUseCase, + private val wasCardScannedUseCase: WasCardScannedUseCase, private val clickIntents: WalletClickIntents, ) { @@ -33,8 +35,9 @@ internal class WalletNotificationsListFactory( cardTypesResolver: CardTypesResolver, cryptoCurrencyList: List, ): Flow> { - return flow { - emit( + return wasCardScannedUseCase.invoke(cardTypesResolver.getCardId()) + .distinctUntilChanged() + .map { buildList { addCriticalNotifications(cardTypesResolver) @@ -42,11 +45,9 @@ internal class WalletNotificationsListFactory( addRateTheAppNotification() - addWarningNotifications(cardTypesResolver, cryptoCurrencyList) - } - .toImmutableList(), - ) - } + addWarningNotifications(cardTypesResolver, cryptoCurrencyList, it) + }.toImmutableList() + } } private fun MutableList.addCriticalNotifications(cardTypesResolver: CardTypesResolver) { @@ -112,9 +113,10 @@ internal class WalletNotificationsListFactory( ) } - private suspend fun MutableList.addWarningNotifications( + private fun MutableList.addWarningNotifications( cardTypesResolver: CardTypesResolver, cryptoCurrencyList: List, + wasCardScanned: Boolean, ) { addIf( element = WalletNotification.Warning.MissingBackup( @@ -133,14 +135,22 @@ internal class WalletNotificationsListFactory( if (cardTypesResolver.isBackupForbidden()) { addIf( element = WalletNotification.Warning.NumberOfSignedHashesIncorrect, - condition = checkSignedHashes(cardTypesResolver = cardTypesResolver, isDemo = isDemo), + condition = checkSignedHashes( + cardTypesResolver = cardTypesResolver, + isDemo = isDemo, + wasCardScanned, + ), ) } else { addIf( element = WalletNotification.Warning.MultiWalletSignedHashesIncorrect( onClick = clickIntents::onMultiWalletSignedHashesNotificationClick, ), - condition = checkSignedHashes(cardTypesResolver = cardTypesResolver, isDemo = isDemo), + condition = checkSignedHashes( + cardTypesResolver = cardTypesResolver, + isDemo = isDemo, + wasCardScanned, + ), ) } } else { @@ -159,7 +169,7 @@ internal class WalletNotificationsListFactory( addIf( element = WalletNotification.Warning.NumberOfSignedHashesIncorrect, - condition = checkSignedHashes(cardTypesResolver, isDemo), + condition = checkSignedHashes(cardTypesResolver, isDemo, wasCardScanned), ) } } @@ -176,9 +186,13 @@ internal class WalletNotificationsListFactory( return any { it.value is CryptoCurrencyStatus.NoAccount } } - private suspend fun checkSignedHashes(cardTypesResolver: CardTypesResolver, isDemo: Boolean): Boolean { - return cardTypesResolver.isReleaseFirmwareType() && cardTypesResolver.hasWalletSignedHashes() && - !isDemo && !getCardWasScannedUseCase(cardId = cardTypesResolver.getCardId()) + private fun checkSignedHashes( + cardTypesResolver: CardTypesResolver, + isDemo: Boolean, + wasCardScanned: Boolean, + ): Boolean { + return cardTypesResolver.isReleaseFirmwareType() && cardTypesResolver.hasWalletSignedHashes() && !isDemo && + !wasCardScanned } private companion object { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt index a3a4576625..df90b7378b 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt @@ -106,7 +106,8 @@ internal class WalletViewModel @Inject constructor( private val reduxStateHolder: ReduxStateHolder, private val dispatchers: CoroutineDispatcherProvider, private val analyticsEventsHandler: AnalyticsEventHandler, - getCardWasScannedUseCase: GetCardWasScannedUseCase, + private val setCardWasScannedUseCase: SetCardWasScannedUseCase, + wasCardScannedUseCase: WasCardScannedUseCase, isUserAlreadyRateAppUseCase: IsUserAlreadyRateAppUseCase, isDemoCardUseCase: IsDemoCardUseCase, // endregion Parameters @@ -119,7 +120,7 @@ internal class WalletViewModel @Inject constructor( private var isBalanceHidden = true private val notificationsListFactory = WalletNotificationsListFactory( - getCardWasScannedUseCase = getCardWasScannedUseCase, + wasCardScannedUseCase = wasCardScannedUseCase, isUserAlreadyRateAppUseCase = isUserAlreadyRateAppUseCase, isDemoCardUseCase = isDemoCardUseCase, clickIntents = this, @@ -413,7 +414,21 @@ internal class WalletViewModel @Inject constructor( } override fun onMultiWalletSignedHashesNotificationClick() { - // TODO: [REDACTED_JIRA] + val state = uiState as? WalletState.ContentState ?: return + + uiState = stateFactory.getStateAndTriggerEvent( + state = uiState, + event = WalletEvent.ShowWalletAlreadySignedHashesMessage( + onUnderstandClick = { + viewModelScope.launch(dispatchers.main) { + setCardWasScannedUseCase( + cardId = getWallet(index = state.walletsListConfig.selectedWalletIndex).cardId, + ) + } + }, + ), + setUiState = { uiState = it }, + ) } override fun onLikeTangemAppClick() {