Updated on 2026-08-14

This commit is contained in:
Tangem 2025-02-18 12:55:55 +03:00
parent 930693b301
commit 5bdb9513aa
18 changed files with 249 additions and 44 deletions

View file

@ -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"
}
}
}

View file

@ -123,6 +123,17 @@ interface TangemTechApi {
@Body body: SeedPhraseNotificationDTO,
): ApiResponse<Unit>
@GET("seedphrase-notification/{wallet_id}/confirmed")
suspend fun getSeedPhraseSecondNotificationStatus(
@Path("wallet_id") walletId: String,
): ApiResponse<SeedPhraseNotificationDTO>
@PUT("seedphrase-notification/{wallet_id}/confirmed")
suspend fun updateSeedPhraseSecondNotificationStatus(
@Path("wallet_id") walletId: String,
@Body body: SeedPhraseNotificationDTO,
): ApiResponse<Unit>
@GET("hot_crypto")
suspend fun getHotCrypto(@Query("currency") currencyId: String): ApiResponse<HotCryptoResponse>

View file

@ -19,6 +19,12 @@ data class SeedPhraseNotificationDTO(val status: Status) {
@Json(name = "confirmed")
CONFIRMED,
@Json(name = "rejected")
REJECTED,
@Json(name = "accepted")
ACCEPTED,
;
}
}

View file

@ -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

View file

@ -881,13 +881,13 @@
<string name="swap_give_permission_fee_footer">Le réseau facturera des frais d\'approbation de jeton pour vérifier que vous autorisez l\'utilisation de votre jeton pour l\'échange.</string>
<string name="swap_promo_text">Échangez plus de jetons à de meilleurs taux directement dans votre portefeuille.</string>
<string name="swap_promo_title">Nouveau fournisseur d\'échange disponible !</string>
<string name="swap_story_fifth_subtitle">Ayez confiance en bénéficiant d\'un support constant, garantissant que vos transactions se déroulent sans problème à tout moment</string>
<string name="swap_story_fifth_subtitle">Ayez confiance en notre assistance 24 heures sur 24 pour vous aider à résoudre tous vos problèmes</string>
<string name="swap_story_fifth_title">Assistance 24 heures sur 24</string>
<string name="swap_story_first_subtitle">Les fournisseurs d\'échange de confiance vous permettent d\'échanger des actifs sans effort, en gardant tout en sécurité dans votre portefeuille</string>
<string name="swap_story_first_subtitle">Plusieurs fournisseurs de confiance en un seul endroit : échangez n\'importe quel actif facilement</string>
<string name="swap_story_first_title">Échangez Avec Nous</string>
<string name="swap_story_forth_subtitle">Une sécurité de haut niveau et des fournisseurs vérifiés garantissant que vos actifs sont protégés à chaque échange</string>
<string name="swap_story_forth_title">Plus Sûr Que Jamais</string>
<string name="swap_story_second_subtitle">Maximisez votre valeur avec des tarifs provenant d\'un large réseau de fournisseurs de confiance, en choisissant toujours le meilleur</string>
<string name="swap_story_second_subtitle">Maximisez votre valeur avec des tarifs d\'un large réseau de fournisseurs de confiance</string>
<string name="swap_story_second_title">Meilleurs Tarifs</string>
<string name="swap_story_third_subtitle">Simple et intuitif, vous permettant d\'échanger des jetons en quelques clics</string>
<string name="swap_story_third_title">Plus Simple Que Jamais</string>

View file

@ -871,16 +871,16 @@
<string name="swap_give_permission_fee_footer">ネットワークは、あなたがトークンのスワップを承認していることを確認するために、トークン承認手数料を請求します。</string>
<string name="swap_promo_text">より多くのトークンをより良いレートで、ウォレット内にて直接交換します。</string>
<string name="swap_promo_title">新しいスワッププロバイダーが利用可能になりました!</string>
<string name="swap_story_fifth_subtitle">継続的なサポートで、いつでもスムーズに取引を行うことができます</string>
<string name="swap_story_fifth_title">24時間体制のサポート</string>
<string name="swap_story_first_subtitle">信頼できる交換プロバイダーは、ウォレット内の資産を安全に保管しながら、簡単に交換できるようにします。</string>
<string name="swap_story_first_title">当社の交換機能をご利用ください</string>
<string name="swap_story_forth_subtitle">トップレベルのセキュリティと認証済みプロバイダーが、スワップ時にユーザーの資産を確実に保護します。</string>
<string name="swap_story_forth_title">最高に安全</string>
<string name="swap_story_fifth_subtitle">24時間体制のサポートであらゆる問題に対応します。</string>
<string name="swap_story_fifth_title">いつもここに</string>
<string name="swap_story_first_subtitle">複数の信頼できるプロバイダーが一箇所に集結。ウォレット内で様々な暗号資産を簡単に交換できます。</string>
<string name="swap_story_first_title">ぜひスワップしてください</string>
<string name="swap_story_forth_subtitle">失敗も死角もありません。取引は常に保護されます。</string>
<string name="swap_story_forth_title">難攻不落の防御</string>
<string name="swap_story_second_subtitle">幅広いネットワークの中から、常に最適なプロバイダーと料金レートを選択します</string>
<string name="swap_story_second_title">ベストレート</string>
<string name="swap_story_second_title">破格のレート</string>
<string name="swap_story_third_subtitle">手間がかからず直感的に操作でき、数回タップするだけでトークンを交換できます。</string>
<string name="swap_story_third_title">最高に簡単</string>
<string name="swap_story_third_title">とにかく便利</string>
<string name="swapping_alert_cex_description">この金額には以下が含まれます:\n- サービスプロバイダーの手数料\n- 取引所からユーザーのアドレスに%s を送り返すためのネットワーク手数料。</string>
<string name="swapping_alert_cex_description_with_slippage">金額には以下が含まれます: \n • サービス プロバイダーの手数料\n • 取引所からユーザーのアドレスに%1$sを送金するためのネットワーク手数料。 \n\nプロバイダーのスリッページは最大%2$sです</string>
<string name="swapping_alert_dex_description">この金額には、サービスプロバイダーの手数料が含まれています。</string>

View file

@ -674,6 +674,8 @@
<string name="scan_card_settings_message">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.</string>
<string name="scan_card_settings_title">Get your Tangem ready!</string>
<string name="security_alert_title">Security Alert</string>
<string name="seed_warning_no">No, I did not</string>
<string name="seed_warning_yes">Yes, guide me</string>
<string name="selling_insufficient_balance_alert_message">You dont have enough funds in your balance to sell cryptocurrency. Please deposit the desired asset to proceed.</string>
<string name="selling_insufficient_balance_alert_title">Insufficient Balance</string>
<string name="selling_regional_restriction_alert_message">Selling cryptocurrency is unavailable in your region at the moment. Were actively working to bring this option to you soon—stay tuned!</string>
@ -1089,6 +1091,8 @@
<string name="warning_rate_app_title">Enjoying Tangem?</string>
<string name="warning_receive_blocked_hedera_token_association_required_message">You must associate your token before receiving tokens</string>
<string name="warning_rent_fee_title">Network rent fee required</string>
<string name="warning_seedphrase_action_required_title">Action required</string>
<string name="warning_seedphrase_contacted_support">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.</string>
<string name="warning_seedphrase_issue_answer_no">Thank you! All set! No further actions required.</string>
<string name="warning_seedphrase_issue_answer_yes">You will now be redirected to the official Tangem website. Please read and follow instructions there.</string>
<string name="warning_seedphrase_issue_message">Have you ever contacted the Tangem support team directly through this application?</string>

View file

@ -0,0 +1,4 @@
package com.tangem.utils
const val H24_MILLIS = 24L * 60 * 60 * 1000
const val WEEK_MILLIS = 7L * H24_MILLIS

View file

@ -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<UserWalletId, SeedPhraseNotificationsStatus>
internal class DefaultWalletsRepository(
private val appPreferencesStore: AppPreferencesStore,
private val tangemTechApi: TangemTechApi,
private val userWalletsStore: UserWalletsStore,
private val seedPhraseNotificationVisibilityStore: RuntimeStateStore<Map<UserWalletId, Boolean>>,
private val seedPhraseNotificationVisibilityStore: RuntimeStateStore<SeedPhraseNotificationsStatuses>,
private val dispatchers: CoroutineDispatcherProvider,
) : WalletsRepository {
@ -57,11 +62,16 @@ internal class DefaultWalletsRepository(
}
}
override fun seedPhraseNotificationStatus(userWalletId: UserWalletId): Flow<Boolean> {
override fun seedPhraseNotificationStatus(userWalletId: UserWalletId): Flow<SeedPhraseNotificationsStatus> {
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

View file

@ -0,0 +1,8 @@
package com.tangem.domain.wallets.models
enum class SeedPhraseNotificationsStatus {
SHOW_FIRST,
SHOW_SECOND,
NOT_NEEDED,
}

View file

@ -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<Boolean>
fun seedPhraseNotificationStatus(userWalletId: UserWalletId): Flow<SeedPhraseNotificationsStatus>
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)
}

View file

@ -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<Boolean> {
operator fun invoke(userWalletId: UserWalletId): Flow<SeedPhraseNotificationsStatus> {
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)
}
}

View file

@ -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")
}

View file

@ -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")
}
}

View file

@ -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
}
}
}

View file

@ -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<WalletNotification>.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<WalletNotification>.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<WalletNotification>.addInformationalNotifications(
cardTypesResolver: CardTypesResolver,
maybeTokenList: Lce<TokenListError, TokenList>,

View file

@ -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(

View file

@ -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 {