Updated on 2026-08-14
This commit is contained in:
parent
2cd0164d1d
commit
5016ee56ea
10 changed files with 1798 additions and 1560 deletions
|
|
@ -1,38 +1,43 @@
|
|||
package com.tangem.feature.tokendetails.presentation.tokendetails.state.components
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import com.tangem.core.ui.components.currency.tokenicon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.core.ui.components.notifications.CurrencyNotificationConfig
|
||||
import com.tangem.core.ui.components.notifications.NotificationConfig
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.features.tokendetails.impl.R
|
||||
|
||||
@Immutable
|
||||
internal sealed class ExchangeStatusNotifications(val config: NotificationConfig) {
|
||||
internal sealed interface ExchangeStatusNotifications {
|
||||
|
||||
data class NeedVerification(
|
||||
val onGoToProviderClick: () -> Unit,
|
||||
) : ExchangeStatusNotifications(
|
||||
sealed class CommonNotification(val config: NotificationConfig) : ExchangeStatusNotifications
|
||||
|
||||
data class NeedVerification(val onGoToProviderClick: () -> Unit) : CommonNotification(
|
||||
config = NotificationConfig(
|
||||
title = TextReference.Res(R.string.express_exchange_notification_verification_title),
|
||||
subtitle = TextReference.Res(R.string.express_exchange_notification_verification_text),
|
||||
title = resourceReference(R.string.express_exchange_notification_verification_title),
|
||||
subtitle = resourceReference(R.string.express_exchange_notification_verification_text),
|
||||
iconResId = R.drawable.ic_alert_triangle_20,
|
||||
buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
|
||||
text = TextReference.Res(R.string.common_go_to_provider),
|
||||
text = resourceReference(R.string.common_go_to_provider),
|
||||
onClick = onGoToProviderClick,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
data class Failed(
|
||||
val onGoToProviderClick: () -> Unit,
|
||||
) : ExchangeStatusNotifications(
|
||||
data class Failed(val onGoToProviderClick: () -> Unit) : CommonNotification(
|
||||
config = NotificationConfig(
|
||||
title = TextReference.Res(R.string.express_exchange_notification_failed_title),
|
||||
subtitle = TextReference.Res(R.string.express_exchange_notification_failed_text),
|
||||
title = resourceReference(R.string.express_exchange_notification_failed_title),
|
||||
subtitle = resourceReference(R.string.express_exchange_notification_failed_text),
|
||||
iconResId = R.drawable.ic_alert_circle_24,
|
||||
buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
|
||||
text = TextReference.Res(R.string.common_go_to_provider),
|
||||
text = resourceReference(R.string.common_go_to_provider),
|
||||
onClick = onGoToProviderClick,
|
||||
),
|
||||
),
|
||||
|
|
@ -40,16 +45,48 @@ internal sealed class ExchangeStatusNotifications(val config: NotificationConfig
|
|||
|
||||
data class TokenRefunded(
|
||||
val cryptoCurrency: CryptoCurrency,
|
||||
val onReadMoreClick: () -> Unit,
|
||||
val onGoToTokenClick: () -> Unit,
|
||||
) : ExchangeStatusNotifications(
|
||||
config = NotificationConfig(
|
||||
title = stringReference("TITLE FOR TOKEN REFUND"),
|
||||
subtitle = stringReference("SUBTITLE FOR TOKEN REFUND"),
|
||||
iconResId = R.drawable.ic_alert_triangle_20,
|
||||
) : ExchangeStatusNotifications {
|
||||
|
||||
val config = CurrencyNotificationConfig(
|
||||
title = resourceReference(
|
||||
id = R.string.express_exchange_notification_refund_title,
|
||||
formatArgs = wrappedList(cryptoCurrency.symbol, cryptoCurrency.network.name),
|
||||
),
|
||||
subtitle = CurrencyNotificationConfig.AnnotatedSubtitle(
|
||||
valueProvider = {
|
||||
val linkText = stringResource(R.string.common_read_more)
|
||||
val fullString = stringResource(
|
||||
R.string.express_exchange_notification_refund_text,
|
||||
cryptoCurrency.symbol,
|
||||
linkText,
|
||||
)
|
||||
|
||||
val linkTextPosition = fullString.length - linkText.length
|
||||
|
||||
buildAnnotatedString {
|
||||
withStyle(SpanStyle(TangemTheme.colors.text.tertiary)) {
|
||||
append(fullString.substring(0, linkTextPosition))
|
||||
}
|
||||
|
||||
withStyle(SpanStyle(TangemTheme.colors.text.accent)) {
|
||||
append(fullString.substring(linkTextPosition, fullString.length))
|
||||
}
|
||||
}
|
||||
},
|
||||
onClick = { value, position ->
|
||||
val readMoreStyle = requireNotNull(value.spanStyles.getOrNull(1))
|
||||
if (position in readMoreStyle.start..readMoreStyle.end) {
|
||||
onReadMoreClick()
|
||||
}
|
||||
},
|
||||
),
|
||||
tokenIconState = CryptoCurrencyToIconStateConverter().convert(cryptoCurrency),
|
||||
buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
|
||||
text = stringReference("Go to token"),
|
||||
text = resourceReference(R.string.common_go_to_token),
|
||||
onClick = onGoToTokenClick,
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -25,6 +25,7 @@ import kotlinx.collections.immutable.PersistentList
|
|||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import java.math.BigDecimal
|
||||
import java.util.Locale
|
||||
|
||||
internal class TokenDetailsSwapTransactionsStateConverter(
|
||||
private val clickIntents: TokenDetailsClickIntents,
|
||||
|
|
@ -163,9 +164,11 @@ internal class TokenDetailsSwapTransactionsStateConverter(
|
|||
if (refundToken == null) {
|
||||
null
|
||||
} else {
|
||||
ExchangeStatusNotifications.TokenRefunded(refundToken) {
|
||||
clickIntents.onGoToRefundedTokenClick(refundToken)
|
||||
}
|
||||
ExchangeStatusNotifications.TokenRefunded(
|
||||
cryptoCurrency = refundToken,
|
||||
onReadMoreClick = { clickIntents.onOpenUrlClick(url = getAboutCrossChainBridgesLink()) },
|
||||
onGoToTokenClick = { clickIntents.onGoToRefundedTokenClick(refundToken) },
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
|
|
@ -316,4 +319,12 @@ internal class TokenDetailsSwapTransactionsStateConverter(
|
|||
isDone = isSendingDone,
|
||||
)
|
||||
}
|
||||
|
||||
private fun getAboutCrossChainBridgesLink(): String {
|
||||
return if (Locale.getDefault().country == "RU") {
|
||||
"https://tangem.com/ru/blog/post/an-overview-of-cross-chain-bridges/"
|
||||
} else {
|
||||
"https://tangem.com/en/blog/post/an-overview-of-cross-chain-bridges/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,11 +17,12 @@ import com.tangem.core.ui.components.SpacerH24
|
|||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.core.ui.components.notifications.CurrencyNotification
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.swap.domain.models.domain.ExchangeStatus
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.SwapTransactionsState
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.ExchangeStatusNotifications
|
||||
|
||||
@Composable
|
||||
internal fun ExchangeStatusBottomSheet(config: TangemBottomSheetConfig) {
|
||||
|
|
@ -29,16 +30,13 @@ internal fun ExchangeStatusBottomSheet(config: TangemBottomSheetConfig) {
|
|||
config = config,
|
||||
containerColor = TangemTheme.colors.background.tertiary,
|
||||
) { content: ExchangeStatusBottomSheetConfig ->
|
||||
ExchangeStatusBottomSheetContent(content = content)
|
||||
ExchangeStatusBottomSheetContent(config = content.value)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ExchangeStatusBottomSheetContent(content: ExchangeStatusBottomSheetConfig) {
|
||||
val config = content.value
|
||||
Column(
|
||||
modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing16),
|
||||
) {
|
||||
private fun ExchangeStatusBottomSheetContent(config: SwapTransactionsState) {
|
||||
Column(modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing16)) {
|
||||
SpacerH10()
|
||||
Text(
|
||||
text = stringResource(id = R.string.express_exchange_status_title),
|
||||
|
|
@ -80,25 +78,39 @@ private fun ExchangeStatusBottomSheetContent(content: ExchangeStatusBottomSheetC
|
|||
showLink = config.showProviderLink,
|
||||
onClick = { config.onGoToProviderClick(config.txUrl.orEmpty()) },
|
||||
)
|
||||
AnimatedContent(
|
||||
targetState = config.notification,
|
||||
label = "Exchange Status Notification Change",
|
||||
) {
|
||||
it?.let {
|
||||
val tint = when (config.activeStatus) {
|
||||
ExchangeStatus.Verifying -> TangemTheme.colors.icon.attention
|
||||
ExchangeStatus.Failed -> TangemTheme.colors.icon.warning
|
||||
else -> null
|
||||
}
|
||||
Notification(
|
||||
config = it.config,
|
||||
iconTint = tint,
|
||||
if (config.notification != null) {
|
||||
Notification(state = config.notification, activeStatus = config.activeStatus)
|
||||
}
|
||||
SpacerH24()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Notification(state: ExchangeStatusNotifications, activeStatus: ExchangeStatus?) {
|
||||
AnimatedContent(
|
||||
targetState = state,
|
||||
modifier = Modifier.padding(top = TangemTheme.dimens.spacing12),
|
||||
label = "Exchange Status Notification Change",
|
||||
) { notification ->
|
||||
when (notification) {
|
||||
is ExchangeStatusNotifications.CommonNotification -> {
|
||||
com.tangem.core.ui.components.notifications.Notification(
|
||||
config = notification.config,
|
||||
iconTint = when (activeStatus) {
|
||||
ExchangeStatus.Verifying -> TangemTheme.colors.icon.attention
|
||||
ExchangeStatus.Failed -> TangemTheme.colors.icon.warning
|
||||
else -> null
|
||||
},
|
||||
containerColor = TangemTheme.colors.background.action,
|
||||
)
|
||||
}
|
||||
is ExchangeStatusNotifications.TokenRefunded -> {
|
||||
CurrencyNotification(
|
||||
config = notification.config,
|
||||
containerColor = TangemTheme.colors.background.action,
|
||||
modifier = Modifier.padding(top = TangemTheme.dimens.spacing12),
|
||||
)
|
||||
}
|
||||
}
|
||||
SpacerH24()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,4 +57,6 @@ interface TokenDetailsClickIntents {
|
|||
fun onAssociateClick()
|
||||
|
||||
fun onGoToRefundedTokenClick(cryptoCurrency: CryptoCurrency)
|
||||
|
||||
fun onOpenUrlClick(url: String)
|
||||
}
|
||||
|
|
@ -726,6 +726,10 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
router.openTokenDetails(userWalletId, cryptoCurrency)
|
||||
}
|
||||
|
||||
override fun onOpenUrlClick(url: String) {
|
||||
router.openUrl(url)
|
||||
}
|
||||
|
||||
override fun onSwapPromoDismiss() {
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
shouldShowSwapPromoTokenUseCase.neverToShow()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue