Updated on 2026-08-14

This commit is contained in:
Tangem 2026-02-03 18:37:15 +05:00
parent 03c65b35cf
commit 931cb4d20b
9 changed files with 161 additions and 390 deletions

View file

@ -7,6 +7,7 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.domain.models.account.Account
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
@ -100,6 +101,7 @@ internal class WalletContentClickIntentsImplementor @Inject constructor(
private val accountDependencies: AccountDependencies,
private val yieldSupplySetShouldShowMainPromoUseCase: YieldSupplySetShouldShowMainPromoUseCase,
private val tokenListAnalyticsSender: TokenListAnalyticsSender,
private val uiMessageSender: UiMessageSender,
) : BaseWalletClickIntents(), WalletContentClickIntents {
override fun onDetailsClick() {
@ -311,15 +313,12 @@ internal class WalletContentClickIntentsImplementor @Inject constructor(
}
override fun onConfirmDisposeExpressStatus() {
walletEventSender.send(
WalletEvent.ShowAlert(
WalletAlertState.ConfirmExpressStatusHide(
onConfirmClick = {
walletEventSender.onConsume()
onDisposeExpressStatus()
},
onCancelClick = walletEventSender::onConsume,
),
uiMessageSender.send(
WalletAlertUM.confirmExpressStatusHide(
onConfirmClick = {
walletEventSender.onConsume()
onDisposeExpressStatus()
},
),
)
}

View file

@ -12,13 +12,14 @@ import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.ui.clipboard.ClipboardManager
import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.WrappedList
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.haptic.TangemHapticEffect
import com.tangem.core.ui.haptic.VibratorHapticManager
import com.tangem.core.ui.message.DialogMessage
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase
import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase
@ -56,7 +57,7 @@ import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.wallet.domain.unwrap
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAlertState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAlertUM
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletEvent
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTokensListState
@ -150,6 +151,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
private val accountsFeatureToggles: AccountsFeatureToggles,
private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase,
private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase,
private val uiMessageSender: UiMessageSender,
) : BaseWalletClickIntents(), WalletCurrencyActionsClickIntents {
override fun onSendClick(
@ -269,48 +271,19 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
)
modelScope.launch(dispatchers.main) {
walletEventSender.send(
event = WalletEvent.ShowAlert(
state = getHideTokeAlertConfig(userWalletId, cryptoCurrencyStatus),
),
)
}
}
val currency = cryptoCurrencyStatus.currency
val isCryptoCurrencyCoinCouldHide = currency is CryptoCurrency.Coin &&
!isCryptoCurrencyCoinCouldHide(userWalletId = userWalletId, cryptoCurrencyCoin = currency)
private suspend fun getHideTokeAlertConfig(
userWalletId: UserWalletId,
cryptoCurrencyStatus: CryptoCurrencyStatus,
): WalletAlertState.DefaultAlert {
val currency = cryptoCurrencyStatus.currency
val isCryptoCurrencyCoinCouldHide = currency is CryptoCurrency.Coin &&
!isCryptoCurrencyCoinCouldHide(userWalletId = userWalletId, cryptoCurrencyCoin = currency)
return if (isCryptoCurrencyCoinCouldHide) {
WalletAlertState.DefaultAlert(
title = resourceReference(
id = R.string.token_details_unable_hide_alert_title,
formatArgs = WrappedList(listOf(cryptoCurrencyStatus.currency.name)),
),
message = resourceReference(
id = R.string.token_details_unable_hide_alert_message,
formatArgs = WrappedList(
listOf(
cryptoCurrencyStatus.currency.name,
cryptoCurrencyStatus.currency.symbol,
cryptoCurrencyStatus.currency.network.name,
),
),
),
onConfirmClick = null,
)
} else {
WalletAlertState.DefaultAlert(
title = resourceReference(
id = R.string.token_details_hide_alert_title,
formatArgs = WrappedList(listOf(cryptoCurrencyStatus.currency.name)),
),
message = resourceReference(R.string.token_details_hide_alert_message),
onConfirmClick = { onPerformHideToken(userWalletId, cryptoCurrencyStatus) },
)
if (isCryptoCurrencyCoinCouldHide) {
uiMessageSender.send(WalletAlertUM.unableHideToken(cryptoCurrency = cryptoCurrencyStatus.currency))
} else {
uiMessageSender.send(
WalletAlertUM.hideTokenConfirm(cryptoCurrency = cryptoCurrencyStatus.currency) {
onPerformHideToken(userWalletId, cryptoCurrencyStatus)
},
)
}
}
}
@ -618,17 +591,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
private fun handleUnavailabilityReason(unavailabilityReason: ScenarioUnavailabilityReason): Boolean {
if (unavailabilityReason == ScenarioUnavailabilityReason.None) return false
modelScope.launch(dispatchers.main) {
walletEventSender.send(
event = WalletEvent.ShowAlert(
state = WalletAlertState.DefaultAlert(
title = null,
message = unavailabilityReason.getUnavailabilityReasonText(),
onConfirmClick = null,
),
),
)
}
uiMessageSender.send(DialogMessage(message = unavailabilityReason.getUnavailabilityReasonText()))
return true
}
@ -641,7 +604,10 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
modelScope.launch {
statusFlow.foldStatus(
onContent = { handleContent(route, eventCreator) },
onError = { handleError(eventCreator = eventCreator) },
onError = {
analyticsEventHandler.send(event = eventCreator(AnalyticsParam.Status.Error))
uiMessageSender.send(WalletAlertUM.unavailableOperation())
},
onLoading = { handleLoading(eventCreator) },
)
}
@ -667,21 +633,10 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
appRouter.push(route = route)
}
private fun handleError(
alertState: WalletAlertState = WalletAlertState.UnavailableOperation,
eventCreator: (AnalyticsParam.Status) -> MainScreenAnalyticsEvent,
) {
analyticsEventHandler.send(event = eventCreator(AnalyticsParam.Status.Error))
walletEventSender.send(event = WalletEvent.ShowAlert(state = alertState))
}
private fun handleLoading(eventCreator: (AnalyticsParam.Status) -> MainScreenAnalyticsEvent) {
analyticsEventHandler.send(event = eventCreator(AnalyticsParam.Status.Pending))
walletEventSender.send(
event = WalletEvent.ShowAlert(state = WalletAlertState.ProvidersStillLoading),
)
uiMessageSender.send(WalletAlertUM.providersStillLoading())
}
private suspend fun getSwapRoute(targetRoute: AppRoute): AppRoute {
@ -743,12 +698,8 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
private fun checkSwapCryptoAvailability(tokenCount: Int) {
if (tokenCount < 2) {
handleError(
alertState = WalletAlertState.InsufficientTokensCountForSwapping,
eventCreator = MainScreenAnalyticsEvent::ButtonSwap,
)
return
analyticsEventHandler.send(event = MainScreenAnalyticsEvent.ButtonSwap(AnalyticsParam.Status.Error))
uiMessageSender.send(WalletAlertUM.insufficientTokensCountForSwapping())
}
}
}

View file

@ -11,7 +11,7 @@ import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.navigation.url.UrlOpener
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.navigation.review.ReviewManager
import com.tangem.domain.card.SetCardWasScannedUseCase
import com.tangem.domain.common.wallets.UserWalletsListRepository
import com.tangem.domain.feedback.GetWalletMetaInfoUseCase
@ -38,14 +38,11 @@ import com.tangem.domain.tokens.model.analytics.PromoAnalyticsEvent.Program
import com.tangem.domain.tokens.model.analytics.PromoAnalyticsEvent.PromotionBannerClicked
import com.tangem.domain.tokens.model.details.NavigationAction
import com.tangem.domain.wallets.usecase.*
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.Basic
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.MainScreen
import com.tangem.feature.wallet.presentation.wallet.domain.ScanCardToUnlockWalletClickHandler
import com.tangem.feature.wallet.presentation.wallet.domain.ScanCardToUnlockWalletError
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAlertState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAlertUM
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletEvent
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSender
import com.tangem.features.pushnotifications.api.analytics.PushNotificationAnalyticEvents
@ -70,8 +67,6 @@ internal interface WalletWarningsClickIntents {
fun onOpenUnlockWalletsBottomSheetClick()
fun onUnlockVisaAccessClick()
fun onLikeAppClick()
fun onDislikeAppClick()
@ -113,7 +108,6 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
private val neverToSuggestRateAppUseCase: NeverToSuggestRateAppUseCase,
private val remindToRateAppLaterUseCase: RemindToRateAppLaterUseCase,
private val getUserWalletUseCase: GetUserWalletUseCase,
private val scanCardToUnlockWalletClickHandler: ScanCardToUnlockWalletClickHandler,
private val nonBiometricUnlockWalletUseCase: NonBiometricUnlockWalletUseCase,
private val analyticsEventHandler: AnalyticsEventHandler,
private val dispatchers: CoroutineDispatcherProvider,
@ -133,6 +127,7 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
private val setNotificationsEnabledUseCase: SetNotificationsEnabledUseCase,
private val getWalletsListForEnablingUseCase: GetWalletsForAutomaticallyPushEnablingUseCase,
private val uiMessageSender: UiMessageSender,
private val reviewManager: ReviewManager,
) : BaseWalletClickIntents(), WalletWarningsClickIntents {
override fun onAddBackupCardClick() {
@ -212,38 +207,14 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
}
}
override fun onUnlockVisaAccessClick() {
openScanCardDialog()
}
private fun openScanCardDialog() {
modelScope.launch(dispatchers.main) {
scanCardToUnlockWalletClickHandler(walletId = stateHolder.getSelectedWalletId())
.onLeft { error ->
when (error) {
ScanCardToUnlockWalletError.WrongCardIsScanned -> {
walletEventSender.send(
event = WalletEvent.ShowAlert(WalletAlertState.WrongCardIsScanned),
)
}
ScanCardToUnlockWalletError.ManyScanFails -> router.openScanFailedDialog(::openScanCardDialog)
}
}
}
}
override fun onLikeAppClick() {
analyticsEventHandler.send(MainScreen.NoticeRateAppButton(AnalyticsParam.RateApp.Liked))
walletEventSender.send(
event = WalletEvent.RateApp(
onDismissClick = {
modelScope.launch(dispatchers.main) {
neverToSuggestRateAppUseCase()
}
},
),
)
reviewManager.request {
modelScope.launch(dispatchers.main) {
neverToSuggestRateAppUseCase()
}
}
}
override fun onDislikeAppClick() {
@ -293,7 +264,6 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
action = PromotionBannerClicked.BannerAction.Closed(),
)
},
)
modelScope.launch(dispatchers.main) {
shouldShowPromoWalletUseCase.neverToShow(promoId)
@ -374,21 +344,16 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
analyticsEventHandler.send(MainScreen.NoticeSeedPhraseSupportButtonYes())
walletEventSender.send(
event = WalletEvent.ShowAlert(
state = WalletAlertState.SimpleOkAlert(
message = resourceReference(R.string.warning_seedphrase_issue_answer_yes),
onOkClick = {
modelScope.launch {
seedPhraseNotificationUseCase.confirm(userWalletId = userWallet.walletId)
uiMessageSender.send(
WalletAlertUM.seedPhraseConfirm {
modelScope.launch {
seedPhraseNotificationUseCase.confirm(userWalletId = userWallet.walletId)
urlOpener.openUrl(
url = TangemBlogUrlBuilder.build(post = TangemBlogUrlBuilder.Post.SeedNotify),
)
}
},
),
),
urlOpener.openUrl(
url = TangemBlogUrlBuilder.build(post = TangemBlogUrlBuilder.Post.SeedNotify),
)
}
},
)
}
@ -397,17 +362,12 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
analyticsEventHandler.send(MainScreen.NoticeSeedPhraseSupportButtonNo())
walletEventSender.send(
event = WalletEvent.ShowAlert(
state = WalletAlertState.SimpleOkAlert(
message = resourceReference(R.string.warning_seedphrase_issue_answer_no),
onOkClick = {
modelScope.launch {
seedPhraseNotificationUseCase.decline(userWalletId = userWallet.walletId)
}
},
),
),
uiMessageSender.send(
WalletAlertUM.seedPhraseDismiss {
modelScope.launch {
seedPhraseNotificationUseCase.decline(userWalletId = userWallet.walletId)
}
},
)
}
@ -416,21 +376,16 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
analyticsEventHandler.send(MainScreen.NoticeSeedPhraseSupportButtonUsed())
walletEventSender.send(
event = WalletEvent.ShowAlert(
state = WalletAlertState.SimpleOkAlert(
message = resourceReference(R.string.warning_seedphrase_issue_answer_yes),
onOkClick = {
modelScope.launch {
seedPhraseNotificationUseCase.acceptSecond(userWalletId = userWallet.walletId)
uiMessageSender.send(
WalletAlertUM.seedPhraseConfirm {
modelScope.launch {
seedPhraseNotificationUseCase.acceptSecond(userWalletId = userWallet.walletId)
urlOpener.openUrl(
url = TangemBlogUrlBuilder.build(post = TangemBlogUrlBuilder.Post.SeedNotifySecond),
)
}
},
),
),
urlOpener.openUrl(
url = TangemBlogUrlBuilder.build(post = TangemBlogUrlBuilder.Post.SeedNotifySecond),
)
}
},
)
}

View file

@ -1,106 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.state.model
import androidx.compose.runtime.Immutable
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.feature.wallet.impl.R
@Immutable
internal sealed interface WalletAlertState {
@Immutable
sealed class Basic : WalletAlertState {
abstract val title: TextReference?
abstract val message: TextReference
open val confirmButtonText: TextReference = resourceReference(id = R.string.common_ok)
open val isWarningConfirmButton: Boolean = false
abstract val onConfirmClick: (() -> Unit)?
open val cancelButtonText: TextReference? = null
open val onCancelClick: (() -> Unit)? = null
}
@Immutable
sealed class TextInput : WalletAlertState {
abstract val title: TextReference
abstract val label: TextReference
open val text: String = ""
open val confirmButtonText: TextReference = resourceReference(id = R.string.common_ok)
abstract val onConfirmClick: (String) -> Unit
abstract val errorTextProvider: (String) -> TextReference?
}
data class SimpleOkAlert(val message: TextReference, val onOkClick: () -> Unit) : WalletAlertState
data class DefaultAlert(
override val title: TextReference?,
override val message: TextReference,
override val onConfirmClick: (() -> Unit)?,
) : Basic()
data class VisaLimitsInfo(
val totalLimit: String,
val otherLimit: String,
) : Basic() {
override val title: TextReference? = null
override val message: TextReference = stringReference(
value = "Limits are needed to control costs, improve security, manage risk. " +
"You can spend $totalLimit during the week for card payments in shops and " +
"$otherLimit for other transactions, e. g. subscriptions or debts.",
)
override val onConfirmClick: (() -> Unit)? = null
}
data object WrongCardIsScanned : Basic() {
override val title: TextReference = resourceReference(R.string.common_warning)
override val message: TextReference = resourceReference(R.string.error_wrong_wallet_tapped)
override val onConfirmClick: (() -> Unit)? = null
}
data object RescanWallets : Basic() {
override val title: TextReference = resourceReference(R.string.common_attention)
override val message: TextReference = resourceReference(R.string.key_invalidated_warning_description)
override val onConfirmClick: (() -> Unit)? = null
}
data object VisaBalancesInfo : Basic() {
override val title: TextReference? = null
override val message: TextReference = stringReference(
value = "Available balance is actual funds available, considering pending transactions, " +
"blocked amounts, and debit balance to prevent overdrafts.",
)
override val onConfirmClick: (() -> Unit)? = null
}
data object ProvidersStillLoading : Basic() {
override val title: TextReference = resourceReference(R.string.action_buttons_service_loading_alert_title)
override val message: TextReference = resourceReference(R.string.action_buttons_service_loading_alert_message)
override val onConfirmClick: (() -> Unit)? = null
}
data object UnavailableOperation : Basic() {
override val title: TextReference = resourceReference(R.string.action_buttons_something_wrong_alert_title)
override val message: TextReference = resourceReference(R.string.action_buttons_something_wrong_alert_message)
override val onConfirmClick: (() -> Unit)? = null
}
data object InsufficientTokensCountForSwapping : Basic() {
override val title: TextReference =
resourceReference(id = R.string.action_buttons_swap_no_tokens_added_alert_title)
override val message: TextReference =
resourceReference(id = R.string.action_buttons_swap_no_tokens_added_alert_message)
override val onConfirmClick: (() -> Unit)? = null
}
data class ConfirmExpressStatusHide(
override val onConfirmClick: (() -> Unit),
override val onCancelClick: (() -> Unit),
) : Basic() {
override val title: TextReference = resourceReference(R.string.express_status_hide_dialog_title)
override val message: TextReference = resourceReference(R.string.express_status_hide_dialog_text)
override val confirmButtonText: TextReference = resourceReference(R.string.common_hide)
override val cancelButtonText: TextReference = resourceReference(R.string.common_cancel)
}
}

View file

@ -0,0 +1,96 @@
package com.tangem.feature.wallet.presentation.wallet.state.model
import com.tangem.core.ui.extensions.WrappedList
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.message.DialogMessage
import com.tangem.core.ui.message.EventMessageAction
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.feature.wallet.impl.R
internal object WalletAlertUM {
fun seedPhraseConfirm(onClick: () -> Unit): DialogMessage {
return DialogMessage(
message = resourceReference(R.string.warning_seedphrase_issue_answer_yes),
firstActionBuilder = {
okAction(onClick = onClick)
},
)
}
fun seedPhraseDismiss(onClick: () -> Unit): DialogMessage {
return DialogMessage(
message = resourceReference(R.string.warning_seedphrase_issue_answer_no),
firstActionBuilder = {
okAction(onClick = onClick)
},
)
}
fun unableHideToken(cryptoCurrency: CryptoCurrency): DialogMessage {
return DialogMessage(
title = resourceReference(
id = R.string.token_details_unable_hide_alert_title,
formatArgs = WrappedList(listOf(cryptoCurrency.name)),
),
message = resourceReference(
id = R.string.token_details_unable_hide_alert_message,
formatArgs = WrappedList(
listOf(
cryptoCurrency.name,
cryptoCurrency.symbol,
cryptoCurrency.network.name,
),
),
),
)
}
fun hideTokenConfirm(cryptoCurrency: CryptoCurrency, onClick: () -> Unit): DialogMessage {
return DialogMessage(
title = resourceReference(
id = R.string.token_details_hide_alert_title,
formatArgs = WrappedList(listOf(cryptoCurrency.name)),
),
message = resourceReference(R.string.token_details_hide_alert_message),
firstActionBuilder = {
okAction(onClick)
},
)
}
fun providersStillLoading(): DialogMessage {
return DialogMessage(
title = resourceReference(R.string.action_buttons_service_loading_alert_title),
message = resourceReference(R.string.action_buttons_service_loading_alert_message),
)
}
fun unavailableOperation(): DialogMessage {
return DialogMessage(
title = resourceReference(R.string.action_buttons_something_wrong_alert_title),
message = resourceReference(R.string.action_buttons_something_wrong_alert_message),
)
}
fun insufficientTokensCountForSwapping(): DialogMessage {
return DialogMessage(
title = resourceReference(R.string.action_buttons_swap_no_tokens_added_alert_title),
message = resourceReference(R.string.action_buttons_swap_no_tokens_added_alert_message),
)
}
fun confirmExpressStatusHide(onConfirmClick: () -> Unit): DialogMessage {
return DialogMessage(
title = resourceReference(R.string.express_status_hide_dialog_title),
message = resourceReference(R.string.express_status_hide_dialog_text),
firstActionBuilder = {
EventMessageAction(
title = resourceReference(R.string.common_hide),
onClick = onConfirmClick,
)
},
secondActionBuilder = { cancelAction() },
)
}
}

View file

@ -13,12 +13,8 @@ internal sealed class WalletEvent {
data class ShowError(val text: TextReference) : WalletEvent()
data class ShowAlert(val state: WalletAlertState) : WalletEvent()
data object CopyAddress : WalletEvent()
data class RateApp(val onDismissClick: () -> Unit) : WalletEvent()
data class DemonstrateWalletsScrollPreview(val direction: Direction) : WalletEvent() {
enum class Direction {

View file

@ -1,98 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.ui
import androidx.compose.runtime.*
import androidx.compose.ui.text.input.TextFieldValue
import com.tangem.core.ui.components.AdditionalTextInputDialogUM
import com.tangem.core.ui.components.BasicDialog
import com.tangem.core.ui.components.DialogButtonUM
import com.tangem.core.ui.components.TextInputDialog
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAlertState
@Composable
internal fun WalletAlert(state: WalletAlertState, onDismiss: () -> Unit) {
when (state) {
is WalletAlertState.Basic -> BasicAlert(state, onDismiss)
is WalletAlertState.TextInput -> TextInputAlert(state, onDismiss)
is WalletAlertState.SimpleOkAlert -> {
BasicDialog(
message = state.message.resolveReference(),
confirmButton = DialogButtonUM(
onClick = {
state.onOkClick()
onDismiss()
},
),
onDismissDialog = onDismiss,
isDismissable = false,
)
}
}
}
@Composable
private fun BasicAlert(state: WalletAlertState.Basic, onDismiss: () -> Unit) {
val confirmButton: DialogButtonUM
val dismissButton: DialogButtonUM?
val onActionClick = state.onConfirmClick
if (onActionClick != null) {
confirmButton = DialogButtonUM(
title = state.confirmButtonText.resolveReference(),
isWarning = state.isWarningConfirmButton,
onClick = {
onActionClick()
onDismiss()
},
)
dismissButton = DialogButtonUM(
title = stringResourceSafe(id = R.string.common_cancel),
onClick = onDismiss,
)
} else {
confirmButton = DialogButtonUM(
title = state.confirmButtonText.resolveReference(),
isWarning = state.isWarningConfirmButton,
onClick = onDismiss,
)
dismissButton = null
}
BasicDialog(
message = state.message.resolveReference(),
confirmButton = confirmButton,
onDismissDialog = onDismiss,
title = state.title?.resolveReference(),
dismissButton = dismissButton,
)
}
@Composable
private fun TextInputAlert(state: WalletAlertState.TextInput, onDismiss: () -> Unit) {
var value by remember { mutableStateOf(TextFieldValue(text = state.text)) }
TextInputDialog(
fieldValue = value,
confirmButton = DialogButtonUM(
title = state.confirmButtonText.resolveReference(),
isEnabled = value.text.isNotEmpty() &&
value.text != state.text &&
state.errorTextProvider(value.text) == null,
onClick = {
state.onConfirmClick(value.text)
onDismiss()
},
),
onDismissDialog = onDismiss,
onValueChange = { value = it },
title = state.title.resolveReference(),
dismissButton = DialogButtonUM(title = stringResourceSafe(id = R.string.common_cancel), onClick = onDismiss),
textFieldParams = AdditionalTextInputDialogUM(
label = state.label.resolveReference(),
isError = state.errorTextProvider(value.text) != null,
caption = state.errorTextProvider(value.text)?.resolveReference(),
),
)
}

View file

@ -11,9 +11,7 @@ import com.tangem.core.ui.event.StateEvent
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.utils.requestPermission
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAlertState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletEvent
import com.tangem.feature.wallet.presentation.wallet.ui.utils.ReviewManagerRequester
import com.tangem.feature.wallet.presentation.wallet.ui.utils.animateScrollByIndex
import com.tangem.feature.wallet.presentation.wallet.ui.utils.demonstrateScrolling
import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
@ -24,10 +22,8 @@ internal fun WalletEventEffect(
snackbarHostState: SnackbarHostState,
event: StateEvent<WalletEvent>,
onAutoScrollSet: () -> Unit,
onAlertConfigSet: (WalletAlertState) -> Unit,
) {
val coroutineScope = rememberCoroutineScope()
val context = LocalContext.current
val resources = LocalContext.current.resources
var showPermissionRequest by remember { mutableStateOf<Pair<() -> Unit, () -> Unit>?>(null) }
@ -57,10 +53,6 @@ internal fun WalletEventEffect(
duration = SnackbarDuration.Short,
)
}
is WalletEvent.ShowAlert -> onAlertConfigSet(value.state)
is WalletEvent.RateApp -> {
ReviewManagerRequester.request(context = context, onDismissClick = value.onDismissClick)
}
is WalletEvent.DemonstrateWalletsScrollPreview -> {
walletsListState.demonstrateScrolling(coroutineScope = coroutineScope, direction = value.direction)
}

View file

@ -100,13 +100,6 @@ internal fun WalletScreen(
val snackbarHostState = remember(::SnackbarHostState)
val isAutoScroll = remember { mutableStateOf(value = false) }
var alertConfig by remember { mutableStateOf<WalletAlertState?>(value = null) }
val config = alertConfig
if (config != null) {
WalletAlert(state = config, onDismiss = { alertConfig = null })
}
WalletContent(
state = state,
walletsListState = walletsListState,
@ -114,7 +107,6 @@ internal fun WalletScreen(
isAutoScroll = isAutoScroll,
onAutoScrollReset = { isAutoScroll.value = false },
bottomSheetContent = bottomSheetContent,
alertConfig = alertConfig,
bottomSheetHeaderHeightProvider = bottomSheetHeaderHeightProvider,
onBottomSheetStateChange = onBottomSheetStateChange,
)
@ -124,7 +116,6 @@ internal fun WalletScreen(
snackbarHostState = snackbarHostState,
event = state.event,
onAutoScrollSet = { isAutoScroll.value = true },
onAlertConfigSet = { alertConfig = it },
)
}
@ -135,7 +126,6 @@ private fun WalletContent(
walletsListState: LazyListState,
snackbarHostState: SnackbarHostState,
isAutoScroll: State<Boolean>,
alertConfig: WalletAlertState?,
onAutoScrollReset: () -> Unit,
bottomSheetHeaderHeightProvider: () -> Dp,
onBottomSheetStateChange: (BottomSheetState) -> Unit,
@ -279,7 +269,6 @@ private fun WalletContent(
selectedWallet = selectedWallet,
snackbarHostState = snackbarHostState,
bottomSheetHeaderHeightProvider = bottomSheetHeaderHeightProvider,
alertConfig = alertConfig,
onBottomSheetStateChange = onBottomSheetStateChange,
bottomSheetContent = bottomSheetContent,
content = scaffoldContent,
@ -294,7 +283,6 @@ private inline fun BaseScaffoldWithMarkets(
listState: LazyListState,
selectedWallet: WalletState,
snackbarHostState: SnackbarHostState,
alertConfig: WalletAlertState?,
bottomSheetHeaderHeightProvider: () -> Dp,
noinline onBottomSheetStateChange: (BottomSheetState) -> Unit,
crossinline bottomSheetContent: @Composable () -> Unit,
@ -341,7 +329,6 @@ private inline fun BaseScaffoldWithMarkets(
BottomSheetStateEffects(
bottomSheetState = bottomSheetState,
alertConfig = alertConfig,
onBottomSheetStateChange = onBottomSheetStateChange,
navigationBarVisible = isNavBarVisible,
isSearchFieldFocused = isSearchFieldFocused,
@ -615,7 +602,6 @@ private fun BottomSheetScrim(color: Color, visible: Boolean, onDismissRequest: (
@Composable
private fun BottomSheetStateEffects(
bottomSheetState: TangemSheetState,
alertConfig: WalletAlertState?,
navigationBarVisible: MutableState<Boolean>,
onBottomSheetStateChange: (BottomSheetState) -> Unit,
isSearchFieldFocused: Boolean,
@ -634,7 +620,7 @@ private fun BottomSheetStateEffects(
val isKeyboardVisible by rememberIsKeyboardVisible()
LaunchedEffect(isKeyboardVisible) {
if (isKeyboardVisible && alertConfig == null && isSearchFieldFocused) {
if (isKeyboardVisible && isSearchFieldFocused) {
bottomSheetState.expand()
}
}