Updated on 2026-08-14
This commit is contained in:
parent
6b187159d3
commit
29d6298fca
4 changed files with 109 additions and 20 deletions
|
|
@ -11,6 +11,7 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.DpSize
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
|
@ -20,9 +21,45 @@ import com.tangem.core.ui.res.TangemTheme
|
|||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun TangemTooltip(text: String, content: @Composable (Modifier) -> Unit, modifier: Modifier = Modifier) {
|
||||
InternalTangemTooltip(
|
||||
modifier = modifier,
|
||||
tooltipContent = {
|
||||
Text(
|
||||
modifier = Modifier.background(TangemTheme.colors.icon.secondary),
|
||||
text = text,
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.primary2,
|
||||
)
|
||||
},
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TangemTooltip(text: AnnotatedString, content: @Composable (Modifier) -> Unit, modifier: Modifier = Modifier) {
|
||||
InternalTangemTooltip(
|
||||
modifier = modifier,
|
||||
tooltipContent = {
|
||||
Text(
|
||||
modifier = Modifier.background(TangemTheme.colors.icon.secondary),
|
||||
text = text,
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.primary2,
|
||||
)
|
||||
},
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun InternalTangemTooltip(
|
||||
tooltipContent: @Composable () -> Unit,
|
||||
content: @Composable (Modifier) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val tooltipState = rememberTooltipState(isPersistent = true)
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
TooltipBox(
|
||||
|
|
@ -37,14 +74,7 @@ fun TangemTooltip(text: String, content: @Composable (Modifier) -> Unit, modifie
|
|||
caretSize = DpSize(width = 14.dp, height = 8.dp),
|
||||
contentColor = TangemTheme.colors.text.primary2,
|
||||
containerColor = TangemTheme.colors.icon.secondary,
|
||||
content = {
|
||||
Text(
|
||||
modifier = Modifier.background(TangemTheme.colors.icon.secondary),
|
||||
text = text,
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.primary2,
|
||||
)
|
||||
},
|
||||
content = { tooltipContent() },
|
||||
)
|
||||
},
|
||||
content = {
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ internal class DefaultFeeSelectorBlockComponent @AssistedInject constructor(
|
|||
|
||||
FeeSelectorBlockContent(
|
||||
state = state,
|
||||
onReadMoreClick = model::onReadMoreClicked,
|
||||
modifier = modifier
|
||||
.conditional(params.feeDisplaySource == FeeSelectorParams.FeeDisplaySource.Screen) {
|
||||
Modifier.clickable {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.tangem.blockchain.common.AmountType
|
|||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.transaction.usecase.IsFeeApproximateUseCase
|
||||
|
|
@ -26,6 +27,7 @@ import kotlinx.coroutines.flow.StateFlow
|
|||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
|
|
@ -33,13 +35,14 @@ import javax.inject.Inject
|
|||
@ModelScoped
|
||||
internal class FeeSelectorModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
private val urlOpener: UrlOpener,
|
||||
private val isFeeApproximateUseCase: IsFeeApproximateUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val feeSelectorReloadListener: FeeSelectorReloadListener,
|
||||
private val feeSelectorCheckReloadListener: FeeSelectorCheckReloadListener,
|
||||
private val feeSelectorCheckReloadTrigger: FeeSelectorCheckReloadTrigger,
|
||||
private val feeSelectorAlertFactory: FeeSelectorAlertFactory,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
) : Model(), FeeSelectorIntents, FeeSelectorModelCallback {
|
||||
|
||||
private val params = paramsContainer.require<FeeSelectorParams>()
|
||||
|
|
@ -62,6 +65,16 @@ internal class FeeSelectorModel @Inject constructor(
|
|||
uiState.value = feeSelectorUM
|
||||
}
|
||||
|
||||
fun onReadMoreClicked() {
|
||||
val locale = if (Locale.getDefault().language == RU_LOCALE) RU_LOCALE else EN_LOCALE
|
||||
val url = buildString {
|
||||
append(FEE_READ_MORE_URL_FIRST_PART)
|
||||
append(locale)
|
||||
append(FEE_READ_MORE_URL_SECOND_PART)
|
||||
}
|
||||
urlOpener.openUrl(url)
|
||||
}
|
||||
|
||||
private fun initAppCurrency() {
|
||||
modelScope.launch {
|
||||
appCurrency = getSelectedAppCurrencyUseCase.invokeSync().getOrElse { AppCurrency.Default }
|
||||
|
|
@ -174,4 +187,11 @@ internal class FeeSelectorModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val RU_LOCALE = "ru"
|
||||
const val EN_LOCALE = "en"
|
||||
const val FEE_READ_MORE_URL_FIRST_PART = "https://tangem.com/"
|
||||
const val FEE_READ_MORE_URL_SECOND_PART = "/blog/post/what-is-a-transaction-fee-and-why-do-we-need-it/"
|
||||
}
|
||||
}
|
||||
|
|
@ -6,9 +6,11 @@ import androidx.compose.foundation.layout.*
|
|||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.*
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Devices
|
||||
|
|
@ -23,6 +25,7 @@ import com.tangem.blockchain.common.transaction.TransactionFee
|
|||
import com.tangem.common.ui.amountScreen.utils.getFiatString
|
||||
import com.tangem.core.ui.components.TextShimmer
|
||||
import com.tangem.core.ui.components.atoms.text.EllipsisText
|
||||
import com.tangem.core.ui.components.tooltip.TangemTooltip
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.format.bigdecimal.BigDecimalFormatConstants.EMPTY_BALANCE_SIGN
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
|
|
@ -37,8 +40,14 @@ import com.tangem.features.send.v2.impl.R
|
|||
import kotlinx.collections.immutable.persistentListOf
|
||||
import java.math.BigDecimal
|
||||
|
||||
private const val READ_MORE_TAG = "READ_MORE"
|
||||
|
||||
@Composable
|
||||
internal fun FeeSelectorBlockContent(state: FeeSelectorUM, modifier: Modifier = Modifier) {
|
||||
internal fun FeeSelectorBlockContent(
|
||||
state: FeeSelectorUM,
|
||||
onReadMoreClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.background(TangemTheme.colors.background.action)
|
||||
|
|
@ -51,14 +60,14 @@ internal fun FeeSelectorBlockContent(state: FeeSelectorUM, modifier: Modifier =
|
|||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.accent,
|
||||
)
|
||||
FeeSelectorDescription(state = state)
|
||||
FeeSelectorDescription(state = state, onReadMoreClick = onReadMoreClick)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun FeeSelectorDescription(state: FeeSelectorUM, modifier: Modifier = Modifier) {
|
||||
private fun FeeSelectorDescription(state: FeeSelectorUM, onReadMoreClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||
Row(modifier = modifier, horizontalArrangement = Arrangement.SpaceBetween) {
|
||||
FeeSelectorStaticPart(modifier = Modifier.weight(1f))
|
||||
FeeSelectorStaticPart(modifier = Modifier.weight(1f), onReadMoreClick = onReadMoreClick)
|
||||
when (state) {
|
||||
is FeeSelectorUM.Content -> FeeContent(state)
|
||||
is FeeSelectorUM.Loading -> FeeLoading()
|
||||
|
|
@ -68,7 +77,7 @@ private fun FeeSelectorDescription(state: FeeSelectorUM, modifier: Modifier = Mo
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun FeeSelectorStaticPart(modifier: Modifier = Modifier) {
|
||||
private fun FeeSelectorStaticPart(onReadMoreClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||
Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
|
|
@ -80,13 +89,42 @@ private fun FeeSelectorStaticPart(modifier: Modifier = Modifier) {
|
|||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
Icon(
|
||||
val linkText = stringResourceSafe(R.string.common_read_more)
|
||||
val fullString = stringResourceSafe(R.string.common_fee_selector_footer, linkText)
|
||||
val linkTextPosition = fullString.length - linkText.length
|
||||
val defaultStyle = TangemTheme.colors.text.primary2
|
||||
val linkStyle = TangemTheme.colors.text.accent
|
||||
val annotatedString = remember(defaultStyle, linkStyle) {
|
||||
buildAnnotatedString {
|
||||
withStyle(SpanStyle(defaultStyle)) {
|
||||
append(fullString.substring(0, linkTextPosition))
|
||||
}
|
||||
withLink(
|
||||
link = LinkAnnotation.Clickable(
|
||||
tag = READ_MORE_TAG,
|
||||
linkInteractionListener = { onReadMoreClick() },
|
||||
),
|
||||
block = {
|
||||
withStyle(SpanStyle(linkStyle)) {
|
||||
append(fullString.substring(linkTextPosition, fullString.length))
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
TangemTooltip(
|
||||
text = annotatedString,
|
||||
modifier = Modifier
|
||||
.padding(start = TangemTheme.dimens.spacing6)
|
||||
.size(TangemTheme.dimens.size16),
|
||||
painter = painterResource(id = R.drawable.ic_token_info_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
content = { contentModifier ->
|
||||
Icon(
|
||||
modifier = contentModifier.size(TangemTheme.dimens.size16),
|
||||
painter = painterResource(id = R.drawable.ic_token_info_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -148,7 +186,7 @@ private fun FeeContent(state: FeeSelectorUM.Content, modifier: Modifier = Modifi
|
|||
@Composable
|
||||
private fun FeeSelectorBlockContent_Preview(@PreviewParameter(FeeSelectorUMProvider::class) state: FeeSelectorUM) {
|
||||
TangemThemePreview {
|
||||
FeeSelectorBlockContent(modifier = Modifier.fillMaxWidth(), state = state)
|
||||
FeeSelectorBlockContent(modifier = Modifier.fillMaxWidth(), state = state, onReadMoreClick = {})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue