Updated on 2026-08-14
This commit is contained in:
parent
f9feacf074
commit
07f63b47e4
15 changed files with 245 additions and 32 deletions
|
|
@ -1,3 +1,6 @@
|
|||
package com.tangem.features.send.v2.api
|
||||
|
||||
interface SendFeatureToggles
|
||||
interface SendFeatureToggles {
|
||||
|
||||
val isSendRedesignEnabled: Boolean
|
||||
}
|
||||
|
|
@ -4,5 +4,8 @@ import com.tangem.core.configtoggle.feature.FeatureTogglesManager
|
|||
import com.tangem.features.send.v2.api.SendFeatureToggles
|
||||
|
||||
internal class DefaultSendFeatureToggles(
|
||||
@Suppress("UnusedPrivateMember") private val featureToggles: FeatureTogglesManager,
|
||||
) : SendFeatureToggles
|
||||
private val featureToggles: FeatureTogglesManager,
|
||||
) : SendFeatureToggles {
|
||||
override val isSendRedesignEnabled: Boolean
|
||||
get() = featureToggles.isFeatureEnabled("SEND_REDESIGN_ENABLED")
|
||||
}
|
||||
|
|
@ -37,6 +37,7 @@ import com.tangem.domain.wallets.models.isMultiCurrency
|
|||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.features.send.v2.api.SendComponent
|
||||
import com.tangem.features.send.v2.api.SendFeatureToggles
|
||||
import com.tangem.features.send.v2.common.CommonSendRoute
|
||||
import com.tangem.features.send.v2.common.PredefinedValues
|
||||
import com.tangem.features.send.v2.common.SendConfirmAlertFactory
|
||||
|
|
@ -87,6 +88,7 @@ internal class SendModel @Inject constructor(
|
|||
private val createTransferTransactionUseCase: CreateTransferTransactionUseCase,
|
||||
private val getFeeUseCase: GetFeeUseCase,
|
||||
private val sendAmountUpdateQRTrigger: SendAmountUpdateQRTrigger,
|
||||
private val sendFeatureToggles: SendFeatureToggles,
|
||||
) : Model(), SendComponentCallback {
|
||||
|
||||
private val params: SendComponent.Params = paramsContainer.require()
|
||||
|
|
@ -357,6 +359,7 @@ internal class SendModel @Inject constructor(
|
|||
amountUM = AmountState.Empty(),
|
||||
destinationUM = SendDestinationInitialStateTransformer(
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
isRedesignEnabled = sendFeatureToggles.isSendRedesignEnabled,
|
||||
).transform(DestinationUM.Empty()),
|
||||
feeUM = FeeUM.Empty(),
|
||||
confirmUM = ConfirmUM.Empty,
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import com.tangem.domain.wallets.models.UserWallet
|
|||
import com.tangem.domain.wallets.models.isLocked
|
||||
import com.tangem.domain.wallets.models.isMultiCurrency
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
import com.tangem.features.send.v2.api.SendFeatureToggles
|
||||
import com.tangem.features.send.v2.common.PredefinedValues
|
||||
import com.tangem.features.send.v2.common.analytics.CommonSendAnalyticEvents
|
||||
import com.tangem.features.send.v2.common.analytics.CommonSendAnalyticEvents.SendScreenSource
|
||||
|
|
@ -65,6 +66,7 @@ internal class SendDestinationModel @Inject constructor(
|
|||
private val listenToQrScanningUseCase: ListenToQrScanningUseCase,
|
||||
private val parseQrCodeUseCase: ParseQrCodeUseCase,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val sendFeatureToggles: SendFeatureToggles,
|
||||
) : Model(), SendDestinationClickIntents {
|
||||
private val params: SendDestinationComponentParams = paramsContainer.require()
|
||||
|
||||
|
|
@ -90,6 +92,7 @@ internal class SendDestinationModel @Inject constructor(
|
|||
_uiState.update(
|
||||
SendDestinationInitialStateTransformer(
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
isRedesignEnabled = sendFeatureToggles.isSendRedesignEnabled,
|
||||
isInitialized = true,
|
||||
),
|
||||
)
|
||||
|
|
@ -297,6 +300,7 @@ internal class SendDestinationModel @Inject constructor(
|
|||
flow2 = params.currentRoute,
|
||||
transform = { state, route -> state to route },
|
||||
).onEach { (state, route) ->
|
||||
val isRedesignEnabled = sendFeatureToggles.isSendRedesignEnabled
|
||||
params.callback.onNavigationResult(
|
||||
NavigationUM.Content(
|
||||
title = params.title,
|
||||
|
|
@ -319,8 +323,16 @@ internal class SendDestinationModel @Inject constructor(
|
|||
}
|
||||
params.onBackClick()
|
||||
},
|
||||
additionalIconRes = R.drawable.ic_qrcode_scan_24,
|
||||
additionalIconClick = ::onQrCodeScanClick,
|
||||
additionalIconRes = if (isRedesignEnabled) {
|
||||
null
|
||||
} else {
|
||||
R.drawable.ic_qrcode_scan_24
|
||||
},
|
||||
additionalIconClick = if (isRedesignEnabled) {
|
||||
null
|
||||
} else {
|
||||
::onQrCodeScanClick
|
||||
},
|
||||
primaryButton = ButtonsUM.PrimaryButtonUM(
|
||||
text = if (route.isEditMode) {
|
||||
resourceReference(R.string.common_continue)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import com.tangem.utils.transformer.Transformer
|
|||
|
||||
internal class SendDestinationInitialStateTransformer(
|
||||
val cryptoCurrency: CryptoCurrency,
|
||||
val isRedesignEnabled: Boolean,
|
||||
val isInitialized: Boolean = false,
|
||||
) : Transformer<DestinationUM> {
|
||||
override fun transform(prevState: DestinationUM): DestinationUM {
|
||||
|
|
@ -54,6 +55,7 @@ internal class SendDestinationInitialStateTransformer(
|
|||
recent = loadingListState(RECENT_KEY_TAG, RECENT_DEFAULT_COUNT),
|
||||
networkName = cryptoCurrency.network.name,
|
||||
isValidating = false,
|
||||
isRedesignEnabled = isRedesignEnabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,10 @@ import androidx.compose.runtime.getValue
|
|||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.containers.FooterContainer
|
||||
import com.tangem.core.ui.components.inputrow.InputRowRecipient
|
||||
|
|
@ -60,10 +64,13 @@ internal fun SendDestinationContent(
|
|||
isError = isError,
|
||||
isValidating = isValidating,
|
||||
onAddressChange = clickIntents::onRecipientAddressValueChange,
|
||||
onQrCodeClick = clickIntents::onQrCodeScanClick,
|
||||
isRedesignEnabled = state.isRedesignEnabled,
|
||||
)
|
||||
memoField(
|
||||
memoField = memoField,
|
||||
onMemoChange = clickIntents::onRecipientMemoValueChange,
|
||||
isRedesignEnabled = state.isRedesignEnabled,
|
||||
)
|
||||
listHeaderItem(
|
||||
titleRes = R.string.send_recipient_wallets_title,
|
||||
|
|
@ -100,16 +107,23 @@ internal fun SendDestinationContent(
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
private fun LazyListScope.addressItem(
|
||||
address: DestinationTextFieldUM.RecipientAddress,
|
||||
networkName: String,
|
||||
isError: Boolean,
|
||||
isValidating: Boolean,
|
||||
onAddressChange: (String, EnterAddressSource) -> Unit,
|
||||
onQrCodeClick: () -> Unit,
|
||||
isRedesignEnabled: Boolean,
|
||||
) {
|
||||
item(key = ADDRESS_FIELD_KEY) {
|
||||
FooterContainer(
|
||||
footer = resourceReference(R.string.send_recipient_address_footer, wrappedList(networkName)),
|
||||
footer = if (isRedesignEnabled) {
|
||||
buildHighlightedFooterText(networkName)
|
||||
} else {
|
||||
resourceReference(R.string.send_recipient_address_footer, wrappedList(networkName))
|
||||
},
|
||||
) {
|
||||
InputRowRecipient(
|
||||
value = address.value,
|
||||
|
|
@ -117,6 +131,8 @@ private fun LazyListScope.addressItem(
|
|||
placeholder = address.placeholder,
|
||||
onValueChange = { onAddressChange(it, EnterAddressSource.InputField) },
|
||||
onPasteClick = { onAddressChange(it, EnterAddressSource.PasteButton) },
|
||||
onQrCodeClick = onQrCodeClick,
|
||||
isRedesignEnabled = isRedesignEnabled,
|
||||
isError = isError,
|
||||
isLoading = isValidating,
|
||||
error = address.error,
|
||||
|
|
@ -131,9 +147,37 @@ private fun LazyListScope.addressItem(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun buildHighlightedFooterText(networkName: String): TextReference {
|
||||
return annotatedReference(
|
||||
buildAnnotatedString {
|
||||
val styledText = stringResourceSafe(
|
||||
R.string.send_recipient_address_footer_highlighted_part,
|
||||
networkName,
|
||||
)
|
||||
val styledColor = TangemTheme.colors.text.secondary
|
||||
appendWithStyledPlaceholder(
|
||||
template = stringResourceSafe(
|
||||
R.string.send_recipient_address_footer_v2,
|
||||
networkName,
|
||||
),
|
||||
placeholder = networkName,
|
||||
) {
|
||||
withStyle(SpanStyle(fontWeight = FontWeight.Medium)) {
|
||||
appendColored(
|
||||
text = styledText,
|
||||
color = styledColor,
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun LazyListScope.memoField(
|
||||
memoField: DestinationTextFieldUM.RecipientMemo?,
|
||||
onMemoChange: (String, Boolean) -> Unit,
|
||||
isRedesignEnabled: Boolean,
|
||||
) {
|
||||
if (memoField != null) {
|
||||
item(key = MEMO_FIELD_KEY) {
|
||||
|
|
@ -142,7 +186,24 @@ private fun LazyListScope.memoField(
|
|||
value = memoField.value,
|
||||
label = memoField.label,
|
||||
placeholder = placeholder,
|
||||
footer = resourceReference(R.string.send_recipient_memo_footer),
|
||||
footer = if (isRedesignEnabled) {
|
||||
annotatedReference(
|
||||
buildAnnotatedString {
|
||||
append(stringResourceSafe(R.string.send_recipient_memo_footer_v2))
|
||||
append("\n")
|
||||
withStyle(SpanStyle(fontWeight = FontWeight.Medium)) {
|
||||
appendColored(
|
||||
text = stringResourceSafe(
|
||||
R.string.send_recipient_memo_footer_v2_highlighted,
|
||||
),
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
} else {
|
||||
resourceReference(R.string.send_recipient_memo_footer)
|
||||
},
|
||||
onValueChange = { onMemoChange(it, false) },
|
||||
onPasteClick = { onMemoChange(it, true) },
|
||||
modifier = Modifier.padding(top = 20.dp),
|
||||
|
|
@ -151,6 +212,7 @@ private fun LazyListScope.memoField(
|
|||
error = memoField.error,
|
||||
isReadOnly = !memoField.isEnabled,
|
||||
isValuePasted = memoField.isValuePasted,
|
||||
isRedesignEnabled = isRedesignEnabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import com.tangem.core.ui.extensions.resolveReference
|
|||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.components.containers.FooterContainer
|
||||
|
||||
@Suppress("LongMethod", "LongParameterList")
|
||||
@Composable
|
||||
internal fun TextFieldWithPaste(
|
||||
value: String,
|
||||
|
|
@ -27,6 +28,7 @@ internal fun TextFieldWithPaste(
|
|||
label: TextReference,
|
||||
onValueChange: (String) -> Unit,
|
||||
onPasteClick: (String) -> Unit,
|
||||
isRedesignEnabled: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
footer: TextReference? = null,
|
||||
labelStyle: TextStyle = TangemTheme.typography.body2,
|
||||
|
|
@ -96,6 +98,18 @@ internal fun TextFieldWithPaste(
|
|||
PasteButton(
|
||||
isPasteButtonVisible = value.isBlank(),
|
||||
onClick = onPasteClick,
|
||||
backgroundColorEnabled = if (isRedesignEnabled) {
|
||||
TangemTheme.colors.button.secondary
|
||||
} else {
|
||||
TangemTheme.colors.button.primary
|
||||
},
|
||||
textColor = if (isRedesignEnabled) {
|
||||
TangemTheme.colors.text.primary1
|
||||
} else {
|
||||
TangemTheme.colors.text.primary2
|
||||
},
|
||||
modifier = Modifier
|
||||
.padding(start = TangemTheme.dimens.spacing8),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ internal sealed class DestinationUM {
|
|||
val networkName: String,
|
||||
val isValidating: Boolean = false,
|
||||
val isInitialized: Boolean = false,
|
||||
val isRedesignEnabled: Boolean = false,
|
||||
) : DestinationUM()
|
||||
|
||||
data class Empty(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue