diff --git a/common/src/main/kotlin/com/tangem/common/TangemBlogUrlBuilder.kt b/common/src/main/kotlin/com/tangem/common/TangemBlogUrlBuilder.kt index 27017a9505..4966d2d7b0 100644 --- a/common/src/main/kotlin/com/tangem/common/TangemBlogUrlBuilder.kt +++ b/common/src/main/kotlin/com/tangem/common/TangemBlogUrlBuilder.kt @@ -24,5 +24,9 @@ object TangemBlogUrlBuilder { data object SeedNotify : Post { override val path: String = "seed-notify" } + + data object SeedNotifySecond : Post { + override val path: String = "tangem-resolves-log-issue" + } } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt index 44e90009b0..c109e5b91e 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt @@ -123,6 +123,17 @@ interface TangemTechApi { @Body body: SeedPhraseNotificationDTO, ): ApiResponse + @GET("seedphrase-notification/{wallet_id}/confirmed") + suspend fun getSeedPhraseSecondNotificationStatus( + @Path("wallet_id") walletId: String, + ): ApiResponse + + @PUT("seedphrase-notification/{wallet_id}/confirmed") + suspend fun updateSeedPhraseSecondNotificationStatus( + @Path("wallet_id") walletId: String, + @Body body: SeedPhraseNotificationDTO, + ): ApiResponse + @GET("hot_crypto") suspend fun getHotCrypto(@Query("currency") currencyId: String): ApiResponse diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/SeedPhraseNotificationDTO.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/SeedPhraseNotificationDTO.kt index e54c1cab47..3184e87ead 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/SeedPhraseNotificationDTO.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/SeedPhraseNotificationDTO.kt @@ -19,6 +19,12 @@ data class SeedPhraseNotificationDTO(val status: Status) { @Json(name = "confirmed") CONFIRMED, + @Json(name = "rejected") + REJECTED, + + @Json(name = "accepted") + ACCEPTED, + ; } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt index 00e2ab95b4..434d4c4a92 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt @@ -119,6 +119,8 @@ object PreferencesKeys { val WAS_LOG_FILE_CLEARED by lazy { booleanPreferencesKey(name = "wasLogFileCleared") } + val SEED_FIRST_NOTIFICATION_SHOW_TIME by lazy { longPreferencesKey("seedFirstNotificationTime") } + fun getShouldShowStoriesKey(storyId: String) = booleanPreferencesKey("shouldShowStories_$storyId") // region Permission diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml index 60fe380d48..fd85f80b66 100644 --- a/core/res/src/main/res/values-fr/strings.xml +++ b/core/res/src/main/res/values-fr/strings.xml @@ -881,13 +881,13 @@ Le réseau facturera des frais d\'approbation de jeton pour vérifier que vous autorisez l\'utilisation de votre jeton pour l\'échange. Échangez plus de jetons à de meilleurs taux directement dans votre portefeuille. Nouveau fournisseur d\'échange disponible ! - Ayez confiance en bénéficiant d\'un support constant, garantissant que vos transactions se déroulent sans problème à tout moment + Ayez confiance en notre assistance 24 heures sur 24 pour vous aider à résoudre tous vos problèmes Assistance 24 heures sur 24 - Les fournisseurs d\'échange de confiance vous permettent d\'échanger des actifs sans effort, en gardant tout en sécurité dans votre portefeuille + Plusieurs fournisseurs de confiance en un seul endroit : échangez n\'importe quel actif facilement Échangez Avec Nous Une sécurité de haut niveau et des fournisseurs vérifiés garantissant que vos actifs sont protégés à chaque échange Plus Sûr Que Jamais - Maximisez votre valeur avec des tarifs provenant d\'un large réseau de fournisseurs de confiance, en choisissant toujours le meilleur + Maximisez votre valeur avec des tarifs d\'un large réseau de fournisseurs de confiance Meilleurs Tarifs Simple et intuitif, vous permettant d\'échanger des jetons en quelques clics Plus Simple Que Jamais diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index d05722217e..931cb0fd78 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -871,16 +871,16 @@ ネットワークは、あなたがトークンのスワップを承認していることを確認するために、トークン承認手数料を請求します。 より多くのトークンをより良いレートで、ウォレット内にて直接交換します。 新しいスワッププロバイダーが利用可能になりました! - 継続的なサポートで、いつでもスムーズに取引を行うことができます - 24時間体制のサポート - 信頼できる交換プロバイダーは、ウォレット内の資産を安全に保管しながら、簡単に交換できるようにします。 - 当社の交換機能をご利用ください - トップレベルのセキュリティと認証済みプロバイダーが、スワップ時にユーザーの資産を確実に保護します。 - 最高に安全 + 24時間体制のサポートであらゆる問題に対応します。 + いつもここに + 複数の信頼できるプロバイダーが一箇所に集結。ウォレット内で様々な暗号資産を簡単に交換できます。 + ぜひスワップしてください + 失敗も死角もありません。取引は常に保護されます。 + 難攻不落の防御 幅広いネットワークの中から、常に最適なプロバイダーと料金レートを選択します - ベストレート + 破格のレート 手間がかからず直感的に操作でき、数回タップするだけでトークンを交換できます。 - 最高に簡単 + とにかく便利 この金額には以下が含まれます:\n- サービスプロバイダーの手数料\n- 取引所からユーザーのアドレスに%s を送り返すためのネットワーク手数料。 金額には以下が含まれます: \n • サービス プロバイダーの手数料\n • 取引所からユーザーのアドレスに%1$sを送金するためのネットワーク手数料。 \n\nプロバイダーのスリッページは最大%2$sです この金額には、サービスプロバイダーの手数料が含まれています。 diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index dd9d95e11a..b463199a6f 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -674,6 +674,8 @@ Scan the card or ring to change its settings. The changes will impact only the card or ring you\'ve scanned and will not affect other devices tied to your wallet. Get your Tangem ready! Security Alert + No, I did not + Yes, guide me You don’t have enough funds in your balance to sell cryptocurrency. Please deposit the desired asset to proceed. Insufficient Balance Selling cryptocurrency is unavailable in your region at the moment. We’re actively working to bring this option to you soon—stay tuned! @@ -1089,6 +1091,8 @@ Enjoying Tangem? You must associate your token before receiving tokens Network rent fee required + Action required + Did you contact support via the app or email within 7 days of creating a wallet? If you did or are unsure, follow and complete the instructions. Thank you! All set! No further actions required. You will now be redirected to the official Tangem website. Please read and follow instructions there. Have you ever contacted the Tangem support team directly through this application? diff --git a/core/utils/src/main/java/com/tangem/utils/TimeConstants.kt b/core/utils/src/main/java/com/tangem/utils/TimeConstants.kt new file mode 100644 index 0000000000..a2bf41adfe --- /dev/null +++ b/core/utils/src/main/java/com/tangem/utils/TimeConstants.kt @@ -0,0 +1,4 @@ +package com.tangem.utils + +const val H24_MILLIS = 24L * 60 * 60 * 1000 +const val WEEK_MILLIS = 7L * H24_MILLIS \ No newline at end of file diff --git a/data/wallets/src/main/java/com/tangem/data/wallets/DefaultWalletsRepository.kt b/data/wallets/src/main/java/com/tangem/data/wallets/DefaultWalletsRepository.kt index c6e3354caa..0d0c0f38ee 100644 --- a/data/wallets/src/main/java/com/tangem/data/wallets/DefaultWalletsRepository.kt +++ b/data/wallets/src/main/java/com/tangem/data/wallets/DefaultWalletsRepository.kt @@ -9,12 +9,15 @@ import com.tangem.datasource.api.tangemTech.models.SeedPhraseNotificationDTO.Sta import com.tangem.datasource.local.datastore.RuntimeStateStore import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.preferences.PreferencesKeys +import com.tangem.datasource.local.preferences.PreferencesKeys.SEED_FIRST_NOTIFICATION_SHOW_TIME import com.tangem.datasource.local.preferences.utils.get import com.tangem.datasource.local.preferences.utils.getSyncOrDefault import com.tangem.datasource.local.preferences.utils.store import com.tangem.datasource.local.userwallet.UserWalletsStore +import com.tangem.domain.wallets.models.SeedPhraseNotificationsStatus import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.repository.WalletsRepository +import com.tangem.utils.WEEK_MILLIS import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.runCatching import kotlinx.coroutines.flow.Flow @@ -23,11 +26,13 @@ import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch +typealias SeedPhraseNotificationsStatuses = Map + internal class DefaultWalletsRepository( private val appPreferencesStore: AppPreferencesStore, private val tangemTechApi: TangemTechApi, private val userWalletsStore: UserWalletsStore, - private val seedPhraseNotificationVisibilityStore: RuntimeStateStore>, + private val seedPhraseNotificationVisibilityStore: RuntimeStateStore, private val dispatchers: CoroutineDispatcherProvider, ) : WalletsRepository { @@ -57,11 +62,16 @@ internal class DefaultWalletsRepository( } } - override fun seedPhraseNotificationStatus(userWalletId: UserWalletId): Flow { + override fun seedPhraseNotificationStatus(userWalletId: UserWalletId): Flow { return channelFlow { launch { seedPhraseNotificationVisibilityStore.get() - .map { it.getOrDefault(key = userWalletId, defaultValue = false) } + .map { + it.getOrDefault( + key = userWalletId, + defaultValue = SeedPhraseNotificationsStatus.NOT_NEEDED, + ) + } .collectLatest(::send) } @@ -73,18 +83,53 @@ internal class DefaultWalletsRepository( val userWallet = userWalletsStore.getSyncOrNull(key = userWalletId) val status = if (userWallet?.isImported == false) { - false + Status.NOT_NEEDED } else { runCatching(dispatchers.io) { tangemTechApi.getSeedPhraseNotificationStatus(walletId = userWalletId.stringValue).getOrThrow() - } - .fold( - onSuccess = { it.status == Status.NOTIFIED }, - onFailure = { it is HttpException && it.code == HttpException.Code.NOT_FOUND }, - ) + }.fold( + onSuccess = { it.status }, + onFailure = { + if (it is HttpException && it.code == HttpException.Code.NOT_FOUND) { + Status.NOTIFIED + } else { + Status.NOT_NEEDED + } + }, + ) } - updateNotificationVisibility(id = userWalletId, value = status) + when { + status == Status.NOTIFIED -> updateNotificationVisibility( + id = userWalletId, + value = SeedPhraseNotificationsStatus.SHOW_FIRST, + ) + status == Status.CONFIRMED && checkNeedFetchSecondNotification() -> + fetchSeedPhraseSecondNotificationStatus(userWalletId) + else -> updateNotificationVisibility(id = userWalletId, value = SeedPhraseNotificationsStatus.NOT_NEEDED) + } + } + + private suspend fun fetchSeedPhraseSecondNotificationStatus(userWalletId: UserWalletId) { + val status = runCatching(dispatchers.io) { + tangemTechApi.getSeedPhraseSecondNotificationStatus(walletId = userWalletId.stringValue).getOrThrow() + }.fold( + onSuccess = { it.status }, + onFailure = { Status.NOT_NEEDED }, + ) + + val showStatus = when (status) { + Status.CONFIRMED -> SeedPhraseNotificationsStatus.SHOW_SECOND + else -> SeedPhraseNotificationsStatus.NOT_NEEDED + } + + updateNotificationVisibility(id = userWalletId, value = showStatus) + } + + private suspend fun checkNeedFetchSecondNotification(): Boolean { + val firstNotificationTime = + appPreferencesStore.getSyncOrDefault(SEED_FIRST_NOTIFICATION_SHOW_TIME, default = 0L) + return System.currentTimeMillis() - firstNotificationTime > WEEK_MILLIS } override suspend fun notifiedSeedPhraseNotification(userWalletId: UserWalletId) { @@ -102,9 +147,10 @@ internal class DefaultWalletsRepository( walletId = userWalletId.stringValue, body = SeedPhraseNotificationDTO(status = Status.CONFIRMED), ).getOrThrow() + appPreferencesStore.store(key = SEED_FIRST_NOTIFICATION_SHOW_TIME, value = System.currentTimeMillis()) } - updateNotificationVisibility(id = userWalletId, value = false) + updateNotificationVisibility(id = userWalletId, value = SeedPhraseNotificationsStatus.NOT_NEEDED) } override suspend fun declineSeedPhraseNotification(userWalletId: UserWalletId) { @@ -113,9 +159,10 @@ internal class DefaultWalletsRepository( walletId = userWalletId.stringValue, body = SeedPhraseNotificationDTO(status = Status.DECLINED), ).getOrThrow() + appPreferencesStore.store(key = SEED_FIRST_NOTIFICATION_SHOW_TIME, value = System.currentTimeMillis()) } - updateNotificationVisibility(id = userWalletId, value = false) + updateNotificationVisibility(id = userWalletId, value = SeedPhraseNotificationsStatus.NOT_NEEDED) } override suspend fun markWallet2WasCreated(userWalletId: UserWalletId) { @@ -126,7 +173,29 @@ internal class DefaultWalletsRepository( } } - private suspend fun updateNotificationVisibility(id: UserWalletId, value: Boolean) { + override suspend fun rejectSeedPhraseSecondNotification(userWalletId: UserWalletId) { + runCatching(dispatchers.io) { + tangemTechApi.updateSeedPhraseSecondNotificationStatus( + walletId = userWalletId.stringValue, + body = SeedPhraseNotificationDTO(status = Status.REJECTED), + ).getOrThrow() + } + + updateNotificationVisibility(id = userWalletId, value = SeedPhraseNotificationsStatus.NOT_NEEDED) + } + + override suspend fun acceptSeedPhraseSecondNotification(userWalletId: UserWalletId) { + runCatching(dispatchers.io) { + tangemTechApi.updateSeedPhraseSecondNotificationStatus( + walletId = userWalletId.stringValue, + body = SeedPhraseNotificationDTO(status = Status.ACCEPTED), + ).getOrThrow() + } + + updateNotificationVisibility(id = userWalletId, value = SeedPhraseNotificationsStatus.NOT_NEEDED) + } + + private suspend fun updateNotificationVisibility(id: UserWalletId, value: SeedPhraseNotificationsStatus) { return seedPhraseNotificationVisibilityStore.update { it.toMutableMap().apply { this[id] = value diff --git a/domain/wallets/src/main/java/com/tangem/domain/wallets/models/SeedPhraseNotificationsStatus.kt b/domain/wallets/src/main/java/com/tangem/domain/wallets/models/SeedPhraseNotificationsStatus.kt new file mode 100644 index 0000000000..2c9180e6a6 --- /dev/null +++ b/domain/wallets/src/main/java/com/tangem/domain/wallets/models/SeedPhraseNotificationsStatus.kt @@ -0,0 +1,8 @@ +package com.tangem.domain.wallets.models + +enum class SeedPhraseNotificationsStatus { + + SHOW_FIRST, + SHOW_SECOND, + NOT_NEEDED, +} \ No newline at end of file diff --git a/domain/wallets/src/main/java/com/tangem/domain/wallets/repository/WalletsRepository.kt b/domain/wallets/src/main/java/com/tangem/domain/wallets/repository/WalletsRepository.kt index 18be29acdd..f226543d60 100644 --- a/domain/wallets/src/main/java/com/tangem/domain/wallets/repository/WalletsRepository.kt +++ b/domain/wallets/src/main/java/com/tangem/domain/wallets/repository/WalletsRepository.kt @@ -1,5 +1,6 @@ package com.tangem.domain.wallets.repository +import com.tangem.domain.wallets.models.SeedPhraseNotificationsStatus import com.tangem.domain.wallets.models.UserWalletId import kotlinx.coroutines.flow.Flow @@ -15,7 +16,7 @@ interface WalletsRepository { suspend fun setHasWalletsWithRing(userWalletId: UserWalletId) - fun seedPhraseNotificationStatus(userWalletId: UserWalletId): Flow + fun seedPhraseNotificationStatus(userWalletId: UserWalletId): Flow suspend fun notifiedSeedPhraseNotification(userWalletId: UserWalletId) @@ -23,5 +24,9 @@ interface WalletsRepository { suspend fun declineSeedPhraseNotification(userWalletId: UserWalletId) + suspend fun rejectSeedPhraseSecondNotification(userWalletId: UserWalletId) + + suspend fun acceptSeedPhraseSecondNotification(userWalletId: UserWalletId) + suspend fun markWallet2WasCreated(userWalletId: UserWalletId) } \ No newline at end of file diff --git a/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/SeedPhraseNotificationUseCase.kt b/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/SeedPhraseNotificationUseCase.kt index e5e1217c7c..6488fb915a 100644 --- a/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/SeedPhraseNotificationUseCase.kt +++ b/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/SeedPhraseNotificationUseCase.kt @@ -1,5 +1,6 @@ package com.tangem.domain.wallets.usecase +import com.tangem.domain.wallets.models.SeedPhraseNotificationsStatus import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.repository.WalletsRepository import kotlinx.coroutines.flow.Flow @@ -8,7 +9,7 @@ class SeedPhraseNotificationUseCase( private val walletsRepository: WalletsRepository, ) { - operator fun invoke(userWalletId: UserWalletId): Flow { + operator fun invoke(userWalletId: UserWalletId): Flow { return walletsRepository.seedPhraseNotificationStatus(userWalletId) } @@ -23,4 +24,12 @@ class SeedPhraseNotificationUseCase( suspend fun decline(userWalletId: UserWalletId) { walletsRepository.declineSeedPhraseNotification(userWalletId) } + + suspend fun acceptSecond(userWalletId: UserWalletId) { + walletsRepository.acceptSeedPhraseSecondNotification(userWalletId) + } + + suspend fun rejectSecond(userWalletId: UserWalletId) { + walletsRepository.rejectSeedPhraseSecondNotification(userWalletId) + } } \ No newline at end of file diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/formatter/MarketsDateTimeFormatters.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/formatter/MarketsDateTimeFormatters.kt index 46ba611519..f36474bbee 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/formatter/MarketsDateTimeFormatters.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/formatter/MarketsDateTimeFormatters.kt @@ -8,15 +8,14 @@ import com.tangem.core.ui.utils.DateTimeFormatters import com.tangem.core.ui.utils.formatAsDateTime import com.tangem.domain.markets.PriceChangeInterval import com.tangem.features.markets.impl.R +import com.tangem.utils.H24_MILLIS +import com.tangem.utils.WEEK_MILLIS import org.joda.time.DateTime import org.joda.time.DateTimeZone import java.math.BigDecimal internal object MarketsDateTimeFormatters { - private const val H24_MILLIS = 24L * 60 * 60 * 1000 - private const val WEEK_MILLIS = 7L * H24_MILLIS - private val dateTimeMMMFormatter by lazy { DateTimeFormatters.getBestFormatterBySkeleton("dd MMM Hm") } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt index aae1a9292b..c39efabf74 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt @@ -129,8 +129,14 @@ sealed class WalletScreenAnalyticsEvent { data object NoticeSeedPhraseSupport : MainScreen(event = "Notice - Seed Phrase Support") + data object NoticeSeedPhraseSupportSecond : MainScreen(event = "Notice - Seed Phrase Support2") + data object NoticeSeedPhraseSupportButtonNo : MainScreen(event = "Button - Support No") data object NoticeSeedPhraseSupportButtonYes : MainScreen(event = "Button - Support Yes") + + data object NoticeSeedPhraseSupportButtonUsed : MainScreen(event = "Button - Support Used") + + data object NoticeSeedPhraseSupportButtonDeclined : MainScreen(event = "Button - Support Declined") } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt index 6313ea4653..20073ee9ee 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt @@ -51,7 +51,7 @@ internal class WalletWarningsAnalyticsSender @Inject constructor( is WalletNotification.NoteMigration -> MainScreen.NotePromo is WalletNotification.SwapPromo -> TokenSwapPromoAnalyticsEvent.NoticePromotionBanner( source = AnalyticsParam.ScreensSources.Main, - programName = TokenSwapPromoAnalyticsEvent.ProgramName.Empty, // Use it on new promo action + programName = ProgramName.Empty, // Use it on new promo action ) is WalletNotification.UnlockWallets -> null // See [SelectedWalletAnalyticsSender] is WalletNotification.Informational.NoAccount, @@ -60,6 +60,7 @@ internal class WalletWarningsAnalyticsSender @Inject constructor( is WalletNotification.Warning.NetworksUnreachable, -> null is WalletNotification.Critical.SeedPhraseNotification -> MainScreen.NoticeSeedPhraseSupport + is WalletNotification.Critical.SeedPhraseSecondNotification -> MainScreen.NoticeSeedPhraseSupportSecond } } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt index d863a3dea9..877fb3ad46 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt @@ -9,6 +9,7 @@ import com.tangem.domain.tokens.error.TokenListError import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.tokens.model.TokenList +import com.tangem.domain.wallets.models.SeedPhraseNotificationsStatus import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase import com.tangem.domain.wallets.usecase.SeedPhraseNotificationUseCase @@ -63,21 +64,10 @@ internal class GetMultiWalletWarningsFactory @Inject constructor( private fun MutableList.addCriticalNotifications( userWallet: UserWallet, - seedPhraseIssueStatus: Boolean, + seedPhraseIssueStatus: SeedPhraseNotificationsStatus, clickIntents: WalletClickIntents, ) { - addIf( - element = WalletNotification.Critical.SeedPhraseNotification( - onDeclineClick = clickIntents::onSeedPhraseNotificationDecline, - onConfirmClick = clickIntents::onSeedPhraseNotificationConfirm, - ), - condition = with(userWallet) { - val isDemo = isDemoCardUseCase(cardId = userWallet.cardId) - val isWalletWithSeedPhrase = scanResponse.cardTypesResolver.isWallet2() && userWallet.isImported - - !isDemo && isWalletWithSeedPhrase && seedPhraseIssueStatus - }, - ) + addSeedNotificationIfNeeded(userWallet, seedPhraseIssueStatus, clickIntents) val cardTypesResolver = userWallet.scanResponse.cardTypesResolver addIf( @@ -103,6 +93,39 @@ internal class GetMultiWalletWarningsFactory @Inject constructor( } } + private fun MutableList.addSeedNotificationIfNeeded( + userWallet: UserWallet, + seedPhraseIssueStatus: SeedPhraseNotificationsStatus, + clickIntents: WalletClickIntents, + ) { + val isNotificationAvailable = with(userWallet) { + val isDemo = isDemoCardUseCase(cardId = userWallet.cardId) + val isWalletWithSeedPhrase = scanResponse.cardTypesResolver.isWallet2() && userWallet.isImported + + !isDemo && isWalletWithSeedPhrase + } + + when (seedPhraseIssueStatus) { + SeedPhraseNotificationsStatus.SHOW_FIRST -> addIf( + element = WalletNotification.Critical.SeedPhraseNotification( + onDeclineClick = clickIntents::onSeedPhraseNotificationDecline, + onConfirmClick = clickIntents::onSeedPhraseNotificationConfirm, + ), + condition = isNotificationAvailable, + ) + SeedPhraseNotificationsStatus.SHOW_SECOND -> addIf( + element = WalletNotification.Critical.SeedPhraseSecondNotification( + onDeclineClick = clickIntents::onSeedPhraseSecondNotificationReject, + onConfirmClick = clickIntents::onSeedPhraseSecondNotificationAccept, + ), + condition = isNotificationAvailable, + ) + SeedPhraseNotificationsStatus.NOT_NEEDED -> { + // do nothing + } + } + } + private fun MutableList.addInformationalNotifications( cardTypesResolver: CardTypesResolver, maybeTokenList: Lce, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt index dfcfda9298..632dff3210 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt @@ -51,7 +51,10 @@ sealed class WalletNotification(val config: NotificationConfig) { ), ) - data class SeedPhraseNotification(val onDeclineClick: () -> Unit, val onConfirmClick: () -> Unit) : Critical( + data class SeedPhraseNotification( + val onDeclineClick: () -> Unit, + val onConfirmClick: () -> Unit, + ) : Critical( title = resourceReference(R.string.warning_seedphrase_issue_title), subtitle = resourceReference(R.string.warning_seedphrase_issue_message), buttonsState = NotificationConfig.ButtonsState.SecondaryPairButtonsConfig( @@ -61,6 +64,20 @@ sealed class WalletNotification(val config: NotificationConfig) { onRightClick = onConfirmClick, ), ) + + data class SeedPhraseSecondNotification( + val onDeclineClick: () -> Unit, + val onConfirmClick: () -> Unit, + ) : Critical( + title = resourceReference(R.string.warning_seedphrase_action_required_title), + subtitle = resourceReference(R.string.warning_seedphrase_contacted_support), + buttonsState = NotificationConfig.ButtonsState.SecondaryPairButtonsConfig( + leftText = resourceReference(R.string.seed_warning_no), + onLeftClick = onDeclineClick, + rightText = resourceReference(R.string.seed_warning_yes), + onRightClick = onConfirmClick, + ), + ) } sealed class Warning( diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt index 732ee16502..115c9535ab 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt @@ -72,6 +72,10 @@ internal interface WalletWarningsClickIntents { fun onSeedPhraseNotificationConfirm() fun onSeedPhraseNotificationDecline() + + fun onSeedPhraseSecondNotificationAccept() + + fun onSeedPhraseSecondNotificationReject() } @Suppress("LongParameterList") @@ -312,6 +316,39 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( ) } + override fun onSeedPhraseSecondNotificationAccept() { + val userWallet = getSelectedUserWallet() ?: return + + analyticsEventHandler.send(MainScreen.NoticeSeedPhraseSupportButtonUsed) + + walletEventSender.send( + event = WalletEvent.ShowAlert( + state = WalletAlertState.SimpleOkAlert( + message = resourceReference(R.string.warning_seedphrase_issue_answer_yes), + onOkClick = { + viewModelScope.launch { + seedPhraseNotificationUseCase.acceptSecond(userWalletId = userWallet.walletId) + + urlOpener.openUrl( + url = TangemBlogUrlBuilder.build(post = TangemBlogUrlBuilder.Post.SeedNotifySecond), + ) + } + }, + ), + ), + ) + } + + override fun onSeedPhraseSecondNotificationReject() { + val userWallet = getSelectedUserWallet() ?: return + + analyticsEventHandler.send(MainScreen.NoticeSeedPhraseSupportButtonDeclined) + + viewModelScope.launch { + seedPhraseNotificationUseCase.rejectSecond(userWalletId = userWallet.walletId) + } + } + private fun getSelectedUserWallet(): UserWallet? { val userWalletId = stateHolder.getSelectedWalletId() return getUserWalletUseCase(userWalletId).getOrElse {