Updated on 2026-08-14
This commit is contained in:
commit
cefd2a26b5
7 changed files with 119 additions and 37 deletions
|
|
@ -25,15 +25,8 @@ import com.tangem.core.ui.res.TangemThemePreview
|
|||
* */
|
||||
@Composable
|
||||
fun ChainRow(model: ChainRowUM, modifier: Modifier = Modifier, action: @Composable BoxScope.() -> Unit = {}) {
|
||||
RowContentContainer(
|
||||
modifier = modifier
|
||||
.heightIn(min = TangemTheme.dimens.size68)
|
||||
.padding(vertical = TangemTheme.dimens.spacing8)
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing8,
|
||||
end = TangemTheme.dimens.spacing12,
|
||||
),
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
|
||||
ChainRowContainer(
|
||||
modifier = modifier,
|
||||
icon = {
|
||||
CurrencyIcon(
|
||||
state = model.icon,
|
||||
|
|
@ -57,6 +50,28 @@ fun ChainRow(model: ChainRowUM, modifier: Modifier = Modifier, action: @Composab
|
|||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
inline fun ChainRowContainer(
|
||||
icon: @Composable BoxScope.() -> Unit,
|
||||
text: @Composable BoxScope.() -> Unit,
|
||||
action: @Composable BoxScope.() -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
RowContentContainer(
|
||||
modifier = modifier
|
||||
.heightIn(min = TangemTheme.dimens.size68)
|
||||
.padding(vertical = TangemTheme.dimens.spacing8)
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing8,
|
||||
end = TangemTheme.dimens.spacing12,
|
||||
),
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
|
||||
icon = icon,
|
||||
text = text,
|
||||
action = action,
|
||||
)
|
||||
}
|
||||
|
||||
// region Preview
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import com.tangem.core.ui.extensions.resolveReference
|
|||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
||||
@Composable
|
||||
internal inline fun RowContentContainer(
|
||||
inline fun RowContentContainer(
|
||||
icon: @Composable BoxScope.() -> Unit,
|
||||
text: @Composable BoxScope.() -> Unit,
|
||||
action: @Composable BoxScope.() -> Unit,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ import kotlinx.collections.immutable.toPersistentList
|
|||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
|
||||
internal class PreviewManageTokensComponent : ManageTokensComponent {
|
||||
internal class PreviewManageTokensComponent(
|
||||
private val isLoading: Boolean = false,
|
||||
) : ManageTokensComponent {
|
||||
|
||||
private val changedItemsIds: MutableSet<String> = mutableSetOf()
|
||||
|
||||
|
|
@ -94,10 +96,14 @@ internal class PreviewManageTokensComponent : ManageTokensComponent {
|
|||
}
|
||||
|
||||
private fun initItems() = List(size = 30) { index ->
|
||||
if (index < 2) {
|
||||
getCustomItem(index)
|
||||
if (isLoading) {
|
||||
CurrencyItemUM.Loading(index)
|
||||
} else {
|
||||
getBasicItem(index)
|
||||
if (index < 2) {
|
||||
getCustomItem(index)
|
||||
} else {
|
||||
getBasicItem(index)
|
||||
}
|
||||
}
|
||||
}.toPersistentList()
|
||||
|
||||
|
|
@ -138,8 +144,8 @@ internal class PreviewManageTokensComponent : ManageTokensComponent {
|
|||
network = Network(
|
||||
id = Network.ID(networkIndex.toString()),
|
||||
backendId = networkIndex.toString(),
|
||||
name = "",
|
||||
currencySymbol = "",
|
||||
name = "Network $networkIndex",
|
||||
currencySymbol = "N$networkIndex",
|
||||
derivationPath = Network.DerivationPath.Card(""),
|
||||
isTestnet = false,
|
||||
standardType = Network.StandardType.ERC20,
|
||||
|
|
@ -164,7 +170,9 @@ internal class PreviewManageTokensComponent : ManageTokensComponent {
|
|||
CurrencyItemUM.Basic.NetworksUM.Collapsed
|
||||
},
|
||||
)
|
||||
is CurrencyItemUM.Custom -> return
|
||||
is CurrencyItemUM.Custom,
|
||||
is CurrencyItemUM.Loading,
|
||||
-> return
|
||||
}
|
||||
|
||||
previewState.update { state ->
|
||||
|
|
@ -199,7 +207,9 @@ internal class PreviewManageTokensComponent : ManageTokensComponent {
|
|||
|
||||
item.copy(networks = updatedNetworks)
|
||||
}
|
||||
is CurrencyItemUM.Custom -> return
|
||||
is CurrencyItemUM.Custom,
|
||||
is CurrencyItemUM.Loading,
|
||||
-> return
|
||||
}
|
||||
|
||||
val id = "${currencyIndex}_$networkIndex"
|
||||
|
|
|
|||
|
|
@ -40,4 +40,12 @@ internal sealed class CurrencyItemUM {
|
|||
override val icon: CurrencyIconState,
|
||||
val onRemoveClick: () -> Unit,
|
||||
) : CurrencyItemUM()
|
||||
|
||||
class Loading(val index: Int) : CurrencyItemUM() {
|
||||
|
||||
override val id: ManagedCryptoCurrency.ID = ManagedCryptoCurrency.ID(value = "loading_$index")
|
||||
override val name: String = "loading"
|
||||
override val symbol: String = "loading"
|
||||
override val icon: CurrencyIconState = CurrencyIconState.Loading
|
||||
}
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ import com.tangem.pagination.BatchFetchResult
|
|||
import com.tangem.pagination.PaginationStatus
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -91,7 +91,7 @@ internal class ManageTokensModel @Inject constructor(
|
|||
popBack = router::pop,
|
||||
isInitialBatchLoading = true,
|
||||
isNextBatchLoading = false,
|
||||
items = persistentListOf(),
|
||||
items = getLoadingItems(),
|
||||
topBar = ManageTokensTopBarUM.ReadContent(
|
||||
title = resourceReference(R.string.common_search_tokens),
|
||||
onBackButtonClick = router::pop,
|
||||
|
|
@ -112,7 +112,7 @@ internal class ManageTokensModel @Inject constructor(
|
|||
popBack = router::pop,
|
||||
isInitialBatchLoading = true,
|
||||
isNextBatchLoading = false,
|
||||
items = persistentListOf(),
|
||||
items = getLoadingItems(),
|
||||
topBar = ManageTokensTopBarUM.ManageContent(
|
||||
title = resourceReference(id = R.string.main_manage_tokens),
|
||||
onBackButtonClick = router::pop,
|
||||
|
|
@ -175,9 +175,12 @@ internal class ManageTokensModel @Inject constructor(
|
|||
is PaginationStatus.InitialLoading,
|
||||
-> {
|
||||
if (state.search.isActive) {
|
||||
state
|
||||
state.copySealed(
|
||||
items = getLoadingItems(),
|
||||
)
|
||||
} else {
|
||||
state.copySealed(
|
||||
items = getLoadingItems(),
|
||||
isInitialBatchLoading = true,
|
||||
)
|
||||
}
|
||||
|
|
@ -224,6 +227,12 @@ internal class ManageTokensModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getLoadingItems(): ImmutableList<CurrencyItemUM> {
|
||||
return List(size = 10) { index ->
|
||||
CurrencyItemUM.Loading(index)
|
||||
}.toPersistentList()
|
||||
}
|
||||
|
||||
private fun consumeScrollToTopEvent() {
|
||||
this.state.update { state ->
|
||||
state.copySealed(
|
||||
|
|
|
|||
|
|
@ -29,20 +29,24 @@ import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
|||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEachIndexed
|
||||
import com.tangem.core.ui.components.BottomFade
|
||||
import com.tangem.core.ui.components.PrimaryButtonIconEnd
|
||||
import com.tangem.core.ui.components.TangemSwitch
|
||||
import com.tangem.core.ui.components.*
|
||||
import com.tangem.core.ui.components.appbar.TangemTopAppBar
|
||||
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
|
||||
import com.tangem.core.ui.components.buttons.SecondarySmallButton
|
||||
import com.tangem.core.ui.components.buttons.SmallButtonConfig
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIcon
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.components.fields.SearchBar
|
||||
import com.tangem.core.ui.components.fields.entity.SearchBarUM
|
||||
import com.tangem.core.ui.components.list.InfiniteListHandler
|
||||
import com.tangem.core.ui.components.rows.ArrowRow
|
||||
import com.tangem.core.ui.components.rows.BlockchainRow
|
||||
import com.tangem.core.ui.components.rows.ChainRow
|
||||
import com.tangem.core.ui.components.rows.ChainRowContainer
|
||||
import com.tangem.core.ui.components.rows.model.BlockchainRowUM
|
||||
import com.tangem.core.ui.components.rows.model.ChainRowUM
|
||||
import com.tangem.core.ui.components.snackbar.TangemSnackbarHost
|
||||
|
|
@ -53,6 +57,7 @@ import com.tangem.core.ui.res.LocalSnackbarHostState
|
|||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.utils.WindowInsetsZero
|
||||
import com.tangem.features.managetokens.component.ManageTokensComponent
|
||||
import com.tangem.features.managetokens.component.preview.PreviewManageTokensComponent
|
||||
import com.tangem.features.managetokens.entity.item.CurrencyItemUM
|
||||
import com.tangem.features.managetokens.entity.item.CurrencyItemUM.Basic.NetworksUM
|
||||
|
|
@ -183,14 +188,6 @@ private fun Content(state: ManageTokensUM, modifier: Modifier = Modifier) {
|
|||
BottomFade(modifier = Modifier.align(Alignment.BottomCenter))
|
||||
}
|
||||
|
||||
Crossfade(targetState = state.isInitialBatchLoading, label = "ManageTokensLoadingContent") { isVisible ->
|
||||
if (isVisible) {
|
||||
ProgressIndicator(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
EventEffect(event = state.scrollToTop) {
|
||||
listState.animateScrollToItem(index = 0)
|
||||
}
|
||||
|
|
@ -234,6 +231,11 @@ private fun Currencies(
|
|||
item = item,
|
||||
)
|
||||
}
|
||||
is CurrencyItemUM.Loading -> {
|
||||
LoadingItem(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -265,6 +267,30 @@ private fun ProgressIndicator(modifier: Modifier = Modifier) {
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LoadingItem(modifier: Modifier = Modifier) {
|
||||
ChainRowContainer(
|
||||
modifier = modifier,
|
||||
icon = {
|
||||
CurrencyIcon(CurrencyIconState.Loading)
|
||||
},
|
||||
text = {
|
||||
TextShimmer(
|
||||
modifier = Modifier.width(70.dp),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
)
|
||||
},
|
||||
action = {
|
||||
RectangleShimmer(
|
||||
modifier = Modifier.size(
|
||||
width = 24.dp,
|
||||
height = 16.dp,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CustomCurrencyItem(item: CurrencyItemUM.Custom, modifier: Modifier = Modifier) {
|
||||
ChainRow(
|
||||
|
|
@ -393,9 +419,19 @@ private fun NetworksList(
|
|||
@Preview(showBackground = true, widthDp = 360, heightDp = 800)
|
||||
@Preview(showBackground = true, widthDp = 360, heightDp = 800, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun Preview_ManageTokens() {
|
||||
private fun Preview_ManageTokens(
|
||||
@PreviewParameter(PreviewManageTokensComponentProvider::class) component: ManageTokensComponent,
|
||||
) {
|
||||
TangemThemePreview {
|
||||
PreviewManageTokensComponent().Content(Modifier.fillMaxWidth())
|
||||
component.Content(Modifier.fillMaxWidth())
|
||||
}
|
||||
}
|
||||
|
||||
private class PreviewManageTokensComponentProvider : PreviewParameterProvider<ManageTokensComponent> {
|
||||
override val values: Sequence<ManageTokensComponent>
|
||||
get() = sequenceOf(
|
||||
PreviewManageTokensComponent(),
|
||||
PreviewManageTokensComponent(isLoading = true),
|
||||
)
|
||||
}
|
||||
// endregion Preview
|
||||
|
|
@ -15,7 +15,9 @@ internal fun CurrencyItemUM.toggleExpanded(
|
|||
if (currency !is ManagedCryptoCurrency.Token) return this
|
||||
|
||||
return when (this) {
|
||||
is CurrencyItemUM.Custom -> this
|
||||
is CurrencyItemUM.Custom,
|
||||
is CurrencyItemUM.Loading,
|
||||
-> this
|
||||
is CurrencyItemUM.Basic -> {
|
||||
val isExpanded = networks !is NetworksUM.Expanded
|
||||
|
||||
|
|
@ -35,7 +37,9 @@ internal fun CurrencyItemUM.toggleExpanded(
|
|||
|
||||
internal fun CurrencyItemUM.update(currency: ManagedCryptoCurrency): CurrencyItemUM {
|
||||
return when (this) {
|
||||
is CurrencyItemUM.Custom -> this
|
||||
is CurrencyItemUM.Custom,
|
||||
is CurrencyItemUM.Loading,
|
||||
-> this
|
||||
is CurrencyItemUM.Basic -> {
|
||||
if (currency !is ManagedCryptoCurrency.Token) {
|
||||
return this
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue