Updated on 2026-08-14

This commit is contained in:
Tangem 2024-04-04 17:04:08 +05:00
commit 02b8e8c039
5 changed files with 112 additions and 53 deletions

View file

@ -33,7 +33,7 @@ private fun CameraDeniedBottomSheet(content: CameraDeniedBottomSheetConfig) {
title = stringResource(id = R.string.qr_scanner_camera_denied_settings_button),
icon = R.drawable.ic_settings_24,
onItemsClick = {
val intent: Intent = Intent(
val intent = Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", context.packageName, null),
)
@ -47,7 +47,7 @@ private fun CameraDeniedBottomSheet(content: CameraDeniedBottomSheetConfig) {
)
SimpleSettingsRow(
title = stringResource(id = R.string.common_close),
icon = R.drawable.ic_close,
icon = R.drawable.ic_close_24,
onItemsClick = content.onCancelClick,
modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing16),
)

View file

@ -122,6 +122,7 @@ private fun SendScreenContent(uiState: SendUiState, currentState: SendUiCurrentS
SendUiStateType.Recipient -> SendRecipientContent(
uiState = uiState.recipientState,
clickIntents = uiState.clickIntents,
isBalanceHidden = uiState.isBalanceHidden,
)
SendUiStateType.Fee -> SendSpeedAndFeeContent(
state = uiState.feeState,

View file

@ -18,6 +18,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.stringResource
import com.tangem.common.Strings.STARS
import com.tangem.core.ui.components.inputrow.InputRowRecipient
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
@ -25,6 +26,7 @@ import com.tangem.features.send.impl.R
import com.tangem.features.send.impl.presentation.analytics.EnterAddressSource
import com.tangem.features.send.impl.presentation.domain.SendRecipientListContent
import com.tangem.features.send.impl.presentation.state.SendStates
import com.tangem.features.send.impl.presentation.state.fields.SendTextField
import com.tangem.features.send.impl.presentation.ui.common.FooterContainer
import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents
import kotlinx.collections.immutable.ImmutableList
@ -33,7 +35,11 @@ private const val ADDRESS_FIELD_KEY = "ADDRESS_FIELD_KEY"
private const val MEMO_FIELD_KEY = "MEMO_FIELD_KEY"
@Composable
internal fun SendRecipientContent(uiState: SendStates.RecipientState?, clickIntents: SendClickIntents) {
internal fun SendRecipientContent(
uiState: SendStates.RecipientState?,
clickIntents: SendClickIntents,
isBalanceHidden: Boolean,
) {
if (uiState == null) return
val recipients = uiState.recent
val wallets = uiState.wallets
@ -47,56 +53,89 @@ internal fun SendRecipientContent(uiState: SendStates.RecipientState?, clickInte
.background(TangemTheme.colors.background.tertiary)
.padding(horizontal = TangemTheme.dimens.spacing16),
) {
item(key = ADDRESS_FIELD_KEY) {
FooterContainer(
footer = stringResource(R.string.send_recipient_address_footer, uiState.network),
) {
InputRowRecipient(
value = address.value,
title = address.label,
placeholder = address.placeholder,
onValueChange = address.onValueChange,
onPasteClick = { clickIntents.onRecipientAddressValueChange(it, EnterAddressSource.PasteButton) },
isError = isError,
isLoading = isValidating,
error = address.error,
modifier = Modifier
.background(
color = TangemTheme.colors.background.action,
shape = TangemTheme.shapes.roundedCornersXMedium,
),
)
}
}
if (memoField != null) {
item(key = MEMO_FIELD_KEY) {
val placeholder = if (memoField.isEnabled) memoField.placeholder else memoField.disabledText
TextFieldWithPaste(
value = memoField.value,
label = memoField.label,
placeholder = placeholder,
footer = stringResource(R.string.send_recipient_memo_footer),
onValueChange = memoField.onValueChange,
onPasteClick = clickIntents::onRecipientMemoValueChange,
modifier = Modifier.padding(top = TangemTheme.dimens.spacing20),
isError = memoField.isError,
error = memoField.error,
isReadOnly = !memoField.isEnabled,
)
}
}
addressItem(
address = address,
network = uiState.network,
isError = isError,
isValidating = isValidating,
onAddressChange = clickIntents::onRecipientAddressValueChange,
)
memoField(
memoField = memoField,
onMemoChange = clickIntents::onRecipientMemoValueChange,
)
listHeaderItem(
titleRes = R.string.send_recipient_wallets_title,
isVisible = wallets.isNotEmpty() && wallets.first().isVisible,
isFirst = true,
)
listItem(wallets, clickIntents, isLast = recipients.isEmpty())
listItem(
list = wallets,
clickIntents = clickIntents,
isLast = recipients.isEmpty(),
isBalanceHidden = isBalanceHidden,
)
listHeaderItem(
titleRes = R.string.send_recent_transactions,
isVisible = recipients.isNotEmpty() && recipients.first().isVisible,
isFirst = wallets.isEmpty(),
)
listItem(recipients, clickIntents, isLast = true)
listItem(
list = recipients,
clickIntents = clickIntents,
isLast = true,
isBalanceHidden = isBalanceHidden,
)
}
}
private fun LazyListScope.addressItem(
address: SendTextField.RecipientAddress,
network: String,
isError: Boolean,
isValidating: Boolean,
onAddressChange: (String, EnterAddressSource?) -> Unit,
) {
item(key = ADDRESS_FIELD_KEY) {
FooterContainer(
footer = stringResource(R.string.send_recipient_address_footer, network),
) {
InputRowRecipient(
value = address.value,
title = address.label,
placeholder = address.placeholder,
onValueChange = address.onValueChange,
onPasteClick = { onAddressChange(it, EnterAddressSource.PasteButton) },
isError = isError,
isLoading = isValidating,
error = address.error,
modifier = Modifier
.background(
color = TangemTheme.colors.background.action,
shape = TangemTheme.shapes.roundedCornersXMedium,
),
)
}
}
}
private fun LazyListScope.memoField(memoField: SendTextField.RecipientMemo?, onMemoChange: (String) -> Unit) {
if (memoField != null) {
item(key = MEMO_FIELD_KEY) {
val placeholder = if (memoField.isEnabled) memoField.placeholder else memoField.disabledText
TextFieldWithPaste(
value = memoField.value,
label = memoField.label,
placeholder = placeholder,
footer = stringResource(R.string.send_recipient_memo_footer),
onValueChange = memoField.onValueChange,
onPasteClick = onMemoChange,
modifier = Modifier.padding(top = TangemTheme.dimens.spacing20),
isError = memoField.isError,
error = memoField.error,
isReadOnly = !memoField.isEnabled,
)
}
}
}
@ -154,6 +193,7 @@ private fun LazyListScope.listItem(
list: ImmutableList<SendRecipientListContent>,
clickIntents: SendClickIntents,
isLast: Boolean,
isBalanceHidden: Boolean,
) {
items(
count = list.size,
@ -173,7 +213,7 @@ private fun LazyListScope.listItem(
) {
ListItemWithIcon(
title = title,
subtitle = item.subtitle.resolveReference(),
subtitle = if (isBalanceHidden) STARS else item.subtitle.resolveReference(),
info = item.timestamp?.resolveReference(),
subtitleEndOffset = item.subtitleEndOffset,
subtitleIconRes = item.subtitleIconRes,

View file

@ -1,5 +1,8 @@
package com.tangem.features.send.impl.presentation.ui.recipient
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Text
@ -63,17 +66,29 @@ internal fun TextFieldWithPaste(
.padding(top = TangemTheme.dimens.spacing6),
)
}
CrossIcon(
onClick = onPasteClick,
AnimatedVisibility(
visible = !isReadOnly,
label = "Animate read only status change",
enter = fadeIn(),
exit = fadeOut(),
modifier = Modifier
.align(CenterVertically),
)
) {
CrossIcon(
onClick = onPasteClick,
)
}
}
if (!isReadOnly) {
AnimatedVisibility(
visible = !isReadOnly,
label = "Animate read only status change",
enter = fadeIn(),
exit = fadeOut(),
modifier = Modifier.align(CenterEnd),
) {
PasteButton(
isPasteButtonVisible = value.isBlank(),
onClick = onPasteClick,
modifier = Modifier.align(CenterEnd),
)
}
}

View file

@ -618,7 +618,9 @@ internal class SendViewModel @Inject constructor(
network = cryptoCurrency.network,
address = value,
).getOrElse { false }
onEnteredValidAddress(isValidAddress)
val isAddressInWallet = cryptoCurrencyStatus.value.networkAddress?.availableAddresses
?.any { it.value == value } ?: true
onEnteredValidAddress(isValidAddress, isAddressInWallet)
return isValidAddress
}
@ -632,12 +634,13 @@ internal class SendViewModel @Inject constructor(
} ?: false
}
private fun onEnteredValidAddress(isValidAddress: Boolean) {
private fun onEnteredValidAddress(isValidAddress: Boolean, isAddressInWallet: Boolean) {
val recipientState = uiState.recipientState ?: return
val isVisible = isAddressInWallet || !isValidAddress
uiState = uiState.copy(
recipientState = recipientState.copy(
recent = recipientState.recent.map { it.copy(isVisible = !isValidAddress) }.toPersistentList(),
wallets = recipientState.wallets.map { it.copy(isVisible = !isValidAddress) }.toPersistentList(),
recent = recipientState.recent.map { it.copy(isVisible = isVisible) }.toPersistentList(),
wallets = recipientState.wallets.map { it.copy(isVisible = isVisible) }.toPersistentList(),
),
)
}