diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/tooltip/TangemTooltip.kt b/core/ui/src/main/java/com/tangem/core/ui/components/tooltip/TangemTooltip.kt index 65936ee076..b436ca3287 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/tooltip/TangemTooltip.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/tooltip/TangemTooltip.kt @@ -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 = { diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/DefaultFeeSelectorBlockComponent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/DefaultFeeSelectorBlockComponent.kt index 46ae5e9aad..3e1665101c 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/DefaultFeeSelectorBlockComponent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/DefaultFeeSelectorBlockComponent.kt @@ -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 { diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorModel.kt index 10971a2545..2175fa9e65 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorModel.kt @@ -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() @@ -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/" + } } \ No newline at end of file diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/ui/FeeSelectorBlockContent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/ui/FeeSelectorBlockContent.kt index 972b35167f..d35a67837b 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/ui/FeeSelectorBlockContent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/ui/FeeSelectorBlockContent.kt @@ -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 = {}) } }