Updated on 2026-08-14
This commit is contained in:
commit
364f4e51b7
16 changed files with 170 additions and 35 deletions
|
|
@ -9,4 +9,5 @@ interface OnrampIntents {
|
|||
fun onBuyClick(quote: OnrampProviderWithQuote.Data)
|
||||
fun openProviders()
|
||||
fun onRefresh()
|
||||
fun onLinkClick(link: String)
|
||||
}
|
||||
|
|
@ -9,7 +9,10 @@ sealed class OnrampProviderBlockUM {
|
|||
val providerId: String,
|
||||
val paymentMethod: OnrampPaymentMethod,
|
||||
val providerName: String,
|
||||
val termsOfUseLink: String?,
|
||||
val privacyPolicyLink: String?,
|
||||
val isBestRate: Boolean,
|
||||
val onLinkClick: (String) -> Unit,
|
||||
val onClick: () -> Unit,
|
||||
) : OnrampProviderBlockUM()
|
||||
}
|
||||
|
|
@ -61,6 +61,7 @@ internal class OnrampAmountFieldChangeConverter(
|
|||
amountFieldModel = amountFieldModel,
|
||||
secondaryFieldModel = OnrampAmountSecondaryFieldUM.Content(TextReference.EMPTY),
|
||||
),
|
||||
buyButtonConfig = buyButtonConfig.copy(enabled = false),
|
||||
providerBlockState = OnrampProviderBlockUM.Empty,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,6 +122,9 @@ internal class OnrampAmountStateFactory(
|
|||
providerName = providerResult.provider.info.name,
|
||||
isBestRate = isBestRate,
|
||||
onClick = onrampIntents::openProviders,
|
||||
termsOfUseLink = providerResult.provider.info.termsOfUseLink,
|
||||
privacyPolicyLink = providerResult.provider.info.privacyPolicyLink,
|
||||
onLinkClick = onrampIntents::onLinkClick,
|
||||
),
|
||||
buyButtonConfig = currentState.buyButtonConfig.copy(
|
||||
enabled = providerResult is SelectProviderResult.ProviderWithQuote,
|
||||
|
|
@ -148,6 +151,9 @@ internal class OnrampAmountStateFactory(
|
|||
providerName = provider.info.name,
|
||||
isBestRate = isBestRate,
|
||||
onClick = onrampIntents::openProviders,
|
||||
termsOfUseLink = provider.info.termsOfUseLink,
|
||||
privacyPolicyLink = provider.info.privacyPolicyLink,
|
||||
onLinkClick = onrampIntents::onLinkClick,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.tangem.core.decompose.model.Model
|
|||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.core.ui.components.BasicDialog
|
||||
import com.tangem.core.ui.components.DialogButtonUM
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
|
|
@ -60,6 +61,7 @@ internal class OnrampMainComponentModel @Inject constructor(
|
|||
private val fetchPairsUseCase: OnrampFetchPairsUseCase,
|
||||
private val amountInputManager: InputManager,
|
||||
private val messageSender: UiMessageSender,
|
||||
private val urlOpener: UrlOpener,
|
||||
getWalletsUseCase: GetWalletsUseCase,
|
||||
paramsContainer: ParamsContainer,
|
||||
) : Model(), OnrampIntents {
|
||||
|
|
@ -286,6 +288,8 @@ internal class OnrampMainComponentModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun onLinkClick(link: String) = urlOpener.openUrl(link)
|
||||
|
||||
override fun onDestroy() {
|
||||
modelScope.launch { clearOnrampCacheUseCase.invoke() }
|
||||
quotesTaskScheduler.cancelTask()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
package com.tangem.features.onramp.main.ui
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.text.ClickableText
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.PrimaryButton
|
||||
import com.tangem.core.ui.extensions.appendColored
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.onramp.impl.R
|
||||
import com.tangem.features.onramp.main.entity.OnrampMainComponentUM
|
||||
import com.tangem.features.onramp.main.entity.OnrampProviderBlockUM
|
||||
|
||||
private const val TERMS_OF_USE_KEY = "termsOfUse"
|
||||
private const val PRIVACY_POLICY_KEY = "privacyPolicy"
|
||||
|
||||
@Composable
|
||||
internal fun OnrampButtonComponent(state: OnrampMainComponentUM) {
|
||||
val content = state as? OnrampMainComponentUM.Content
|
||||
val providerState = content?.providerBlockState as? OnrampProviderBlockUM.Content
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.navigationBarsPadding()
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
OnrampTosText(providerState)
|
||||
PrimaryButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = stringResource(id = R.string.common_buy),
|
||||
onClick = state.buyButtonConfig.onClick,
|
||||
enabled = state.buyButtonConfig.enabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun OnrampTosText(provider: OnrampProviderBlockUM.Content?) {
|
||||
val termsOfUse = stringResource(R.string.common_terms_of_use)
|
||||
val privacyPolicy = stringResource(R.string.common_privacy_policy)
|
||||
val tosText = stringResource(R.string.onramp_legal, termsOfUse, privacyPolicy)
|
||||
|
||||
val clickableAnnotation = buildAnnotatedString {
|
||||
append(tosText.substringBefore(termsOfUse))
|
||||
|
||||
pushStringAnnotation(TERMS_OF_USE_KEY, "")
|
||||
appendColored(termsOfUse, TangemTheme.colors.text.accent)
|
||||
pop()
|
||||
|
||||
append(tosText.substringAfter(termsOfUse).substringBefore(privacyPolicy))
|
||||
|
||||
pushStringAnnotation(PRIVACY_POLICY_KEY, "")
|
||||
appendColored(privacyPolicy, TangemTheme.colors.text.accent)
|
||||
pop()
|
||||
}
|
||||
|
||||
AnimatedContent(
|
||||
targetState = provider,
|
||||
transitionSpec = { fadeIn().togetherWith(fadeOut()) },
|
||||
label = "Onramp Legal Info Animation",
|
||||
) { state ->
|
||||
val termsOfUseLink = provider?.termsOfUseLink
|
||||
val privacyPolicyLink = provider?.privacyPolicyLink
|
||||
|
||||
if (state != null && termsOfUseLink != null && privacyPolicyLink != null) {
|
||||
ClickableText(
|
||||
text = clickableAnnotation,
|
||||
style = TangemTheme.typography.caption2.copy(
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
textAlign = TextAlign.Center,
|
||||
),
|
||||
onClick = { offset ->
|
||||
clickableAnnotation.getStringAnnotations(
|
||||
tag = TERMS_OF_USE_KEY,
|
||||
start = offset,
|
||||
end = offset,
|
||||
).firstOrNull()?.let {
|
||||
state.onLinkClick(termsOfUseLink)
|
||||
}
|
||||
|
||||
clickableAnnotation.getStringAnnotations(
|
||||
tag = PRIVACY_POLICY_KEY,
|
||||
start = offset,
|
||||
end = offset,
|
||||
).firstOrNull()?.let {
|
||||
state.onLinkClick(privacyPolicyLink)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,16 +11,13 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.tangem.core.ui.components.CircleShimmer
|
||||
import com.tangem.core.ui.components.PrimaryButton
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.appbar.TangemTopAppBar
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.WindowInsetsZero
|
||||
import com.tangem.features.onramp.impl.R
|
||||
import com.tangem.features.onramp.main.entity.OnrampMainComponentUM
|
||||
|
||||
@Composable
|
||||
|
|
@ -49,15 +46,7 @@ internal fun OnrampMainComponentContent(state: OnrampMainComponentUM, modifier:
|
|||
}
|
||||
},
|
||||
floatingActionButton = {
|
||||
PrimaryButton(
|
||||
modifier = Modifier
|
||||
.navigationBarsPadding()
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16)
|
||||
.fillMaxWidth(),
|
||||
text = stringResource(id = R.string.common_buy),
|
||||
onClick = state.buyButtonConfig.onClick,
|
||||
enabled = state.buyButtonConfig.enabled,
|
||||
)
|
||||
OnrampButtonComponent(state)
|
||||
},
|
||||
floatingActionButtonPosition = FabPosition.Center,
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue