Updated on 2026-08-14
This commit is contained in:
parent
0b78c692ee
commit
16ebea436f
10 changed files with 101 additions and 79 deletions
|
|
@ -94,16 +94,17 @@ fun TangemHeaderRow(
|
|||
AnimatedVisibility(
|
||||
visible = subtitle != null,
|
||||
) {
|
||||
val wrappedSubtitle = remember(this) { requireNotNull(subtitle) }
|
||||
Text(
|
||||
text = wrappedSubtitle.orMaskWithStars(isBalanceHidden).resolveAnnotatedReference(),
|
||||
style = TangemTheme.typography2.captionSemibold12,
|
||||
color = TangemTheme.colors2.text.neutral.secondary,
|
||||
maxLines = 1,
|
||||
modifier = Modifier
|
||||
.testTag(tag = TokenElementsTestTags.TOKEN_CRYPTO_AMOUNT)
|
||||
.padding(start = TangemTheme.dimens2.x1),
|
||||
)
|
||||
if (subtitle != null) {
|
||||
Text(
|
||||
text = subtitle.orMaskWithStars(isBalanceHidden).resolveAnnotatedReference(),
|
||||
style = TangemTheme.typography2.captionSemibold12,
|
||||
color = TangemTheme.colors2.text.neutral.secondary,
|
||||
maxLines = 1,
|
||||
modifier = Modifier
|
||||
.testTag(tag = TokenElementsTestTags.TOKEN_CRYPTO_AMOUNT)
|
||||
.padding(start = TangemTheme.dimens2.x1),
|
||||
)
|
||||
}
|
||||
}
|
||||
SpacerWMax()
|
||||
TangemRowTail(tangemRowTailUM = tailUM)
|
||||
|
|
@ -165,16 +166,17 @@ fun TangemHeaderRow(
|
|||
AnimatedVisibility(
|
||||
visible = subtitle != null,
|
||||
) {
|
||||
val wrappedSubtitle = remember(this) { requireNotNull(subtitle) }
|
||||
Text(
|
||||
text = wrappedSubtitle.orMaskWithStars(isBalanceHidden).resolveAnnotatedReference(),
|
||||
style = TangemTheme.typography2.captionSemibold12,
|
||||
color = TangemTheme.colors2.text.neutral.secondary,
|
||||
maxLines = 1,
|
||||
modifier = Modifier
|
||||
.testTag(tag = TokenElementsTestTags.TOKEN_CRYPTO_AMOUNT)
|
||||
.padding(start = TangemTheme.dimens2.x1),
|
||||
)
|
||||
if (subtitle != null) {
|
||||
Text(
|
||||
text = subtitle.orMaskWithStars(isBalanceHidden).resolveAnnotatedReference(),
|
||||
style = TangemTheme.typography2.captionSemibold12,
|
||||
color = TangemTheme.colors2.text.neutral.secondary,
|
||||
maxLines = 1,
|
||||
modifier = Modifier
|
||||
.testTag(tag = TokenElementsTestTags.TOKEN_CRYPTO_AMOUNT)
|
||||
.padding(start = TangemTheme.dimens2.x1),
|
||||
)
|
||||
}
|
||||
}
|
||||
SpacerWMax()
|
||||
TangemRowTail(
|
||||
|
|
|
|||
|
|
@ -263,41 +263,41 @@ private fun TangemTopBarTitle(title: TextReference?, @DrawableRes titleIconRes:
|
|||
enter = slideInVertically(initialOffsetY = { it / 2 }) + fadeIn(),
|
||||
exit = slideOutVertically(targetOffsetY = { it / 2 }) + fadeOut(),
|
||||
) {
|
||||
val wrappedTitle = remember(this) { requireNotNull(title) }
|
||||
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(
|
||||
space = TangemTheme.dimens2.x1,
|
||||
alignment = Alignment.CenterHorizontally,
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = titleIconRes != null,
|
||||
label = "Title Icon Visibility",
|
||||
if (title != null) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(
|
||||
space = TangemTheme.dimens2.x1,
|
||||
alignment = Alignment.CenterHorizontally,
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
val wrappedTitleIconRes = remember(this) {
|
||||
requireNotNull(titleIconRes)
|
||||
AnimatedVisibility(
|
||||
visible = titleIconRes != null,
|
||||
label = "Title Icon Visibility",
|
||||
) {
|
||||
val wrappedTitleIconRes = remember(this) {
|
||||
requireNotNull(titleIconRes)
|
||||
}
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(id = wrappedTitleIconRes),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors2.graphic.neutral.primary,
|
||||
modifier = Modifier.size(TangemTheme.dimens2.x4),
|
||||
)
|
||||
}
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(id = wrappedTitleIconRes),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors2.graphic.neutral.primary,
|
||||
modifier = Modifier.size(TangemTheme.dimens2.x4),
|
||||
|
||||
Text(
|
||||
text = title.resolveAnnotatedReference(),
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
style = TangemTheme.typography2.headingSemibold17,
|
||||
textAlign = TextAlign.Center,
|
||||
maxLines = 1,
|
||||
autoSize = TextAutoSize.StepBased(
|
||||
minFontSize = TangemTheme.typography2.captionRegular12.fontSize,
|
||||
maxFontSize = TangemTheme.typography2.headingSemibold17.fontSize,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = wrappedTitle.resolveAnnotatedReference(),
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
style = TangemTheme.typography2.headingSemibold17,
|
||||
textAlign = TextAlign.Center,
|
||||
maxLines = 1,
|
||||
autoSize = TextAutoSize.StepBased(
|
||||
minFontSize = TangemTheme.typography2.captionRegular12.fontSize,
|
||||
maxFontSize = TangemTheme.typography2.headingSemibold17.fontSize,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ object StringsSigns {
|
|||
const val INFINITY_SIGN = "∞"
|
||||
const val NON_BREAKING_SPACE = '\u00A0'
|
||||
const val PERCENT = "%"
|
||||
const val THREE_STARS = "\u2217\u2217\u2217"
|
||||
const val ASTERISK = "\u2217"
|
||||
const val THREE_STARS = "***"
|
||||
const val ASTERISK = "*"
|
||||
const val PASSWORD_VISUAL_CHAR = '\u2022'
|
||||
const val APPROXIMATE = "≈"
|
||||
const val WHITE_SPACE = " "
|
||||
|
|
|
|||
|
|
@ -99,7 +99,6 @@ internal class DefaultSearchComponent(
|
|||
params = SearchTokenSelectorComponent.Params(
|
||||
entries = config.entries,
|
||||
appCurrency = config.appCurrency,
|
||||
isBalanceHidden = config.isBalanceHidden,
|
||||
onTokenSelected = config.onTokenSelected,
|
||||
onDismiss = config.onDismiss,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ internal sealed interface SearchBottomSheetRoute {
|
|||
data class TokenSelector(
|
||||
val entries: List<UserAssetEntry>,
|
||||
val appCurrency: AppCurrency,
|
||||
val isBalanceHidden: Boolean,
|
||||
val onTokenSelected: (UserAssetEntry) -> Unit,
|
||||
val onDismiss: () -> Unit,
|
||||
) : SearchBottomSheetRoute
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ internal class SearchTokenSelectorComponent @AssistedInject constructor(
|
|||
data class Params(
|
||||
val entries: List<UserAssetEntry>,
|
||||
val appCurrency: AppCurrency,
|
||||
val isBalanceHidden: Boolean,
|
||||
val onTokenSelected: (UserAssetEntry) -> Unit,
|
||||
val onDismiss: () -> Unit,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -229,7 +229,6 @@ internal class SearchModel @Inject constructor(
|
|||
SearchBottomSheetRoute.TokenSelector(
|
||||
entries = grouped.entries,
|
||||
appCurrency = currentAppCurrency.value,
|
||||
isBalanceHidden = isBalanceHidden.value,
|
||||
onTokenSelected = ::onTokenSelectedFromGroup,
|
||||
onDismiss = { bottomSheetNavigation.dismiss() },
|
||||
),
|
||||
|
|
|
|||
|
|
@ -6,25 +6,31 @@ import com.tangem.common.ui.userwallet.converter.WalletIconUMConverter
|
|||
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.ui.ds.image.DeviceIconUM
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetWalletIconUseCase
|
||||
import com.tangem.features.feed.components.search.SearchTokenSelectorComponent
|
||||
import com.tangem.features.feed.model.search.state.TokenSelectorStateController
|
||||
import com.tangem.features.feed.model.search.state.transformers.BuildTokenSelectorSectionsTransformer
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Stable
|
||||
@ModelScoped
|
||||
internal class SearchTokenSelectorModel @Inject constructor(
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
paramsContainer: ParamsContainer,
|
||||
getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
userWalletsListRepository: UserWalletsListRepository,
|
||||
private val stateController: TokenSelectorStateController,
|
||||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
private val getWalletIconUseCase: GetWalletIconUseCase,
|
||||
private val walletIconUMConverter: WalletIconUMConverter,
|
||||
) : Model() {
|
||||
|
|
@ -35,25 +41,37 @@ internal class SearchTokenSelectorModel @Inject constructor(
|
|||
get() = stateController.uiState
|
||||
|
||||
init {
|
||||
modelScope.launch(dispatchers.default) {
|
||||
val requiredWalletIds = params.entries.map { it.userWalletId }.toSet()
|
||||
val walletIcons = userWalletsListRepository.userWallets
|
||||
.filterNotNull()
|
||||
.first()
|
||||
.filter { it.walletId in requiredWalletIds }
|
||||
.associate { wallet ->
|
||||
wallet.walletId to walletIconUMConverter.convert(getWalletIconUseCase(wallet))
|
||||
}
|
||||
val requiredWalletIds = params.entries.map { it.userWalletId }.toSet()
|
||||
val walletIconsFlow = userWalletsListRepository.userWallets
|
||||
.filterNotNull()
|
||||
.map { wallets ->
|
||||
wallets
|
||||
.filter { it.walletId in requiredWalletIds }
|
||||
.associate { wallet ->
|
||||
wallet.walletId to walletIconUMConverter.convert(getWalletIconUseCase(wallet))
|
||||
}
|
||||
}
|
||||
|
||||
stateController.update(
|
||||
BuildTokenSelectorSectionsTransformer(
|
||||
entries = params.entries,
|
||||
appCurrency = params.appCurrency,
|
||||
isBalanceHidden = params.isBalanceHidden,
|
||||
walletIcons = walletIcons,
|
||||
onTokenSelected = params.onTokenSelected,
|
||||
),
|
||||
)
|
||||
modelScope.launch(dispatchers.default) {
|
||||
combine(
|
||||
walletIconsFlow,
|
||||
getBalanceHidingSettingsUseCase.isBalanceHidden(),
|
||||
::Pair,
|
||||
).collect { (walletIcons, isBalanceHidden) ->
|
||||
rebuildSections(isBalanceHidden, walletIcons)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun rebuildSections(isBalanceHidden: Boolean, walletIcons: Map<UserWalletId, DeviceIconUM>) {
|
||||
stateController.update(
|
||||
BuildTokenSelectorSectionsTransformer(
|
||||
entries = params.entries,
|
||||
appCurrency = params.appCurrency,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
walletIcons = walletIcons,
|
||||
onTokenSelected = params.onTokenSelected,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -187,6 +187,7 @@ private fun WalletContent2(
|
|||
WalletTopBar(
|
||||
topBarConfig = state.topBarConfig,
|
||||
walletBalance = walletBalance,
|
||||
isBalanceHidden = state.isHidingMode,
|
||||
behavior = behavior,
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import com.tangem.core.ui.ds.topbar.TangemTopBarActionUM
|
|||
import com.tangem.core.ui.ds.topbar.collapsing.TangemCollapsingAppBarBehavior
|
||||
import com.tangem.core.ui.ds.topbar.collapsing.rememberTangemExitUntilCollapsedScrollBehavior
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.orMaskWithStars
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.LocalRootBackgroundColor
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
@ -46,12 +47,14 @@ private const val VISIBILITY_THRESHOLD = 0.5f
|
|||
*
|
||||
* @param topBarConfig top bar config
|
||||
* @param walletBalance wallet balance text reference
|
||||
* @param isBalanceHidden whether the balance must be masked with stars
|
||||
* @param behavior collapsing behavior
|
||||
*/
|
||||
@Composable
|
||||
internal fun WalletTopBar(
|
||||
topBarConfig: WalletTopBarConfig,
|
||||
walletBalance: TextReference?,
|
||||
isBalanceHidden: Boolean,
|
||||
behavior: TangemCollapsingAppBarBehavior,
|
||||
) {
|
||||
Surface(
|
||||
|
|
@ -63,8 +66,8 @@ internal fun WalletTopBar(
|
|||
derivedStateOf { behavior.state.collapsedFraction > VISIBILITY_THRESHOLD }
|
||||
}
|
||||
|
||||
val wrappedBalance = remember(walletBalance, isWrappedBalanceShown) {
|
||||
walletBalance.takeIf { isWrappedBalanceShown }
|
||||
val wrappedBalance = remember(walletBalance, isWrappedBalanceShown, isBalanceHidden) {
|
||||
walletBalance?.orMaskWithStars(isBalanceHidden).takeIf { isWrappedBalanceShown }
|
||||
}
|
||||
|
||||
TangemTopBar(
|
||||
|
|
@ -173,6 +176,7 @@ private fun WalletTopBar_Preview() {
|
|||
WalletTopBar(
|
||||
topBarConfig = WalletTopBarConfig(),
|
||||
walletBalance = stringReference("$ 8923,05"),
|
||||
isBalanceHidden = false,
|
||||
behavior = rememberTangemExitUntilCollapsedScrollBehavior(),
|
||||
)
|
||||
}
|
||||
|
|
@ -197,6 +201,7 @@ private fun WalletTopBar_WithQrButton_Preview() {
|
|||
),
|
||||
),
|
||||
walletBalance = stringReference("$ 8923,05"),
|
||||
isBalanceHidden = false,
|
||||
behavior = rememberTangemExitUntilCollapsedScrollBehavior(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue