From 504a49949a4ad6ec4aae4ed25f07e134268a71b5 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 31 Dec 2024 14:44:40 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../java/com/tangem/tap/TangemApplication.kt | 21 ++--- .../tap/di/domain/WalletsDomainModule.kt | 6 ++ .../redux/OnboardingWalletMiddleware.kt | 8 ++ common/build.gradle.kts | 3 + .../com/tangem/common/TangemBlogUrlBuilder.kt | 28 +++++++ .../api/tangemTech/TangemTechApi.kt | 14 ++++ .../models/MarkUserWalletWasCreatedBody.kt | 9 ++ .../models/SeedPhraseNotificationDTO.kt | 24 ++++++ .../datasource/local/logs/AppLogsStore.kt | 6 ++ core/res/src/main/res/values-de/strings.xml | 4 + core/res/src/main/res/values-es/strings.xml | 2 + core/res/src/main/res/values-fr/strings.xml | 4 + core/res/src/main/res/values-ja/strings.xml | 2 + core/res/src/main/res/values-ru/strings.xml | 2 + .../src/main/res/values-uk-rUA/strings.xml | 2 + core/res/src/main/res/values/strings.xml | 2 + .../data/wallets/DefaultWalletsRepository.kt | 84 +++++++++++++++++++ .../data/wallets/di/WalletsDataModule.kt | 19 ++++- .../feedback/SendFeedbackEmailUseCase.kt | 3 +- .../wallets/repository/WalletsRepository.kt | 10 +++ .../usecase/SeedPhraseNotificationUseCase.kt | 26 ++++++ features/wallet/impl/build.gradle.kts | 3 +- .../analytics/WalletScreenAnalyticsEvent.kt | 6 ++ .../utils/WalletWarningsAnalyticsSender.kt | 1 + .../utils/WalletWarningsSingleEventSender.kt | 34 ++++++++ .../domain/GetMultiWalletWarningsFactory.kt | 39 +++++++-- .../implementors/MultiWalletContentLoader.kt | 3 + .../MultiWalletContentLoaderFactory.kt | 3 + .../SingleWalletWithTokenContentLoader.kt | 3 + ...ngleWalletWithTokenContentLoaderFactory.kt | 3 + .../wallet/state/model/WalletNotification.kt | 16 +++- .../MultiWalletWarningsSubscriber.kt | 7 ++ .../intents/WalletWarningsClickIntents.kt | 36 +++++++- 33 files changed, 408 insertions(+), 25 deletions(-) create mode 100644 common/src/main/java/com/tangem/common/TangemBlogUrlBuilder.kt create mode 100644 core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/MarkUserWalletWasCreatedBody.kt create mode 100644 core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/SeedPhraseNotificationDTO.kt create mode 100644 domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/SeedPhraseNotificationUseCase.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsSingleEventSender.kt diff --git a/app/src/main/java/com/tangem/tap/TangemApplication.kt b/app/src/main/java/com/tangem/tap/TangemApplication.kt index d7190e3514..05fd529eaa 100644 --- a/app/src/main/java/com/tangem/tap/TangemApplication.kt +++ b/app/src/main/java/com/tangem/tap/TangemApplication.kt @@ -28,9 +28,6 @@ import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage import com.tangem.datasource.local.config.issuers.IssuersConfigStorage import com.tangem.datasource.local.logs.AppLogsStore import com.tangem.datasource.local.preferences.AppPreferencesStore -import com.tangem.datasource.local.preferences.PreferencesKeys.WAS_LOG_FILE_CLEARED -import com.tangem.datasource.local.preferences.utils.getSyncOrDefault -import com.tangem.datasource.local.preferences.utils.store import com.tangem.domain.appcurrency.repository.AppCurrencyRepository import com.tangem.domain.apptheme.GetAppThemeModeUseCase import com.tangem.domain.apptheme.repository.AppThemeModeRepository @@ -69,11 +66,8 @@ import com.tangem.wallet.BuildConfig import dagger.hilt.EntryPoints import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import org.rekotlin.Store -import kotlin.collections.MutableMap -import kotlin.collections.listOf import kotlin.collections.set import com.tangem.tap.domain.walletconnect2.domain.LegacyWalletConnectRepository as WalletConnect2Repository @@ -220,12 +214,15 @@ abstract class TangemApplication : Application(), ImageLoaderFactory { private fun updateLogFiles() { appLogsStore.deleteOldLogsFile() - scope.launch { - if (!appPreferencesStore.getSyncOrDefault(WAS_LOG_FILE_CLEARED, false)) { - appLogsStore.deleteLastLogFile() - appPreferencesStore.store(WAS_LOG_FILE_CLEARED, true) - } - } + appLogsStore.deleteLastLogFile() + + // Temporally logs are not saved + // scope.launch { + // if (!appPreferencesStore.getSyncOrDefault(WAS_LOG_FILE_CLEARED, false)) { + // appLogsStore.deleteLastLogFile() + // appPreferencesStore.store(WAS_LOG_FILE_CLEARED, true) + // } + // } } fun init() { diff --git a/app/src/main/java/com/tangem/tap/di/domain/WalletsDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/WalletsDomainModule.kt index cc9b89e775..49fdf2c1be 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/WalletsDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/WalletsDomainModule.kt @@ -159,4 +159,10 @@ internal object WalletsDomainModule { dispatchers = dispatchers, ) } + + @Provides + @Singleton + fun providesSeedPhraseNotificationUseCase(walletsRepository: WalletsRepository): SeedPhraseNotificationUseCase { + return SeedPhraseNotificationUseCase(walletsRepository = walletsRepository) + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index 352ec6b36b..d99a38a119 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -692,6 +692,14 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) ) } + scope.launch { + userWallet?.let { + if (it.scanResponse.cardTypesResolver.isWallet2() && it.isImported) { + store.inject(DaggerGraphState::walletsRepository).markWallet2WasCreated(it.walletId) + } + } + } + val notActivatedCardIds = gatherCardIds(backupState, card).mapNotNull { if (store.state.globalState.onboardingState.onboardingManager?.isActivationFinished(it) == true) { null diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 7ff7fb7522..6707a2bbb2 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -1,4 +1,7 @@ plugins { alias(deps.plugins.kotlin.jvm) id("configuration") +} +dependencies { + implementation(projects.core.utils) } \ No newline at end of file diff --git a/common/src/main/java/com/tangem/common/TangemBlogUrlBuilder.kt b/common/src/main/java/com/tangem/common/TangemBlogUrlBuilder.kt new file mode 100644 index 0000000000..27017a9505 --- /dev/null +++ b/common/src/main/java/com/tangem/common/TangemBlogUrlBuilder.kt @@ -0,0 +1,28 @@ +package com.tangem.common + +import com.tangem.utils.SupportedLanguages + +/** +[REDACTED_AUTHOR] + */ +object TangemBlogUrlBuilder { + + fun build(post: Post): String { + val code = SupportedLanguages.getCurrentSupportedLanguageCode() + .takeIf { code -> + code == SupportedLanguages.RUSSIAN || code == SupportedLanguages.ENGLISH + } + ?: SupportedLanguages.ENGLISH + + return "https://tangem.com/$code/blog/post/${post.path}/" + } + + sealed interface Post { + + val path: String + + data object SeedNotify : Post { + override val path: String = "seed-notify" + } + } +} \ 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 99b5144126..660e465d75 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 @@ -49,6 +49,9 @@ interface TangemTechApi { @Body userTokens: UserTokensResponse, ): ApiResponse + @POST("user-tokens") + suspend fun markUserWallerWasCreated(@Body body: MarkUserWalletWasCreatedBody): ApiResponse + /** Returns referral status by [walletId] */ @GET("referral/{walletId}") suspend fun getReferralStatus(@Path("walletId") walletId: String): ReferralResponse @@ -108,6 +111,17 @@ interface TangemTechApi { @GET("networks/providers") suspend fun getBlockchainProviders(): Map> + @GET("seedphrase-notification/{wallet_id}") + suspend fun getSeedPhraseNotificationStatus( + @Path("wallet_id") walletId: String, + ): ApiResponse + + @PUT("seedphrase-notification/{wallet_id}") + suspend fun updateSeedPhraseNotificationStatus( + @Path("wallet_id") walletId: String, + @Body body: SeedPhraseNotificationDTO, + ): ApiResponse + companion object { val marketsQuoteFields = listOf( "price", diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/MarkUserWalletWasCreatedBody.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/MarkUserWalletWasCreatedBody.kt new file mode 100644 index 0000000000..0c4d2a5bd8 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/MarkUserWalletWasCreatedBody.kt @@ -0,0 +1,9 @@ +package com.tangem.datasource.api.tangemTech.models + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class MarkUserWalletWasCreatedBody( + @Json(name = "user_wallet_id") val userWalletId: String, +) \ No newline at end of file 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 new file mode 100644 index 0000000000..e54c1cab47 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/SeedPhraseNotificationDTO.kt @@ -0,0 +1,24 @@ +package com.tangem.datasource.api.tangemTech.models + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class SeedPhraseNotificationDTO(val status: Status) { + + enum class Status { + @Json(name = "notneeded") + NOT_NEEDED, + + @Json(name = "notified") + NOTIFIED, + + @Json(name = "declined") + DECLINED, + + @Json(name = "confirmed") + CONFIRMED, + + ; + } +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/logs/AppLogsStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/logs/AppLogsStore.kt index 3869ea8162..bb1112d268 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/logs/AppLogsStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/logs/AppLogsStore.kt @@ -59,6 +59,9 @@ class AppLogsStore @Inject constructor( /** Save log [message] */ fun saveLogMessage(message: String) { + // Temporally logs are not saved + return + launchWithLock { createFileIfNotExist() @@ -68,6 +71,9 @@ class AppLogsStore @Inject constructor( /** Save log that consists from [messages] */ fun saveLogMessage(vararg messages: String) { + // Temporally logs are not saved + return + launchWithLock { createFileIfNotExist() diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml index aa37b93bdc..b428791460 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -51,6 +51,8 @@ Nicht mehr anzeigen Verstanden Guthaben sind ausgeblendet + Laut den Blockchain-Entwicklern befinden sich der Kaspa-Token derzeit in der Betaphase. Bleibe dran für Updates! + Beta-Phase Bitte Karte oder Ring scannen Bitte versuche es in 30 Sekunden erneut oder scanne die Karte oder Ring Zu viele Versuche @@ -1065,6 +1067,8 @@ Gefällt dir Tangem? Du musst deinen Token zuordnen, bevor du Token erhalten kannst Netzmietgebühr erforderlich + Haben Sie schon einmal unser Support-Team über die App kontaktiert? + Wir haben ein Problem im Support-System von Tangem festgestellt %1$s ist ein Vermögenswert im %2$s Netzwerk. Um eine %3$s Transaktion durchzuführen, musst du etwas %4$s (%5$s) einzahlen, um die Netzwerkgebühr zu decken. Unzureichende %1$s zur Deckung der Netzgebühr Das Solana-Netz ist überlastet. Wenn deine Transaktion nicht innerhalb von 2 Minuten bearbeitet wird, wiederhole bitte die Transaktion. diff --git a/core/res/src/main/res/values-es/strings.xml b/core/res/src/main/res/values-es/strings.xml index 1bd3de114c..9d93bea2d7 100644 --- a/core/res/src/main/res/values-es/strings.xml +++ b/core/res/src/main/res/values-es/strings.xml @@ -1065,6 +1065,8 @@ ¿Disfrutando de Tangem? Deba asociar su token antes de recibir tokens Se requiere tarifa de alquiler de red + ¿Alguna vez te has puesto en contacto con nuestro equipo de soporte a través de la aplicación? + Hemos encontrado un problema en el sistema de soporte de Tangem %1$s un activo en la red %2$s. Para realizar una transacción %3$s, deposite %4$s (%5$s) para cubrir la tarifa de red. %1$s insuficiente para cubrir la tarifa de red La red Solana está congestionada. Si su transacción no se procesa dentro de 2 minutos, repita la transacción. diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml index e6647acb4d..0b54ff6140 100644 --- a/core/res/src/main/res/values-fr/strings.xml +++ b/core/res/src/main/res/values-fr/strings.xml @@ -51,6 +51,8 @@ Ne plus afficher Compris Les soldes sont masqués + Selon les développeurs de la blockchain, les jetons Kaspa sont actuellement en version bêta. Restez à l\'écoute des mises à jour ! + Mode bêta Veuillez scanner la carte/bague Veuillez réessayer dans 30 secondes ou scannez la carte/bague Trop de tentatives @@ -1065,6 +1067,8 @@ Vous appréciez Tangem ? Vous devez associer votre jeton avant de recevoir des jetons Frais de location de réseau requis + Avez-vous déjà contacté notre équipe d\'assistance via l\'application ? + Nous avons trouvé un problème dans le système de support de Tangem %1$s s\'agit d\'un actif du réseau %2$s. Pour effectuer une transaction %3$s, vous devez déposer une certaine quantité de %4$s (%5$s) pour couvrir les frais de réseau. %1$s insuffisant pour couvrir les frais de réseau Le réseau Solana est encombré. Si votre transaction n\'est pas traitée dans les 2 minutes, veuillez répéter la transaction. diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index 66cd763ddb..7d9a780c4d 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -51,6 +51,8 @@ 今後表示しない わかりました 残高は非表示 + ブロックチェーン開発者によると、Kaspaトークンは現在ベータ版です。アップデートをお楽しみに! + ベータモード カードまたはリングをスキャンしてください 30秒後に再試行するか、カードまたはリングをスキャンしてください 試行回数が多すぎます diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index f63d0d3e28..c650c893b0 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -1086,6 +1086,8 @@ Нравится Tangem? Вам необходимо провести ассоциацию токена для того, чтобы иметь возможность принимать его Необходима плата за аренду сети + Вы когда-либо связывались с нашей службой поддержки через приложение? + Мы обнаружили проблему в системе поддержки Tangem %1$s - это монета в сети %2$s. Для совершения транзакции %3$s, вам необходимо внести немного %4$s (%5$s), чтобы покрыть комиссию сети. Недостаточно %1$s для оплаты комиссии сети Сеть Солана испытывает высокую нагрузку. Если Ваша транзакция не прошла в течение 2 минут, повторите её отправку. diff --git a/core/res/src/main/res/values-uk-rUA/strings.xml b/core/res/src/main/res/values-uk-rUA/strings.xml index 9b615a149f..21ecc9653a 100644 --- a/core/res/src/main/res/values-uk-rUA/strings.xml +++ b/core/res/src/main/res/values-uk-rUA/strings.xml @@ -1087,6 +1087,8 @@ Подобається Tangem? Вам необхідно провести асоціацію токена, щоб мати можливість приймати його Необхідна плата за оренду мережі + Ви коли-небудь зверталися до нашої служби підтримки через застосунок? + Ми виявили проблему в системі підтримки Tangem %1$s є активом у мережі %2$s. Щоб здійснити транзакцію %3$s, ви повинні внести певну суму %4$s (%5$s), щоб покрити комісію мережі. Недостатньо %1$s для покриття комісії мережі Мережа Солана зазнає високого навантаження. Якщо транзакція не пройшла протягом 2 хвилин, повторіть транзакцію. diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 99759792da..e7fb1e3a4a 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -1067,6 +1067,8 @@ Enjoying Tangem? You must associate your token before receiving tokens Network rent fee required + Have you ever contacted our support team through the app? + We found an issue in Tangem\'s support system %1$s is an asset in the %2$s network. To make a %3$s transaction, you must deposit some %4$s (%5$s) to cover the network fee. Insufficient %1$s to cover network fee The Solana network is congested. If your transaction is not processed within 2 minutes, please repeat the transaction. 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 b7102a6b52..1b4083ad77 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 @@ -1,16 +1,33 @@ package com.tangem.data.wallets +import com.tangem.datasource.api.common.response.ApiResponseError.HttpException +import com.tangem.datasource.api.common.response.getOrThrow +import com.tangem.datasource.api.tangemTech.TangemTechApi +import com.tangem.datasource.api.tangemTech.models.MarkUserWalletWasCreatedBody +import com.tangem.datasource.api.tangemTech.models.SeedPhraseNotificationDTO +import com.tangem.datasource.api.tangemTech.models.SeedPhraseNotificationDTO.Status +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.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.UserWalletId import com.tangem.domain.wallets.repository.WalletsRepository +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.coroutines.runCatching import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.channelFlow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.launch internal class DefaultWalletsRepository( private val appPreferencesStore: AppPreferencesStore, + private val tangemTechApi: TangemTechApi, + private val userWalletsStore: UserWalletsStore, + private val seedPhraseNotificationVisibilityStore: RuntimeStateStore, + private val dispatchers: CoroutineDispatcherProvider, ) : WalletsRepository { override suspend fun shouldSaveUserWalletsSync(): Boolean { @@ -38,4 +55,71 @@ internal class DefaultWalletsRepository( it[PreferencesKeys.ADDED_WALLETS_WITH_RING_KEY] = added + userWalletId.stringValue } } + + override fun seedPhraseNotificationStatus(userWalletId: UserWalletId): Flow { + return channelFlow { + launch { + seedPhraseNotificationVisibilityStore.get().collectLatest(::send) + } + + fetchSeedPhraseNotificationStatus(userWalletId) + } + } + + private suspend fun fetchSeedPhraseNotificationStatus(userWalletId: UserWalletId) { + val userWallet = userWalletsStore.getSyncOrNull(key = userWalletId) + + val status = if (userWallet?.isImported == false) { + false + } 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 }, + ) + } + + seedPhraseNotificationVisibilityStore.store(value = status) + } + + override suspend fun notifiedSeedPhraseNotification(userWalletId: UserWalletId) { + runCatching(dispatchers.io) { + tangemTechApi.updateSeedPhraseNotificationStatus( + walletId = userWalletId.stringValue, + body = SeedPhraseNotificationDTO(status = Status.NOTIFIED), + ).getOrThrow() + } + } + + override suspend fun confirmSeedPhraseNotification(userWalletId: UserWalletId) { + runCatching(dispatchers.io) { + tangemTechApi.updateSeedPhraseNotificationStatus( + walletId = userWalletId.stringValue, + body = SeedPhraseNotificationDTO(status = Status.CONFIRMED), + ).getOrThrow() + } + + seedPhraseNotificationVisibilityStore.store(value = false) + } + + override suspend fun declineSeedPhraseNotification(userWalletId: UserWalletId) { + runCatching(dispatchers.io) { + tangemTechApi.updateSeedPhraseNotificationStatus( + walletId = userWalletId.stringValue, + body = SeedPhraseNotificationDTO(status = Status.DECLINED), + ).getOrThrow() + } + + seedPhraseNotificationVisibilityStore.store(value = false) + } + + override suspend fun markWallet2WasCreated(userWalletId: UserWalletId) { + runCatching(dispatchers.io) { + tangemTechApi.markUserWallerWasCreated( + body = MarkUserWalletWasCreatedBody(userWalletId = userWalletId.stringValue), + ) + } + } } \ No newline at end of file diff --git a/data/wallets/src/main/java/com/tangem/data/wallets/di/WalletsDataModule.kt b/data/wallets/src/main/java/com/tangem/data/wallets/di/WalletsDataModule.kt index c41bb99652..20cf86eaa0 100644 --- a/data/wallets/src/main/java/com/tangem/data/wallets/di/WalletsDataModule.kt +++ b/data/wallets/src/main/java/com/tangem/data/wallets/di/WalletsDataModule.kt @@ -2,9 +2,13 @@ package com.tangem.data.wallets.di import com.tangem.data.wallets.DefaultWalletNamesMigrationRepository import com.tangem.data.wallets.DefaultWalletsRepository +import com.tangem.datasource.api.tangemTech.TangemTechApi +import com.tangem.datasource.local.datastore.RuntimeStateStore import com.tangem.datasource.local.preferences.AppPreferencesStore +import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.wallets.repository.WalletNamesMigrationRepository import com.tangem.domain.wallets.repository.WalletsRepository +import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -17,8 +21,19 @@ internal object WalletsDataModule { @Provides @Singleton - fun providesWalletsRepository(appPreferencesStore: AppPreferencesStore): WalletsRepository { - return DefaultWalletsRepository(appPreferencesStore = appPreferencesStore) + fun providesWalletsRepository( + appPreferencesStore: AppPreferencesStore, + tangemTechApi: TangemTechApi, + userWalletsStore: UserWalletsStore, + dispatchers: CoroutineDispatcherProvider, + ): WalletsRepository { + return DefaultWalletsRepository( + appPreferencesStore = appPreferencesStore, + tangemTechApi = tangemTechApi, + userWalletsStore = userWalletsStore, + seedPhraseNotificationVisibilityStore = RuntimeStateStore(defaultValue = false), + dispatchers = dispatchers, + ) } @Provides diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/SendFeedbackEmailUseCase.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/SendFeedbackEmailUseCase.kt index 302680f4c6..2839cb01c0 100644 --- a/domain/feedback/src/main/java/com/tangem/domain/feedback/SendFeedbackEmailUseCase.kt +++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/SendFeedbackEmailUseCase.kt @@ -29,7 +29,8 @@ class SendFeedbackEmailUseCase( address = getAddress(type.cardInfo), subject = emailSubjectResolver.resolve(type), message = createMessage(type), - file = feedbackRepository.getLogFile(), + // Temporally user data is not sent + file = null, // feedbackRepository.getLogFile(), ) feedbackRepository.sendEmail(email) 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 ff8f854078..18be29acdd 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 @@ -14,4 +14,14 @@ interface WalletsRepository { suspend fun isWalletWithRing(userWalletId: UserWalletId): Boolean suspend fun setHasWalletsWithRing(userWalletId: UserWalletId) + + fun seedPhraseNotificationStatus(userWalletId: UserWalletId): Flow + + suspend fun notifiedSeedPhraseNotification(userWalletId: UserWalletId) + + suspend fun confirmSeedPhraseNotification(userWalletId: UserWalletId) + + suspend fun declineSeedPhraseNotification(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 new file mode 100644 index 0000000000..e5e1217c7c --- /dev/null +++ b/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/SeedPhraseNotificationUseCase.kt @@ -0,0 +1,26 @@ +package com.tangem.domain.wallets.usecase + +import com.tangem.domain.wallets.models.UserWalletId +import com.tangem.domain.wallets.repository.WalletsRepository +import kotlinx.coroutines.flow.Flow + +class SeedPhraseNotificationUseCase( + private val walletsRepository: WalletsRepository, +) { + + operator fun invoke(userWalletId: UserWalletId): Flow { + return walletsRepository.seedPhraseNotificationStatus(userWalletId) + } + + suspend fun notified(userWalletId: UserWalletId) { + walletsRepository.notifiedSeedPhraseNotification(userWalletId) + } + + suspend fun confirm(userWalletId: UserWalletId) { + walletsRepository.confirmSeedPhraseNotification(userWalletId) + } + + suspend fun decline(userWalletId: UserWalletId) { + walletsRepository.declineSeedPhraseNotification(userWalletId) + } +} \ No newline at end of file diff --git a/features/wallet/impl/build.gradle.kts b/features/wallet/impl/build.gradle.kts index 2aa0052b0a..229ccc95ae 100644 --- a/features/wallet/impl/build.gradle.kts +++ b/features/wallet/impl/build.gradle.kts @@ -101,8 +101,9 @@ dependencies { implementation(projects.features.onboardingV2.api) /** Common modules */ - implementation(projects.common.ui) + implementation(projects.common) implementation(projects.common.routing) + implementation(projects.common.ui) /** Test libraries */ implementation(deps.test.junit) 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 0ab4cced59..aae1a9292b 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 @@ -126,5 +126,11 @@ sealed class WalletScreenAnalyticsEvent { data object EditWalletTapped : MainScreen(event = "Button - Edit Wallet Tapped") data object DeleteWalletTapped : MainScreen(event = "Button - Delete Wallet Tapped") + + data object NoticeSeedPhraseSupport : MainScreen(event = "Notice - Seed Phrase Support") + + data object NoticeSeedPhraseSupportButtonNo : MainScreen(event = "Button - Support No") + + data object NoticeSeedPhraseSupportButtonYes : MainScreen(event = "Button - Support Yes") } } \ 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 89d0467012..cbe0c57c5f 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 @@ -62,6 +62,7 @@ internal class WalletWarningsAnalyticsSender @Inject constructor( source = AnalyticsParam.ScreensSources.Main, programName = TokenSwapPromoAnalyticsEvent.ProgramName.Ring, ) + is WalletNotification.Critical.SeedPhraseNotification -> MainScreen.NoticeSeedPhraseSupport } } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsSingleEventSender.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsSingleEventSender.kt new file mode 100644 index 0000000000..e00a7a429b --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsSingleEventSender.kt @@ -0,0 +1,34 @@ +package com.tangem.feature.wallet.presentation.wallet.analytics.utils + +import com.tangem.domain.wallets.models.UserWalletId +import com.tangem.domain.wallets.usecase.SeedPhraseNotificationUseCase +import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification +import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState +import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider +import dagger.hilt.android.scopes.ViewModelScoped +import javax.inject.Inject + +@ViewModelScoped +internal class WalletWarningsSingleEventSender @Inject constructor( + private val seedPhraseNotificationUseCase: SeedPhraseNotificationUseCase, + private val screenLifecycleProvider: ScreenLifecycleProvider, +) { + + suspend fun send( + userWalletId: UserWalletId, + displayedUiState: WalletState?, + newWarnings: List, + ) { + if (screenLifecycleProvider.isBackgroundState.value) return + if (newWarnings.isEmpty()) return + if (displayedUiState == null || displayedUiState.pullToRefreshConfig.isRefreshing) return + + val events = newWarnings.filter { it !in displayedUiState.warnings } + + events.forEach { event -> + if (event is WalletNotification.Critical.SeedPhraseNotification) { + seedPhraseNotificationUseCase.notified(userWalletId = userWalletId) + } + } + } +} \ 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 7178667b98..3bf1f70562 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 @@ -14,6 +14,7 @@ import com.tangem.domain.tokens.model.TokenList import com.tangem.domain.tokens.repository.PromoRepository import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase +import com.tangem.domain.wallets.usecase.SeedPhraseNotificationUseCase import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntents import dagger.hilt.android.scopes.ViewModelScoped @@ -35,23 +36,33 @@ internal class GetMultiWalletWarningsFactory @Inject constructor( private val promoRepository: PromoRepository, private val isNeedToBackupUseCase: IsNeedToBackupUseCase, private val backupValidator: BackupValidator, + private val seedPhraseNotificationUseCase: SeedPhraseNotificationUseCase, ) { + @Suppress("MagicNumber", "MaximumLineLength") fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): Flow> { val cardTypesResolver = userWallet.scanResponse.cardTypesResolver val promoFlow = flow { emit(promoRepository.getRingPromoBanner()) } return combine( - flow = tokenListStore.getOrThrow(userWallet.walletId), - flow2 = isReadyToShowRateAppUseCase(), - flow3 = isNeedToBackupUseCase(userWallet.walletId), - flow4 = shouldShowRingPromoUseCase(userWalletId = userWallet.walletId), - flow5 = promoFlow, - ) { maybeTokenList, isReadyToShowRating, isNeedToBackup, shouldShowPromo, promoBanner -> + tokenListStore.getOrThrow(userWallet.walletId), + isReadyToShowRateAppUseCase(), + isNeedToBackupUseCase(userWallet.walletId), + shouldShowRingPromoUseCase(userWalletId = userWallet.walletId), + promoFlow, + seedPhraseNotificationUseCase(userWalletId = userWallet.walletId), + ) { + val maybeTokenList = it[0] as Lce + val isReadyToShowRating = it[1] as Boolean + val isNeedToBackup = it[2] as Boolean + val shouldShowPromo = it[3] as Boolean + val promoBanner = it[4] as? PromoBanner + val seedPhraseIssueStatus = it[5] as Boolean + buildList { addRingPromoNotification(shouldShowPromo, promoBanner, clickIntents) - addCriticalNotifications(userWallet, clickIntents) + addCriticalNotifications(userWallet, seedPhraseIssueStatus, clickIntents) addInformationalNotifications(cardTypesResolver, maybeTokenList, clickIntents) @@ -83,8 +94,22 @@ internal class GetMultiWalletWarningsFactory @Inject constructor( private fun MutableList.addCriticalNotifications( userWallet: UserWallet, + seedPhraseIssueStatus: Boolean, 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 + }, + ) + val cardTypesResolver = userWallet.scanResponse.cardTypesResolver addIf( element = WalletNotification.Critical.BackupError { clickIntents.onSupportClick() }, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt index 6b1652a33a..46ff5ba54e 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoader.kt @@ -6,6 +6,7 @@ import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase import com.tangem.domain.wallets.models.UserWallet import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender +import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarningsFactory import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker @@ -22,6 +23,7 @@ internal class MultiWalletContentLoader( private val clickIntents: WalletClickIntents, private val tokenListAnalyticsSender: TokenListAnalyticsSender, private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender, + private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender, private val walletWithFundsChecker: WalletWithFundsChecker, private val tokenListStore: MultiWalletTokenListStore, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, @@ -49,6 +51,7 @@ internal class MultiWalletContentLoader( clickIntents = clickIntents, getMultiWalletWarningsFactory = getMultiWalletWarningsFactory, walletWarningsAnalyticsSender = walletWarningsAnalyticsSender, + walletWarningsSingleEventSender = walletWarningsSingleEventSender, ), ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt index 7a70b865b2..7dcd6859a7 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/MultiWalletContentLoaderFactory.kt @@ -6,6 +6,7 @@ import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase import com.tangem.domain.wallets.models.UserWallet import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender +import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarningsFactory import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker @@ -25,6 +26,7 @@ internal class MultiWalletContentLoaderFactory @Inject constructor( private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val applyTokenListSortingUseCase: ApplyTokenListSortingUseCase, private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender, + private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender, private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase, ) { @@ -39,6 +41,7 @@ internal class MultiWalletContentLoaderFactory @Inject constructor( getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase, getMultiWalletWarningsFactory = getMultiWalletWarningsFactory, walletWarningsAnalyticsSender = walletWarningsAnalyticsSender, + walletWarningsSingleEventSender = walletWarningsSingleEventSender, applyTokenListSortingUseCase = applyTokenListSortingUseCase, runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase, ) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt index 897b44ae92..956ded275b 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoader.kt @@ -5,6 +5,7 @@ import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase import com.tangem.domain.wallets.models.UserWallet import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender +import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarningsFactory import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker @@ -21,6 +22,7 @@ internal class SingleWalletWithTokenContentLoader( private val stateHolder: WalletStateController, private val tokenListAnalyticsSender: TokenListAnalyticsSender, private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender, + private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender, private val walletWithFundsChecker: WalletWithFundsChecker, private val getMultiWalletWarningsFactory: GetMultiWalletWarningsFactory, private val tokenListStore: MultiWalletTokenListStore, @@ -46,6 +48,7 @@ internal class SingleWalletWithTokenContentLoader( clickIntents = clickIntents, getMultiWalletWarningsFactory = getMultiWalletWarningsFactory, walletWarningsAnalyticsSender = walletWarningsAnalyticsSender, + walletWarningsSingleEventSender = walletWarningsSingleEventSender, ), ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt index 1c433dc756..3352d671cf 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletWithTokenContentLoaderFactory.kt @@ -5,6 +5,7 @@ import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase import com.tangem.domain.wallets.models.UserWallet import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender +import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarningsFactory import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker @@ -22,6 +23,7 @@ internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor( private val tokenListStore: MultiWalletTokenListStore, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender, + private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender, private val runPolkadotAccountHealthCheckUseCase: RunPolkadotAccountHealthCheckUseCase, ) { @@ -36,6 +38,7 @@ internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor( tokenListStore = tokenListStore, getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase, walletWarningsAnalyticsSender = walletWarningsAnalyticsSender, + walletWarningsSingleEventSender = walletWarningsSingleEventSender, runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase, ) } 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 feb796546d..8c607733a3 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 @@ -2,7 +2,10 @@ package com.tangem.feature.wallet.presentation.wallet.state.model import androidx.compose.runtime.Immutable import com.tangem.core.ui.components.notifications.NotificationConfig -import com.tangem.core.ui.extensions.* +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.pluralReference +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.wrappedList import com.tangem.feature.wallet.impl.R import org.joda.time.DateTime @@ -47,6 +50,17 @@ sealed class WalletNotification(val config: NotificationConfig) { onClick = onSupportClick, ), ) + + 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.PairButtonsConfig( + primaryText = resourceReference(R.string.common_yes), + onPrimaryClick = onConfirmClick, + secondaryText = resourceReference(R.string.common_no), + onSecondaryClick = onDeclineClick, + ), + ) } sealed class Warning( diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/MultiWalletWarningsSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/MultiWalletWarningsSubscriber.kt index cf18d05d6d..f4a628c17a 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/MultiWalletWarningsSubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/MultiWalletWarningsSubscriber.kt @@ -2,6 +2,7 @@ package com.tangem.feature.wallet.presentation.wallet.subscribers import com.tangem.domain.wallets.models.UserWallet import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender +import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarningsFactory import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification @@ -20,6 +21,7 @@ internal class MultiWalletWarningsSubscriber( private val clickIntents: WalletClickIntents, private val getMultiWalletWarningsFactory: GetMultiWalletWarningsFactory, private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender, + private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender, ) : WalletSubscriber() { override fun create(coroutineScope: CoroutineScope): Flow> { @@ -31,6 +33,11 @@ internal class MultiWalletWarningsSubscriber( stateHolder.update(SetWarningsTransformer(userWallet.walletId, warnings)) walletWarningsAnalyticsSender.send(displayedState, warnings) + walletWarningsSingleEventSender.send( + userWalletId = userWallet.walletId, + displayedUiState = displayedState, + newWarnings = warnings, + ) } } } \ No newline at end of file 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 8fbfd08c16..9333f60fc3 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 @@ -1,8 +1,10 @@ package com.tangem.feature.wallet.presentation.wallet.viewmodels.intents import arrow.core.getOrElse +import com.tangem.common.TangemBlogUrlBuilder import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsParam +import com.tangem.core.navigation.url.UrlOpener import com.tangem.core.ui.extensions.resourceReference import com.tangem.domain.card.DerivePublicKeysUseCase import com.tangem.domain.card.SetCardWasScannedUseCase @@ -11,7 +13,10 @@ import com.tangem.domain.feedback.SendFeedbackEmailUseCase import com.tangem.domain.feedback.models.FeedbackEmailType import com.tangem.domain.redux.LegacyAction import com.tangem.domain.redux.ReduxStateHolder -import com.tangem.domain.settings.* +import com.tangem.domain.settings.NeverToSuggestRateAppUseCase +import com.tangem.domain.settings.RemindToRateAppLaterUseCase +import com.tangem.domain.settings.ShouldShowRingPromoUseCase +import com.tangem.domain.settings.ShouldShowSwapPromoWalletUseCase import com.tangem.domain.tokens.FetchTokenListUseCase import com.tangem.domain.tokens.FetchTokenListUseCase.RefreshMode import com.tangem.domain.tokens.model.CryptoCurrency @@ -20,6 +25,7 @@ import com.tangem.domain.wallets.legacy.UserWalletsListManager.Lockable.UnlockTy import com.tangem.domain.wallets.models.UnlockWalletsError import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.usecase.GetUserWalletUseCase +import com.tangem.domain.wallets.usecase.SeedPhraseNotificationUseCase import com.tangem.domain.wallets.usecase.UnlockWalletsUseCase import com.tangem.feature.wallet.impl.R import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.Basic @@ -65,6 +71,10 @@ internal interface WalletWarningsClickIntents { fun onSupportClick() fun onNoteMigrationButtonClick(url: String) + + fun onSeedPhraseNotificationConfirm() + + fun onSeedPhraseNotificationDecline() } @Suppress("LongParameterList") @@ -87,6 +97,8 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( private val shouldShowRingPromoUseCase: ShouldShowRingPromoUseCase, private val getCardInfoUseCase: GetCardInfoUseCase, private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, + private val seedPhraseNotificationUseCase: SeedPhraseNotificationUseCase, + private val urlOpener: UrlOpener, ) : BaseWalletClickIntents(), WalletWarningsClickIntents { override fun onAddBackupCardClick() { @@ -276,6 +288,28 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( } } + override fun onSeedPhraseNotificationConfirm() { + val userWallet = getSelectedUserWallet() ?: return + + analyticsEventHandler.send(MainScreen.NoticeSeedPhraseSupportButtonYes) + + viewModelScope.launch { + seedPhraseNotificationUseCase.confirm(userWalletId = userWallet.walletId) + + urlOpener.openUrl(url = TangemBlogUrlBuilder.build(post = TangemBlogUrlBuilder.Post.SeedNotify)) + } + } + + override fun onSeedPhraseNotificationDecline() { + val userWallet = getSelectedUserWallet() ?: return + + analyticsEventHandler.send(MainScreen.NoticeSeedPhraseSupportButtonNo) + + viewModelScope.launch { + seedPhraseNotificationUseCase.decline(userWalletId = userWallet.walletId) + } + } + private fun getSelectedUserWallet(): UserWallet? { val userWalletId = stateHolder.getSelectedWalletId() return getUserWalletUseCase(userWalletId).getOrElse {