Updated on 2026-08-14
This commit is contained in:
commit
8126bf44b8
79 changed files with 715 additions and 530 deletions
|
|
@ -372,6 +372,8 @@ dependencies {
|
|||
implementation(deps.coil.svg)
|
||||
implementation(deps.amplitude)
|
||||
implementation(deps.appsflyer)
|
||||
implementation(deps.appsflyer.oaid)
|
||||
implementation("com.android.installreferrer:installreferrer:2.2")
|
||||
implementation(deps.spongecastle.core)
|
||||
implementation(deps.lottie)
|
||||
implementation(deps.compose.accompanist.appCompatTheme)
|
||||
|
|
|
|||
|
|
@ -26,8 +26,9 @@ class AppsFlyerAnalyticsHandler(
|
|||
}
|
||||
is AppsFlyerIncludedEvent -> {
|
||||
Timber.tag("AppsFlyer").i("Sending event to AppsFlyer: ${event.id} with params: ${event.params}")
|
||||
val replacedEvent = event.appsFlyerReplacedEvent ?: event.event
|
||||
client.logEvent(
|
||||
event = AnalyticsEvent(category = event.category, event = event.appsFlyerReplacedEvent).id,
|
||||
event = AnalyticsEvent(category = event.category, event = replacedEvent).id,
|
||||
params = event.params,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import com.tangem.sdk.storage.AndroidSecureStorageV2
|
|||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
|
|
@ -71,12 +72,21 @@ internal class DefaultTangemPayStorage @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
override suspend fun getAuthTokens(customerWalletAddress: String): TangemPayAuthTokens? =
|
||||
withContext(dispatcherProvider.io) {
|
||||
secureStorage.get(createAuthTokensKey(customerWalletAddress))
|
||||
?.decodeToString(throwOnInvalidSequence = true)
|
||||
?.let(tokensAdapter::fromJson)
|
||||
override suspend fun getAuthTokens(customerWalletAddress: String): TangemPayAuthTokens? {
|
||||
val authTokens = secureStorage.get(createAuthTokensKey(customerWalletAddress))
|
||||
?.decodeToString(throwOnInvalidSequence = true)
|
||||
?.let(tokensAdapter::fromJson)
|
||||
|
||||
return authTokens?.let { tokens ->
|
||||
if (tokens.idempotencyKey == null) {
|
||||
val newAuthTokens = tokens.copy(idempotencyKey = UUID.randomUUID().toString())
|
||||
storeAuthTokens(customerWalletAddress, newAuthTokens)
|
||||
newAuthTokens
|
||||
} else {
|
||||
tokens
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun clearAuthTokens(customerWalletAddress: String) {
|
||||
secureStorage.delete(createAuthTokensKey(customerWalletAddress))
|
||||
|
|
|
|||
|
|
@ -190,6 +190,7 @@ internal class ChildFactory @Inject constructor(
|
|||
context = context,
|
||||
params = WalletBackupComponent.Params(
|
||||
userWalletId = route.userWalletId,
|
||||
isColdWalletOptionShown = route.isColdWalletOptionShown,
|
||||
),
|
||||
componentFactory = walletBackupComponentFactory,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -232,7 +232,8 @@ sealed class AppRoute(val path: String) : Route {
|
|||
@Serializable
|
||||
data class WalletBackup(
|
||||
val userWalletId: UserWalletId,
|
||||
) : AppRoute(path = "/wallet_backup/${userWalletId.stringValue}")
|
||||
val isColdWalletOptionShown: Boolean,
|
||||
) : AppRoute(path = "/wallet_backup/${userWalletId.stringValue}/$isColdWalletOptionShown")
|
||||
|
||||
@Serializable
|
||||
data class WalletHardwareBackup(
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import com.tangem.core.ui.extensions.resolveReference
|
|||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.test.SendScreenTestTags
|
||||
import com.tangem.core.ui.utils.GlobalMultipleClickPreventer
|
||||
import com.tangem.core.ui.utils.singleEvent
|
||||
|
||||
@Composable
|
||||
|
|
@ -112,10 +113,12 @@ fun NavigationPrimaryButton(primaryButton: NavigationButton?, modifier: Modifier
|
|||
text = button.textReference.resolveReference(),
|
||||
enabled = button.isEnabled,
|
||||
onClick = {
|
||||
if (button.isHapticClick) {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
GlobalMultipleClickPreventer.processEvent {
|
||||
if (button.isHapticClick) {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
}
|
||||
button.onClick()
|
||||
}
|
||||
button.onClick()
|
||||
},
|
||||
showProgress = button.shouldShowProgress,
|
||||
colors = color,
|
||||
|
|
|
|||
|
|
@ -11,5 +11,6 @@ interface AppsFlyerOnlyEvent
|
|||
* Events implementing this interface will be sent to AppsFlyer along with other analytics handlers
|
||||
*/
|
||||
interface AppsFlyerIncludedEvent {
|
||||
val appsFlyerReplacedEvent: String
|
||||
val appsFlyerReplacedEvent: String?
|
||||
get() = null
|
||||
}
|
||||
|
|
@ -93,7 +93,7 @@ sealed class Basic(
|
|||
}
|
||||
this["Memo"] = memoType.name
|
||||
},
|
||||
) {
|
||||
), AppsFlyerIncludedEvent {
|
||||
enum class MemoType {
|
||||
Empty, Full, Null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package com.tangem.core.analytics.models.event
|
|||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.AppsFlyerIncludedEvent
|
||||
import com.tangem.core.analytics.models.AppsFlyerOnlyEvent
|
||||
|
||||
sealed class OnboardingAnalyticsEvent(
|
||||
category: String,
|
||||
|
|
@ -16,8 +15,6 @@ sealed class OnboardingAnalyticsEvent(
|
|||
params: Map<String, String> = mapOf(),
|
||||
) : OnboardingAnalyticsEvent(category = "Onboarding", event = event, params = params) {
|
||||
|
||||
class AppsFlyerOnlyEntryScreenView : Onboarding(event = "wallet_entry_screen_view"), AppsFlyerOnlyEvent
|
||||
|
||||
class Started(
|
||||
source: String,
|
||||
) : Onboarding(
|
||||
|
|
@ -68,12 +65,7 @@ sealed class OnboardingAnalyticsEvent(
|
|||
put("Seed Phrase Length", seedPhraseLength.toString())
|
||||
}
|
||||
},
|
||||
), AppsFlyerIncludedEvent {
|
||||
override val appsFlyerReplacedEvent = when (creationType) {
|
||||
WalletCreationType.NewSeed -> "wallet_created_successfully"
|
||||
WalletCreationType.SeedImport -> "wallet_imported"
|
||||
}
|
||||
}
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
sealed class WalletCreationType(val value: String) {
|
||||
data object NewSeed : WalletCreationType(value = "New Seed")
|
||||
|
|
@ -93,7 +85,7 @@ sealed class OnboardingAnalyticsEvent(
|
|||
params = mapOf(
|
||||
AnalyticsParam.SOURCE to source,
|
||||
),
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
class ButtonImportWallet : SeedPhrase("Button - Import Wallet")
|
||||
class ImportSeedPhraseScreenOpened : SeedPhrase("Import Seed Phrase Screen Opened")
|
||||
|
|
|
|||
|
|
@ -35,6 +35,10 @@
|
|||
"name": "HOT_WALLET_ENABLED",
|
||||
"version": "5.32.0"
|
||||
},
|
||||
{
|
||||
"name": "HOT_WALLET_CREATION_RESTRICTION_ENABLED",
|
||||
"version": "5.32.0"
|
||||
},
|
||||
{
|
||||
"name": "TANGEM_PAY_ENABLED",
|
||||
"version": "5.31.0"
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.tangem.datasource.api.pay.models.request.RefreshCustomerWalletAccessT
|
|||
import com.tangem.datasource.api.pay.models.response.TangemPayGenerateNonceResponse
|
||||
import com.tangem.datasource.api.pay.models.response.TangemPayGetTokensResponse
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.Header
|
||||
import retrofit2.http.POST
|
||||
|
||||
interface TangemPayAuthApi {
|
||||
|
|
@ -23,6 +24,7 @@ interface TangemPayAuthApi {
|
|||
|
||||
@POST("auth/token/refresh")
|
||||
suspend fun refreshCustomerWalletAccessToken(
|
||||
@Header("Idempotency-Key") idempotencyKey: String,
|
||||
@Body request: RefreshCustomerWalletAccessTokenRequest,
|
||||
): ApiResponse<TangemPayGetTokensResponse>
|
||||
}
|
||||
|
|
@ -327,6 +327,7 @@
|
|||
<string name="common_now">Ahora</string>
|
||||
<string name="common_ok">OK</string>
|
||||
<string name="common_open_in_browser">Abrir en el navegador</string>
|
||||
<string name="common_or">o</string>
|
||||
<string name="common_origin_card">Tarjeta principal</string>
|
||||
<string name="common_origin_ring">Anillo primario</string>
|
||||
<string name="common_passphrase">Frase de contraseña</string>
|
||||
|
|
@ -437,6 +438,7 @@
|
|||
<string name="details_manage_security_long_tap_description">Este mecanismo protege contra los ataques de proximidad a una tarjeta o anillo. Aplicará un retardo entre la recepción y la ejecución de un comando.</string>
|
||||
<string name="details_manage_security_passcode">Contraseña</string>
|
||||
<string name="details_manage_security_passcode_description">Antes de ejecutar un comando que cambie el estado de la tarjeta, deberá ingresar una contraseña.</string>
|
||||
<string name="details_mobile_wallet_upgrade_action_title">Actualizar a billetera de hardware</string>
|
||||
<string name="details_nft_title">NFT</string>
|
||||
<string name="details_referral_title">Programa de referidos</string>
|
||||
<string name="details_row_description_flip_to_hide">Gire la pantalla de su dispositivo hacia abajo para ocultar y mostrar rápidamente los saldos</string>
|
||||
|
|
@ -450,6 +452,7 @@
|
|||
<string name="details_row_title_signed_hashes">Firmado</string>
|
||||
<string name="details_send_feedback">Enviar comentarios</string>
|
||||
<string name="details_title">Detalles</string>
|
||||
<string name="details_wallets_section_description">Puedes tener solo una billetera móvil a la vez. Puede actualizarse a una billetera fría Tangem o usarse junto con una nueva billetera fría.</string>
|
||||
<string name="disclaimer_error_loading">Compruebe su conexión a internet o cambia a una red diferente</string>
|
||||
<string name="disclaimer_title">Condiciones de uso</string>
|
||||
<string name="domain_receive_assets_default_address">Dirección por defecto</string>
|
||||
|
|
@ -569,8 +572,8 @@
|
|||
<string name="give_permission_swap_subtitle" formatted="false">Para continuar, conceda a los contratos inteligentes de %1s permiso para utilizar su %2s</string>
|
||||
<string name="give_permission_title">Dar autorización</string>
|
||||
<string name="give_permission_unlimited">Ilimitado</string>
|
||||
<string name="hardware_wallet_backup_feature_description">Su copia de seguridad se crea utilizando 2 o 3 tarjetas Tangem. Guárdalas en lugares seguros y separados para protegerlas de pérdidas o daños.</string>
|
||||
<string name="hardware_wallet_backup_feature_title">Copia de seguridad con varias tarjetas</string>
|
||||
<string name="hardware_wallet_backup_feature_description">Se generarán nuevas direcciones dentro de su billetera física, listas para su uso y totalmente seguras.</string>
|
||||
<string name="hardware_wallet_backup_feature_title">Nuevas direcciones</string>
|
||||
<string name="hardware_wallet_create_title">Agregar billetera Tangem</string>
|
||||
<string name="hardware_wallet_key_feature_description">Su clave privada se genera directamente dentro de la tarjeta Tangem y nunca sale de ella.</string>
|
||||
<string name="hardware_wallet_key_feature_title">Generación de claves</string>
|
||||
|
|
@ -611,11 +614,15 @@
|
|||
<string name="hw_backup_seed_title">Frase de recuperación</string>
|
||||
<string name="hw_backup_to_secure_description">Para proteger su billetera con un código de acceso, complete el proceso de copia de seguridad.</string>
|
||||
<string name="hw_backup_to_upgrade_description">Para actualizar a una billetera de hardware, complete el proceso de copia de seguridad.</string>
|
||||
<string name="hw_backup_upgrade_description">Actualice su billetera móvil a una billetera de hardware Tangem para obtener la máxima seguridad. Importe su billetera o transfiera fondos a una nueva.</string>
|
||||
<string name="hw_backup_upgrade_title">Actualizar a billetera fría</string>
|
||||
<string name="hw_create_keys_description">Sus claves privadas están encriptadas de forma segura y almacenadas en su teléfono</string>
|
||||
<string name="hw_create_keys_title">Las claves privadas permanecen en su dispositivo</string>
|
||||
<string name="hw_create_seed_description">Cree o restaure su billetera con una frase de recuperación.</string>
|
||||
<string name="hw_create_seed_title">Copia de seguridad de la frase semilla</string>
|
||||
<string name="hw_create_title">Crear una billetera móvil</string>
|
||||
<string name="hw_create_upgrade_description">Transfiera su billetera móvil a una tarjeta o anillo Tangem en cualquier momento, de forma segura.</string>
|
||||
<string name="hw_create_upgrade_title">Actualización a billetera de hardware</string>
|
||||
<string name="hw_import_existing_wallet">Importar billetera existente</string>
|
||||
<string name="hw_import_seed_phrase_already_imported">Esta frase de recuperación ya ha sido importada</string>
|
||||
<string name="hw_mobile_wallet">Billetera móvil</string>
|
||||
|
|
@ -633,14 +640,14 @@
|
|||
<string name="hw_remove_wallet_warning_access">Entiendo que si no he hecho una copia de seguridad de mi billetera antes de eliminarla, perderé el acceso a ella.</string>
|
||||
<string name="hw_remove_wallet_warning_device">Entiendo que quitar mi billetera no la borra, solo la elimina de mi dispositivo.</string>
|
||||
<string name="hw_upgrade">Actualizar</string>
|
||||
<string name="hw_upgrade_backup_description">No se requiere frase semilla. Su tarjeta o anillo Tangem se convierte en su copia de seguridad.</string>
|
||||
<string name="hw_upgrade_backup_title">Copia de seguridad con Tangem</string>
|
||||
<string name="hw_upgrade_backup_description">Todas sus direcciones y saldos permanecen completamente accesibles al actualizar su billetera móvil a una tarjeta o anillo Tangem.</string>
|
||||
<string name="hw_upgrade_backup_title">Mismas direcciones</string>
|
||||
<string name="hw_upgrade_error_card_already_has_wallet">No se puede actualizar. Ya existe una billetera en este dispositivo.</string>
|
||||
<string name="hw_upgrade_error_card_key_import">Elija otro dispositivo. Este no se puede usar para la actualización.</string>
|
||||
<string name="hw_upgrade_error_wallet2_card_required">Se produjo un error durante la operación.</string>
|
||||
<string name="hw_upgrade_funds_access_description">Sus fondos permanecen seguros y totalmente accesibles durante el proceso</string>
|
||||
<string name="hw_upgrade_funds_access_title">Acceso a los fondos</string>
|
||||
<string name="hw_upgrade_general_security_description">Los datos de su billetera se borrarán de la aplicación y se almacenarán en su billetera de hardware.</string>
|
||||
<string name="hw_upgrade_general_security_description">Después de la actualización, su billetera móvil se eliminará de la aplicación y se almacenará en su billetera de hardware; su frase de recuperación permanecerá bajo su control.</string>
|
||||
<string name="hw_upgrade_general_security_title">Seguridad general</string>
|
||||
<string name="hw_upgrade_key_migration_description">Las claves privadas se transferirán de la aplicación a su billetera de hardware Tangem</string>
|
||||
<string name="hw_upgrade_key_migration_title">Migración de claves</string>
|
||||
|
|
@ -1242,6 +1249,11 @@
|
|||
<string name="settings_card_settings_footer">Escanee la tarjeta/anillo que quiere configurar</string>
|
||||
<string name="settings_forget_wallet">Olvidar la billetera</string>
|
||||
<string name="settings_forget_wallet_footer">Esto eliminará la wallet de la aplicación. La wallet en sí puede\nañadirse de nuevo.</string>
|
||||
<string name="settings_upgrade_banner_advantage_feature_title">Fácil de usar</string>
|
||||
<string name="settings_upgrade_banner_description">Mantenga sus criptos seguras y sin conexión. Tan delgadas como una tarjeta de crédito, más seguras que una bóveda bancaria.</string>
|
||||
<string name="settings_upgrade_banner_seed_phrase_feature_title">Sin seed phrase</string>
|
||||
<string name="settings_upgrade_banner_superiority_feature_title">La mejor billetera de hardware de su clase</string>
|
||||
<string name="settings_upgrade_banner_title">Billetera Fría Tangem</string>
|
||||
<string name="settings_wallet_name_title">Nombre</string>
|
||||
<string name="stake_token_description">Haga que su token trabaje para Ud.</string>
|
||||
<string name="staking_account_initialization_footer">Una tarifa de red es un pequeño pago necesario para procesar y confirmar su transacción en la blockchain.</string>
|
||||
|
|
@ -1613,6 +1625,7 @@
|
|||
<string name="universal_error">Hemos encontrado un error. Código de error: %s. Póngase en contacto con nuestro servicio de soporte.</string>
|
||||
<string name="unlock_wallet_description_full">Use %s o escanee una tarjeta/anillo para tener acceso a su billetera</string>
|
||||
<string name="unsupported_wc_version">Error de conexión: Esta dApp utiliza la versión 1.0 de Wallet Connect, que no es compatible. Asegúrese de que la dApp sea compatible con la versión 2.0 de Wallet Connect para conectarse correctamente.</string>
|
||||
<string name="upgrade_to_hardware_wallet_button_title">Actualización a billetera de hardware</string>
|
||||
<string name="user_push_notification_agreement_argument_one">Manténgase actualizado con las últimas funciones y noticias</string>
|
||||
<string name="user_push_notification_agreement_argument_one_subtitle">Alertas en tiempo real de transacciones, intercambios y actualizaciones críticas.</string>
|
||||
<string name="user_push_notification_agreement_argument_one_title">Alertas de transacciones</string>
|
||||
|
|
@ -1982,6 +1995,7 @@
|
|||
<string name="welcome_create_wallet_feature_delivery">Entrega rápida</string>
|
||||
<string name="welcome_create_wallet_feature_one_tap">Empiece con un solo toque</string>
|
||||
<string name="welcome_create_wallet_feature_seamless">Fácil y seguro</string>
|
||||
<string name="welcome_create_wallet_feature_seedphrase">Sin seed phrase</string>
|
||||
<string name="welcome_create_wallet_feature_use">Fácil de usar</string>
|
||||
<string name="welcome_create_wallet_hardware_description">Cree una billetera de hardware con Tangem. Delgada como una tarjeta bancaria, segura como una bóveda.</string>
|
||||
<string name="welcome_create_wallet_mobile_description">Crear o importar una billetera de software</string>
|
||||
|
|
|
|||
|
|
@ -322,6 +322,7 @@
|
|||
<string name="common_now">今</string>
|
||||
<string name="common_ok">わかりました</string>
|
||||
<string name="common_open_in_browser">ブラウザで開く</string>
|
||||
<string name="common_or">または</string>
|
||||
<string name="common_origin_card">プライマリーカード</string>
|
||||
<string name="common_origin_ring">プライマリーリング</string>
|
||||
<string name="common_passphrase">パスフレーズ</string>
|
||||
|
|
@ -444,7 +445,7 @@
|
|||
<string name="details_row_title_signed_hashes">署名済み</string>
|
||||
<string name="details_send_feedback">フィードバックを送信</string>
|
||||
<string name="details_title">詳細</string>
|
||||
<string name="details_wallets_section_description">同時に利用できるのは、モバイルウォレットまたはハードウェアウォレットのいずれか一方のみです。Tangemのコールドウォレットを利用するには、現在のウォレットをアップグレードするか、アプリから削除してください。</string>
|
||||
<string name="details_wallets_section_description">モバイルウォレットは同時に1つのみ利用できます。Tangemコールドウォレットにアップグレードすることも、新しいコールドウォレットと併用することも可能です。</string>
|
||||
<string name="disclaimer_error_loading">インターネット接続を確認するか、別のネットワークに切り替えてください。</string>
|
||||
<string name="disclaimer_title">利用規約</string>
|
||||
<string name="domain_receive_assets_default_address">デフォルトアドレス</string>
|
||||
|
|
@ -555,7 +556,7 @@
|
|||
<string name="feedback_subject_tx_failed">取引を送信できません</string>
|
||||
<string name="feedback_token_description_error">コインの説明エラー</string>
|
||||
<string name="gasless_not_enough_funds_to_cover_token_fee">残高不足</string>
|
||||
<string name="gasless_transaction_fee">ガス代不要の取引手数料</string>
|
||||
<string name="gasless_transaction_fee">取引手数料</string>
|
||||
<string name="generic_error">エラーが発生しました</string>
|
||||
<string name="generic_error_code">エラーが発生しました。コード: %s 。</string>
|
||||
<string name="generic_requires_memo_error">メモが必要</string>
|
||||
|
|
@ -567,10 +568,10 @@
|
|||
<string name="give_permission_swap_subtitle" formatted="false">続行するには、%1sスマートコントラクトに%2sを使用する権限を付与してください</string>
|
||||
<string name="give_permission_title">許可を与える</string>
|
||||
<string name="give_permission_unlimited">無制限</string>
|
||||
<string name="hardware_wallet_backup_feature_description">バックアップは2〜3枚のTangemカードを使用して作成されます。紛失や破損に備え、カードはそれぞれ安全な別の場所に保管してください。シードフレーズは不要です。</string>
|
||||
<string name="hardware_wallet_backup_feature_title">複数のカードでバックアップ</string>
|
||||
<string name="hardware_wallet_backup_feature_description">ハードウェアウォレット内に新しいアドレスが自動生成され、安全にすぐ利用できる状態になります。</string>
|
||||
<string name="hardware_wallet_backup_feature_title">新しいアドレス</string>
|
||||
<string name="hardware_wallet_create_title">Tangemウォレットを追加</string>
|
||||
<string name="hardware_wallet_key_feature_description">あなたの秘密鍵はTangemカード内部で直接生成され、決してカードの外に出ることはありません。</string>
|
||||
<string name="hardware_wallet_key_feature_description">秘密鍵はTangemカード内部で直接生成され、外部に出ることは一切ありません。</string>
|
||||
<string name="hardware_wallet_key_feature_title">鍵生成</string>
|
||||
<string name="hardware_wallet_security_feature_description">すべての暗号処理は、複製や物理的な改ざんに対する認証を受けたセキュアチップ内で行われます。</string>
|
||||
<string name="hardware_wallet_security_feature_title">ハードウェアレベルのセキュリティ</string>
|
||||
|
|
@ -605,15 +606,20 @@
|
|||
<string name="hw_backup_need_title">まずバックアップを完了する</string>
|
||||
<string name="hw_backup_no_backup">未完了</string>
|
||||
<string name="hw_backup_section_other_title">その他の方法</string>
|
||||
<string name="hw_backup_seed_code_description">リカバリーフレーズは安全な場所に保管し、他人に知られないようにしてください。あわせて、資産をさらに強力に保護するためにアクセスコードを設定してください。</string>
|
||||
<string name="hw_backup_seed_description">資金を保護するため、リカバリーフレーズは安全な場所に保管し、他人に知られないようにしてください。</string>
|
||||
<string name="hw_backup_seed_title">リカバリーフレーズ</string>
|
||||
<string name="hw_backup_to_secure_description">アクセスコードでウォレットを保護するには、バックアップの手続きを完了してください。</string>
|
||||
<string name="hw_backup_to_upgrade_description">ハードウェアウォレットにアップグレードするには、バックアップの手続きを完了してください。</string>
|
||||
<string name="hw_backup_upgrade_description">業界最高レベルのセキュリティを実現するため、モバイルウォレットをTangemハードウェアウォレットにアップグレードしましょう。既存のウォレットをインポートするか、新しいウォレットへ資産を移行できます。</string>
|
||||
<string name="hw_backup_upgrade_title">コールドウォレットにアップグレード</string>
|
||||
<string name="hw_create_keys_description">秘密鍵は安全に暗号化され、スマートフォン上に保存されています</string>
|
||||
<string name="hw_create_keys_title">秘密鍵はデバイス上に保持されます</string>
|
||||
<string name="hw_create_seed_description">リカバリーフレーズを使ってウォレットを作成または復元してください。</string>
|
||||
<string name="hw_create_seed_title">シードフレーズのバックアップ</string>
|
||||
<string name="hw_create_title">モバイルウォレットを作成する</string>
|
||||
<string name="hw_create_upgrade_description">モバイルウォレットは、いつでも安全にTangemカードまたはリングへ移行できます。</string>
|
||||
<string name="hw_create_upgrade_title">ハードウェアウォレットにアップグレード</string>
|
||||
<string name="hw_import_existing_wallet">既存のウォレットをインポートする</string>
|
||||
<string name="hw_import_seed_phrase_already_imported">このリカバリーフレーズはすでにインポートされています。</string>
|
||||
<string name="hw_mobile_wallet">モバイルウォレット</string>
|
||||
|
|
@ -631,14 +637,14 @@
|
|||
<string name="hw_remove_wallet_warning_access">ウォレットを削除する前にバックアップを行っていない場合、ウォレットへのアクセスを失うことを理解しています。</string>
|
||||
<string name="hw_remove_wallet_warning_device">ウォレットを削除しても中身自体が消えるわけではなく、このデバイスから表示が消えるだけであることを理解しています。</string>
|
||||
<string name="hw_upgrade">アップグレード</string>
|
||||
<string name="hw_upgrade_backup_description">シードフレーズは不要です。Tangemカードまたはリングが安全なバックアップとなります。</string>
|
||||
<string name="hw_upgrade_backup_title">Tangemでバックアップ</string>
|
||||
<string name="hw_upgrade_backup_description">モバイルウォレットをTangemカードまたはリングにアップグレードしても、すべてのアドレスと残高は引き続き完全に利用できます。</string>
|
||||
<string name="hw_upgrade_backup_title">同じアドレス</string>
|
||||
<string name="hw_upgrade_error_card_already_has_wallet">アップグレードできません。このデバイスにはすでにウォレットが存在します。</string>
|
||||
<string name="hw_upgrade_error_card_key_import">別のデバイスを選択してください。このデバイスはアップグレードに使用できません。</string>
|
||||
<string name="hw_upgrade_error_wallet2_card_required">操作中にエラーが発生しました。</string>
|
||||
<string name="hw_upgrade_funds_access_description">処理中も、資金は安全に保たれ、常にアクセス可能です。</string>
|
||||
<string name="hw_upgrade_funds_access_title">資金へのアクセス</string>
|
||||
<string name="hw_upgrade_general_security_description">ウォレット情報はアプリから削除され、ハードウェアウォレットに保存されます</string>
|
||||
<string name="hw_upgrade_general_security_description">アップグレード後、モバイルウォレットはアプリから削除され、ハードウェアウォレットに保存されます。リカバリーフレーズは引き続きご自身で管理してください。</string>
|
||||
<string name="hw_upgrade_general_security_title">セキュリティ全般</string>
|
||||
<string name="hw_upgrade_key_migration_description">秘密鍵はアプリからTangemハードウェアウォレットへ移行されます</string>
|
||||
<string name="hw_upgrade_key_migration_title">キーの移行</string>
|
||||
|
|
@ -1414,6 +1420,7 @@
|
|||
<string name="swapping_insufficient_funds">残高不足</string>
|
||||
<string name="swapping_permission_header">許可を与える</string>
|
||||
<string name="swapping_swap_action">スワップ</string>
|
||||
<string name="swapping_swap_action_in_progress">スワップ中…</string>
|
||||
<string name="swapping_to_title">受け取る</string>
|
||||
<string name="swapping_token_list_title">トークンを選択</string>
|
||||
<string name="swapping_token_not_available">利用不可</string>
|
||||
|
|
@ -1540,6 +1547,8 @@
|
|||
<string name="tangempay_temporarily_unavailable">Tangem Payは現在一時的に利用できません。</string>
|
||||
<string name="tangempay_title">Tangem Pay</string>
|
||||
<string name="tangempay_use_tangem_device_to_restore_payment_account">下のボタンをクリックしてアクセスを復元してください</string>
|
||||
<string name="tangempay_withdrawal_note_description">現在引き出せるのは、保留中の取引分を差し引いたオンチェーンアドレス上のUSDC(Polygon)のみです。以前に返金や購入のキャンセルを行った場合、暗号資産アカウントの残高は2営業日以内に更新されます。</string>
|
||||
<string name="tangempay_withdrawal_note_title">ご注意ください</string>
|
||||
<string name="tangempay_your_pin_code">PINコード</string>
|
||||
<string name="this_is_my_wallet_title">これは私のウォレットです</string>
|
||||
<string name="toast_balances_hidden">残高非表示</string>
|
||||
|
|
@ -1935,6 +1944,7 @@
|
|||
<string name="welcome_create_wallet_feature_delivery">迅速な配送</string>
|
||||
<string name="welcome_create_wallet_feature_one_tap">ワンタップで開始</string>
|
||||
<string name="welcome_create_wallet_feature_seamless">シームレスで安全</string>
|
||||
<string name="welcome_create_wallet_feature_seedphrase">シードフレーズ不要</string>
|
||||
<string name="welcome_create_wallet_feature_use">シンプルな操作</string>
|
||||
<string name="welcome_create_wallet_hardware_description">Tangemでハードウェアウォレットを作成しよう。キャッシュカードのようにスリムで、金庫のように安全。</string>
|
||||
<string name="welcome_create_wallet_mobile_description">ソフトウェアウォレットを作成またはインポート</string>
|
||||
|
|
|
|||
|
|
@ -334,10 +334,12 @@
|
|||
<string name="common_no">Нет</string>
|
||||
<string name="common_no_address">Нет адреса</string>
|
||||
<string name="common_not_added">Не добавлено</string>
|
||||
<string name="common_not_available">Не доступно</string>
|
||||
<string name="common_not_now">Не сейчас</string>
|
||||
<string name="common_now">Сейчас</string>
|
||||
<string name="common_ok">OK</string>
|
||||
<string name="common_open_in_browser">Открыть в браузере</string>
|
||||
<string name="common_or">или</string>
|
||||
<string name="common_origin_card">Основная карта</string>
|
||||
<string name="common_origin_ring">Основное кольцо</string>
|
||||
<string name="common_passphrase">Парольная фраза</string>
|
||||
|
|
@ -450,6 +452,7 @@
|
|||
<string name="details_manage_security_long_tap_description">Этот механизм защищает карту или кольцо от бесконтактных атак. Между сканированием и выполнением команды будет добавлена задержка.</string>
|
||||
<string name="details_manage_security_passcode">Пароль</string>
|
||||
<string name="details_manage_security_passcode_description">Перед выполнением любой команды, влекущей за собой изменение состояния карты, вам необходимо будет ввести пароль.</string>
|
||||
<string name="details_mobile_wallet_upgrade_action_title">Апгрейд до аппаратного кошелька</string>
|
||||
<string name="details_nft_title">NFT</string>
|
||||
<string name="details_referral_title">Реферальная программа</string>
|
||||
<string name="details_row_description_flip_to_hide">Переверните экран вашего устройства вниз, чтобы быстро скрыть и отобразить балансы</string>
|
||||
|
|
@ -463,6 +466,7 @@
|
|||
<string name="details_row_title_signed_hashes">Подписано</string>
|
||||
<string name="details_send_feedback">Отправить отзыв</string>
|
||||
<string name="details_title">Подробности</string>
|
||||
<string name="details_wallets_section_description">Одновременно у вас может быть только один мобильный кошелек. Его можно апгрейдить до Tangem cold wallet или использовать вместе с новым холодным кошельком.</string>
|
||||
<string name="disclaimer_error_loading">Проверьте подключение с интернетом или переключитесь на другую сеть</string>
|
||||
<string name="disclaimer_title">Условия использования</string>
|
||||
<string name="domain_receive_assets_default_address">Основной адрес</string>
|
||||
|
|
@ -569,6 +573,8 @@
|
|||
<string name="feedback_subject_support_tangem">Обращение в поддержку Tangem</string>
|
||||
<string name="feedback_subject_tx_failed">Не могу отправить транзакцию</string>
|
||||
<string name="feedback_token_description_error">Ошибка в описании монеты</string>
|
||||
<string name="gasless_not_enough_funds_to_cover_token_fee">Недостаточно средств</string>
|
||||
<string name="gasless_transaction_fee">Комиссия за транзакцию</string>
|
||||
<string name="generic_error">Произошла ошибка</string>
|
||||
<string name="generic_error_code">Произошла ошибка. Код: %s.</string>
|
||||
<string name="generic_requires_memo_error">Требуется memo</string>
|
||||
|
|
@ -580,10 +586,10 @@
|
|||
<string name="give_permission_swap_subtitle" formatted="false">Чтобы продолжить, вам нужно разрешить смарт-контракту %1s использовать ваш %2s</string>
|
||||
<string name="give_permission_title">Дать разрешение</string>
|
||||
<string name="give_permission_unlimited">Безлимитно</string>
|
||||
<string name="hardware_wallet_backup_feature_description">Резервная копия создаётся на 2–3 картах Tangem. Храните их отдельно для безопасности — seed-фраза не нужна.</string>
|
||||
<string name="hardware_wallet_backup_feature_title">Бэкап на несколько карт</string>
|
||||
<string name="hardware_wallet_backup_feature_description">Новые адреса будут сгенерированы прямо в вашем аппаратном кошельке, готовы к использованию и полностью защищены.</string>
|
||||
<string name="hardware_wallet_backup_feature_title">Новые адреса</string>
|
||||
<string name="hardware_wallet_create_title">Добавить кошелек Tangem</string>
|
||||
<string name="hardware_wallet_key_feature_description">Ваш приватный ключ генерируется на карте Tangem и никогда не покидает её.</string>
|
||||
<string name="hardware_wallet_key_feature_description">Ваш приватный ключ будет сгенерирован на карте Tangem и никогда не покинет её.</string>
|
||||
<string name="hardware_wallet_key_feature_title">Генерация ключа</string>
|
||||
<string name="hardware_wallet_security_feature_description">Операции с криптографией выполняются внутри защищённого чипа, устойчивого к клонированию и физическому взлому.</string>
|
||||
<string name="hardware_wallet_security_feature_title">Аппаратная безопасность</string>
|
||||
|
|
@ -618,15 +624,20 @@
|
|||
<string name="hw_backup_need_title">Сначала завершите создание резервной копии</string>
|
||||
<string name="hw_backup_no_backup">Не завершено</string>
|
||||
<string name="hw_backup_section_other_title">Другие способы</string>
|
||||
<string name="hw_backup_seed_code_description">Сохраните фразу восстановления в надежном месте и держите её в секрете, чтобы защитить свои средства, а также установите код доступа для дополнительной безопасности.</string>
|
||||
<string name="hw_backup_seed_description">Сохраните фразу восстановления в безопасном месте и держите её в секрете.</string>
|
||||
<string name="hw_backup_seed_title">Фраза восстановления</string>
|
||||
<string name="hw_backup_to_secure_description">Чтобы защитить ваш кошелёк с помощью кода доступа, сначала завершите резервное копирование.</string>
|
||||
<string name="hw_backup_to_upgrade_description">Чтобы улучшить кошелёк до аппаратного, сначала создайте резервную копию.</string>
|
||||
<string name="hw_backup_upgrade_description">Перенесите свой мобильный кошелек на аппаратный кошелек Tangem для максимальной безопасности. Импортируйте существующий кошелек или переведите средства на новый.</string>
|
||||
<string name="hw_backup_upgrade_title">Апгрейд до холодного кошелька</string>
|
||||
<string name="hw_create_keys_description">Ваши приватные ключи надёжно зашифрованы и хранятся на вашем телефоне</string>
|
||||
<string name="hw_create_keys_title">Ключи хранятся в приложении</string>
|
||||
<string name="hw_create_seed_description">Создайте или импортируйте кошелёк с помощью вашей фразы восстановления.</string>
|
||||
<string name="hw_create_seed_title">Резервная копия</string>
|
||||
<string name="hw_create_title">Создать мобильный кошелек</string>
|
||||
<string name="hw_create_upgrade_description">Перенесите свой мобильный кошелек на Tangem-карту или кольцо в любое время.</string>
|
||||
<string name="hw_create_upgrade_title">Апгрейд до аппаратного кошелька</string>
|
||||
<string name="hw_import_existing_wallet">Импортировать существующий</string>
|
||||
<string name="hw_import_seed_phrase_already_imported">Эта фраза восстановления уже была импортирована</string>
|
||||
<string name="hw_mobile_wallet">Мобильный кошелек</string>
|
||||
|
|
@ -644,14 +655,14 @@
|
|||
<string name="hw_remove_wallet_warning_access">Я понимаю, что если я не создал резервную копию кошелька перед его удалением, я могу потерять к нему доступ.</string>
|
||||
<string name="hw_remove_wallet_warning_device">Я понимаю, что удаление моего кошелька не стирает его — оно просто удаляет его с моего устройства.</string>
|
||||
<string name="hw_upgrade">Апгрейд</string>
|
||||
<string name="hw_upgrade_backup_description">Фраза восстановления больше не нужна — ваша карта или кольцо Tangem становятся вашей надёжной резервной копией.</string>
|
||||
<string name="hw_upgrade_backup_title">Резервное копирование</string>
|
||||
<string name="hw_upgrade_backup_description">Все ваши адреса и балансы остаются полностью доступными при апгрейде мобильного кошелька на Tangem-карту или кольцо.</string>
|
||||
<string name="hw_upgrade_backup_title">Те же адреса</string>
|
||||
<string name="hw_upgrade_error_card_already_has_wallet">Это устройство не может быть использовано для апгрейда, оно уже содержит другой кошелек.</string>
|
||||
<string name="hw_upgrade_error_card_key_import">Выберите другое устройство. Это нельзя использовать для обновления.</string>
|
||||
<string name="hw_upgrade_error_wallet2_card_required">Во время операции произошла ошибка.</string>
|
||||
<string name="hw_upgrade_funds_access_description">Ваши средства остаются в безопасности и полностью доступны в процессе.</string>
|
||||
<string name="hw_upgrade_funds_access_title">Доступ к средствам</string>
|
||||
<string name="hw_upgrade_general_security_description">Данные вашего кошелька будут удалены из приложения и сохранены на вашем устройстве Tangem.</string>
|
||||
<string name="hw_upgrade_general_security_description">После апгрейда ваш мобильный кошелек будет удалён из приложения и сохранён на аппаратном кошельке; фраза восстановления остаётся у вас.</string>
|
||||
<string name="hw_upgrade_general_security_title">Общая безопасность</string>
|
||||
<string name="hw_upgrade_key_migration_description">Приватные ключи будут перемещены из приложения в вашу Tangem карту или кольцо</string>
|
||||
<string name="hw_upgrade_key_migration_title">Миграция ключей</string>
|
||||
|
|
@ -1277,6 +1288,11 @@
|
|||
<string name="settings_card_settings_footer">Подготовьтесь к сканированию кольца или карты, которую вы хотите настроить.</string>
|
||||
<string name="settings_forget_wallet">Забыть кошелек</string>
|
||||
<string name="settings_forget_wallet_footer">Это приведет к удалению кошелька из приложения. Сам кошелек можно добавить снова.</string>
|
||||
<string name="settings_upgrade_banner_advantage_feature_title">Прост в использовании</string>
|
||||
<string name="settings_upgrade_banner_description">Хранит вашу криптовалюту в безопасности и офлайн. Тонкий, как кредитная карта, надежнее банковского сейфа.</string>
|
||||
<string name="settings_upgrade_banner_seed_phrase_feature_title">Без seed-фразы</string>
|
||||
<string name="settings_upgrade_banner_superiority_feature_title">Лучший в своём классе аппаратный кошелек</string>
|
||||
<string name="settings_upgrade_banner_title">Холодный кошелек Tangem</string>
|
||||
<string name="settings_wallet_name_title">Имя</string>
|
||||
<string name="stake_token_description">Заставьте ваш токен работать</string>
|
||||
<string name="staking_account_initialization_footer">Сетевая комиссия — это небольшая плата за обработку и подтверждение вашей транзакции в блокчейне.</string>
|
||||
|
|
@ -1442,6 +1458,7 @@
|
|||
<string name="swap_story_third_subtitle">Интуитивный обмен в пару касаний — без сложностей и ожидания</string>
|
||||
<string name="swap_story_third_title">Проще простого</string>
|
||||
<string name="swap_via_provider">Обмен через провайдера</string>
|
||||
<string name="swap_your_assets_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>
|
||||
|
|
@ -1456,6 +1473,7 @@
|
|||
<string name="swapping_insufficient_funds">Недостаточно средств</string>
|
||||
<string name="swapping_permission_header">Дать разрешение</string>
|
||||
<string name="swapping_swap_action">Обменять</string>
|
||||
<string name="swapping_swap_action_in_progress">Обмен…</string>
|
||||
<string name="swapping_to_title">Вы получите</string>
|
||||
<string name="swapping_token_list_title">Выберите токен</string>
|
||||
<string name="swapping_token_not_available">не доступен</string>
|
||||
|
|
@ -1646,6 +1664,7 @@
|
|||
<string name="universal_error">Произошла ошибка. Код ошибки: %s. Попробуйте, пожалуйста, снова. Если проблема будет продолжать возникать — обратитесь в службу поддержки.</string>
|
||||
<string name="unlock_wallet_description_full">Используйте %s или отсканируйте карту/кольцо, чтобы получить доступ к своему кошельку</string>
|
||||
<string name="unsupported_wc_version">Соединение не удалось: это dApp использует Wallet Connect версии 1.0, которая не поддерживается. Убедитесь, что dApp поддерживает Wallet Connect версии 2.0 для успешного подключения.</string>
|
||||
<string name="upgrade_to_hardware_wallet_button_title">Апгрейд до аппаратного кошелька</string>
|
||||
<string name="user_push_notification_agreement_argument_one">Будьте в курсе новых функций и новостей</string>
|
||||
<string name="user_push_notification_agreement_argument_one_subtitle">Мгновенные уведомления о транзакциях, обменах и важных обновлениях.</string>
|
||||
<string name="user_push_notification_agreement_argument_one_title">Уведомления о транзакциях</string>
|
||||
|
|
@ -1957,6 +1976,7 @@
|
|||
<string name="welcome_create_wallet_feature_delivery">Быстрая доставка</string>
|
||||
<string name="welcome_create_wallet_feature_one_tap">Начните в один клик</string>
|
||||
<string name="welcome_create_wallet_feature_seamless">Просто и надёжно</string>
|
||||
<string name="welcome_create_wallet_feature_seedphrase">Без seed-фразы</string>
|
||||
<string name="welcome_create_wallet_feature_use">Интуитивно понятный</string>
|
||||
<string name="welcome_create_wallet_hardware_description">Создайте аппаратный кошелёк с Tangem. Тонкий, как банковская карта, безопасный, как банковский сейф.</string>
|
||||
<string name="welcome_create_wallet_mobile_description">Создать или импортировать мобильный кошелёк</string>
|
||||
|
|
|
|||
|
|
@ -328,6 +328,7 @@
|
|||
<string name="common_now">Now</string>
|
||||
<string name="common_ok">OK</string>
|
||||
<string name="common_open_in_browser">Open in Browser</string>
|
||||
<string name="common_or">or</string>
|
||||
<string name="common_origin_card">Primary card</string>
|
||||
<string name="common_origin_ring">Primary ring</string>
|
||||
<string name="common_passphrase">Passphrase</string>
|
||||
|
|
@ -452,7 +453,7 @@
|
|||
<string name="details_row_title_signed_hashes">Signed</string>
|
||||
<string name="details_send_feedback">Send feedback</string>
|
||||
<string name="details_title">Details</string>
|
||||
<string name="details_wallets_section_description">You can have either one mobile wallet or hardware wallet at the same time. Upgrade you wallet or delete it from the app to start using a Tangem cold wallet.</string>
|
||||
<string name="details_wallets_section_description">You can have only one mobile wallet at a time. It can be upgraded to a Tangem cold wallet or used alongside a new cold wallet.</string>
|
||||
<string name="disclaimer_error_loading">Check your internet connection or switch to a different network</string>
|
||||
<string name="disclaimer_title">Terms of service</string>
|
||||
<string name="domain_receive_assets_default_address">Default Address</string>
|
||||
|
|
@ -563,7 +564,7 @@
|
|||
<string name="feedback_subject_tx_failed">Can\'t send a transaction</string>
|
||||
<string name="feedback_token_description_error">Coin description error</string>
|
||||
<string name="gasless_not_enough_funds_to_cover_token_fee">Not enough funds</string>
|
||||
<string name="gasless_transaction_fee">Gasless transaction fee</string>
|
||||
<string name="gasless_transaction_fee">Transaction fee</string>
|
||||
<string name="generic_error">An error occurred</string>
|
||||
<string name="generic_error_code">An error occurred. Code: %s.</string>
|
||||
<string name="generic_requires_memo_error">Requires memo</string>
|
||||
|
|
@ -575,10 +576,10 @@
|
|||
<string name="give_permission_swap_subtitle" formatted="false">To continue, grant %1s smart contracts permission to use your %2s</string>
|
||||
<string name="give_permission_title">Give Permission</string>
|
||||
<string name="give_permission_unlimited">Unlimited</string>
|
||||
<string name="hardware_wallet_backup_feature_description">A backup is created using 2–3 Tangem cards. Store them separately in secure locations to protect against loss or damage. No seed phrase needed.</string>
|
||||
<string name="hardware_wallet_backup_feature_title">Backup With Multiple Cards</string>
|
||||
<string name="hardware_wallet_backup_feature_description">New addresses will be generated for you inside your hardware wallet, ready for use and fully secure.</string>
|
||||
<string name="hardware_wallet_backup_feature_title">New Addresses</string>
|
||||
<string name="hardware_wallet_create_title">Add Tangem Wallet</string>
|
||||
<string name="hardware_wallet_key_feature_description">Your private key is generated directly inside the Tangem card and never leaves it.</string>
|
||||
<string name="hardware_wallet_key_feature_description">Your private key will be generated directly inside the Tangem card and will never leave it.</string>
|
||||
<string name="hardware_wallet_key_feature_title">Key Generation</string>
|
||||
<string name="hardware_wallet_security_feature_description">All cryptographic operations happen inside the secure chip, certified against cloning and physical tampering.</string>
|
||||
<string name="hardware_wallet_security_feature_title">Hardware-Level Security</string>
|
||||
|
|
@ -613,15 +614,20 @@
|
|||
<string name="hw_backup_need_title">Finalize backup first</string>
|
||||
<string name="hw_backup_no_backup">Incomplete</string>
|
||||
<string name="hw_backup_section_other_title">Other methods</string>
|
||||
<string name="hw_backup_seed_code_description">Save your recovery phrase in a secure place and keep it private to protect your funds, and set up an access code for additional security.</string>
|
||||
<string name="hw_backup_seed_description">Save your recovery phrase in a secure place and keep it private to protect your funds.</string>
|
||||
<string name="hw_backup_seed_title">Recovery phrase</string>
|
||||
<string name="hw_backup_to_secure_description">To secure your wallet with an access code, complete the backup process.</string>
|
||||
<string name="hw_backup_to_upgrade_description">To upgrade to a hardware wallet, complete the backup process.</string>
|
||||
<string name="hw_backup_upgrade_description">Upgrade your mobile wallet to a Tangem hardware wallet for the highest security. Import your wallet or transfer funds to a new one.</string>
|
||||
<string name="hw_backup_upgrade_title">Upgrade to cold wallet</string>
|
||||
<string name="hw_create_keys_description">Your private keys are securely encrypted and stored on your phone</string>
|
||||
<string name="hw_create_keys_title">Private keys stay on your device</string>
|
||||
<string name="hw_create_seed_description">Create or restore your wallet with a recovery phrase.</string>
|
||||
<string name="hw_create_seed_title">Seed phrase backup</string>
|
||||
<string name="hw_create_title">Create Mobile Wallet</string>
|
||||
<string name="hw_create_upgrade_description">Transfer your mobile wallet to a Tangem card or ring anytime, securely.</string>
|
||||
<string name="hw_create_upgrade_title">Upgrade to hardware wallet</string>
|
||||
<string name="hw_import_existing_wallet">Import existing wallet</string>
|
||||
<string name="hw_import_seed_phrase_already_imported">This recovery phrase has already been imported</string>
|
||||
<string name="hw_mobile_wallet">Mobile Wallet</string>
|
||||
|
|
@ -639,14 +645,14 @@
|
|||
<string name="hw_remove_wallet_warning_access">I understand that if I haven\'t backed up my wallet before removing it, I will lose access to it.</string>
|
||||
<string name="hw_remove_wallet_warning_device">I understand that removing my wallet does not delete it, only removes it from my device.</string>
|
||||
<string name="hw_upgrade">Upgrade</string>
|
||||
<string name="hw_upgrade_backup_description">Seed phrase not required. Your Tangem card or ring becomes your secure backup.</string>
|
||||
<string name="hw_upgrade_backup_title">Backup With Tangem</string>
|
||||
<string name="hw_upgrade_backup_description">All your addresses and balances stay fully accessible when upgrading your mobile wallet to a Tangem card or ring.</string>
|
||||
<string name="hw_upgrade_backup_title">Same Addresses</string>
|
||||
<string name="hw_upgrade_error_card_already_has_wallet">Can\'t upgrade. A wallet already exists on this device.</string>
|
||||
<string name="hw_upgrade_error_card_key_import">Pick another device. This one can\'t be used for the upgrade.</string>
|
||||
<string name="hw_upgrade_error_wallet2_card_required">An error occurred during the operation.</string>
|
||||
<string name="hw_upgrade_funds_access_description">Your funds remain safe and fully accessible during the process</string>
|
||||
<string name="hw_upgrade_funds_access_title">Access to funds</string>
|
||||
<string name="hw_upgrade_general_security_description">Your wallet information will be erased from the app and stored on your hardware wallet</string>
|
||||
<string name="hw_upgrade_general_security_description">After upgrading, your mobile wallet will be removed from the app and stored on your hardware wallet; your recovery phrase stays with you.</string>
|
||||
<string name="hw_upgrade_general_security_title">General security</string>
|
||||
<string name="hw_upgrade_key_migration_description">Private keys will be moved from the app to your Tangem hardware wallet</string>
|
||||
<string name="hw_upgrade_key_migration_title">Key migration</string>
|
||||
|
|
@ -1562,6 +1568,8 @@
|
|||
<string name="tangempay_temporarily_unavailable">Tangem Pay is temporarily unreachable</string>
|
||||
<string name="tangempay_title">Tangem Pay</string>
|
||||
<string name="tangempay_use_tangem_device_to_restore_payment_account">Click the button below to restore access</string>
|
||||
<string name="tangempay_withdrawal_note_description">You can only withdraw USDC (Polygon) currently available on your on‑chain address balance, taking into account pending transactions. If you previously made a refund or cancelled a purchase, your crypto account balance will update within 2 business days.</string>
|
||||
<string name="tangempay_withdrawal_note_title">Please note</string>
|
||||
<string name="tangempay_your_pin_code">Your PIN code</string>
|
||||
<string name="this_is_my_wallet_title">This is my wallet</string>
|
||||
<string name="toast_balances_hidden">Balances hidden</string>
|
||||
|
|
@ -1633,7 +1641,7 @@
|
|||
<string name="universal_error">We\'ve encountered an error. Error code: %s. Please contact our support.</string>
|
||||
<string name="unlock_wallet_description_full">Use %s or scan a card/ring to have access to your wallet</string>
|
||||
<string name="unsupported_wc_version">Connection failed: This dApp uses Wallet Connect version 1.0, which is not supported. Please ensure the dApp supports Wallet Connect version 2.0 to connect successfully.</string>
|
||||
<string name="upgrade_to_hardware_wallet_button_title">Upgrade to a hardware wallet</string>
|
||||
<string name="upgrade_to_hardware_wallet_button_title">Upgrade to hardware wallet</string>
|
||||
<string name="user_push_notification_agreement_argument_one">Stay up to date with the latest features and news</string>
|
||||
<string name="user_push_notification_agreement_argument_one_subtitle">Real-time alerts for transactions, exchanges, and critical updates.</string>
|
||||
<string name="user_push_notification_agreement_argument_one_title">Transaction Alerts</string>
|
||||
|
|
@ -2004,6 +2012,7 @@
|
|||
<string name="welcome_create_wallet_feature_delivery">Fast delivery</string>
|
||||
<string name="welcome_create_wallet_feature_one_tap">Start in one tap</string>
|
||||
<string name="welcome_create_wallet_feature_seamless">Seamless and secure</string>
|
||||
<string name="welcome_create_wallet_feature_seedphrase">No seed phrase</string>
|
||||
<string name="welcome_create_wallet_feature_use">Simple to use</string>
|
||||
<string name="welcome_create_wallet_hardware_description">Create a hardware wallet with Tangem. Slim as a bank card, secure as a bank vault.</string>
|
||||
<string name="welcome_create_wallet_mobile_description">Create or import a software wallet</string>
|
||||
|
|
|
|||
|
|
@ -27,16 +27,18 @@ fun BlockItem(model: BlockUM, modifier: Modifier = Modifier) {
|
|||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12, Alignment.Start),
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size24),
|
||||
painter = painterResource(id = model.iconRes),
|
||||
tint = when (model.accentType) {
|
||||
BlockUM.AccentType.NONE -> TangemTheme.colors.icon.secondary
|
||||
BlockUM.AccentType.ACCENT -> TangemTheme.colors.text.accent
|
||||
BlockUM.AccentType.WARNING -> TangemTheme.colors.text.warning
|
||||
},
|
||||
contentDescription = null,
|
||||
)
|
||||
if (model.iconRes != null) {
|
||||
Icon(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size24),
|
||||
painter = painterResource(id = model.iconRes),
|
||||
tint = when (model.accentType) {
|
||||
BlockUM.AccentType.NONE -> TangemTheme.colors.icon.secondary
|
||||
BlockUM.AccentType.ACCENT -> TangemTheme.colors.text.accent
|
||||
BlockUM.AccentType.WARNING -> TangemTheme.colors.text.warning
|
||||
},
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import javax.annotation.concurrent.Immutable
|
|||
|
||||
data class BlockUM(
|
||||
val text: TextReference,
|
||||
@DrawableRes val iconRes: Int,
|
||||
@DrawableRes val iconRes: Int?,
|
||||
val onClick: () -> Unit,
|
||||
val accentType: AccentType = AccentType.NONE,
|
||||
val endContent: EndContent = EndContent.None,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,18 @@ interface MultipleClickPreventer {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A global instance of [MultipleClickPreventer]
|
||||
* Use for preventing multiple clicks in the entire app.
|
||||
* For example, when we must ensure correct data is passed while editing values and navigating to next screen.
|
||||
*
|
||||
* @example
|
||||
* GlobalMultipleClickPreventer.processEvent {
|
||||
* // Handle click event
|
||||
* }
|
||||
*/
|
||||
val GlobalMultipleClickPreventer = MultipleClickPreventer.get()
|
||||
|
||||
private class DefaultMultipleClickPreventer : MultipleClickPreventer {
|
||||
private val now: Long get() = SystemClock.elapsedRealtime()
|
||||
private var lastEventTimeMs: Long = 0
|
||||
|
|
|
|||
9
core/ui/src/main/res/drawable/ic_backup_repeat_24.xml
Normal file
9
core/ui/src/main/res/drawable/ic_backup_repeat_24.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:pathData="M2.471,8.909C2.673,8.559 3.179,8.559 3.382,8.909L5.743,13.001C5.945,13.352 5.693,13.79 5.288,13.79H3.922C4.143,14.787 4.547,15.739 5.12,16.597C6.029,17.957 7.322,19.018 8.834,19.645C10.345,20.271 12.009,20.434 13.614,20.115C15.219,19.796 16.693,19.008 17.851,17.851C18.163,17.538 18.669,17.538 18.981,17.851C19.294,18.163 19.294,18.669 18.981,18.981C17.601,20.362 15.841,21.303 13.926,21.685C12.011,22.065 10.026,21.869 8.222,21.122C6.417,20.375 4.875,19.109 3.79,17.485C3.04,16.363 2.532,15.105 2.29,13.79H0.563C0.159,13.79 -0.094,13.351 0.108,13.001L2.471,8.909Z"/>
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:fillType="evenOdd" android:pathData="M11.999,7.391C13.442,7.391 14.612,8.561 14.612,10.004V10.702C14.612,10.763 14.606,10.822 14.602,10.882C15.113,11.095 15.515,11.51 15.708,12.032C15.832,12.368 15.832,12.787 15.832,13.626C15.832,14.464 15.832,14.884 15.708,15.219C15.505,15.767 15.073,16.2 14.525,16.402C14.19,16.526 13.77,16.526 12.932,16.526H11.068C10.229,16.526 9.81,16.526 9.474,16.402C8.926,16.2 8.494,15.767 8.292,15.219C8.168,14.884 8.168,14.464 8.168,13.626C8.168,12.787 8.168,12.368 8.292,12.032C8.484,11.511 8.885,11.097 9.394,10.883C9.39,10.823 9.386,10.763 9.386,10.702V10.004C9.386,8.561 10.556,7.391 11.999,7.391ZM11.999,8.994C11.442,8.994 10.989,9.447 10.989,10.004V10.702C10.989,10.71 10.99,10.717 10.99,10.725H13.006C13.006,10.717 13.008,10.71 13.008,10.702V10.004C13.008,9.447 12.556,8.994 11.999,8.994Z"/>
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:pathData="M10.074,2.315C11.989,1.935 13.974,2.131 15.778,2.878C17.582,3.625 19.125,4.891 20.21,6.515C21.061,7.788 21.6,9.238 21.793,10.746H23.434C23.839,10.746 24.092,11.184 23.889,11.535L21.528,15.627C21.326,15.977 20.82,15.977 20.617,15.627L18.255,11.535C18.052,11.184 18.305,10.746 18.71,10.746H20.178C19.995,9.555 19.555,8.413 18.88,7.403C17.971,6.043 16.678,4.982 15.166,4.355C13.654,3.729 11.99,3.566 10.386,3.885C8.781,4.204 7.306,4.992 6.149,6.149C5.837,6.462 5.331,6.461 5.018,6.149C4.706,5.837 4.706,5.331 5.018,5.019C6.399,3.638 8.159,2.696 10.074,2.315Z"/>
|
||||
|
||||
</vector>
|
||||
7
core/ui/src/main/res/drawable/ic_double_star_24.xml
Normal file
7
core/ui/src/main/res/drawable/ic_double_star_24.xml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:pathData="M11,3L12.128,7.508C12.665,9.657 14.343,11.335 16.492,11.872L21,13L16.492,14.128C14.343,14.665 12.665,16.343 12.128,18.492L11,23L9.872,18.492C9.335,16.343 7.657,14.665 5.508,14.128L1,13L5.508,11.872C7.657,11.335 9.335,9.657 9.872,7.508L11,3Z"/>
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:pathData="M18,2L18.509,4.036C18.688,4.752 19.248,5.311 19.964,5.491L22,6L19.964,6.509C19.248,6.689 18.688,7.248 18.509,7.964L18,10L17.491,7.964C17.312,7.248 16.752,6.689 16.036,6.509L14,6L16.036,5.491C16.752,5.311 17.312,4.752 17.491,4.036L18,2Z"/>
|
||||
|
||||
</vector>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:pathData="M8.019,15.148C9.252,15.148 10.337,15.769 10.997,16.713C11.076,16.826 11.117,16.884 11.168,16.91C11.219,16.937 11.283,16.938 11.409,16.938H18.121C18.302,16.937 18.493,16.937 18.653,16.959C18.84,16.985 19.069,17.049 19.26,17.244C19.372,17.359 19.437,17.496 19.475,17.593C19.515,17.698 19.545,17.812 19.566,17.921C19.61,18.139 19.631,18.388 19.633,18.628C19.635,18.867 19.618,19.12 19.575,19.345C19.554,19.457 19.524,19.575 19.48,19.685C19.44,19.79 19.373,19.925 19.26,20.041C19.069,20.236 18.84,20.302 18.653,20.327C18.57,20.339 18.313,20.343 18.087,20.346C17.901,20.348 17.807,20.349 17.743,20.402C17.679,20.455 17.661,20.547 17.625,20.728C17.542,21.146 17.415,21.773 17.387,21.86C17.337,22.015 17.251,22.198 17.074,22.347C16.895,22.496 16.698,22.548 16.535,22.568L14.904,22.563C14.718,22.538 14.488,22.473 14.297,22.278C14.108,22.085 14.047,21.855 14.023,21.671C14.001,21.51 14.001,21.318 14.001,21.132V20.818C14.001,20.597 14.001,20.486 13.933,20.417C13.864,20.348 13.752,20.349 13.531,20.349H11.68C11.534,20.349 11.46,20.348 11.404,20.382C11.349,20.416 11.311,20.487 11.236,20.628C10.621,21.789 9.416,22.586 8.019,22.586C5.989,22.586 4.365,20.908 4.365,18.866C4.365,16.824 5.989,15.148 8.019,15.148ZM8.079,17.692C7.433,17.692 6.91,18.219 6.91,18.867C6.911,19.515 7.434,20.041 8.079,20.041H8.09C8.735,20.041 9.258,19.515 9.259,18.867C9.259,18.219 8.736,17.692 8.09,17.692H8.079ZM18.411,7.852C20.246,7.852 21.197,8.794 21.197,10.612V16.551C21.111,16.385 20.992,16.19 20.826,15.994L20.691,15.846L20.573,15.731C19.978,15.187 19.316,15.031 18.928,14.977C18.766,14.955 18.6,14.945 18.457,14.94L18.123,14.938H12.124C11.103,13.847 9.651,13.148 8.021,13.148C5.64,13.148 3.651,14.617 2.805,16.66V10.612C2.805,8.794 3.756,7.852 5.591,7.852H18.411ZM17.325,4.606C17.936,4.606 18.242,4.607 18.482,4.708C18.796,4.84 19.045,5.089 19.177,5.403C19.272,5.63 19.276,5.915 19.276,6.456H4.72C4.72,5.915 4.725,5.63 4.819,5.403C4.951,5.089 5.2,4.84 5.514,4.708C5.754,4.607 6.06,4.606 6.671,4.606H17.325ZM15.203,1.414C16.009,1.414 16.411,1.415 16.729,1.549C17.141,1.723 17.47,2.052 17.644,2.466C17.729,2.669 17.757,2.908 17.768,3.265H6.136C6.147,2.908 6.175,2.669 6.26,2.466C6.433,2.052 6.762,1.723 7.175,1.549C7.492,1.415 7.895,1.414 8.7,1.414H15.203Z"/>
|
||||
|
||||
</vector>
|
||||
15
core/ui/src/main/res/drawable/ic_seed_phrase_24.xml
Normal file
15
core/ui/src/main/res/drawable/ic_seed_phrase_24.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:pathData="M16.794,2.585C17.619,2.585 18.292,2.584 18.838,2.629C19.394,2.674 19.896,2.772 20.364,3.011C21.098,3.385 21.694,3.981 22.068,4.715C22.307,5.184 22.405,5.685 22.45,6.241C22.495,6.787 22.494,7.46 22.494,8.285C22.494,8.782 22.091,9.186 21.594,9.186C21.097,9.186 20.693,8.782 20.693,8.285C20.693,7.431 20.693,6.844 20.656,6.389C20.62,5.944 20.553,5.705 20.465,5.532C20.264,5.137 19.942,4.816 19.547,4.614C19.374,4.526 19.135,4.459 18.69,4.423C18.235,4.386 17.649,4.386 16.794,4.386H7.206C6.352,4.386 5.765,4.386 5.31,4.423C4.865,4.459 4.626,4.526 4.453,4.614C4.058,4.816 3.736,5.137 3.535,5.532C3.447,5.705 3.38,5.944 3.344,6.389C3.307,6.844 3.307,7.431 3.307,8.285V15.715C3.307,16.57 3.307,17.157 3.344,17.612C3.38,18.056 3.447,18.295 3.535,18.468C3.736,18.863 4.058,19.184 4.453,19.386C4.626,19.474 4.865,19.541 5.31,19.577C5.765,19.614 6.352,19.614 7.206,19.614H11.884C12.381,19.614 12.784,20.018 12.784,20.515C12.784,21.012 12.381,21.415 11.884,21.415H7.206C6.381,21.415 5.707,21.416 5.162,21.371C4.606,21.326 4.105,21.228 3.636,20.989C2.902,20.615 2.306,20.019 1.932,19.285C1.693,18.816 1.595,18.315 1.55,17.759C1.505,17.213 1.506,16.54 1.506,15.715V8.285C1.506,7.46 1.505,6.787 1.55,6.241C1.595,5.685 1.693,5.184 1.932,4.715C2.306,3.981 2.902,3.385 3.636,3.011C4.105,2.772 4.606,2.674 5.162,2.629C5.707,2.584 6.381,2.585 7.206,2.585H16.794Z"/>
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:pathData="M17.925,11.582C18.796,11.582 19.16,12.242 19.657,12.486C19.822,12.567 19.967,12.643 20.1,12.713C20.399,12.87 20.638,12.996 20.913,13.079C21.086,13.131 21.261,13.184 21.384,13.229C21.49,13.269 21.683,13.345 21.831,13.501C21.962,13.64 22.025,13.792 22.062,13.914C22.092,14.016 22.119,14.152 22.138,14.253C22.663,17.02 21.211,19.382 18.678,20.713C18.369,20.875 18.07,21.073 17.861,21.073C17.652,21.073 17.294,20.881 16.95,20.713C14.379,19.456 12.964,17.02 13.489,14.253C13.508,14.152 13.535,14.016 13.565,13.914C13.602,13.792 13.665,13.639 13.796,13.501C13.944,13.345 14.137,13.269 14.243,13.229C14.365,13.184 14.54,13.131 14.713,13.079C14.988,12.996 15.227,12.87 15.526,12.713C15.659,12.643 15.804,12.567 15.969,12.486C16.465,12.242 17.054,11.582 17.925,11.582Z"/>
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:pathData="M10.096,15.247C10.593,15.247 10.995,15.651 10.995,16.147C10.995,16.644 10.593,17.048 10.096,17.048H5.898C5.401,17.048 4.998,16.645 4.998,16.147C4.998,15.65 5.401,15.247 5.898,15.247H10.096Z"/>
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:pathData="M10.096,11.101C10.593,11.101 10.995,11.504 10.995,12.001C10.995,12.498 10.593,12.901 10.096,12.901H5.898C5.401,12.901 4.998,12.498 4.998,12.001C4.998,11.504 5.401,11.101 5.898,11.101H10.096Z"/>
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:pathData="M10.096,6.953C10.593,6.953 10.995,7.357 10.995,7.854C10.995,8.35 10.593,8.754 10.096,8.754H5.898C5.401,8.754 4.998,8.351 4.998,7.854C4.998,7.356 5.401,6.953 5.898,6.953H10.096Z"/>
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:pathData="M18.104,6.953C18.6,6.953 19.003,7.357 19.003,7.854C19.003,8.35 18.6,8.754 18.104,8.754H13.906C13.409,8.754 13.006,8.351 13.006,7.854C13.006,7.356 13.409,6.953 13.906,6.953H18.104Z"/>
|
||||
|
||||
</vector>
|
||||
9
core/ui/src/main/res/drawable/ic_smartphone_24.xml
Normal file
9
core/ui/src/main/res/drawable/ic_smartphone_24.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:pathData="M9.75,6.5C12.814,6.5 14.346,6.5 15.298,7.525C16.25,8.551 16.25,10.2 16.25,13.5V22H3.25V13.5C3.25,10.2 3.25,8.551 4.202,7.525C5.154,6.5 6.686,6.5 9.75,6.5ZM7.25,16.88V18.862C7.25,19.26 7.25,19.46 7.331,19.612C7.402,19.746 7.515,19.855 7.654,19.923C7.813,20 8.02,20 8.435,20H8.916V16.88H7.25ZM10.583,16.88L10.584,17.102V20H11.064C11.479,20 11.687,20 11.846,19.923C11.985,19.855 12.098,19.746 12.169,19.612C12.25,19.46 12.25,19.26 12.25,18.862V16.88H10.583ZM8.435,14C8.02,14 7.813,14 7.654,14.077C7.515,14.145 7.402,14.254 7.331,14.388C7.25,14.54 7.25,14.739 7.25,15.138V15.56H12.25V15.138C12.25,14.739 12.25,14.54 12.169,14.388C12.098,14.254 11.985,14.145 11.846,14.077C11.687,14 11.48,14 11.065,14H8.435Z"/>
|
||||
|
||||
<path android:fillColor="#00000000" android:pathData="M8.5,9H11" android:strokeColor="#EBEBEB" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="1.5"/>
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:pathData="M17.75,11.5H17.25V9.5C17.25,7.291 15.459,5.5 13.25,5.5H5.25V5C5.25,3.343 6.593,2 8.25,2H17.75C19.407,2 20.75,3.343 20.75,5V8.5C20.75,10.157 19.407,11.5 17.75,11.5Z"/>
|
||||
|
||||
</vector>
|
||||
5
core/ui/src/main/res/drawable/ic_tangem_card_24.xml
Normal file
5
core/ui/src/main/res/drawable/ic_tangem_card_24.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:pathData="M18,5C19.657,5 21,6.343 21,8V16C21,17.657 19.657,19 18,19H6C4.343,19 3,17.657 3,16V8C3,6.343 4.343,5 6,5H18ZM9.2,11.86V14.173C9.2,14.637 9.201,14.869 9.291,15.047C9.371,15.203 9.496,15.33 9.652,15.409C9.83,15.5 10.063,15.5 10.527,15.5H11.066V11.86H9.2ZM12.934,11.86V15.5H13.473C13.937,15.5 14.17,15.5 14.348,15.409C14.503,15.33 14.629,15.203 14.709,15.047C14.799,14.869 14.8,14.637 14.8,14.173V11.86H12.934ZM10.527,8.5C10.063,8.5 9.83,8.5 9.652,8.591C9.496,8.671 9.37,8.797 9.291,8.953C9.201,9.131 9.2,9.363 9.2,9.827V10.32H14.8V9.827C14.8,9.363 14.799,9.131 14.709,8.953C14.629,8.797 14.503,8.67 14.348,8.591C14.17,8.5 13.937,8.5 13.473,8.5H10.527Z"/>
|
||||
|
||||
</vector>
|
||||
|
|
@ -21,6 +21,7 @@ import kotlinx.coroutines.sync.Mutex
|
|||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
|
@ -95,7 +96,7 @@ internal class TangemPayRequestPerformer @Inject constructor(
|
|||
if (accessExpiresAt.isAfter(now)) {
|
||||
tokens.right()
|
||||
} else if (accessExpiresAt.isBefore(now) && refreshExpiresAt.isAfter(now)) {
|
||||
refreshAuthTokens(userWalletId = userWalletId, refreshToken = tokens.refreshToken)
|
||||
refreshAuthTokens(userWalletId = userWalletId, authTokens = tokens)
|
||||
} else {
|
||||
VisaApiError.RefreshTokenExpired.left()
|
||||
}
|
||||
|
|
@ -104,13 +105,15 @@ internal class TangemPayRequestPerformer @Inject constructor(
|
|||
|
||||
private suspend fun refreshAuthTokens(
|
||||
userWalletId: UserWalletId,
|
||||
refreshToken: String,
|
||||
authTokens: TangemPayAuthTokens,
|
||||
): Either<VisaApiError, TangemPayAuthTokens> {
|
||||
val customerWalletAddress = getCustomerWalletAddress(userWalletId)
|
||||
val idempotencyKey = requireNotNull(authTokens.idempotencyKey) { "Idempotency key is null" }
|
||||
val apiResponse = tangemPayAuthApi.refreshCustomerWalletAccessToken(
|
||||
idempotencyKey = idempotencyKey,
|
||||
request = RefreshCustomerWalletAccessTokenRequest(
|
||||
authType = "customer_wallet",
|
||||
refreshToken = refreshToken,
|
||||
refreshToken = authTokens.refreshToken,
|
||||
),
|
||||
)
|
||||
val responseEither = when (apiResponse) {
|
||||
|
|
@ -123,6 +126,7 @@ internal class TangemPayRequestPerformer @Inject constructor(
|
|||
expiresAt = response.expiresAt,
|
||||
refreshToken = response.refreshToken,
|
||||
refreshExpiresAt = response.refreshExpiresAt,
|
||||
idempotencyKey = UUID.randomUUID().toString(),
|
||||
)
|
||||
}.mapLeft { error ->
|
||||
Timber.tag(TAG).e("Can not refresh auth tokens: $error")
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import com.tangem.domain.visa.model.VisaAuthChallenge
|
|||
import com.tangem.domain.visa.model.VisaAuthSession
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class DefaultTangemPayRemoteDataSource @Inject constructor(
|
||||
|
|
@ -66,6 +67,7 @@ internal class DefaultTangemPayRemoteDataSource @Inject constructor(
|
|||
expiresAt = response.expiresAt,
|
||||
refreshToken = response.refreshToken,
|
||||
refreshExpiresAt = response.refreshExpiresAt,
|
||||
idempotencyKey = UUID.randomUUID().toString(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.tangem.core.analytics.models.AnalyticsParam.Key.PROVIDER
|
|||
import com.tangem.core.analytics.models.AnalyticsParam.Key.RESIDENCE
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.SOURCE
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.TOKEN_PARAM
|
||||
import com.tangem.core.analytics.models.AppsFlyerIncludedEvent
|
||||
import com.tangem.domain.onramp.model.OnrampSource
|
||||
|
||||
sealed class OnrampAnalyticsEvent(
|
||||
|
|
@ -28,7 +29,7 @@ sealed class OnrampAnalyticsEvent(
|
|||
SOURCE to source.analyticsName,
|
||||
TOKEN_PARAM to tokenSymbol,
|
||||
),
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
class SelectCurrencyScreenOpened : OnrampAnalyticsEvent(event = "Currency Screen Opened")
|
||||
|
||||
|
|
@ -133,7 +134,7 @@ sealed class OnrampAnalyticsEvent(
|
|||
"Currency Type" to currency,
|
||||
PAYMENT_METHOD to paymentMethod,
|
||||
),
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
class MinAmountError : OnrampAnalyticsEvent(event = "Error - Min Amount")
|
||||
class MaxAmountError : OnrampAnalyticsEvent(event = "Error - Max Amount")
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.domain.staking.analytics
|
|||
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.AppsFlyerIncludedEvent
|
||||
import com.tangem.domain.staking.model.stakekit.StakingError
|
||||
import com.tangem.domain.models.staking.action.StakingActionType
|
||||
|
||||
|
|
@ -21,7 +22,7 @@ sealed class StakingAnalyticsEvent(
|
|||
params = mapOf(
|
||||
"Validators Count" to validatorsCount.toString(),
|
||||
),
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
class WhatIsStaking : StakingAnalyticsEvent(
|
||||
event = "Link - What Is Staking",
|
||||
|
|
@ -40,7 +41,7 @@ sealed class StakingAnalyticsEvent(
|
|||
"Validator" to validator,
|
||||
"Action" to action.asAnalyticName,
|
||||
),
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
data class StakeInProgressScreenOpened(
|
||||
val validator: String,
|
||||
|
|
@ -51,7 +52,7 @@ sealed class StakingAnalyticsEvent(
|
|||
"Validator" to validator,
|
||||
"Action" to action.asAnalyticName,
|
||||
),
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
class RewardScreenOpened : StakingAnalyticsEvent(
|
||||
event = "Reward Screen Opened",
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ data class TangemPayAuthTokens(
|
|||
@Json(name = "expires_at") val expiresAt: Long,
|
||||
@Json(name = "refresh_token") val refreshToken: String,
|
||||
@Json(name = "refresh_expires_at") val refreshExpiresAt: Long,
|
||||
@Json(name = "idempotency_key") val idempotencyKey: String? = null,
|
||||
)
|
||||
|
||||
fun TangemPayAuthTokens.getAuthHeader(): String {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.domain.blockaid.models.dapp.CheckDAppResult
|
|||
import com.domain.blockaid.models.dapp.CheckDAppResult.*
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.AppsFlyerIncludedEvent
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.walletconnect.WcAnalyticEvents.DAppVerificationStatus
|
||||
import com.tangem.domain.walletconnect.model.WcPairRequest
|
||||
|
|
@ -19,7 +20,8 @@ sealed class WcAnalyticEvents(
|
|||
params: Map<String, String> = emptyMap(),
|
||||
) : AnalyticsEvent(category = WC_CATEGORY_NAME, event = event, params = params) {
|
||||
|
||||
class ScreenOpened : WcAnalyticEvents(event = "WC Screen Opened")
|
||||
class ScreenOpened : WcAnalyticEvents(event = "WC Screen Opened"), AppsFlyerIncludedEvent
|
||||
|
||||
class NewPairInitiated(source: WcPairRequest.Source) : WcAnalyticEvents(
|
||||
event = "Session Initiated",
|
||||
params = mapOf(
|
||||
|
|
@ -74,7 +76,7 @@ sealed class WcAnalyticEvents(
|
|||
AnalyticsParam.BLOCKCHAIN to sessionForApprove.network.joinToString(",") { it.name },
|
||||
DOMAIN_VERIFICATION to securityStatus.toAnalyticVerificationStatus(),
|
||||
),
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
class DAppConnectionFailed(
|
||||
errorCode: String,
|
||||
|
|
@ -85,7 +87,7 @@ sealed class WcAnalyticEvents(
|
|||
AnalyticsParam.ERROR_CODE to errorCode,
|
||||
AnalyticsParam.ERROR_DESCRIPTION to errorMessage,
|
||||
),
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
class SessionDisconnected(dAppMetaData: WcAppMetaData) : WcAnalyticEvents(
|
||||
event = "dApp Disconnected",
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ internal class CreateWalletStartModel @Inject constructor(
|
|||
onPrimaryButtonClick = ::onBuyClick,
|
||||
primaryButtonText = resourceReference(R.string.details_buy_wallet),
|
||||
otherMethodTitle = resourceReference(R.string.welcome_create_wallet_mobile_title),
|
||||
otherMethodDescription = resourceReference(R.string.welcome_create_wallet_mobile_description),
|
||||
otherMethodDescription = null,
|
||||
otherMethodClick = ::onStartWithMobileWalletClick,
|
||||
onBackClick = { router.pop() },
|
||||
onScanClick = ::onScanClick,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ internal data class CreateWalletStartUM(
|
|||
val shouldShowScanSecondaryButton: Boolean,
|
||||
val primaryButtonText: TextReference,
|
||||
val onPrimaryButtonClick: () -> Unit,
|
||||
val otherMethodDescription: TextReference,
|
||||
val otherMethodDescription: TextReference?,
|
||||
val otherMethodTitle: TextReference,
|
||||
val otherMethodClick: () -> Unit,
|
||||
val onScanClick: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ internal fun CreateWalletStartContent(state: CreateWalletStartUM, modifier: Modi
|
|||
.height(16.dp),
|
||||
)
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.welcome_create_wallet_other_method),
|
||||
text = stringResourceSafe(R.string.common_or),
|
||||
style = TangemTheme.typography.caption1,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
textAlign = TextAlign.Center,
|
||||
|
|
@ -193,19 +193,21 @@ internal fun CreateWalletStartContent(state: CreateWalletStartUM, modifier: Modi
|
|||
.scale(scaleX = -1f, scaleY = 1f),
|
||||
)
|
||||
}
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
start = 16.dp,
|
||||
top = 16.dp,
|
||||
end = 16.dp,
|
||||
),
|
||||
text = state.otherMethodDescription.resolveReference(),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
if (state.otherMethodDescription != null) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
start = 16.dp,
|
||||
top = 16.dp,
|
||||
end = 16.dp,
|
||||
),
|
||||
text = state.otherMethodDescription.resolveReference(),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.wrapContentWidth()
|
||||
|
|
@ -429,9 +431,7 @@ private class CreateWalletStartStateProvider : CollectionPreviewParameterProvide
|
|||
onPrimaryButtonClick = { },
|
||||
primaryButtonText = resourceReference(R.string.details_buy_wallet),
|
||||
otherMethodTitle = resourceReference(R.string.welcome_create_wallet_mobile_title),
|
||||
otherMethodDescription = resourceReference(
|
||||
R.string.welcome_create_wallet_mobile_description,
|
||||
),
|
||||
otherMethodDescription = null,
|
||||
otherMethodClick = { },
|
||||
onBackClick = { },
|
||||
onScanClick = { },
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.tangem.features.details.entity.DetailsUM
|
|||
import com.tangem.features.details.ui.DetailsScreen
|
||||
import com.tangem.features.details.utils.ItemsBuilder
|
||||
import com.tangem.features.details.utils.SocialsBuilder
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
internal class PreviewDetailsComponent : DetailsComponent {
|
||||
|
|
@ -19,9 +20,14 @@ internal class PreviewDetailsComponent : DetailsComponent {
|
|||
private val previewBlocks = runBlocking {
|
||||
ItemsBuilder(
|
||||
router = DummyRouter(),
|
||||
hotWalletFeatureToggles = object : HotWalletFeatureToggles {
|
||||
override val isHotWalletEnabled: Boolean = true
|
||||
override val isWalletCreationRestrictionEnabled: Boolean = true
|
||||
},
|
||||
).buildAll(
|
||||
isWalletConnectAvailable = true,
|
||||
isSupportChatAvailable = true,
|
||||
hasAnyMobileWallet = true,
|
||||
userWalletId = UserWalletId(""),
|
||||
onSupportEmailClick = {},
|
||||
onSupportChatClick = {},
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ internal class PreviewUserWalletListComponent : UserWalletListComponent {
|
|||
),
|
||||
addNewWalletText = resourceReference(R.string.user_wallet_list_add_button),
|
||||
isWalletSavingInProgress = true,
|
||||
addNewWalletIconRes = R.drawable.ic_plus_24,
|
||||
onAddNewWalletClick = {},
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.features.details.entity
|
|||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.core.ui.components.block.model.BlockUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Immutable
|
||||
|
|
@ -27,4 +28,9 @@ internal sealed class DetailsItemUM {
|
|||
data object UserWalletList : DetailsItemUM() {
|
||||
override val id: String = "user_wallet_list"
|
||||
}
|
||||
|
||||
data class UnderSectionText(
|
||||
override val id: String,
|
||||
val text: TextReference,
|
||||
) : DetailsItemUM()
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.features.details.entity
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
|
@ -10,5 +11,6 @@ internal data class UserWalletListUM(
|
|||
val userWallets: ImmutableList<UserWalletItemUM>,
|
||||
val isWalletSavingInProgress: Boolean,
|
||||
val addNewWalletText: TextReference,
|
||||
@DrawableRes val addNewWalletIconRes: Int?,
|
||||
val onAddNewWalletClick: () -> Unit,
|
||||
)
|
||||
|
|
@ -97,6 +97,7 @@ internal class DetailsModel @Inject constructor(
|
|||
itemsBuilder.buildAll(
|
||||
isWalletConnectAvailable = isWalletConnectAvailable,
|
||||
isSupportChatAvailable = feedbackFeatureToggles.isUsedeskEnabled,
|
||||
hasAnyMobileWallet = getWalletsUseCase.invokeSync().any { it is UserWallet.Hot },
|
||||
userWalletId = params.userWalletId,
|
||||
onSupportEmailClick = ::sendFeedback,
|
||||
onSupportChatClick = ::openUseDesk,
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ internal class UserWalletListModel @Inject constructor(
|
|||
isWalletSavingInProgress = false,
|
||||
addNewWalletText = TextReference.EMPTY,
|
||||
onAddNewWalletClick = ::onAddNewWalletClick,
|
||||
addNewWalletIconRes = R.drawable.ic_plus_24,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -83,10 +84,11 @@ internal class UserWalletListModel @Inject constructor(
|
|||
value.copy(
|
||||
userWallets = userWallets,
|
||||
isWalletSavingInProgress = isWalletSavingInProgress,
|
||||
addNewWalletText = if (shouldSaveUserWallets || hotWalletFeatureToggles.isHotWalletEnabled) {
|
||||
resourceReference(R.string.user_wallet_list_add_button)
|
||||
} else {
|
||||
resourceReference(R.string.scan_card_settings_button)
|
||||
addNewWalletText = when {
|
||||
shouldSaveUserWallets || hotWalletFeatureToggles.isHotWalletEnabled -> {
|
||||
resourceReference(R.string.user_wallet_list_add_button)
|
||||
}
|
||||
else -> resourceReference(R.string.scan_card_settings_button)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -94,7 +96,14 @@ internal class UserWalletListModel @Inject constructor(
|
|||
private fun onAddNewWalletClick() {
|
||||
if (hotWalletFeatureToggles.isHotWalletEnabled) {
|
||||
analyticsEventHandler.send(SignIn.ButtonAddWallet(AnalyticsParam.ScreensSources.Settings))
|
||||
router.push(AppRoute.CreateWalletSelection)
|
||||
|
||||
if (hotWalletFeatureToggles.isWalletCreationRestrictionEnabled) {
|
||||
withProgress(isWalletSavingInProgress) {
|
||||
userWalletSaver.scanAndSaveUserWallet(modelScope)
|
||||
}
|
||||
} else {
|
||||
router.push(AppRoute.CreateWalletSelection)
|
||||
}
|
||||
} else {
|
||||
withProgress(isWalletSavingInProgress) {
|
||||
userWalletSaver.scanAndSaveUserWallet(modelScope)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import androidx.compose.foundation.background
|
|||
import androidx.compose.foundation.gestures.Orientation
|
||||
import androidx.compose.foundation.gestures.scrollable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
|
|
@ -18,10 +19,14 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.SpacerH16
|
||||
import com.tangem.core.ui.components.appbar.TangemTopAppBar
|
||||
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
|
||||
import com.tangem.core.ui.components.block.BlockItem
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
|
@ -68,7 +73,7 @@ private fun Content(
|
|||
) {
|
||||
LazyColumn(
|
||||
modifier = modifier.testTag(DetailsScreenTestTags.SCREEN_CONTAINER),
|
||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing16),
|
||||
verticalArrangement = Arrangement.SpaceBetween,
|
||||
contentPadding = PaddingValues(
|
||||
top = TangemTheme.dimens.spacing12,
|
||||
bottom = TangemTheme.dimens.spacing16,
|
||||
|
|
@ -94,6 +99,7 @@ private fun Content(
|
|||
}
|
||||
|
||||
item(key = "footer") {
|
||||
SpacerH16()
|
||||
Footer(
|
||||
modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing12),
|
||||
model = state.footer,
|
||||
|
|
@ -108,6 +114,16 @@ private fun Block(
|
|||
userWalletListBlockContent: ComposableContentComponent,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
if (model is DetailsItemUM.UnderSectionText) {
|
||||
UnderSectionTextBlock(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = model.text,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
SpacerH16()
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
|
|
@ -142,10 +158,21 @@ private fun Block(
|
|||
is DetailsItemUM.UserWalletList -> {
|
||||
userWalletListBlockContent.Content(modifier = itemModifier)
|
||||
}
|
||||
is DetailsItemUM.UnderSectionText -> { /* Handled above */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun UnderSectionTextBlock(text: TextReference, modifier: Modifier = Modifier) {
|
||||
Text(
|
||||
modifier = modifier.padding(horizontal = 30.dp, vertical = 8.dp),
|
||||
text = text.resolveReference(),
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Footer(model: DetailsFooterUM, modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.features.details.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
|
|
@ -23,7 +24,6 @@ import com.tangem.core.ui.res.TangemThemePreview
|
|||
import com.tangem.features.details.component.UserWalletListComponent
|
||||
import com.tangem.features.details.component.preview.PreviewUserWalletListComponent
|
||||
import com.tangem.features.details.entity.UserWalletListUM
|
||||
import com.tangem.features.details.impl.R
|
||||
|
||||
@Composable
|
||||
internal fun UserWalletListBlock(state: UserWalletListUM, modifier: Modifier = Modifier) {
|
||||
|
|
@ -42,6 +42,7 @@ internal fun UserWalletListBlock(state: UserWalletListUM, modifier: Modifier = M
|
|||
text = state.addNewWalletText,
|
||||
isInProgress = state.isWalletSavingInProgress,
|
||||
onClick = state.onAddNewWalletClick,
|
||||
icon = state.addNewWalletIconRes,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -49,6 +50,7 @@ internal fun UserWalletListBlock(state: UserWalletListUM, modifier: Modifier = M
|
|||
@Composable
|
||||
private fun AddWalletButton(
|
||||
text: TextReference,
|
||||
@DrawableRes icon: Int?,
|
||||
isInProgress: Boolean,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -65,23 +67,25 @@ private fun AddWalletButton(
|
|||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
AnimatedContent(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size24),
|
||||
targetState = isInProgress,
|
||||
label = "Add wallet progress",
|
||||
) { isInProgress ->
|
||||
if (isInProgress) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size24),
|
||||
color = TangemTheme.colors.icon.accent,
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size24),
|
||||
painter = painterResource(id = R.drawable.ic_plus_24),
|
||||
tint = TangemTheme.colors.icon.accent,
|
||||
contentDescription = null,
|
||||
)
|
||||
if (icon != null) {
|
||||
AnimatedContent(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size24),
|
||||
targetState = isInProgress,
|
||||
label = "Add wallet progress",
|
||||
) { isInProgress ->
|
||||
if (isInProgress) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size24),
|
||||
color = TangemTheme.colors.icon.accent,
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size24),
|
||||
painter = painterResource(id = icon),
|
||||
tint = TangemTheme.colors.icon.accent,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.tangem.core.ui.extensions.resourceReference
|
|||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.features.details.entity.DetailsItemUM
|
||||
import com.tangem.features.details.impl.R
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
|
@ -17,12 +18,16 @@ import javax.inject.Inject
|
|||
private const val TANGEM_PAY_ITEM_ID = "get_tangem_pay"
|
||||
|
||||
@ModelScoped
|
||||
internal class ItemsBuilder @Inject constructor(private val router: Router) {
|
||||
internal class ItemsBuilder @Inject constructor(
|
||||
private val router: Router,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
) {
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
fun buildAll(
|
||||
isWalletConnectAvailable: Boolean,
|
||||
isSupportChatAvailable: Boolean,
|
||||
hasAnyMobileWallet: Boolean,
|
||||
userWalletId: UserWalletId,
|
||||
onSupportEmailClick: () -> Unit,
|
||||
onSupportChatClick: () -> Unit,
|
||||
|
|
@ -30,6 +35,14 @@ internal class ItemsBuilder @Inject constructor(private val router: Router) {
|
|||
): ImmutableList<DetailsItemUM> = buildList {
|
||||
buildWalletConnectBlock(isWalletConnectAvailable, userWalletId)?.let(::add)
|
||||
buildUserWalletListBlock().let(::add)
|
||||
|
||||
if (hotWalletFeatureToggles.isWalletCreationRestrictionEnabled && hasAnyMobileWallet) {
|
||||
DetailsItemUM.UnderSectionText(
|
||||
id = "only_one_mobile_wallet_explanation",
|
||||
text = resourceReference(R.string.only_one_mobile_wallet_explanation),
|
||||
).let(::add)
|
||||
}
|
||||
|
||||
buildShopBlock(onBuyClick).let(::add)
|
||||
buildSettingsBlock().let(::add)
|
||||
buildSupportBlock(
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.common.routing)
|
||||
|
||||
/* Project - Domain */
|
||||
implementation(projects.domain.models)
|
||||
|
|
|
|||
|
|
@ -2,4 +2,5 @@ package com.tangem.features.hotwallet
|
|||
|
||||
interface HotWalletFeatureToggles {
|
||||
val isHotWalletEnabled: Boolean
|
||||
val isWalletCreationRestrictionEnabled: Boolean
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ interface WalletBackupComponent : ComposableContentComponent {
|
|||
|
||||
data class Params(
|
||||
val userWalletId: UserWalletId,
|
||||
val isColdWalletOptionShown: Boolean,
|
||||
)
|
||||
|
||||
interface Factory : ComponentFactory<Params, WalletBackupComponent>
|
||||
|
|
|
|||
|
|
@ -7,4 +7,7 @@ internal class DefaultHotWalletFeatureToggles(
|
|||
) : HotWalletFeatureToggles {
|
||||
override val isHotWalletEnabled: Boolean
|
||||
get() = featureTogglesManager.isFeatureEnabled(name = "HOT_WALLET_ENABLED")
|
||||
override val isWalletCreationRestrictionEnabled: Boolean
|
||||
get() = isHotWalletEnabled &&
|
||||
featureTogglesManager.isFeatureEnabled(name = "HOT_WALLET_CREATION_RESTRICTION_ENABLED")
|
||||
}
|
||||
|
|
@ -26,11 +26,11 @@ private const val DISABLED_COLORS_ALPHA = 0.5f
|
|||
internal fun OptionBlock(
|
||||
title: String,
|
||||
description: String,
|
||||
badge: (@Composable () -> Unit)?,
|
||||
onClick: (() -> Unit)?,
|
||||
enabled: Boolean,
|
||||
backgroundColor: Color,
|
||||
modifier: Modifier = Modifier,
|
||||
backgroundColor: Color = TangemTheme.colors.background.primary,
|
||||
badge: (@Composable () -> Unit)? = null,
|
||||
enabled: Boolean = true,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ internal fun CreateHardwareWalletContent(state: CreateHardwareWalletUM, modifier
|
|||
top = 20.dp,
|
||||
end = 16.dp,
|
||||
),
|
||||
text = stringResourceSafe(R.string.wallet_create_common_title),
|
||||
text = stringResourceSafe(R.string.hardware_wallet_create_title),
|
||||
style = TangemTheme.typography.h2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
textAlign = TextAlign.Center,
|
||||
|
|
@ -74,22 +74,22 @@ internal fun CreateHardwareWalletContent(state: CreateHardwareWalletUM, modifier
|
|||
FeatureBlock(
|
||||
modifier = Modifier
|
||||
.padding(top = 32.dp),
|
||||
title = stringResourceSafe(R.string.hw_upgrade_key_migration_title),
|
||||
description = stringResourceSafe(R.string.hw_upgrade_key_migration_description),
|
||||
iconRes = R.drawable.ic_mobile_security_24,
|
||||
title = stringResourceSafe(R.string.hardware_wallet_key_feature_title),
|
||||
description = stringResourceSafe(R.string.hardware_wallet_key_feature_description),
|
||||
iconRes = R.drawable.ic_mobile_security_2_24,
|
||||
)
|
||||
FeatureBlock(
|
||||
modifier = Modifier
|
||||
.padding(top = 24.dp),
|
||||
title = stringResourceSafe(R.string.hw_upgrade_funds_access_title),
|
||||
description = stringResourceSafe(R.string.hw_upgrade_funds_access_description),
|
||||
iconRes = R.drawable.ic_knight_shield_24,
|
||||
title = stringResourceSafe(R.string.hardware_wallet_backup_feature_title),
|
||||
description = stringResourceSafe(R.string.hardware_wallet_backup_feature_description),
|
||||
iconRes = R.drawable.ic_double_star_24,
|
||||
)
|
||||
FeatureBlock(
|
||||
modifier = Modifier
|
||||
.padding(top = 24.dp),
|
||||
title = stringResourceSafe(R.string.hw_upgrade_general_security_title),
|
||||
description = stringResourceSafe(R.string.hw_upgrade_general_security_description),
|
||||
title = stringResourceSafe(R.string.hardware_wallet_security_feature_title),
|
||||
description = stringResourceSafe(R.string.hardware_wallet_security_feature_description),
|
||||
iconRes = R.drawable.ic_protect_24,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,6 @@ internal class CreateMobileWalletModel @Inject constructor(
|
|||
init {
|
||||
trackingContextProxy.addHotWalletContext()
|
||||
analyticsEventHandler.send(event = OnboardingAnalyticsEvent.Onboarding.Started(source = params.source))
|
||||
analyticsEventHandler.send(event = OnboardingAnalyticsEvent.Onboarding.AppsFlyerOnlyEntryScreenView())
|
||||
analyticsEventHandler.send(
|
||||
event = OnboardingAnalyticsEvent.SeedPhrase.CreateMobileScreenOpened(source = params.source),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -75,14 +75,21 @@ internal fun CreateMobileWalletContent(state: CreateMobileWalletUM, modifier: Mo
|
|||
.padding(top = 32.dp),
|
||||
title = stringResourceSafe(R.string.hw_create_keys_title),
|
||||
description = stringResourceSafe(R.string.hw_create_keys_description),
|
||||
iconRes = R.drawable.ic_lock_24,
|
||||
iconRes = R.drawable.ic_protect_24,
|
||||
)
|
||||
FeatureBlock(
|
||||
modifier = Modifier
|
||||
.padding(top = 24.dp),
|
||||
title = stringResourceSafe(R.string.hw_create_seed_title),
|
||||
description = stringResourceSafe(R.string.hw_create_seed_description),
|
||||
iconRes = R.drawable.ic_settings_24,
|
||||
iconRes = R.drawable.ic_seed_phrase_24,
|
||||
)
|
||||
FeatureBlock(
|
||||
modifier = Modifier
|
||||
.padding(top = 24.dp),
|
||||
title = stringResourceSafe(R.string.hw_create_upgrade_title),
|
||||
description = stringResourceSafe(R.string.hw_create_upgrade_description),
|
||||
iconRes = R.drawable.ic_tangem_card_24,
|
||||
)
|
||||
}
|
||||
SecondaryButton(
|
||||
|
|
|
|||
|
|
@ -83,9 +83,9 @@ internal fun UpgradeWalletContent(state: UpgradeWalletUM, modifier: Modifier = M
|
|||
FeatureBlock(
|
||||
modifier = Modifier
|
||||
.padding(top = 24.dp),
|
||||
title = stringResourceSafe(R.string.hw_upgrade_funds_access_title),
|
||||
description = stringResourceSafe(R.string.hw_upgrade_funds_access_description),
|
||||
iconRes = R.drawable.ic_knight_shield_24,
|
||||
title = stringResourceSafe(R.string.hw_upgrade_backup_title),
|
||||
description = stringResourceSafe(R.string.hw_upgrade_backup_description),
|
||||
iconRes = R.drawable.ic_smartphone_24,
|
||||
)
|
||||
FeatureBlock(
|
||||
modifier = Modifier
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@Stable
|
||||
|
|
@ -48,19 +49,19 @@ internal class ViewPhraseModel @Inject constructor(
|
|||
private fun loadSeedPhrase() {
|
||||
val userWallet = getUserWalletUseCase(params.userWalletId)
|
||||
.getOrElse { error("User wallet with id ${params.userWalletId} not found") }
|
||||
if (userWallet is UserWallet.Hot) {
|
||||
modelScope.launch {
|
||||
val words = exportSeedPhraseUseCase.invoke(userWallet.hotWalletId)
|
||||
.getOrElse { error("Unable to export seed phrase for wallet with id ${params.userWalletId}") }
|
||||
.mnemonic
|
||||
.mnemonicComponents
|
||||
uiState.update {
|
||||
it.copy(
|
||||
words = words.mapIndexed { index, s ->
|
||||
EnumeratedTwoColumnGridItem(index + 1, s)
|
||||
}.toImmutableList(),
|
||||
)
|
||||
}
|
||||
as? UserWallet.Hot ?: return
|
||||
|
||||
modelScope.launch {
|
||||
val words = exportSeedPhraseUseCase.invoke(userWallet.hotWalletId)
|
||||
.getOrElse { error -> Timber.e(error); throw error }
|
||||
.mnemonic.mnemonicComponents
|
||||
|
||||
uiState.update {
|
||||
it.copy(
|
||||
words = words.mapIndexed { index, s ->
|
||||
EnumeratedTwoColumnGridItem(index + 1, s)
|
||||
}.toImmutableList(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ internal data class WalletBackupUM(
|
|||
val recoveryPhraseOption: LabelUM?,
|
||||
val googleDriveOption: LabelUM?,
|
||||
val googleDriveStatus: BackupStatus,
|
||||
val onBuyClick: () -> Unit,
|
||||
val onRecoveryPhraseClick: () -> Unit,
|
||||
val onGoogleDriveClick: () -> Unit,
|
||||
val onHardwareWalletClick: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -2,21 +2,17 @@ package com.tangem.features.hotwallet.walletbackup.model
|
|||
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.Basic
|
||||
import com.tangem.core.analytics.utils.TrackingContextProxy
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.label.entity.LabelStyle
|
||||
import com.tangem.core.ui.components.label.entity.LabelUM
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.wallets.analytics.WalletSettingsAnalyticEvents
|
||||
import com.tangem.domain.wallets.usecase.GenerateBuyTangemCardLinkUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.domain.wallets.usecase.UnlockHotWalletContextualUseCase
|
||||
import com.tangem.features.hotwallet.WalletBackupComponent
|
||||
|
|
@ -36,8 +32,6 @@ internal class WalletBackupModel @Inject constructor(
|
|||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val unlockHotWalletContextualUseCase: UnlockHotWalletContextualUseCase,
|
||||
private val generateBuyTangemCardLinkUseCase: GenerateBuyTangemCardLinkUseCase,
|
||||
private val urlOpener: UrlOpener,
|
||||
private val router: Router,
|
||||
private val trackingContextProxy: TrackingContextProxy,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
|
|
@ -54,7 +48,7 @@ internal class WalletBackupModel @Inject constructor(
|
|||
hardwareWalletOption = LabelUM(
|
||||
text = resourceReference(R.string.common_recommended),
|
||||
style = LabelStyle.ACCENT,
|
||||
),
|
||||
).takeIf { params.isColdWalletOptionShown },
|
||||
recoveryPhraseOption = LabelUM(
|
||||
text = resourceReference(R.string.hw_backup_no_backup),
|
||||
style = LabelStyle.WARNING,
|
||||
|
|
@ -64,7 +58,6 @@ internal class WalletBackupModel @Inject constructor(
|
|||
style = LabelStyle.REGULAR,
|
||||
),
|
||||
googleDriveStatus = BackupStatus.ComingSoon,
|
||||
onBuyClick = ::onBuyClick,
|
||||
onRecoveryPhraseClick = ::onRecoveryPhraseClick,
|
||||
onGoogleDriveClick = { },
|
||||
onHardwareWalletClick = ::onHardwareWalletClick,
|
||||
|
|
@ -129,14 +122,6 @@ internal class WalletBackupModel @Inject constructor(
|
|||
backedUp = userWallet.backedUp,
|
||||
)
|
||||
|
||||
private fun onBuyClick() {
|
||||
analyticsEventHandler.send(Basic.ButtonBuy(source = AnalyticsParam.ScreensSources.Backup))
|
||||
modelScope.launch {
|
||||
generateBuyTangemCardLinkUseCase
|
||||
.invoke(GenerateBuyTangemCardLinkUseCase.Source.Backup).let { urlOpener.openUrl(it) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun onRecoveryPhraseClick() {
|
||||
analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonRecoveryPhrase())
|
||||
if (uiState.value.backedUp) {
|
||||
|
|
@ -157,10 +142,9 @@ internal class WalletBackupModel @Inject constructor(
|
|||
)
|
||||
} else {
|
||||
router.push(
|
||||
AppRoute.CreateWalletBackup(
|
||||
AppRoute.WalletActivation(
|
||||
userWalletId = params.userWalletId,
|
||||
analyticsSource = AnalyticsParam.ScreensSources.Backup.value,
|
||||
analyticsAction = WalletSettingsAnalyticEvents.RecoveryPhraseScreenAction.Backup.value,
|
||||
isBackupExists = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,36 +1,25 @@
|
|||
package com.tangem.features.hotwallet.walletbackup.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.SecondaryButton
|
||||
import com.tangem.core.ui.components.appbar.AppBarWithBackButton
|
||||
import com.tangem.core.ui.components.label.Label
|
||||
import com.tangem.core.ui.components.label.entity.LabelStyle
|
||||
import com.tangem.core.ui.components.label.entity.LabelUM
|
||||
import com.tangem.core.ui.components.rows.NetworkTitle
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.ForceDarkTheme
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.hotwallet.common.ui.OptionBlock
|
||||
|
|
@ -61,33 +50,31 @@ internal fun WalletBackupContent(state: WalletBackupUM, modifier: Modifier = Mod
|
|||
end = 16.dp,
|
||||
),
|
||||
) {
|
||||
Banner(state)
|
||||
if (state.hardwareWalletOption != null) {
|
||||
OptionBlock(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 8.dp),
|
||||
title = stringResourceSafe(R.string.hw_backup_upgrade_title),
|
||||
description = stringResourceSafe(R.string.hw_backup_upgrade_description),
|
||||
badge = { Label(state.hardwareWalletOption) },
|
||||
onClick = state.onHardwareWalletClick,
|
||||
enabled = true,
|
||||
backgroundColor = TangemTheme.colors.background.primary,
|
||||
)
|
||||
|
||||
OptionBlock(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 8.dp),
|
||||
title = stringResourceSafe(R.string.hw_backup_hardware_title),
|
||||
description = stringResourceSafe(R.string.hw_backup_hardware_description),
|
||||
badge = {
|
||||
state.hardwareWalletOption?.let { Label(it) }
|
||||
},
|
||||
onClick = state.onHardwareWalletClick,
|
||||
enabled = true,
|
||||
backgroundColor = TangemTheme.colors.background.primary,
|
||||
)
|
||||
NetworkTitle(
|
||||
modifier = Modifier
|
||||
.padding(top = 8.dp),
|
||||
title = {
|
||||
Text(
|
||||
modifier = Modifier,
|
||||
text = stringResourceSafe(R.string.onboarding_create_wallet_options_button_options),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
},
|
||||
)
|
||||
NetworkTitle(
|
||||
modifier = Modifier.padding(top = 8.dp),
|
||||
title = {
|
||||
Text(
|
||||
modifier = Modifier,
|
||||
text = stringResourceSafe(R.string.onboarding_create_wallet_options_button_options),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
OptionBlock(
|
||||
modifier = Modifier,
|
||||
title = stringResourceSafe(R.string.hw_backup_seed_title),
|
||||
|
|
@ -116,120 +103,6 @@ internal fun WalletBackupContent(state: WalletBackupUM, modifier: Modifier = Mod
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
private fun Banner(state: WalletBackupUM, modifier: Modifier = Modifier) {
|
||||
ForceDarkTheme {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.background(
|
||||
color = TangemTheme.colors.background.primary,
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
),
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
start = 12.dp,
|
||||
top = 20.dp,
|
||||
end = 12.dp,
|
||||
),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
text = "Tangem Wallet",
|
||||
style = TangemTheme.typography.h3,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
top = 4.dp,
|
||||
),
|
||||
text = "Keeps your crypto safe and offline. Slim as a credit card, safer than a bank vault.",
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
||||
FlowRow(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
start = 24.dp,
|
||||
top = 16.dp,
|
||||
end = 24.dp,
|
||||
),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
FeatureItem(
|
||||
iconResId = R.drawable.ic_shield_check_16,
|
||||
text = resourceReference(R.string.welcome_create_wallet_feature_class),
|
||||
)
|
||||
FeatureItem(
|
||||
iconResId = R.drawable.ic_flash_16,
|
||||
text = resourceReference(R.string.welcome_create_wallet_feature_delivery),
|
||||
)
|
||||
FeatureItem(
|
||||
iconResId = R.drawable.ic_sparkles_16,
|
||||
text = resourceReference(R.string.welcome_create_wallet_feature_use),
|
||||
)
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
start = 8.dp,
|
||||
top = 12.dp,
|
||||
end = 8.dp,
|
||||
bottom = 20.dp,
|
||||
),
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.img_tangem_cards_vertical),
|
||||
contentDescription = null,
|
||||
)
|
||||
SecondaryButton(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.align(Alignment.BottomCenter),
|
||||
text = stringResourceSafe(R.string.details_buy_wallet),
|
||||
onClick = state.onBuyClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun FeatureItem(@DrawableRes iconResId: Int, text: TextReference) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.wrapContentWidth()
|
||||
.padding(horizontal = 8.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.size(16.dp),
|
||||
painter = painterResource(iconResId),
|
||||
tint = TangemTheme.colors.icon.accent,
|
||||
contentDescription = null,
|
||||
)
|
||||
Text(
|
||||
text = text.resolveReference(),
|
||||
style = TangemTheme.typography.caption1,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
|
|
@ -256,7 +129,6 @@ private class WalletBackupUMProvider : CollectionPreviewParameterProvider<Wallet
|
|||
),
|
||||
googleDriveStatus = BackupStatus.ComingSoon,
|
||||
onBackClick = {},
|
||||
onBuyClick = {},
|
||||
onRecoveryPhraseClick = {},
|
||||
onGoogleDriveClick = {},
|
||||
onHardwareWalletClick = {},
|
||||
|
|
@ -277,7 +149,6 @@ private class WalletBackupUMProvider : CollectionPreviewParameterProvider<Wallet
|
|||
),
|
||||
googleDriveStatus = BackupStatus.NoBackup,
|
||||
onBackClick = {},
|
||||
onBuyClick = {},
|
||||
onRecoveryPhraseClick = {},
|
||||
onGoogleDriveClick = {},
|
||||
onHardwareWalletClick = {},
|
||||
|
|
@ -298,7 +169,23 @@ private class WalletBackupUMProvider : CollectionPreviewParameterProvider<Wallet
|
|||
),
|
||||
googleDriveStatus = BackupStatus.Done,
|
||||
onBackClick = {},
|
||||
onBuyClick = {},
|
||||
onRecoveryPhraseClick = {},
|
||||
onGoogleDriveClick = {},
|
||||
onHardwareWalletClick = {},
|
||||
backedUp = false,
|
||||
),
|
||||
WalletBackupUM(
|
||||
hardwareWalletOption = null,
|
||||
recoveryPhraseOption = LabelUM(
|
||||
text = resourceReference(R.string.common_done),
|
||||
style = LabelStyle.ACCENT,
|
||||
),
|
||||
googleDriveOption = LabelUM(
|
||||
text = resourceReference(R.string.common_done),
|
||||
style = LabelStyle.ACCENT,
|
||||
),
|
||||
googleDriveStatus = BackupStatus.Done,
|
||||
onBackClick = {},
|
||||
onRecoveryPhraseClick = {},
|
||||
onGoogleDriveClick = {},
|
||||
onHardwareWalletClick = {},
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import com.tangem.core.ui.extensions.TextReference
|
|||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
internal data class WalletHardwareBackupUM(
|
||||
val showPurchaseBlock: Boolean = false,
|
||||
val blocks: ImmutableList<Block>,
|
||||
val onBackClick: () -> Unit,
|
||||
val onBuyClick: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -32,10 +32,8 @@ import com.tangem.features.hotwallet.wallethardwarebackup.entity.WalletHardwareB
|
|||
import com.tangem.hot.sdk.model.HotWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
|
@ -119,7 +117,6 @@ internal class WalletHardwareBackupModel @Inject constructor(
|
|||
init {
|
||||
trackingContextProxy.addHotWalletContext()
|
||||
analyticsEventHandler.send(WalletSettingsAnalyticEvents.HardwareBackupScreenOpened())
|
||||
showPurchaseBlockWithDelay()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
|
@ -127,13 +124,6 @@ internal class WalletHardwareBackupModel @Inject constructor(
|
|||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun showPurchaseBlockWithDelay() {
|
||||
modelScope.launch {
|
||||
delay(SHOW_PURCHASE_BLOCK_DELAY)
|
||||
uiState.update { it.copy(showPurchaseBlock = true) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun onCreateNewWalletClick() {
|
||||
analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonCreateNewWallet())
|
||||
router.push(AppRoute.CreateHardwareWallet)
|
||||
|
|
@ -175,8 +165,4 @@ internal class WalletHardwareBackupModel @Inject constructor(
|
|||
.invoke(GenerateBuyTangemCardLinkUseCase.Source.Backup).let { urlOpener.openUrl(it) }
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val SHOW_PURCHASE_BLOCK_DELAY = 3000L
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +1,26 @@
|
|||
package com.tangem.features.hotwallet.wallethardwarebackup.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.SecondaryButton
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonSize
|
||||
import com.tangem.core.ui.components.label.Label
|
||||
import com.tangem.core.ui.components.label.entity.LabelStyle
|
||||
import com.tangem.core.ui.components.label.entity.LabelUM
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.res.ForceDarkTheme
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.hotwallet.common.ui.OptionBlock
|
||||
|
|
@ -71,6 +71,8 @@ internal fun WalletHardwareBackupContent(state: WalletHardwareBackupUM, modifier
|
|||
end = 16.dp,
|
||||
),
|
||||
) {
|
||||
Banner(onBuyClick = state.onBuyClick)
|
||||
|
||||
state.blocks.forEach { block ->
|
||||
OptionBlock(
|
||||
modifier = Modifier
|
||||
|
|
@ -86,45 +88,119 @@ internal fun WalletHardwareBackupContent(state: WalletHardwareBackupUM, modifier
|
|||
)
|
||||
}
|
||||
}
|
||||
AnimatedVisibility(state.showPurchaseBlock) {
|
||||
PurchaseBlock(
|
||||
onBuyClick = state.onBuyClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
private fun Banner(onBuyClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||
ForceDarkTheme {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.background(
|
||||
color = TangemTheme.colors.background.primary,
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
),
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
start = 12.dp,
|
||||
top = 20.dp,
|
||||
end = 12.dp,
|
||||
),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
text = stringResourceSafe(R.string.common_tangem_wallet),
|
||||
style = TangemTheme.typography.h3,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
top = 4.dp,
|
||||
),
|
||||
text = stringResourceSafe(R.string.hw_backup_banner_description),
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
||||
FlowRow(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
start = 24.dp,
|
||||
top = 16.dp,
|
||||
end = 24.dp,
|
||||
),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
FeatureItem(
|
||||
iconResId = R.drawable.ic_shield_check_16,
|
||||
text = resourceReference(R.string.welcome_create_wallet_feature_class),
|
||||
)
|
||||
FeatureItem(
|
||||
iconResId = R.drawable.ic_flash_16,
|
||||
text = resourceReference(R.string.welcome_create_wallet_feature_delivery),
|
||||
)
|
||||
FeatureItem(
|
||||
iconResId = R.drawable.ic_sparkles_16,
|
||||
text = resourceReference(R.string.welcome_create_wallet_feature_seedphrase),
|
||||
)
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
start = 8.dp,
|
||||
top = 12.dp,
|
||||
end = 8.dp,
|
||||
bottom = 20.dp,
|
||||
),
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.img_tangem_cards_vertical),
|
||||
contentDescription = null,
|
||||
)
|
||||
SecondaryButton(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.align(Alignment.BottomCenter),
|
||||
text = stringResourceSafe(R.string.details_buy_wallet),
|
||||
onClick = onBuyClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PurchaseBlock(onBuyClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||
private fun FeatureItem(@DrawableRes iconResId: Int, text: TextReference) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp)
|
||||
.background(
|
||||
color = TangemTheme.colors.background.primary,
|
||||
shape = TangemTheme.shapes.roundedCornersXMedium,
|
||||
)
|
||||
.padding(
|
||||
horizontal = 20.dp,
|
||||
vertical = 16.dp,
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.wrapContentWidth()
|
||||
.padding(horizontal = 8.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(end = 16.dp),
|
||||
text = stringResourceSafe(R.string.wallet_add_hardware_purchase),
|
||||
style = TangemTheme.typography.button,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
maxLines = 3,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
Icon(
|
||||
modifier = Modifier.size(16.dp),
|
||||
painter = painterResource(iconResId),
|
||||
tint = TangemTheme.colors.icon.accent,
|
||||
contentDescription = null,
|
||||
)
|
||||
|
||||
SecondaryButton(
|
||||
text = stringResourceSafe(R.string.wallet_import_buy_title),
|
||||
onClick = onBuyClick,
|
||||
size = TangemButtonSize.RoundedAction,
|
||||
Text(
|
||||
text = text.resolveReference(),
|
||||
style = TangemTheme.typography.caption1,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -156,7 +232,6 @@ private fun PreviewWalletHardwareBackupContent() {
|
|||
onClick = { },
|
||||
),
|
||||
),
|
||||
showPurchaseBlock = true,
|
||||
onBuyClick = { },
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -34,12 +34,7 @@ sealed class OnboardingEvent(
|
|||
put("Seed Phrase Length", seedPhraseLength.toString())
|
||||
}
|
||||
},
|
||||
), AppsFlyerIncludedEvent {
|
||||
override val appsFlyerReplacedEvent = when (creationType) {
|
||||
WalletCreationType.NewSeed, WalletCreationType.PrivateKey -> "wallet_created_successfully"
|
||||
WalletCreationType.SeedImport -> "wallet_imported"
|
||||
}
|
||||
}
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
sealed class WalletCreationType(val value: String) {
|
||||
data object PrivateKey : WalletCreationType(value = "Private Key")
|
||||
|
|
@ -92,7 +87,6 @@ sealed class OnboardingEvent(
|
|||
) : OnboardingEvent("Onboarding / Twins", event, params) {
|
||||
|
||||
class ScreenOpened : Twins("Twinning Screen Opened")
|
||||
class SetupStarted : Twins("Twin Setup Started")
|
||||
class SetupFinished : Twins("Twin Setup Finished")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.tangem.core.analytics.models.AnalyticsParam.Key.BLOCKCHAIN
|
|||
import com.tangem.core.analytics.models.AnalyticsParam.Key.ERROR_CODE
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.SOURCE
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.TOKEN_PARAM
|
||||
import com.tangem.core.analytics.models.AppsFlyerIncludedEvent
|
||||
|
||||
/**
|
||||
* Send analytics
|
||||
|
|
@ -25,7 +26,7 @@ sealed class CommonSendAnalyticEvents(
|
|||
params = mapOf(
|
||||
SOURCE to source.analyticsName,
|
||||
),
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
/** Amount screen opened */
|
||||
data class AmountScreenOpened(
|
||||
|
|
@ -37,7 +38,7 @@ sealed class CommonSendAnalyticEvents(
|
|||
params = mapOf(
|
||||
SOURCE to source.analyticsName,
|
||||
),
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
/** Fee screen opened */
|
||||
data class FeeScreenOpened(
|
||||
|
|
@ -74,7 +75,7 @@ sealed class CommonSendAnalyticEvents(
|
|||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
/** If transaction delays notification is present */
|
||||
data class NoticeTransactionDelays(
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.tangem.core.analytics.models.AnalyticsParam.Key.ENS_ADDRESS
|
|||
import com.tangem.core.analytics.models.AnalyticsParam.Key.FEE_TYPE
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.NONCE
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.TOKEN_PARAM
|
||||
import com.tangem.core.analytics.models.AppsFlyerIncludedEvent
|
||||
import com.tangem.core.ui.extensions.capitalize
|
||||
import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents
|
||||
|
||||
|
|
@ -41,7 +42,7 @@ internal sealed class SendAnalyticEvents(
|
|||
}
|
||||
put(ENS_ADDRESS, ensAddress)
|
||||
},
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
data class ConvertTokenButtonClicked(
|
||||
val token: String,
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import com.tangem.core.ui.components.inputrow.InputRowRecipient
|
|||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.test.SendAddressScreenTestTags
|
||||
import com.tangem.core.ui.utils.GlobalMultipleClickPreventer
|
||||
import com.tangem.features.send.v2.api.subcomponents.destination.entity.DestinationRecipientListUM
|
||||
import com.tangem.features.send.v2.api.subcomponents.destination.entity.DestinationTextFieldUM
|
||||
import com.tangem.features.send.v2.api.subcomponents.destination.entity.DestinationUM
|
||||
|
|
@ -138,7 +139,11 @@ private fun LazyListScope.addressItem(
|
|||
title = address.label,
|
||||
placeholder = address.placeholder,
|
||||
onValueChange = { onAddressChange(it, EnterAddressSource.InputField) },
|
||||
onPasteClick = { onAddressChange(it, EnterAddressSource.PasteButton) },
|
||||
onPasteClick = {
|
||||
GlobalMultipleClickPreventer.processEvent {
|
||||
onAddressChange(it, EnterAddressSource.PasteButton)
|
||||
}
|
||||
},
|
||||
onQrCodeClick = onQrCodeClick,
|
||||
isError = isError,
|
||||
isLoading = isValidating,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.tangem.core.analytics.models.AnalyticsParam.Key.RECEIVE_BLOCKCHAIN
|
|||
import com.tangem.core.analytics.models.AnalyticsParam.Key.RECEIVE_TOKEN
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.SEND_BLOCKCHAIN
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.SEND_TOKEN
|
||||
import com.tangem.core.analytics.models.AppsFlyerIncludedEvent
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents
|
||||
|
||||
|
|
@ -31,7 +32,7 @@ internal sealed class SendWithSwapAnalyticEvents(
|
|||
SEND_BLOCKCHAIN to fromToken.network.name,
|
||||
RECEIVE_BLOCKCHAIN to toToken.network.name,
|
||||
),
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
data class NoticeCanNotSwapToken(
|
||||
val fromToken: CryptoCurrency,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.tangem.core.analytics.models.AnalyticsParam.Key.ERROR_MESSAGE
|
|||
import com.tangem.core.analytics.models.AnalyticsParam.Key.PROVIDER
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.RECEIVE_TOKEN
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.SEND_TOKEN
|
||||
import com.tangem.core.analytics.models.AppsFlyerIncludedEvent
|
||||
import com.tangem.feature.swap.domain.models.domain.SwapProvider
|
||||
import com.tangem.feature.swap.domain.models.ui.FeeType
|
||||
|
||||
|
|
@ -21,7 +22,7 @@ sealed class SwapEvents(
|
|||
data class SwapScreenOpened(val token: String) : SwapEvents(
|
||||
event = "Swap Screen Opened",
|
||||
params = mapOf("Token" to token),
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
class SendTokenBalanceClicked : SwapEvents(event = "Send Token Balance Clicked")
|
||||
|
||||
|
|
@ -96,7 +97,7 @@ sealed class SwapEvents(
|
|||
"Receive Blockchain" to receiveBlockchain,
|
||||
"Account Derivation From or To (optional)" to "$fromDerivationIndex, $toDerivationIndex",
|
||||
),
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
class ProviderClicked : SwapEvents("Provider Clicked")
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ internal class PreviewWalletSettingsComponent : WalletSettingsComponent {
|
|||
onNotificationsDescriptionClick = {},
|
||||
isNotificationsPermissionGranted = false,
|
||||
onAccessCodeClick = {},
|
||||
onUpgradeWalletClick = {},
|
||||
onBackupClick = {},
|
||||
onCardSettingsClick = {},
|
||||
accountsUM = previewAccounts(),
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ internal sealed class WalletSettingsItemUM {
|
|||
val text: TextReference,
|
||||
val isEnabled: Boolean,
|
||||
val imageState: ImageState,
|
||||
val additionalBlock: BlockUM? = null,
|
||||
val onClick: () -> Unit,
|
||||
) : WalletSettingsItemUM()
|
||||
|
||||
|
|
@ -46,13 +47,6 @@ internal sealed class WalletSettingsItemUM {
|
|||
val title: TextReference,
|
||||
val description: TextReference,
|
||||
) : WalletSettingsItemUM()
|
||||
|
||||
data class UpgradeWallet(
|
||||
override val id: String,
|
||||
val title: TextReference,
|
||||
val description: TextReference,
|
||||
val onClick: () -> Unit,
|
||||
) : WalletSettingsItemUM()
|
||||
}
|
||||
|
||||
@Immutable
|
||||
|
|
|
|||
|
|
@ -96,7 +96,10 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
val params: WalletSettingsComponent.Params = paramsContainer.require()
|
||||
val dialogNavigation = SlotNavigation<DialogConfig>()
|
||||
val bottomSheetNavigation: SlotNavigation<NetworksAvailableForNotificationBSConfig> = SlotNavigation()
|
||||
private val walletCardItemDelegate = walletCardItemDelegateFactory.create(dialogNavigation)
|
||||
private val walletCardItemDelegate = walletCardItemDelegateFactory.create(
|
||||
dialogNavigation = dialogNavigation,
|
||||
onUpgradeHotWalletClick = ::onUpgradeWalletClick,
|
||||
)
|
||||
|
||||
val state: MutableStateFlow<WalletSettingsUM> = MutableStateFlow(
|
||||
value = WalletSettingsUM(
|
||||
|
|
@ -249,7 +252,6 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
onCheckedNotificationsChanged = ::onCheckedNotificationsChange,
|
||||
onNotificationsDescriptionClick = ::onNotificationsDescriptionClick,
|
||||
onAccessCodeClick = { onAccessCodeClick(userWallet) },
|
||||
onUpgradeWalletClick = { onUpgradeWalletClick() },
|
||||
onBackupClick = ::onBackupClick,
|
||||
onCardSettingsClick = ::onCardSettingsClick,
|
||||
accountsUM = accountList,
|
||||
|
|
@ -374,10 +376,7 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
val isCodeSet = userWallet.hotWalletId.authType != HotWalletId.AuthType.NoPassword
|
||||
analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonAccessCode(isCodeSet))
|
||||
if (!state.value.isWalletBackedUp) {
|
||||
showMakeBackupAtFirstAlertBS(
|
||||
isUpgradeFlow = false,
|
||||
action = WalletSettingsAnalyticEvents.NoticeBackupFirst.Action.AccessCode,
|
||||
)
|
||||
showMakeBackupAtFirstAlertBS()
|
||||
} else {
|
||||
unlockWalletIfNeedAndProceed { authorizationRequired ->
|
||||
router.push(
|
||||
|
|
@ -392,35 +391,28 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun onUpgradeWalletClick() {
|
||||
if (!state.value.isWalletBackedUp) {
|
||||
showMakeBackupAtFirstAlertBS(
|
||||
isUpgradeFlow = true,
|
||||
action = WalletSettingsAnalyticEvents.NoticeBackupFirst.Action.Upgrade,
|
||||
)
|
||||
} else {
|
||||
unlockWalletIfNeedAndProceed {
|
||||
router.push(AppRoute.UpgradeWallet(userWalletId = params.userWalletId))
|
||||
}
|
||||
}
|
||||
router.push(AppRoute.WalletHardwareBackup(userWalletId = params.userWalletId))
|
||||
}
|
||||
|
||||
private fun onBackupClick() {
|
||||
analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonBackup())
|
||||
router.push(AppRoute.WalletBackup(params.userWalletId))
|
||||
router.push(
|
||||
AppRoute.WalletBackup(
|
||||
userWalletId = params.userWalletId,
|
||||
isColdWalletOptionShown = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun onCardSettingsClick() {
|
||||
router.push(AppRoute.CardSettings(params.userWalletId))
|
||||
}
|
||||
|
||||
private fun showMakeBackupAtFirstAlertBS(
|
||||
action: WalletSettingsAnalyticEvents.NoticeBackupFirst.Action,
|
||||
isUpgradeFlow: Boolean,
|
||||
) {
|
||||
private fun showMakeBackupAtFirstAlertBS() {
|
||||
analyticsEventHandler.send(
|
||||
event = WalletSettingsAnalyticEvents.NoticeBackupFirst(
|
||||
source = AnalyticsParam.ScreensSources.WalletSettings.value,
|
||||
action = action,
|
||||
action = WalletSettingsAnalyticEvents.NoticeBackupFirst.Action.AccessCode,
|
||||
),
|
||||
)
|
||||
val message = bottomSheetMessage {
|
||||
|
|
@ -438,14 +430,10 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
router.push(
|
||||
AppRoute.CreateWalletBackup(
|
||||
userWalletId = params.userWalletId,
|
||||
isUpgradeFlow = isUpgradeFlow,
|
||||
isUpgradeFlow = false,
|
||||
shouldSetAccessCode = true,
|
||||
analyticsSource = AnalyticsParam.ScreensSources.WalletSettings.value,
|
||||
analyticsAction = if (isUpgradeFlow) {
|
||||
RecoveryPhraseScreenAction.Upgrade.value
|
||||
} else {
|
||||
RecoveryPhraseScreenAction.AccessCode.value
|
||||
},
|
||||
analyticsAction = RecoveryPhraseScreenAction.AccessCode.value,
|
||||
),
|
||||
)
|
||||
closeBs()
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ import com.tangem.core.ui.components.notifications.Notification
|
|||
import com.tangem.core.ui.components.notifications.NotificationConfig
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
|
@ -153,10 +152,6 @@ private fun Content(state: WalletSettingsUM, modifier: Modifier = Modifier) {
|
|||
modifier = itemModifier,
|
||||
model = item,
|
||||
)
|
||||
is WalletSettingsItemUM.UpgradeWallet -> UpgradeWalletBlock(
|
||||
modifier = itemModifier,
|
||||
model = item,
|
||||
)
|
||||
is WalletSettingsAccountsUM.Header -> AccountsHeader(item, itemModifier)
|
||||
is WalletSettingsAccountsUM.Account -> AccountItem(
|
||||
model = item,
|
||||
|
|
@ -211,35 +206,54 @@ private fun CardBlock(model: WalletSettingsItemUM.CardBlock, modifier: Modifier
|
|||
enabled = model.isEnabled,
|
||||
onClick = model.onClick,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.padding(all = TangemTheme.dimens.spacing12),
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
CardImage(model.imageState)
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(
|
||||
text = model.title.resolveReference(),
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography.caption2,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
Text(
|
||||
text = model.text.resolveReference(),
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
Column {
|
||||
Row(
|
||||
modifier = Modifier.padding(all = TangemTheme.dimens.spacing12),
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
CardImage(model.imageState)
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(
|
||||
text = model.title.resolveReference(),
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography.caption2,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
Text(
|
||||
text = model.text.resolveReference(),
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
)
|
||||
}
|
||||
SecondarySmallButton(
|
||||
config = SmallButtonConfig(
|
||||
isEnabled = model.isEnabled,
|
||||
text = resourceReference(R.string.common_rename),
|
||||
onClick = model.onClick,
|
||||
),
|
||||
)
|
||||
}
|
||||
SecondarySmallButton(
|
||||
config = SmallButtonConfig(
|
||||
isEnabled = model.isEnabled,
|
||||
text = resourceReference(R.string.common_rename),
|
||||
onClick = model.onClick,
|
||||
),
|
||||
)
|
||||
|
||||
if (model.additionalBlock != null) {
|
||||
Column {
|
||||
HorizontalDivider(
|
||||
thickness = TangemTheme.dimens.size0_5,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = TangemTheme.dimens.spacing12),
|
||||
color = TangemTheme.colors.stroke.primary,
|
||||
)
|
||||
|
||||
BlockItem(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
model = model.additionalBlock,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -272,21 +286,6 @@ private fun SwitchBlock(model: WalletSettingsItemUM.WithSwitch, modifier: Modifi
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun UpgradeWalletBlock(model: WalletSettingsItemUM.UpgradeWallet, modifier: Modifier = Modifier) {
|
||||
Notification(
|
||||
config = NotificationConfig(
|
||||
title = model.title,
|
||||
subtitle = model.description,
|
||||
iconResId = R.drawable.ic_hardware_backup_36,
|
||||
iconSize = 36.dp,
|
||||
onClick = model.onClick,
|
||||
shouldShowArrowIcon = false,
|
||||
),
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun NotificationAlertBlock(model: WalletSettingsItemUM.NotificationPermission, modifier: Modifier = Modifier) {
|
||||
Notification(
|
||||
|
|
@ -480,20 +479,4 @@ private fun Preview_WalletSettingsScreen() {
|
|||
PreviewWalletSettingsComponent().Content(modifier = Modifier.fillMaxSize())
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun Preview_WalletSettingsScreen1() {
|
||||
TangemThemePreview {
|
||||
UpgradeWalletBlock(
|
||||
model = WalletSettingsItemUM.UpgradeWallet(
|
||||
id = "upgrade_wallet",
|
||||
title = stringReference("Upgrade wallet with a hardware backup"),
|
||||
description = stringReference("Keep your crypto safe with Tangem’s best-in-class hardware wallet."),
|
||||
onClick = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
// endregion Preview
|
||||
|
|
@ -38,17 +38,10 @@ internal class ItemsBuilder @Inject constructor() {
|
|||
onReferralClick: () -> Unit,
|
||||
onManageTokensClick: () -> Unit,
|
||||
onAccessCodeClick: () -> Unit,
|
||||
onUpgradeWalletClick: () -> Unit,
|
||||
onBackupClick: () -> Unit,
|
||||
onCardSettingsClick: () -> Unit,
|
||||
): PersistentList<WalletSettingsItemUM> = persistentListOf<WalletSettingsItemUM>()
|
||||
.add(cardItem)
|
||||
.addAll(
|
||||
buildUpgradeWalletItem(
|
||||
userWallet = userWallet,
|
||||
onUpgradeWalletClick = onUpgradeWalletClick,
|
||||
),
|
||||
)
|
||||
.addAll(buildAccessCodeItem(userWallet, onAccessCodeClick))
|
||||
.addAll(accountsUM)
|
||||
.add(
|
||||
|
|
@ -116,21 +109,6 @@ internal class ItemsBuilder @Inject constructor() {
|
|||
onCheckedChange = onCheckedNFTChange,
|
||||
)
|
||||
|
||||
private fun buildUpgradeWalletItem(
|
||||
userWallet: UserWallet,
|
||||
onUpgradeWalletClick: () -> Unit,
|
||||
): List<WalletSettingsItemUM> = when (userWallet) {
|
||||
is UserWallet.Cold -> emptyList()
|
||||
is UserWallet.Hot -> listOf(
|
||||
WalletSettingsItemUM.UpgradeWallet(
|
||||
id = "upgrade_wallet",
|
||||
title = resourceReference(id = R.string.hw_upgrade_to_cold_banner_title),
|
||||
description = resourceReference(id = R.string.hw_upgrade_to_cold_banner_description),
|
||||
onClick = onUpgradeWalletClick,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun buildNotificationsPermissionItem() = WalletSettingsItemUM.NotificationPermission(
|
||||
id = "notifications_permission",
|
||||
title = resourceReference(id = R.string.transaction_notifications_warning_title),
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.feature.walletsettings.utils
|
|||
|
||||
import com.arkivanov.decompose.router.slot.SlotNavigation
|
||||
import com.arkivanov.decompose.router.slot.activate
|
||||
import com.tangem.core.ui.components.block.model.BlockUM
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
|
@ -24,6 +25,7 @@ internal class WalletCardItemDelegate @AssistedInject constructor(
|
|||
private val getShouldSaveUserWalletsSyncUseCase: ShouldSaveUserWalletsSyncUseCase,
|
||||
private val walletImageFetcher: UserWalletImageFetcher,
|
||||
@Assisted private val dialogNavigation: SlotNavigation<DialogConfig>,
|
||||
@Assisted private val onUpgradeHotWalletClick: () -> Unit,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
) {
|
||||
|
||||
|
|
@ -43,10 +45,20 @@ internal class WalletCardItemDelegate @AssistedInject constructor(
|
|||
isEnabled = isRenameAvailable,
|
||||
onClick = { openRenameWalletDialog(wallet) },
|
||||
imageState = imageState,
|
||||
additionalBlock = buildUpgradeToHardwareWalletBlockOrNull(wallet),
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
private fun buildUpgradeToHardwareWalletBlockOrNull(wallet: UserWallet): BlockUM? {
|
||||
return BlockUM(
|
||||
text = resourceReference(R.string.upgrade_to_hardware_wallet_button_title),
|
||||
iconRes = null,
|
||||
onClick = onUpgradeHotWalletClick,
|
||||
accentType = BlockUM.AccentType.ACCENT,
|
||||
).takeIf { wallet is UserWallet.Hot }
|
||||
}
|
||||
|
||||
private fun openRenameWalletDialog(userWallet: UserWallet) {
|
||||
val config = DialogConfig.RenameWallet(
|
||||
userWalletId = userWallet.walletId,
|
||||
|
|
@ -57,6 +69,9 @@ internal class WalletCardItemDelegate @AssistedInject constructor(
|
|||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(dialogNavigation: SlotNavigation<DialogConfig>): WalletCardItemDelegate
|
||||
fun create(
|
||||
dialogNavigation: SlotNavigation<DialogConfig>,
|
||||
onUpgradeHotWalletClick: () -> Unit,
|
||||
): WalletCardItemDelegate
|
||||
}
|
||||
}
|
||||
|
|
@ -477,7 +477,16 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
|
|||
override fun onFinishWalletActivationClick(isBackupExists: Boolean) {
|
||||
analyticsEventHandler.send(MainScreen.ButtonFinalizeActivation())
|
||||
val userWalletId = stateHolder.getSelectedWalletId()
|
||||
appRouter.push(WalletActivation(userWalletId, isBackupExists))
|
||||
val route = if (isBackupExists) {
|
||||
WalletActivation(userWalletId = userWalletId, isBackupExists = true)
|
||||
} else {
|
||||
WalletBackup(
|
||||
userWalletId = userWalletId,
|
||||
isColdWalletOptionShown = true,
|
||||
)
|
||||
}
|
||||
|
||||
appRouter.push(route)
|
||||
}
|
||||
|
||||
override fun onAllowPermissions() {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.tangem.feature.wallet.presentation.wallet.analytics
|
|||
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.AppsFlyerOnlyEvent
|
||||
import com.tangem.core.analytics.models.AppsFlyerIncludedEvent
|
||||
import com.tangem.core.analytics.models.OneTimeAnalyticsEvent
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
||||
|
|
@ -18,16 +18,11 @@ sealed class WalletScreenAnalyticsEvent {
|
|||
event = "Topped up",
|
||||
params = mapOf(AnalyticsParam.CURRENCY to walletType.value),
|
||||
),
|
||||
OneTimeAnalyticsEvent {
|
||||
OneTimeAnalyticsEvent, AppsFlyerIncludedEvent {
|
||||
|
||||
override val oneTimeEventId: String = id + userWalletId.stringValue
|
||||
}
|
||||
|
||||
class AppsFlyerWalletFunded(userWalletId: UserWalletId) : Basic(event = "wallet_funded"),
|
||||
AppsFlyerOnlyEvent, OneTimeAnalyticsEvent {
|
||||
override val oneTimeEventId: String = id + userWalletId.stringValue
|
||||
}
|
||||
|
||||
class CardWasScanned(source: AnalyticsParam.ScreensSources) : Basic(
|
||||
event = "Card Was Scanned",
|
||||
params = mapOf(
|
||||
|
|
|
|||
|
|
@ -208,7 +208,6 @@ internal class TokenListAnalyticsSender @Inject constructor(
|
|||
}
|
||||
|
||||
analyticsEventHandler.send(Basic.WalletToppedUp(userWallet.walletId, walletType))
|
||||
analyticsEventHandler.send(Basic.AppsFlyerWalletFunded(userWallet.walletId))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.analytics.utils
|
||||
|
||||
import com.tangem.common.routing.AppRoute.WalletActivation
|
||||
import com.tangem.common.routing.AppRoute.WalletBackup
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
|
|
@ -93,7 +93,12 @@ internal class WalletWarningsSingleEventSender @Inject constructor(
|
|||
primaryButton {
|
||||
text = resourceReference(R.string.hw_activation_need_backup)
|
||||
onClick {
|
||||
router.push(WalletActivation(userWallet.walletId, userWallet.backedUp))
|
||||
router.push(
|
||||
WalletBackup(
|
||||
userWalletId = userWalletId,
|
||||
isColdWalletOptionShown = true,
|
||||
),
|
||||
)
|
||||
closeBs()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ android {
|
|||
dependencies {
|
||||
implementation(projects.features.welcome.api)
|
||||
implementation(projects.features.wallet.api)
|
||||
implementation(projects.features.hotWallet.api)
|
||||
|
||||
/** Core */
|
||||
implementation(projects.core.configToggles)
|
||||
|
|
|
|||
|
|
@ -12,14 +12,22 @@ import com.tangem.core.decompose.di.ModelScoped
|
|||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.domain.card.ScanCardProcessor
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.common.wallets.error.SaveWalletError
|
||||
import com.tangem.domain.common.wallets.error.UnlockWalletError
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.models.wallet.isLocked
|
||||
import com.tangem.domain.settings.CanUseBiometryUseCase
|
||||
import com.tangem.domain.wallets.builder.ColdUserWalletBuilder
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.domain.wallets.usecase.NonBiometricUnlockWalletUseCase
|
||||
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.features.wallet.utils.UserWalletsFetcher
|
||||
import com.tangem.features.welcome.impl.ui.state.WelcomeUM
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
|
|
@ -40,10 +48,15 @@ internal class WelcomeModel @Inject constructor(
|
|||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
private val nonBiometricUnlockWalletUseCase: NonBiometricUnlockWalletUseCase,
|
||||
private val canUseBiometryUseCase: CanUseBiometryUseCase,
|
||||
private val coldUserWalletBuilderFactory: ColdUserWalletBuilder.Factory,
|
||||
private val saveWalletUseCase: SaveWalletUseCase,
|
||||
private val walletsRepository: WalletsRepository,
|
||||
private val trackingContextProxy: TrackingContextProxy,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
userWalletsFetcherFactory: UserWalletsFetcher.Factory,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
private val scanCardProcessor: ScanCardProcessor,
|
||||
private val messageSender: UiMessageSender,
|
||||
) : Model() {
|
||||
|
||||
val uiState: StateFlow<WelcomeUM>
|
||||
|
|
@ -168,7 +181,50 @@ internal class WelcomeModel @Inject constructor(
|
|||
|
||||
private fun addWalletClick() {
|
||||
analyticsEventHandler.send(SignIn.ButtonAddWallet(AnalyticsParam.ScreensSources.SignIn))
|
||||
router.push(AppRoute.CreateWalletSelection)
|
||||
if (hotWalletFeatureToggles.isWalletCreationRestrictionEnabled) {
|
||||
scanCard()
|
||||
} else {
|
||||
router.push(AppRoute.CreateWalletSelection)
|
||||
}
|
||||
}
|
||||
|
||||
private fun scanCard() {
|
||||
modelScope.launch {
|
||||
scanCardProcessor.scan(
|
||||
analyticsSource = AnalyticsParam.ScreensSources.SignIn,
|
||||
onWalletNotCreated = {},
|
||||
disclaimerWillShow = { router.pop() },
|
||||
onSuccess = { scanResponse ->
|
||||
val userWallet =
|
||||
coldUserWalletBuilderFactory.create(scanResponse = scanResponse).build() ?: return@scan
|
||||
saveWalletUseCase.invoke(userWallet)
|
||||
.onLeft { error ->
|
||||
if (error is SaveWalletError.WalletAlreadySaved) {
|
||||
userWalletsListRepository.unlock(
|
||||
userWallet.walletId,
|
||||
unlockMethod = UserWalletsListRepository.UnlockMethod.Scan(scanResponse),
|
||||
).onRight {
|
||||
userWalletsListRepository.select(userWallet.walletId)
|
||||
router.replaceAll(AppRoute.Wallet)
|
||||
}
|
||||
}
|
||||
}
|
||||
.onRight {
|
||||
router.replaceAll(AppRoute.Wallet)
|
||||
}
|
||||
},
|
||||
onCancel = {},
|
||||
onFailure = { tangemError ->
|
||||
if (!tangemError.silent) {
|
||||
val message = tangemError.messageResId
|
||||
?.let(::resourceReference)
|
||||
?: stringReference(tangemError.customMessage)
|
||||
|
||||
messageSender.send(SnackbarMessage(message))
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun onlyOneHotWalletWithAccessCode(): Boolean {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.tangem.core.analytics.models.AnalyticsParam.Key.ACTION
|
|||
import com.tangem.core.analytics.models.AnalyticsParam.Key.BLOCKCHAIN
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.ERROR_DESCRIPTION
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.TOKEN_PARAM
|
||||
import com.tangem.core.analytics.models.AppsFlyerIncludedEvent
|
||||
|
||||
sealed class YieldSupplyAnalytics(
|
||||
event: String,
|
||||
|
|
@ -20,7 +21,7 @@ sealed class YieldSupplyAnalytics(
|
|||
TOKEN_PARAM to token,
|
||||
BLOCKCHAIN to blockchain,
|
||||
),
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
data class StartEarningScreen(
|
||||
val token: String,
|
||||
|
|
@ -31,7 +32,7 @@ sealed class YieldSupplyAnalytics(
|
|||
TOKEN_PARAM to token,
|
||||
BLOCKCHAIN to blockchain,
|
||||
),
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
data class StopEarningScreen(
|
||||
val token: String,
|
||||
|
|
@ -42,7 +43,7 @@ sealed class YieldSupplyAnalytics(
|
|||
TOKEN_PARAM to token,
|
||||
BLOCKCHAIN to blockchain,
|
||||
),
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
data class ButtonStartEarning(
|
||||
val token: String,
|
||||
|
|
@ -97,7 +98,7 @@ sealed class YieldSupplyAnalytics(
|
|||
TOKEN_PARAM to token,
|
||||
BLOCKCHAIN to blockchain,
|
||||
),
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
data class FundsEarned(
|
||||
val token: String,
|
||||
|
|
@ -108,7 +109,7 @@ sealed class YieldSupplyAnalytics(
|
|||
TOKEN_PARAM to token,
|
||||
BLOCKCHAIN to blockchain,
|
||||
),
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
data class FundsWithdrawn(
|
||||
val token: String,
|
||||
|
|
@ -119,7 +120,7 @@ sealed class YieldSupplyAnalytics(
|
|||
TOKEN_PARAM to token,
|
||||
BLOCKCHAIN to blockchain,
|
||||
),
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
data class EarnedFundsInfo(
|
||||
val token: String,
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ compose-lifecycle-runtime = "2.7.0"
|
|||
|
||||
# region Other libraries
|
||||
appsflyer = "6.17.3"
|
||||
appsflyer-oaid = "6.12.3"
|
||||
amplitude = "2.36.1"
|
||||
amplitude-experiment = "1.13.1"
|
||||
armadillo = "0.9.0"
|
||||
|
|
@ -238,6 +239,7 @@ test-orchestrator = { module = "androidx.test:orchestrator", version.ref = "orch
|
|||
|
||||
# region Other
|
||||
appsflyer = { module = "com.appsflyer:af-android-sdk", version.ref = "appsflyer" }
|
||||
appsflyer-oaid = { module = "com.appsflyer:oaid", version.ref = "appsflyer-oaid" }
|
||||
amplitude = { module = "com.amplitude:android-sdk", version.ref = "amplitude" }
|
||||
amplitude-experiment = { module = "com.amplitude:experiment-android-client", version.ref = "amplitude-experiment" }
|
||||
armadillo = { module = "at.favre.lib:armadillo", version.ref = "armadillo" }
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
# https://github.com/tangem/tangem-sdk-android/
|
||||
# https://github.com/tangem/vico
|
||||
|
||||
tangemBlockchainSdk = "develop-1371"
|
||||
tangemBlockchainSdk = "develop-1383"
|
||||
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
|
||||
tangemCardSdk = "develop-573"
|
||||
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue