Updated on 2026-08-14
This commit is contained in:
parent
4ed210cd90
commit
1d0028f8b9
7 changed files with 133 additions and 110 deletions
|
|
@ -10,46 +10,31 @@ import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning
|
|||
import com.tangem.features.tokendetails.impl.R
|
||||
|
||||
@Immutable
|
||||
internal sealed class TokenDetailsNotification {
|
||||
internal sealed class TokenDetailsNotification(val config: NotificationConfig) {
|
||||
|
||||
abstract val config: NotificationConfig
|
||||
sealed class Warning(
|
||||
title: TextReference,
|
||||
subtitle: TextReference,
|
||||
iconResId: Int = R.drawable.img_attention_20,
|
||||
buttonsState: NotificationConfig.ButtonsState? = null,
|
||||
) : TokenDetailsNotification(
|
||||
config = NotificationConfig(
|
||||
title = title,
|
||||
subtitle = subtitle,
|
||||
iconResId = iconResId,
|
||||
buttonsState = buttonsState,
|
||||
),
|
||||
) {
|
||||
|
||||
sealed class Informational : TokenDetailsNotification()
|
||||
sealed class Warning : TokenDetailsNotification()
|
||||
|
||||
data class RentInfo(
|
||||
private val rentInfo: CryptoCurrencyWarning.Rent,
|
||||
private val onCloseClick: () -> Unit,
|
||||
) : Warning() {
|
||||
override val config = NotificationConfig(
|
||||
title = TextReference.Res(R.string.warning_rent_fee_title),
|
||||
subtitle = TextReference.Res(
|
||||
id = R.string.warning_solana_rent_fee_message,
|
||||
formatArgs = wrappedList(rentInfo.rent, rentInfo.exemptionAmount),
|
||||
),
|
||||
iconResId = R.drawable.img_attention_20,
|
||||
onCloseClick = onCloseClick,
|
||||
object NetworksUnreachable : Warning(
|
||||
title = resourceReference(R.string.warning_network_unreachable_title),
|
||||
subtitle = resourceReference(R.string.warning_network_unreachable_message),
|
||||
)
|
||||
}
|
||||
|
||||
data class ExistentialDeposit(
|
||||
private val existentialInfo: CryptoCurrencyWarning.ExistentialDeposit,
|
||||
) : Informational() {
|
||||
override val config = NotificationConfig(
|
||||
title = resourceReference(R.string.warning_existential_deposit_title),
|
||||
subtitle = TextReference.Res(
|
||||
id = R.string.warning_existential_deposit_message,
|
||||
formatArgs = wrappedList(existentialInfo.currencyName, existentialInfo.edStringValueWithSymbol),
|
||||
),
|
||||
iconResId = R.drawable.ic_alert_circle_24,
|
||||
)
|
||||
}
|
||||
|
||||
data class NetworkFee(
|
||||
private val feeInfo: CryptoCurrencyWarning.BalanceNotEnoughForFee,
|
||||
private val onBuyClick: () -> Unit,
|
||||
) : Warning() {
|
||||
override val config = NotificationConfig(
|
||||
data class NetworkFee(
|
||||
private val feeInfo: CryptoCurrencyWarning.BalanceNotEnoughForFee,
|
||||
private val onBuyClick: () -> Unit,
|
||||
) : Warning(
|
||||
title = TextReference.Res(
|
||||
id = R.string.warning_send_blocked_funds_for_fee_title,
|
||||
formatArgs = wrappedList(feeInfo.blockchainFullName),
|
||||
|
|
@ -75,22 +60,46 @@ internal sealed class TokenDetailsNotification {
|
|||
)
|
||||
}
|
||||
|
||||
object NetworksUnreachable : Warning() {
|
||||
override val config = NotificationConfig(
|
||||
title = resourceReference(R.string.warning_network_unreachable_title),
|
||||
subtitle = resourceReference(R.string.warning_network_unreachable_message),
|
||||
iconResId = R.drawable.img_attention_20,
|
||||
sealed class Informational(
|
||||
title: TextReference,
|
||||
subtitle: TextReference,
|
||||
onCloseClick: (() -> Unit)? = null,
|
||||
) : TokenDetailsNotification(
|
||||
config = NotificationConfig(
|
||||
title = title,
|
||||
subtitle = subtitle,
|
||||
iconResId = R.drawable.ic_alert_circle_24,
|
||||
onCloseClick = onCloseClick,
|
||||
),
|
||||
) {
|
||||
data class RentInfo(
|
||||
private val rentInfo: CryptoCurrencyWarning.Rent,
|
||||
private val onCloseClick: () -> Unit,
|
||||
) : Informational(
|
||||
title = TextReference.Res(R.string.warning_rent_fee_title),
|
||||
subtitle = TextReference.Res(
|
||||
id = R.string.warning_solana_rent_fee_message,
|
||||
formatArgs = wrappedList(rentInfo.rent, rentInfo.exemptionAmount),
|
||||
),
|
||||
onCloseClick = onCloseClick,
|
||||
)
|
||||
}
|
||||
|
||||
class NetworksNoAccount(val network: String, val symbol: String, val amount: String) : Informational() {
|
||||
override val config = NotificationConfig(
|
||||
data class ExistentialDeposit(
|
||||
private val existentialInfo: CryptoCurrencyWarning.ExistentialDeposit,
|
||||
) : Informational(
|
||||
title = resourceReference(R.string.warning_existential_deposit_title),
|
||||
subtitle = TextReference.Res(
|
||||
id = R.string.warning_existential_deposit_message,
|
||||
formatArgs = wrappedList(existentialInfo.currencyName, existentialInfo.edStringValueWithSymbol),
|
||||
),
|
||||
)
|
||||
|
||||
class NetworksNoAccount(val network: String, val symbol: String, val amount: String) : Informational(
|
||||
title = resourceReference(R.string.warning_no_account_title),
|
||||
subtitle = resourceReference(
|
||||
R.string.no_account_generic,
|
||||
wrappedList(network, amount, symbol),
|
||||
),
|
||||
iconResId = R.drawable.ic_alert_circle_24,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -40,7 +40,7 @@ internal class TokenDetailsLoadedBalanceConverter(
|
|||
return state.copy(
|
||||
tokenBalanceBlockState = TokenDetailsBalanceBlockState.Error(state.tokenBalanceBlockState.actionButtons),
|
||||
marketPriceBlockState = MarketPriceBlockState.Error(state.marketPriceBlockState.currencySymbol),
|
||||
notifications = persistentListOf(TokenDetailsNotification.NetworksUnreachable),
|
||||
notifications = persistentListOf(TokenDetailsNotification.Warning.NetworksUnreachable),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,25 +19,25 @@ internal class TokenDetailsNotificationConverter(
|
|||
|
||||
fun removeRentInfo(currentState: TokenDetailsState): ImmutableList<TokenDetailsNotification> {
|
||||
val newNotifications = currentState.notifications.toMutableList()
|
||||
newNotifications.removeBy { it is TokenDetailsNotification.RentInfo }
|
||||
newNotifications.removeBy { it is TokenDetailsNotification.Informational.RentInfo }
|
||||
return newNotifications.toImmutableList()
|
||||
}
|
||||
|
||||
private fun mapToNotification(warning: CryptoCurrencyWarning): TokenDetailsNotification {
|
||||
return when (warning) {
|
||||
is CryptoCurrencyWarning.BalanceNotEnoughForFee -> TokenDetailsNotification.NetworkFee(
|
||||
is CryptoCurrencyWarning.BalanceNotEnoughForFee -> TokenDetailsNotification.Warning.NetworkFee(
|
||||
feeInfo = warning,
|
||||
onBuyClick = clickIntents::onBuyClick,
|
||||
)
|
||||
is CryptoCurrencyWarning.ExistentialDeposit -> TokenDetailsNotification.ExistentialDeposit(
|
||||
is CryptoCurrencyWarning.ExistentialDeposit -> TokenDetailsNotification.Informational.ExistentialDeposit(
|
||||
existentialInfo = warning,
|
||||
)
|
||||
is CryptoCurrencyWarning.Rent -> TokenDetailsNotification.RentInfo(
|
||||
is CryptoCurrencyWarning.Rent -> TokenDetailsNotification.Informational.RentInfo(
|
||||
rentInfo = warning,
|
||||
onCloseClick = clickIntents::onCloseRentInfoNotification,
|
||||
)
|
||||
CryptoCurrencyWarning.SomeNetworksUnreachable -> TokenDetailsNotification.NetworksUnreachable
|
||||
is CryptoCurrencyWarning.SomeNetworksNoAccount -> TokenDetailsNotification.NetworksNoAccount(
|
||||
CryptoCurrencyWarning.SomeNetworksUnreachable -> TokenDetailsNotification.Warning.NetworksUnreachable
|
||||
is CryptoCurrencyWarning.SomeNetworksNoAccount -> TokenDetailsNotification.Informational.NetworksNoAccount(
|
||||
network = warning.amountCurrency.name,
|
||||
amount = warning.amountToCreateAccount.toString(),
|
||||
symbol = warning.amountCurrency.symbol,
|
||||
|
|
|
|||
|
|
@ -382,7 +382,7 @@ internal object WalletPreviewData {
|
|||
),
|
||||
notifications = persistentListOf(
|
||||
WalletNotification.Critical.DevCard,
|
||||
WalletNotification.MissingAddresses(missingAddressesCount = 0, onGenerateClick = {}),
|
||||
WalletNotification.Informational.MissingAddresses(missingAddressesCount = 0, onGenerateClick = {}),
|
||||
WalletNotification.Warning.NetworksUnreachable,
|
||||
),
|
||||
bottomSheetConfig = bottomSheet,
|
||||
|
|
|
|||
|
|
@ -31,16 +31,6 @@ sealed class WalletNotification(val config: NotificationConfig) {
|
|||
subtitle = resourceReference(id = R.string.warning_developer_card_message),
|
||||
)
|
||||
|
||||
object DemoCard : Critical(
|
||||
title = resourceReference(id = R.string.warning_demo_mode_title),
|
||||
subtitle = resourceReference(id = R.string.warning_demo_mode_message),
|
||||
)
|
||||
|
||||
object TestNetCard : Critical(
|
||||
title = resourceReference(id = R.string.warning_testnet_card_title),
|
||||
subtitle = resourceReference(id = R.string.warning_testnet_card_message),
|
||||
)
|
||||
|
||||
object FailedCardValidation : Critical(
|
||||
title = resourceReference(id = R.string.warning_failed_to_verify_card_title),
|
||||
subtitle = resourceReference(id = R.string.warning_failed_to_verify_card_message),
|
||||
|
|
@ -96,35 +86,53 @@ sealed class WalletNotification(val config: NotificationConfig) {
|
|||
subtitle = resourceReference(id = R.string.warning_number_of_signed_hashes_incorrect_message),
|
||||
onCloseClick = onCloseClick,
|
||||
)
|
||||
|
||||
object TestNetCard : Warning(
|
||||
title = resourceReference(id = R.string.warning_testnet_card_title),
|
||||
subtitle = resourceReference(id = R.string.warning_testnet_card_message),
|
||||
)
|
||||
}
|
||||
|
||||
data class MissingAddresses(val missingAddressesCount: Int, val onGenerateClick: () -> Unit) : WalletNotification(
|
||||
sealed class Informational(
|
||||
title: TextReference,
|
||||
subtitle: TextReference,
|
||||
buttonsState: NotificationConfig.ButtonsState? = null,
|
||||
) : WalletNotification(
|
||||
config = NotificationConfig(
|
||||
title = title,
|
||||
subtitle = subtitle,
|
||||
iconResId = R.drawable.ic_alert_circle_24,
|
||||
buttonsState = buttonsState,
|
||||
),
|
||||
) {
|
||||
|
||||
data class MissingAddresses(val missingAddressesCount: Int, val onGenerateClick: () -> Unit) : Informational(
|
||||
title = resourceReference(id = R.string.warning_missing_derivation_title),
|
||||
subtitle = pluralReference(
|
||||
id = R.plurals.warning_missing_derivation_message,
|
||||
count = missingAddressesCount,
|
||||
formatArgs = wrappedList(missingAddressesCount),
|
||||
),
|
||||
iconResId = R.drawable.ic_alert_circle_24,
|
||||
buttonsState = NotificationConfig.ButtonsState.PrimaryButtonConfig(
|
||||
text = resourceReference(id = R.string.common_generate_addresses),
|
||||
iconResId = R.drawable.ic_tangem_24,
|
||||
onClick = onGenerateClick,
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
data class NoAccount(val network: String, val symbol: String, val amount: String) : WalletNotification(
|
||||
config = NotificationConfig(
|
||||
data class NoAccount(val network: String, val symbol: String, val amount: String) : Informational(
|
||||
title = resourceReference(id = R.string.warning_no_account_title),
|
||||
subtitle = resourceReference(
|
||||
id = R.string.no_account_generic,
|
||||
wrappedList(network, amount, symbol),
|
||||
),
|
||||
iconResId = R.drawable.ic_alert_circle_24,
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
object DemoCard : Informational(
|
||||
title = resourceReference(id = R.string.warning_demo_mode_title),
|
||||
subtitle = resourceReference(id = R.string.warning_demo_mode_message),
|
||||
)
|
||||
}
|
||||
|
||||
data class UnlockWallets(val onClick: () -> Unit) : WalletNotification(
|
||||
config = NotificationConfig(
|
||||
|
|
|
|||
|
|
@ -29,10 +29,9 @@ internal fun LazyListScope.notifications(configs: ImmutableList<WalletNotificati
|
|||
modifier = modifier.animateItemPlacement(),
|
||||
iconTint = when (it) {
|
||||
is WalletNotification.Critical -> TangemTheme.colors.icon.warning
|
||||
is WalletNotification.MissingAddresses -> TangemTheme.colors.icon.accent
|
||||
is WalletNotification.Informational -> TangemTheme.colors.icon.accent
|
||||
is WalletNotification.RateApp -> TangemTheme.colors.icon.attention
|
||||
is WalletNotification.UnlockWallets -> TangemTheme.colors.icon.primary1
|
||||
is WalletNotification.NoAccount -> TangemTheme.colors.icon.accent
|
||||
is WalletNotification.Warning -> null
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -47,11 +47,11 @@ internal class WalletNotificationsListFactory(
|
|||
buildList {
|
||||
addCriticalNotifications(cardTypesResolver)
|
||||
|
||||
addMissingAddressesNotification(cryptoCurrencyList)
|
||||
|
||||
addRateTheAppNotification(isReadyToShowRating)
|
||||
addInformationalNotifications(cardTypesResolver, cryptoCurrencyList)
|
||||
|
||||
addWarningNotifications(cardTypesResolver, cryptoCurrencyList, wasCardScanned, isNeedToBackup)
|
||||
|
||||
addRateTheAppNotification(isReadyToShowRating)
|
||||
}.toImmutableList()
|
||||
}
|
||||
}
|
||||
|
|
@ -62,16 +62,6 @@ internal class WalletNotificationsListFactory(
|
|||
condition = !cardTypesResolver.isReleaseFirmwareType(),
|
||||
)
|
||||
|
||||
addIf(
|
||||
element = WalletNotification.Critical.DemoCard,
|
||||
condition = isDemoCardUseCase(cardId = cardTypesResolver.getCardId()),
|
||||
)
|
||||
|
||||
addIf(
|
||||
element = WalletNotification.Critical.TestNetCard,
|
||||
condition = cardTypesResolver.isTestCard(),
|
||||
)
|
||||
|
||||
addIf(
|
||||
element = WalletNotification.Critical.FailedCardValidation,
|
||||
condition = cardTypesResolver.isReleaseFirmwareType() && cardTypesResolver.isAttestationFailed(),
|
||||
|
|
@ -85,28 +75,6 @@ internal class WalletNotificationsListFactory(
|
|||
}
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotification>.addMissingAddressesNotification(
|
||||
cryptoCurrencyList: List<CryptoCurrencyStatus>,
|
||||
) {
|
||||
val missedAddressCurrencies = cryptoCurrencyList.getMissedAddressCurrencies()
|
||||
|
||||
addIf(
|
||||
element = WalletNotification.MissingAddresses(
|
||||
missingAddressesCount = missedAddressCurrencies.count(),
|
||||
onGenerateClick = {
|
||||
clickIntents.onGenerateMissedAddressesClick(missedAddressCurrencies = missedAddressCurrencies)
|
||||
},
|
||||
),
|
||||
condition = missedAddressCurrencies.isNotEmpty(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun List<CryptoCurrencyStatus>.getMissedAddressCurrencies(): List<CryptoCurrency> {
|
||||
return this
|
||||
.filter { it.value is CryptoCurrencyStatus.MissedDerivation }
|
||||
.map(CryptoCurrencyStatus::currency)
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotification>.addRateTheAppNotification(isReadyToShowRating: Boolean) {
|
||||
addIf(
|
||||
element = WalletNotification.RateApp(
|
||||
|
|
@ -131,6 +99,11 @@ internal class WalletNotificationsListFactory(
|
|||
condition = isNeedToBackup,
|
||||
)
|
||||
|
||||
addIf(
|
||||
element = WalletNotification.Warning.TestNetCard,
|
||||
condition = cardTypesResolver.isTestCard(),
|
||||
)
|
||||
|
||||
val isDemo = isDemoCardUseCase(cardId = cardTypesResolver.getCardId())
|
||||
if (cardTypesResolver.isMultiwalletAllowed()) {
|
||||
addIf(
|
||||
|
|
@ -158,10 +131,44 @@ internal class WalletNotificationsListFactory(
|
|||
}
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotification>.addInformationalNotifications(
|
||||
cardTypesResolver: CardTypesResolver,
|
||||
cryptoCurrencyList: List<CryptoCurrencyStatus>,
|
||||
) {
|
||||
addIf(
|
||||
element = WalletNotification.Informational.DemoCard,
|
||||
condition = isDemoCardUseCase(cardId = cardTypesResolver.getCardId()),
|
||||
)
|
||||
|
||||
addMissingAddressesNotification(cryptoCurrencyList)
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotification>.addIf(element: WalletNotification, condition: Boolean) {
|
||||
if (condition) add(element = element)
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotification>.addMissingAddressesNotification(
|
||||
cryptoCurrencyList: List<CryptoCurrencyStatus>,
|
||||
) {
|
||||
val missedAddressCurrencies = cryptoCurrencyList.getMissedAddressCurrencies()
|
||||
|
||||
addIf(
|
||||
element = WalletNotification.Informational.MissingAddresses(
|
||||
missingAddressesCount = missedAddressCurrencies.count(),
|
||||
onGenerateClick = {
|
||||
clickIntents.onGenerateMissedAddressesClick(missedAddressCurrencies = missedAddressCurrencies)
|
||||
},
|
||||
),
|
||||
condition = missedAddressCurrencies.isNotEmpty(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun List<CryptoCurrencyStatus>.getMissedAddressCurrencies(): List<CryptoCurrency> {
|
||||
return this
|
||||
.filter { it.value is CryptoCurrencyStatus.MissedDerivation }
|
||||
.map(CryptoCurrencyStatus::currency)
|
||||
}
|
||||
|
||||
private fun List<CryptoCurrencyStatus>.hasUnreachableNetworks(): Boolean {
|
||||
return any { it.value is CryptoCurrencyStatus.Unreachable }
|
||||
}
|
||||
|
|
@ -172,7 +179,7 @@ internal class WalletNotificationsListFactory(
|
|||
val amountToCreateAccount = (noAccountNetwork.value as? CryptoCurrencyStatus.NoAccount)
|
||||
?.amountToCreateAccount.toString()
|
||||
add(
|
||||
element = WalletNotification.NoAccount(
|
||||
element = WalletNotification.Informational.NoAccount(
|
||||
network = noAccountNetwork.currency.name,
|
||||
amount = amountToCreateAccount,
|
||||
symbol = noAccountNetwork.currency.symbol,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue