Updated on 2026-08-14

This commit is contained in:
Tangem 2026-03-24 11:11:09 +04:00
parent f192c85914
commit d376a7118d
22 changed files with 44 additions and 221 deletions

View file

@ -3,16 +3,11 @@ package com.tangem.tap.common
import android.app.Dialog
import android.content.Context
import com.tangem.domain.redux.StateDialog
import com.tangem.tap.common.redux.AppDialog
import com.tangem.tap.common.redux.global.GlobalState
import com.tangem.tap.common.ui.ScanFailsDialog
import com.tangem.tap.common.ui.SimpleAlertDialog
import com.tangem.tap.common.ui.SimpleOkDialog
import com.tangem.tap.features.onboarding.OnboardingDialog
import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.WalletActivationErrorDialog
import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.WalletAlreadyWasUsedDialog
import com.tangem.tap.store
import com.tangem.wallet.R
import org.rekotlin.StoreSubscriber
class DialogManager : StoreSubscriber<GlobalState> {
@ -44,34 +39,12 @@ class DialogManager : StoreSubscriber<GlobalState> {
if (dialog != null) return
dialog = when (state.dialog) {
is AppDialog.SimpleOkDialogRes -> SimpleOkDialog.create(state.dialog, context)
is StateDialog.ScanFailsDialog -> ScanFailsDialog.create(
context = context,
source = state.dialog.source,
onTryAgain = state.dialog.onTryAgain,
)
is StateDialog.NfcFeatureIsUnavailable -> SimpleAlertDialog.create(
titleRes = R.string.common_error,
messageRes = R.string.nfc_error_unavailable,
context = context,
)
is OnboardingDialog.WalletActivationError -> WalletActivationErrorDialog.create(context, state.dialog)
is AppDialog.TokensAreLinkedDialog -> SimpleAlertDialog.create(
title = context.getString(state.dialog.titleRes, state.dialog.currencySymbol),
message = context.getString(
state.dialog.messageRes,
state.dialog.currencyTitle,
state.dialog.currencySymbol,
state.dialog.networkName,
),
context = context,
)
is AppDialog.WalletAlreadyWasUsedDialog -> WalletAlreadyWasUsedDialog.create(
context = context,
onOk = state.dialog.onOk,
onSupport = state.dialog.onSupportClick,
onCancel = state.dialog.onCancel,
)
else -> null
}
dialog?.show()

View file

@ -1,32 +0,0 @@
package com.tangem.tap.common.redux
import com.tangem.common.extensions.VoidCallback
import com.tangem.domain.redux.StateDialog
import com.tangem.wallet.R
/**
[REDACTED_AUTHOR]
*/
sealed class AppDialog : StateDialog {
data class SimpleOkDialogRes(
val headerId: Int,
val messageId: Int,
val args: List<String> = emptyList(),
val onOk: VoidCallback? = null,
) : AppDialog()
data class TokensAreLinkedDialog(
val currencyTitle: String,
val currencySymbol: String,
val networkName: String,
) : AppDialog() {
val messageRes: Int = R.string.token_details_unable_hide_alert_message
val titleRes: Int = R.string.token_details_unable_hide_alert_title
}
data class WalletAlreadyWasUsedDialog(
val onOk: () -> Unit,
val onSupportClick: () -> Unit,
val onCancel: () -> Unit,
) : AppDialog()
}

View file

@ -1,55 +0,0 @@
package com.tangem.tap.common.ui
import android.content.Context
import androidx.appcompat.app.AlertDialog
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.store
import com.tangem.wallet.R
object SimpleAlertDialog {
fun create(
titleRes: Int? = null,
messageRes: Int? = null,
title: String? = null,
message: String? = null,
primaryButtonRes: Int = R.string.common_ok,
context: Context,
): AlertDialog {
return SimpleCancelableAlertDialog.create(
titleRes = titleRes,
messageRes = messageRes,
title = title,
message = message,
primaryButtonRes = primaryButtonRes,
secondaryButtonRes = null,
context = context,
)
}
}
object SimpleCancelableAlertDialog {
fun create(
titleRes: Int? = null,
messageRes: Int? = null,
title: String? = null,
message: String? = null,
primaryButtonRes: Int = R.string.common_ok,
secondaryButtonRes: Int? = R.string.common_cancel,
primaryButtonAction: () -> Unit = {},
secondaryButtonAction: () -> Unit = {},
context: Context,
): AlertDialog {
return MaterialAlertDialogBuilder(context, R.style.CustomMaterialDialog).apply {
setTitle(if (titleRes != null) context.getString(titleRes) else title)
setMessage(if (messageRes != null) context.getString(messageRes) else message)
setPositiveButton(context.getText(primaryButtonRes)) { _, _ -> primaryButtonAction() }
if (secondaryButtonRes != null) {
setNegativeButton(context.getText(secondaryButtonRes)) { _, _ -> secondaryButtonAction() }
}
setOnDismissListener {
store.dispatch(GlobalAction.HideDialog)
}
}.create()
}
}

View file

@ -1,31 +0,0 @@
package com.tangem.tap.common.ui
import android.content.Context
import androidx.appcompat.app.AlertDialog
import com.tangem.tap.common.extensions.dispatchDialogHide
import com.tangem.tap.common.redux.AppDialog
import com.tangem.tap.store
import com.tangem.wallet.R
/**
[REDACTED_AUTHOR]
*/
object SimpleOkDialog {
fun create(dialog: AppDialog.SimpleOkDialogRes, context: Context): AlertDialog {
val message = if (dialog.args.isEmpty()) {
context.getString(dialog.messageId)
} else {
context.getString(dialog.messageId, *dialog.args.toTypedArray())
}
return AlertDialog.Builder(context).apply {
setTitle(context.getString(dialog.headerId))
setMessage(message)
setPositiveButton(R.string.common_ok) { _, _ -> }
setOnDismissListener {
store.dispatchDialogHide()
dialog.onOk?.invoke()
}
}.create()
}
}

View file

@ -10,6 +10,8 @@ import com.tangem.core.analytics.Analytics
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.ui.UiMessageSender
import com.tangem.core.ui.message.dialog.Dialogs
import com.tangem.domain.card.CardTypesResolver
import com.tangem.domain.card.ScanCardProcessor
import com.tangem.domain.card.common.util.cardTypesResolver
@ -25,9 +27,7 @@ import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.sdk.api.TangemSdkManager
import com.tangem.tap.common.analytics.events.AnalyticsParam
import com.tangem.tap.common.analytics.events.Settings
import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.extensions.dispatchNavigationAction
import com.tangem.tap.common.redux.AppDialog
import com.tangem.tap.features.details.ui.cardsettings.CardInfo
import com.tangem.tap.features.details.ui.cardsettings.CardSettingsScreenState
import com.tangem.tap.features.details.ui.cardsettings.api.CardSettingsComponent
@ -37,7 +37,6 @@ import com.tangem.tap.store
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.extensions.addIf
import com.tangem.utils.logging.TangemLogger
import com.tangem.wallet.R
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
@ -56,6 +55,7 @@ internal class CardSettingsModel @Inject constructor(
private val cardSdkConfigRepository: CardSdkConfigRepository,
private val settingsRepository: SettingsRepository,
private val onboardingRepository: OnboardingRepository,
private val uiMessageSender: UiMessageSender,
) : Model() {
private val params = paramsContainer.require<CardSettingsComponent.Params>()
@ -115,12 +115,7 @@ internal class CardSettingsModel @Inject constructor(
if (userWalletId == scannedUserWalletId || scannedUserWalletId == null) {
cardSettingsInteractor.initialize(scanResponse)
} else {
store.dispatchDialogShow(
AppDialog.SimpleOkDialogRes(
headerId = R.string.common_warning,
messageId = R.string.error_wrong_wallet_tapped,
),
)
uiMessageSender.send(Dialogs.wrongWalletTapped())
}
}
}

View file

@ -1,33 +0,0 @@
package com.tangem.tap.features.onboarding.products.wallet.ui.dialogs
import android.content.Context
import androidx.appcompat.app.AlertDialog
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.store
import com.tangem.wallet.R
object WalletAlreadyWasUsedDialog {
fun create(context: Context, onOk: () -> Unit, onCancel: () -> Unit, onSupport: () -> Unit): AlertDialog {
return MaterialAlertDialogBuilder(context, R.style.CustomMaterialDialog).apply {
setTitle(R.string.security_alert_title)
setMessage(R.string.wallet_been_activated_message)
setPositiveButton(R.string.this_is_my_wallet_title) { dialog, _ ->
onOk()
dialog.dismiss()
}
setNeutralButton(R.string.common_cancel) { dialog, _ ->
onCancel()
dialog.dismiss()
}
setNegativeButton(R.string.alert_button_request_support) { dialog, _ ->
onSupport()
dialog.dismiss()
}
setOnDismissListener {
store.dispatch(GlobalAction.HideDialog)
}
}.create()
}
}

View file

@ -8,6 +8,7 @@ import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.message.DialogMessage
import com.tangem.core.ui.message.EventMessage
import com.tangem.core.ui.message.dialog.Dialogs
import com.tangem.core.ui.message.SnackbarMessage
import com.tangem.domain.common.wallets.error.UnlockWalletError
import com.tangem.domain.common.wallets.error.UnlockWalletError.UnableToUnlock.Reason
@ -22,12 +23,7 @@ inline fun UnlockWalletError.handle(
when (this) {
UnlockWalletError.AlreadyUnlocked -> onAlreadyUnlocked()
UnlockWalletError.ScannedCardWalletNotMatched -> {
showMessage(
DialogMessage(
title = resourceReference(R.string.common_warning),
message = resourceReference(R.string.error_wrong_wallet_tapped),
),
)
showMessage(Dialogs.wrongWalletTapped())
}
UnlockWalletError.UserCancelled -> onUserCancelled()
UnlockWalletError.UserWalletNotFound -> {

View file

@ -404,6 +404,7 @@
<string name="common_utxo_validate_withdrawal_message_warning">Aufgrund der Beschränkungen von %1$s können nur %2$d UTXOs in eine einzige Transaktion passen. Das bedeutet, dass du nur %3$s oder weniger senden kannst. Du musst den Betrag reduzieren.</string>
<string name="common_value_copied">Wert kopiert</string>
<string name="common_wallets">Meine Wallet</string>
<string name="common_warning">Warnung</string>
<string name="common_week">Woche</string>
<string name="common_with">mit</string>
<string name="common_yes">Ja</string>

View file

@ -401,6 +401,7 @@
<string name="common_utxo_validate_withdrawal_message_warning">Debido a limitaciones sobre %1$s, solo %2$d UTXO pueden caber en una sola transacción. Esto significa que solo puedes enviar %3$s o menos. Debe reducir la cantidad.</string>
<string name="common_value_copied">Valor copiado</string>
<string name="common_wallets">Billeteras</string>
<string name="common_warning">Alerta</string>
<string name="common_week">semana</string>
<string name="common_with">con</string>
<string name="common_yes"></string>

View file

@ -400,6 +400,7 @@
<string name="common_unstake">Unstakez</string>
<string name="common_utxo_validate_withdrawal_message_warning">En raison d\'une limitations sur les %1$s, seuls les %2$d UTXO peuvent s\'intégrer dans une seule transaction. Ce qui signifie vous ne pouvez envoyer que %3$s ou moins. Réduisez le montant.</string>
<string name="common_value_copied">Valeur copiée</string>
<string name="common_warning">Alerte</string>
<string name="common_week">semaine</string>
<string name="common_with">avec</string>
<string name="common_yes">Oui</string>

View file

@ -26,6 +26,7 @@
<item quantity="one">%d gettone</item>
<item quantity="other">%d gettoni</item>
</plurals>
<string name="common_warning">Avviso</string>
<string name="details_manage_security_access_code">Codice di accesso</string>
<string name="details_manage_security_access_code_description">Prima di scansionare la carta sarà necessario inserire il codice di accesso corretto</string>
<string name="details_manage_security_long_tap">Mantenimento della carta</string>

View file

@ -301,6 +301,7 @@
<string name="common_hour">時間</string>
<string name="common_import">インポート</string>
<string name="common_in_progress">進行中</string>
<string name="common_insufficient_balance">残高不足</string>
<string name="common_later">後で</string>
<string name="common_learn_more">もっと詳しく</string>
<string name="common_left">残り%1$s</string>
@ -397,6 +398,7 @@
<string name="common_utxo_validate_withdrawal_message_warning">%1$sの制限により、1つのトランザクションに収まるUTXOは%2$d個のみです。つまり、 %3$s以下しか送信できません。量を減らす必要があります。</string>
<string name="common_value_copied">値がコピーされました</string>
<string name="common_wallets">ウォレット</string>
<string name="common_warning">警告</string>
<string name="common_week"></string>
<string name="common_with"></string>
<string name="common_yes">はい</string>
@ -473,7 +475,7 @@
<string name="earn_filter_by">絞り込み</string>
<string name="earn_filter_my_networks">マイネットワーク</string>
<string name="earn_filter_networks">ネットワーク</string>
<string name="earn_mostly_used">よく使われています</string>
<string name="earn_mostly_used">人気</string>
<string name="earn_no_results">該当する結果はありません</string>
<string name="earn_title">ステーキング・利息モード</string>
<string name="email_preface_wc_error">こんにちは、サポートチームの皆さん、コード %s のエラーが発生しました。</string>

View file

@ -404,6 +404,7 @@
<string name="common_utxo_validate_withdrawal_message_warning">Devido a %1$s limitações apenas %2$d Os UTXOs podem caber em uma única transação. Isso significa que você só pode enviar %3$s ou menos. Você precisa reduzir a quantidade.</string>
<string name="common_value_copied">Valor copiado</string>
<string name="common_wallets">Carteiras</string>
<string name="common_warning">Aviso</string>
<string name="common_week">semana</string>
<string name="common_with">com</string>
<string name="common_yes">Sim</string>

View file

@ -415,6 +415,7 @@
<string name="common_utxo_validate_withdrawal_message_warning">Из-за ограничений %1$s в одну транзакцию может поместиться только %2$d UTXO. Это означает, что вы можете отправить только %3$s или меньше. Вам нужно уменьшить сумму.</string>
<string name="common_value_copied">Значение скопировано</string>
<string name="common_wallets">Кошельки</string>
<string name="common_warning">Предупреждение</string>
<string name="common_week">неделю</string>
<string name="common_with">с</string>
<string name="common_yes">Да</string>

View file

@ -415,6 +415,7 @@
<string name="common_utxo_validate_withdrawal_message_warning">Через обмеження %1$s в одну транзакцію може поміститися тільки %2$d UTXO. Це означає, що ви можете відправити тільки %3$s або менше. Вам потрібно зменшити суму.</string>
<string name="common_value_copied">Скопійовано</string>
<string name="common_wallets">Гаманці</string>
<string name="common_warning">Увага</string>
<string name="common_week">тиждень</string>
<string name="common_with">з</string>
<string name="common_yes">Так</string>

View file

@ -99,6 +99,7 @@
<string name="common_understand">我了解</string>
<string name="common_unreachable">無法觸達</string>
<string name="common_utxo_validate_withdrawal_message_warning">由於 %1$s 的限制,只有%2$d UTXO 可以放入單次交易中。這意味著您只能發送%3$s或更少數量。您需要減少數量。</string>
<string name="common_warning">警告</string>
<string name="common_yes"></string>
<string name="contract_address_copied_message">已複製代幣地址</string>
<string name="currency_subtitle_expanded">支持的網路</string>

View file

@ -405,6 +405,7 @@
<string name="common_utxo_validate_withdrawal_message_warning">Due to %1$s limitations only %2$d UTXOs can fit in a single transaction. This means you can only send %3$s or less. You need to reduce the amount.</string>
<string name="common_value_copied">Value copied</string>
<string name="common_wallets">Wallets</string>
<string name="common_warning">Warning</string>
<string name="common_week">week</string>
<string name="common_with">with</string>
<string name="common_yes">Yes</string>
@ -481,7 +482,7 @@
<string name="earn_filter_by">Filter by</string>
<string name="earn_filter_my_networks">My networks</string>
<string name="earn_filter_networks">Networks</string>
<string name="earn_mostly_used">Mostly used</string>
<string name="earn_mostly_used">Popular</string>
<string name="earn_no_results">No results</string>
<string name="earn_title">Staking &amp; Yield mode</string>
<string name="email_preface_wc_error">Hi support team, I\'ve encountered an error with code: %s</string>
@ -703,7 +704,7 @@
<string name="koinos_insufficient_mana_to_send_koin_title">Not enough Mana</string>
<string name="koinos_mana_exceeds_koin_balance_description">You can transfer only %s due to the Mana limit imposed by the Koinos network</string>
<string name="koinos_mana_exceeds_koin_balance_title">Mana limit</string>
<string name="koinos_mana_level_description">The Koinos network requires Mana for network fees. Your have %1$s/%2$s Mana</string>
<string name="koinos_mana_level_description">The Koinos network requires Mana for network fees. You have %1$s/%2$s Mana</string>
<string name="koinos_mana_level_title">Mana level</string>
<string name="main_empty_tokens_list_message">To begin tracking your crypto assets and transactions, add tokens</string>
<string name="main_manage_tokens">Manage tokens</string>
@ -829,6 +830,7 @@
<string name="markets_token_details_market_rating_description">Position in crypto rating between all coins based on market capitalization</string>
<string name="markets_token_details_market_rating_full">Market position</string>
<string name="markets_token_details_max_supply">Max supply</string>
<string name="markets_token_details_max_supply_and_circulation_full">Circulating and Max Supply</string>
<string name="markets_token_details_max_supply_description">The maximum number of coins or tokens that can ever exist for a particular cryptocurrency</string>
<string name="markets_token_details_max_supply_full">Max supply</string>
<string name="markets_token_details_metrics">Metrics</string>
@ -1666,6 +1668,7 @@
<string name="token_details_token_type_subtitle_no_standard">Token in %%image%% %1$s network</string>
<string name="token_details_unable_hide_alert_message">The %1$s (%2$s) token is the main currency on the %3$s network and cannot be hidden as long as you have other tokens on this network in the list</string>
<string name="token_details_unable_hide_alert_title">Unable to hide %s</string>
<string name="token_market_metrics_no_data">N/A</string>
<string name="token_receive_show_qr_code_title">Show QR code</string>
<string name="token_swap_changelly_promotion_message">Exchange this token for another at %1$s service fees from February %2$s-%3$s.</string>
<string name="token_swap_changelly_promotion_title">Swap with Changelly, %s fees</string>

View file

@ -13,6 +13,22 @@ import com.tangem.core.ui.message.EventMessageAction
*/
object Dialogs {
/**
* NFC feature is unavailable dialog
*/
fun nfcFeatureUnavailable(): DialogMessage = DialogMessage(
title = resourceReference(id = R.string.common_error),
message = resourceReference(R.string.nfc_error_unavailable),
)
/**
* Wrong wallet tapped dialog
*/
fun wrongWalletTapped(): DialogMessage = DialogMessage(
title = resourceReference(id = R.string.common_warning),
message = resourceReference(id = R.string.error_wrong_wallet_tapped),
)
/**
* Card verification failed dialog
*

View file

@ -2,8 +2,6 @@ package com.tangem.domain.redux
interface StateDialog {
data object NfcFeatureIsUnavailable : StateDialog
data class ScanFailsDialog(val source: ScanFailsSource, val onTryAgain: (() -> Unit)? = null) : StateDialog
enum class ScanFailsSource {

View file

@ -18,7 +18,7 @@ import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.navigation.url.UrlOpener
import com.tangem.core.ui.R
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.message.DialogMessage
import com.tangem.core.ui.message.dialog.Dialogs
import com.tangem.core.ui.message.dialog.Dialogs.hotWalletCreationNotSupportedDialog
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
import com.tangem.domain.card.ScanCardProcessor
@ -252,11 +252,6 @@ internal class CreateWalletStartModel @Inject constructor(
}
private fun handleNfcFeatureUnavailable() {
uiMessageSender.send(
message = DialogMessage(
message = resourceReference(R.string.nfc_error_unavailable),
title = resourceReference(id = R.string.common_error),
),
)
uiMessageSender.send(Dialogs.nfcFeatureUnavailable())
}
}

View file

@ -17,9 +17,7 @@ import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.decompose.navigation.Router
import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.navigation.url.UrlOpener
import com.tangem.core.ui.R
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.message.DialogMessage
import com.tangem.core.ui.message.dialog.Dialogs
import com.tangem.domain.card.ScanCardProcessor
import com.tangem.domain.card.analytics.IntroductionProcess
import com.tangem.domain.card.analytics.ParamCardCurrencyConverter
@ -251,11 +249,6 @@ internal class HomeModel @Inject constructor(
}
private fun handleNfcFeatureUnavailable() {
uiMessageSender.send(
message = DialogMessage(
message = resourceReference(R.string.nfc_error_unavailable),
title = resourceReference(id = R.string.common_error),
),
)
uiMessageSender.send(Dialogs.nfcFeatureUnavailable())
}
}

View file

@ -12,9 +12,9 @@ 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.navigation.url.UrlOpener
import com.tangem.core.ui.R
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.message.DialogMessage
import com.tangem.core.ui.message.dialog.Dialogs
import com.tangem.domain.card.ScanCardProcessor
import com.tangem.domain.card.analytics.IntroductionProcess
import com.tangem.domain.card.repository.CardSdkConfigRepository
@ -170,12 +170,7 @@ internal class CreateHardwareWalletModel @Inject constructor(
}
private fun handleNfcFeatureUnavailable() {
uiMessageSender.send(
message = DialogMessage(
message = resourceReference(R.string.nfc_error_unavailable),
title = resourceReference(id = R.string.common_error),
),
)
uiMessageSender.send(Dialogs.nfcFeatureUnavailable())
}
private suspend fun handleAlreadySavedCard(messageId: Int, walletId: UserWalletId, scanResponse: ScanResponse) {