Updated on 2026-08-14
This commit is contained in:
commit
3571f0e4b4
9 changed files with 56 additions and 31 deletions
|
|
@ -49,12 +49,14 @@ fun Notification(
|
|||
modifier: Modifier = Modifier,
|
||||
containerColor: Color? = null,
|
||||
iconTint: Color? = null,
|
||||
isEnabled: Boolean = true,
|
||||
) {
|
||||
BaseContainer(
|
||||
buttonsState = config.buttonsState,
|
||||
onClick = config.onClick,
|
||||
modifier = modifier,
|
||||
containerColor = containerColor,
|
||||
isEnabled = isEnabled,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(all = TangemTheme.dimens.spacing12),
|
||||
|
|
@ -65,15 +67,16 @@ fun Notification(
|
|||
iconTint = iconTint,
|
||||
title = config.title,
|
||||
subtitle = config.subtitle,
|
||||
isClickableComponent = config.onClick != null,
|
||||
isClickableComponent = isEnabled && config.onClick != null,
|
||||
)
|
||||
|
||||
Buttons(state = config.buttonsState)
|
||||
Buttons(state = config.buttonsState, isEnabled = isEnabled)
|
||||
}
|
||||
|
||||
CloseableIconButton(
|
||||
onClick = config.onCloseClick,
|
||||
modifier = Modifier.align(alignment = Alignment.TopEnd),
|
||||
isEnabled = isEnabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -83,6 +86,7 @@ private fun BaseContainer(
|
|||
buttonsState: NotificationConfig.ButtonsState?,
|
||||
onClick: (() -> Unit)?,
|
||||
modifier: Modifier = Modifier,
|
||||
isEnabled: Boolean = true,
|
||||
containerColor: Color? = null,
|
||||
content: @Composable BoxScope.() -> Unit,
|
||||
) {
|
||||
|
|
@ -99,7 +103,7 @@ private fun BaseContainer(
|
|||
modifier = modifier
|
||||
.defaultMinSize(minHeight = TangemTheme.dimens.size62)
|
||||
.fillMaxWidth(),
|
||||
enabled = onClick != null,
|
||||
enabled = onClick != null && isEnabled,
|
||||
shape = TangemTheme.shapes.roundedCornersXMedium,
|
||||
color = containerColor ?: tempContainerColor,
|
||||
) {
|
||||
|
|
@ -177,27 +181,31 @@ private fun TextsBlock(title: TextReference, subtitle: TextReference) {
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun Buttons(state: NotificationButtonsState?) {
|
||||
private fun Buttons(state: NotificationButtonsState?, isEnabled: Boolean = true) {
|
||||
when (state) {
|
||||
is NotificationButtonsState.SecondaryButtonConfig -> SingleSecondaryButton(config = state)
|
||||
is NotificationButtonsState.PrimaryButtonConfig -> SinglePrimaryButton(config = state)
|
||||
is NotificationButtonsState.PairButtonsConfig -> PairButtons(config = state)
|
||||
is NotificationButtonsState.SecondaryButtonConfig -> SingleSecondaryButton(
|
||||
config = state,
|
||||
isEnabled = isEnabled,
|
||||
)
|
||||
is NotificationButtonsState.PrimaryButtonConfig -> SinglePrimaryButton(config = state, isEnabled = isEnabled)
|
||||
is NotificationButtonsState.PairButtonsConfig -> PairButtons(config = state, isEnabled = isEnabled)
|
||||
null -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SingleSecondaryButton(config: NotificationButtonsState.SecondaryButtonConfig) {
|
||||
private fun SingleSecondaryButton(config: NotificationButtonsState.SecondaryButtonConfig, isEnabled: Boolean = true) {
|
||||
SecondaryButton(
|
||||
text = config.text.resolveReference(),
|
||||
onClick = config.onClick,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
size = TangemButtonSize.WideAction,
|
||||
enabled = isEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SinglePrimaryButton(config: NotificationButtonsState.PrimaryButtonConfig) {
|
||||
private fun SinglePrimaryButton(config: NotificationButtonsState.PrimaryButtonConfig, isEnabled: Boolean = true) {
|
||||
if (config.iconResId != null) {
|
||||
PrimaryButtonIconEnd(
|
||||
text = config.text.resolveReference(),
|
||||
|
|
@ -205,6 +213,7 @@ private fun SinglePrimaryButton(config: NotificationButtonsState.PrimaryButtonCo
|
|||
onClick = config.onClick,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
size = TangemButtonSize.WideAction,
|
||||
enabled = isEnabled,
|
||||
)
|
||||
} else {
|
||||
PrimaryButton(
|
||||
|
|
@ -212,18 +221,20 @@ private fun SinglePrimaryButton(config: NotificationButtonsState.PrimaryButtonCo
|
|||
onClick = config.onClick,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
size = TangemButtonSize.WideAction,
|
||||
enabled = isEnabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PairButtons(config: NotificationButtonsState.PairButtonsConfig) {
|
||||
private fun PairButtons(config: NotificationButtonsState.PairButtonsConfig, isEnabled: Boolean = true) {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing8)) {
|
||||
SecondaryButton(
|
||||
text = config.secondaryText.resolveReference(),
|
||||
onClick = config.onSecondaryClick,
|
||||
modifier = Modifier.weight(weight = 1f),
|
||||
size = TangemButtonSize.WideAction,
|
||||
enabled = isEnabled,
|
||||
)
|
||||
|
||||
PrimaryButton(
|
||||
|
|
@ -231,12 +242,13 @@ private fun PairButtons(config: NotificationButtonsState.PairButtonsConfig) {
|
|||
onClick = config.onPrimaryClick,
|
||||
modifier = Modifier.weight(weight = 1f),
|
||||
size = TangemButtonSize.WideAction,
|
||||
enabled = isEnabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CloseableIconButton(onClick: (() -> Unit)?, modifier: Modifier = Modifier) {
|
||||
private fun CloseableIconButton(onClick: (() -> Unit)?, modifier: Modifier = Modifier, isEnabled: Boolean = true) {
|
||||
AnimatedVisibility(visible = onClick != null, modifier = modifier) {
|
||||
onClick ?: return@AnimatedVisibility
|
||||
|
||||
|
|
@ -253,6 +265,7 @@ private fun CloseableIconButton(onClick: (() -> Unit)?, modifier: Modifier = Mod
|
|||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = LocalIndication.current,
|
||||
role = Role.Button,
|
||||
enabled = isEnabled,
|
||||
onClick = onClick,
|
||||
),
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.tangem.features.send.impl.presentation.state.StateRouter
|
|||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.utils.isNullOrZero
|
||||
import java.math.RoundingMode
|
||||
|
||||
internal class SendAmountFieldMaxAmountConverter(
|
||||
private val stateRouterProvider: Provider<StateRouter>,
|
||||
|
|
@ -33,7 +34,7 @@ internal class SendAmountFieldMaxAmountConverter(
|
|||
|
||||
val isDoneActionEnabled = !decimalCryptoValue.isNullOrZero()
|
||||
val cryptoValue = decimalCryptoValue?.parseBigDecimal(cryptoDecimals).orEmpty()
|
||||
val fiatValue = decimalFiatValue?.parseBigDecimal(fiatDecimals).orEmpty()
|
||||
val fiatValue = decimalFiatValue?.parseBigDecimal(fiatDecimals, roundingMode = RoundingMode.HALF_UP).orEmpty()
|
||||
return state.copyWrapped(
|
||||
isEditState = isEditState,
|
||||
amountState = amountState.copy(
|
||||
|
|
|
|||
|
|
@ -33,7 +33,10 @@ import kotlinx.coroutines.flow.withIndex
|
|||
@Composable
|
||||
internal fun SendScreen(uiState: SendUiState, currentState: SendUiCurrentScreen) {
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
BackHandler(onBack = uiState.clickIntents::onBackClick)
|
||||
val onBackClick = uiState.clickIntents::onBackClick.takeIf {
|
||||
uiState.sendState?.isSending != true
|
||||
} ?: {}
|
||||
BackHandler(onBack = onBackClick)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ internal fun LazyListScope.notifications(
|
|||
notifications: ImmutableList<SendNotification>,
|
||||
modifier: Modifier = Modifier,
|
||||
hasPaddingAbove: Boolean = false,
|
||||
isClickDisabled: Boolean = false,
|
||||
) {
|
||||
itemsIndexed(
|
||||
items = notifications,
|
||||
|
|
@ -44,6 +45,7 @@ internal fun LazyListScope.notifications(
|
|||
-> null
|
||||
is SendNotification.Error -> TangemTheme.colors.icon.warning
|
||||
},
|
||||
isEnabled = !isClickDisabled,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import com.tangem.features.send.impl.presentation.state.previewdata.AmountStateP
|
|||
@Composable
|
||||
internal fun AmountBlock(
|
||||
amountState: SendStates.AmountState,
|
||||
isSuccess: Boolean,
|
||||
isClickDisabled: Boolean,
|
||||
isEditingDisabled: Boolean,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
|
|
@ -53,7 +53,7 @@ internal fun AmountBlock(
|
|||
modifier = Modifier
|
||||
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||
.background(backgroundColor)
|
||||
.clickable(enabled = !isSuccess && !isEditingDisabled, onClick = onClick)
|
||||
.clickable(enabled = !isClickDisabled && !isEditingDisabled, onClick = onClick)
|
||||
.padding(
|
||||
vertical = TangemTheme.dimens.spacing14,
|
||||
horizontal = TangemTheme.dimens.spacing16,
|
||||
|
|
@ -91,7 +91,7 @@ private fun AmountBlockPreview_Light(
|
|||
TangemTheme {
|
||||
AmountBlock(
|
||||
amountState = value,
|
||||
isSuccess = false,
|
||||
isClickDisabled = false,
|
||||
isEditingDisabled = false,
|
||||
onClick = {},
|
||||
)
|
||||
|
|
@ -106,7 +106,7 @@ private fun AmountBlockPreview_Dark(
|
|||
TangemTheme(isDark = true) {
|
||||
AmountBlock(
|
||||
amountState = value,
|
||||
isSuccess = true,
|
||||
isClickDisabled = true,
|
||||
isEditingDisabled = false,
|
||||
onClick = {},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -26,13 +26,13 @@ import com.tangem.features.send.impl.presentation.utils.getCryptoReference
|
|||
import com.tangem.features.send.impl.presentation.utils.getFiatReference
|
||||
|
||||
@Composable
|
||||
internal fun FeeBlock(feeState: SendStates.FeeState, isSuccess: Boolean, onClick: () -> Unit) {
|
||||
internal fun FeeBlock(feeState: SendStates.FeeState, isClickDisabled: Boolean, onClick: () -> Unit) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||
.background(TangemTheme.colors.background.action)
|
||||
.clickable(enabled = !isSuccess, onClick = onClick)
|
||||
.clickable(enabled = !isClickDisabled, onClick = onClick)
|
||||
.padding(TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
Text(
|
||||
|
|
@ -115,7 +115,7 @@ private fun FeeBlockPreview_Light(@PreviewParameter(FeeBlockPreviewProvider::cla
|
|||
TangemTheme {
|
||||
FeeBlock(
|
||||
feeState = value,
|
||||
isSuccess = true,
|
||||
isClickDisabled = true,
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
|
|
@ -127,7 +127,7 @@ private fun FeeBlockPreview_Dark(@PreviewParameter(FeeBlockPreviewProvider::clas
|
|||
TangemTheme(isDark = true) {
|
||||
FeeBlock(
|
||||
feeState = value,
|
||||
isSuccess = true,
|
||||
isClickDisabled = true,
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import com.tangem.features.send.impl.presentation.state.previewdata.RecipientSta
|
|||
@Composable
|
||||
internal fun RecipientBlock(
|
||||
recipientState: SendStates.RecipientState,
|
||||
isSuccess: Boolean,
|
||||
isClickDisabled: Boolean,
|
||||
isEditingDisabled: Boolean,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
|
|
@ -38,7 +38,7 @@ internal fun RecipientBlock(
|
|||
.fillMaxWidth()
|
||||
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||
.background(backgroundColor)
|
||||
.clickable(enabled = !isSuccess && !isEditingDisabled, onClick = onClick)
|
||||
.clickable(enabled = !isClickDisabled && !isEditingDisabled, onClick = onClick)
|
||||
.padding(TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
AddressBlock(recipientState.addressTextField)
|
||||
|
|
@ -104,7 +104,7 @@ private fun RecipientBlockPreview_Light(
|
|||
TangemTheme {
|
||||
RecipientBlock(
|
||||
recipientState = value,
|
||||
isSuccess = true,
|
||||
isClickDisabled = true,
|
||||
isEditingDisabled = false,
|
||||
onClick = {},
|
||||
)
|
||||
|
|
@ -119,7 +119,7 @@ private fun RecipientBlockPreview_Dark(
|
|||
TangemTheme(isDark = true) {
|
||||
RecipientBlock(
|
||||
recipientState = value,
|
||||
isSuccess = true,
|
||||
isClickDisabled = true,
|
||||
isEditingDisabled = false,
|
||||
onClick = {},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -35,12 +35,13 @@ private const val TAP_HELP_ANIMATION_DELAY = 500L
|
|||
@Composable
|
||||
internal fun SendContent(uiState: SendUiState) {
|
||||
val sendState = uiState.sendState ?: return
|
||||
val isClickDisabled = sendState.isSending || sendState.isSuccess
|
||||
LazyColumn(
|
||||
modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing16),
|
||||
) {
|
||||
blocks(uiState)
|
||||
tapHelp(isDisplay = sendState.showTapHelp)
|
||||
notifications(sendState.notifications)
|
||||
notifications(notifications = sendState.notifications, isClickDisabled = isClickDisabled)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -50,6 +51,7 @@ private fun LazyListScope.blocks(uiState: SendUiState) {
|
|||
val feeState = uiState.feeState ?: return
|
||||
val sendState = uiState.sendState ?: return
|
||||
val isSuccess = sendState.isSuccess
|
||||
val isClickDisabled = sendState.isSending || isSuccess
|
||||
val timestamp = sendState.transactionDate
|
||||
|
||||
item(key = BLOCKS_KEY) {
|
||||
|
|
@ -65,19 +67,19 @@ private fun LazyListScope.blocks(uiState: SendUiState) {
|
|||
}
|
||||
RecipientBlock(
|
||||
recipientState = recipientState,
|
||||
isSuccess = isSuccess,
|
||||
isClickDisabled = isClickDisabled,
|
||||
isEditingDisabled = uiState.isEditingDisabled,
|
||||
onClick = uiState.clickIntents::showRecipient,
|
||||
)
|
||||
AmountBlock(
|
||||
amountState = amountState,
|
||||
isSuccess = isSuccess,
|
||||
isClickDisabled = isClickDisabled,
|
||||
isEditingDisabled = uiState.isEditingDisabled,
|
||||
onClick = uiState.clickIntents::showAmount,
|
||||
)
|
||||
FeeBlock(
|
||||
feeState = feeState,
|
||||
isSuccess = isSuccess,
|
||||
isClickDisabled = isClickDisabled,
|
||||
onClick = uiState.clickIntents::showFee,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -422,14 +422,18 @@ internal class SendViewModel @Inject constructor(
|
|||
.mapNotNull { wallet ->
|
||||
val status = if (!wallet.isMultiCurrency) {
|
||||
getCryptoCurrencyUseCase(wallet.walletId).getOrNull()?.let {
|
||||
getNetworkAddressesUseCase(wallet.walletId, it.network)
|
||||
if (it.network.id == cryptoCurrency.network.id) {
|
||||
getNetworkAddressesUseCase(wallet.walletId, it.network)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getNetworkAddressesUseCase(wallet.walletId, cryptoCurrency.network)
|
||||
}
|
||||
status?.map { address ->
|
||||
AvailableWallet(
|
||||
wallet.name,
|
||||
name = wallet.name,
|
||||
address = address,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue