Updated on 2026-08-14

This commit is contained in:
Tangem 2022-10-17 19:57:07 +05:00
parent 7355e24baa
commit d0c4d92a8c
12 changed files with 346 additions and 0 deletions

View file

@ -17,6 +17,9 @@ import com.tangem.tap.features.onboarding.AddressInfoBottomSheetDialog
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction
import com.tangem.tap.features.onboarding.products.twins.ui.dialog.CreateWalletInterruptDialog
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupDialog
import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.NoFundsForActivationDialog
import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.RegistrationErrorDialog
import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.SaltPayDialog
import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.AddMoreBackupCardsDialog
import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.BackupInProgressDialog
import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.ConfirmDiscardingBackupDialog
@ -126,6 +129,8 @@ class DialogManager : StoreSubscriber<GlobalState> {
is BackupDialog.BackupInProgress -> BackupInProgressDialog.create(context)
is BackupDialog.UnfinishedBackupFound -> UnfinishedBackupFoundDialog.create(context)
is BackupDialog.ConfirmDiscardingBackup -> ConfirmDiscardingBackupDialog.create(context)
is SaltPayDialog.NoFundsForActivation -> NoFundsForActivationDialog.create(context)
is SaltPayDialog.RegistrationError -> RegistrationErrorDialog.create(context, state.dialog)
is WalletDialog.CurrencySelectionDialog ->
CurrencySelectionDialog.create(state.dialog, context)
is WalletDialog.ChooseTradeActionDialog ->

View file

@ -15,6 +15,10 @@ fun postBackground(ms: Long = 0, func: Runnable) {
if (ms == 0L) backgroundHandler.post { func.run() } else backgroundHandler.postDelayed(func, ms)
}
fun postUiDelayBg(ms: Long, func: Runnable) {
backgroundHandler.postDelayed({ uiHandler.post(func) }, ms)
}
fun post(ms: Long = 0, func: Runnable) {
if (ms == 0L) {
func.run()

View file

@ -0,0 +1,32 @@
package com.tangem.tap.domain.moduleMessage
/**
[REDACTED_AUTHOR]
* Base interface for conversion outputs from ModuleMessageConverter
*/
interface ConvertedMessage {
val message: String
}
/**
* Dialog message used to construct a android.Dialog
*/
interface DialogMessage : ConvertedMessage {
val title: String
override val message: String
val onPositive: String?
val onNegative: String?
val onNeutral: String?
}
data class ConvertedStringMessage(
override val message: String,
) : ConvertedMessage
data class ConvertedDialogMessage(
override val title: String,
override val message: String,
override val onPositive: String? = null,
override val onNegative: String? = null,
override val onNeutral: String? = null,
) : DialogMessage

View file

@ -0,0 +1,27 @@
package com.tangem.tap.domain.moduleMessage
import android.content.Context
import com.tangem.common.module.ModuleMessage
import com.tangem.common.module.ModuleMessageConverter
import com.tangem.domain.DomainModuleMessage
import com.tangem.tap.domain.moduleMessage.domain.DomainMessageConverter
import com.tangem.tap.domain.moduleMessage.saltPay.SaltPayMessageConverter
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayModuleMessage
class ModuleMessageConverter(
private val context: Context,
) : ModuleMessageConverter<ModuleMessage, ConvertedMessage> {
override fun convert(message: ModuleMessage): ConvertedMessage {
val convertedMessage = when (message) {
is DomainModuleMessage -> DomainMessageConverter(context).convert(message)
is SaltPayModuleMessage -> SaltPayMessageConverter(context).convert(message)
else -> null
}
return convertedMessage ?: convertUnknownMessage(message)
}
private fun convertUnknownMessage(message: ModuleMessage): ConvertedMessage {
return ConvertedStringMessage("Unknown message: ${message::class.java.simpleName}")
}
}

View file

@ -0,0 +1,34 @@
package com.tangem.tap.domain.moduleMessage.domain
import android.content.Context
import com.tangem.common.module.ModuleMessageConverter
import com.tangem.domain.AddCustomTokenError
import com.tangem.domain.DomainModuleError
import com.tangem.domain.DomainModuleMessage
import com.tangem.tap.domain.moduleMessage.ConvertedMessage
import com.tangem.tap.domain.moduleMessage.domain.converter.AddCustomTokenErrorConverter
/**
[REDACTED_AUTHOR]
*/
class DomainMessageConverter(
private val context: Context,
) : ModuleMessageConverter<DomainModuleMessage, ConvertedMessage?> {
override fun convert(message: DomainModuleMessage): ConvertedMessage? {
return when (message) {
is DomainModuleError -> DomainErrorConverter(context).convert(message)
else -> null
}
}
}
class DomainErrorConverter(
private val context: Context,
) : ModuleMessageConverter<DomainModuleError, ConvertedMessage?> {
override fun convert(message: DomainModuleError): ConvertedMessage? = when (message) {
is AddCustomTokenError -> AddCustomTokenErrorConverter(context).convert(message)
else -> null
}
}

View file

@ -0,0 +1,41 @@
package com.tangem.tap.domain.moduleMessage.domain.converter
import android.content.Context
import com.tangem.common.module.ModuleMessageConverter
import com.tangem.domain.AddCustomTokenError
import com.tangem.domain.DomainModuleError
import com.tangem.tap.domain.moduleMessage.ConvertedMessage
import com.tangem.tap.domain.moduleMessage.ConvertedStringMessage
import com.tangem.wallet.R
/**
[REDACTED_AUTHOR]
*/
internal class AddCustomTokenErrorConverter(
private val context: Context,
) : ModuleMessageConverter<DomainModuleError, ConvertedMessage?> {
override fun convert(message: DomainModuleError): ConvertedMessage? {
val customTokenError = (message as? AddCustomTokenError) ?: throw UnsupportedOperationException()
val rawMessage = when (customTokenError) {
AddCustomTokenError.Warning.PotentialScamToken -> R.string.custom_token_validation_error_not_found
AddCustomTokenError.Warning.TokenAlreadyAdded -> R.string.custom_token_validation_error_already_added
AddCustomTokenError.Warning.UnsupportedSolanaToken -> R.string.alert_manage_tokens_unsupported_message
AddCustomTokenError.InvalidContractAddress -> R.string.custom_token_creation_error_invalid_contract_address
AddCustomTokenError.NetworkIsNotSelected -> R.string.custom_token_creation_error_network_not_selected
AddCustomTokenError.InvalidDerivationPath -> R.string.custom_token_creation_error_invalid_derivation_path
AddCustomTokenError.InvalidDecimalsCount -> {
context.getString(R.string.custom_token_creation_error_wrong_decimals, 30)
}
AddCustomTokenError.FieldIsEmpty -> R.string.custom_token_creation_error_required_field
else -> null
}
return when (rawMessage) {
is Int -> ConvertedStringMessage(context.getString(rawMessage))
is String -> ConvertedStringMessage(rawMessage)
else -> null
}
}
}

View file

@ -0,0 +1,34 @@
package com.tangem.tap.domain.moduleMessage.saltPay
import android.content.Context
import com.tangem.common.module.ModuleMessageConverter
import com.tangem.tap.domain.moduleMessage.ConvertedMessage
import com.tangem.tap.domain.moduleMessage.saltPay.converter.SaltPayRegistrationErrorConverter
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayModuleError
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayModuleMessage
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayRegistrationError
/**
[REDACTED_AUTHOR]
*/
class SaltPayMessageConverter(
private val context: Context,
) : ModuleMessageConverter<SaltPayModuleMessage, ConvertedMessage?> {
override fun convert(message: SaltPayModuleMessage): ConvertedMessage? {
return when (message) {
is SaltPayModuleError -> SaltPayErrorConverter(context).convert(message)
else -> null
}
}
}
class SaltPayErrorConverter(
private val context: Context,
) : ModuleMessageConverter<SaltPayModuleError, ConvertedMessage?> {
override fun convert(message: SaltPayModuleError): ConvertedMessage? = when (message) {
is SaltPayRegistrationError -> SaltPayRegistrationErrorConverter(context).convert(message)
else -> null
}
}

View file

@ -0,0 +1,46 @@
package com.tangem.tap.domain.moduleMessage.saltPay.converter
import android.content.Context
import com.tangem.common.module.ModuleMessageConverter
import com.tangem.tap.domain.moduleMessage.ConvertedDialogMessage
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayRegistrationError
import com.tangem.wallet.R
/**
[REDACTED_AUTHOR]
*/
internal class SaltPayRegistrationErrorConverter(
private val context: Context,
) : ModuleMessageConverter<SaltPayRegistrationError, ConvertedDialogMessage?> {
override fun convert(message: SaltPayRegistrationError): ConvertedDialogMessage? {
val saltPayError = (message as? SaltPayRegistrationError) ?: throw UnsupportedOperationException()
val dialogMessage = when (saltPayError) {
SaltPayRegistrationError.NoGas -> {
ConvertedDialogMessage(
title = context.getString(R.string.saltpay_error_no_gas_title),
message = context.getString(R.string.saltpay_error_no_gas_message),
)
}
SaltPayRegistrationError.EmptyBackupCardScanned -> {
ConvertedDialogMessage(
title = context.getString(R.string.saltpay_error_empty_backup_title),
message = context.getString(R.string.saltpay_error_empty_backup_message),
)
}
SaltPayRegistrationError.WeakPin -> {
ConvertedDialogMessage(
title = context.getString(R.string.saltpay_error_pin_weak_title),
message = context.getString(R.string.saltpay_error_pin_weak_message),
)
}
else -> ConvertedDialogMessage(
title = context.getString(R.string.common_error),
message = saltPayError::class.java.simpleName,
)
}
return dialogMessage
}
}

View file

@ -0,0 +1,33 @@
package com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog
import android.app.Dialog
import android.content.Context
import androidx.appcompat.app.AlertDialog
import com.tangem.tap.common.feedback.SupportInfo
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.store
import com.tangem.wallet.R
/**
[REDACTED_AUTHOR]
*/
class NoFundsForActivationDialog {
companion object {
fun create(context: Context): Dialog {
return AlertDialog.Builder(context).apply {
setTitle(R.string.saltpay_error_no_gas_title)
setMessage(R.string.saltpay_error_no_gas_message)
//TODO: SaltPay: change onboarding_supplement_button_kyc_waiting -> to appropriate string
setPositiveButton(R.string.onboarding_supplement_button_kyc_waiting) { _, _ ->
store.dispatch(GlobalAction.OpenChat(SupportInfo()))
}
setNegativeButton(R.string.common_cancel) { _, _ ->
}
setOnDismissListener {
store.dispatch(GlobalAction.HideDialog)
}
setCancelable(false)
}.create()
}
}
}

View file

@ -0,0 +1,33 @@
package com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog
import android.app.Dialog
import android.content.Context
import androidx.appcompat.app.AlertDialog
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.domain.moduleMessage.ConvertedDialogMessage
import com.tangem.tap.domain.moduleMessage.saltPay.SaltPayErrorConverter
import com.tangem.tap.store
import com.tangem.wallet.R
/**
[REDACTED_AUTHOR]
*/
class RegistrationErrorDialog {
companion object {
fun create(context: Context, dialog: SaltPayDialog.RegistrationError): Dialog {
val convertedMessage = SaltPayErrorConverter(context).convert(dialog.error) as ConvertedDialogMessage
return AlertDialog.Builder(context).apply {
setTitle(convertedMessage.title)
setMessage(convertedMessage.message)
setPositiveButton(R.string.common_ok) { _, _ ->
store.dispatch(GlobalAction.HideDialog)
}
setOnDismissListener {
store.dispatch(GlobalAction.HideDialog)
}
setCancelable(false)
}.create()
}
}
}

View file

@ -0,0 +1,12 @@
package com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog
import com.tangem.tap.common.redux.StateDialog
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayRegistrationError
/**
[REDACTED_AUTHOR]
*/
sealed class SaltPayDialog : StateDialog {
object NoFundsForActivation : SaltPayDialog()
data class RegistrationError(val error: SaltPayRegistrationError) : SaltPayDialog()
}

View file

@ -0,0 +1,45 @@
package com.tangem.tap.features.onboarding.products.wallet.saltPay.message
import com.tangem.common.module.ModuleError
import com.tangem.common.module.ModuleErrorCode
import com.tangem.common.module.ModuleMessage
sealed interface SaltPayModuleMessage : ModuleMessage
sealed class SaltPayModuleError(
subCode: Int,
override val message: String,
override val data: Any? = null,
) : SaltPayModuleMessage, ModuleError() {
override val code: Int = ModuleErrorCode.SALT_PAY + subCode
companion object {
// base code used for all errors in the module
internal const val ERROR_CODE_REGISTRATION = 100
// const val CODE_ANY_OTHER = 200..299, 300..399 etc
}
}
sealed class SaltPayRegistrationError(
subCode: Int,
message: String? = null,
override val data: Any? = null,
) : SaltPayModuleError(
subCode = ERROR_CODE_REGISTRATION + subCode,
message = message ?: this::class.java.simpleName,
) {
object Unknown : SaltPayRegistrationError(4)
object Empty : SaltPayRegistrationError(4)
object FailedToMakeTxData : SaltPayRegistrationError(1)
object FailedToSendTx : SaltPayRegistrationError(2)
object NeedPin : SaltPayRegistrationError(3)
object NoGas : SaltPayRegistrationError(5)
object EmptyResponse : SaltPayRegistrationError(6)
object Card : SaltPayRegistrationError(7)
object CardNotFound : SaltPayRegistrationError(8)
object CardDisabled : SaltPayRegistrationError(9)
object CardNotPassed : SaltPayRegistrationError(10)
object EmptyDynamicAttestResponse : SaltPayRegistrationError(11)
object EmptyBackupCardScanned : SaltPayRegistrationError(12)
object WeakPin : SaltPayRegistrationError(13)
}