Updated on 2026-08-14

This commit is contained in:
Tangem 2023-06-28 21:49:51 +08:00
parent b97ea5faf8
commit 6145f3c5db
16 changed files with 716 additions and 478 deletions

View file

@ -170,6 +170,14 @@ internal object WalletPreviewData {
),
)
val manageButtons = persistentListOf(
WalletManageButton.Buy(onClick = {}),
WalletManageButton.Send(onClick = {}),
WalletManageButton.Receive(onClick = {}),
WalletManageButton.Exchange(onClick = {}),
WalletManageButton.CopyAddress(onClick = {}),
)
val multicurrencyWalletScreenState = WalletStateHolder.MultiCurrencyContent(
onBackClick = {},
topBarConfig = walletTopBarConfig,
@ -273,5 +281,6 @@ internal object WalletPreviewData {
WalletNotification.NeedToBackup(onClick = {}),
WalletNotification.ScanCard(onClick = {}),
),
buttons = manageButtons,
)
}

View file

@ -21,9 +21,10 @@ 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.datasource.CollectionPreviewParameterProvider
import com.tangem.core.ui.components.BackgroundActionButton
import com.tangem.core.ui.components.PrimaryButton
import com.tangem.core.ui.components.SecondaryButton
import com.tangem.core.ui.components.buttons.actions.ActionConfig
import com.tangem.core.ui.components.buttons.actions.BackgroundActionButton
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
@ -214,16 +215,20 @@ private fun TopBar(
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
) {
BackgroundActionButton(
config = ActionConfig(
text = stringResource(id = R.string.organize_tokens_sort_by_balance),
iconResId = R.drawable.ic_sort_24,
onClick = config.onSortByBalanceClick,
),
modifier = Modifier.weight(1f),
text = stringResource(id = R.string.organize_tokens_sort_by_balance),
iconResId = R.drawable.ic_sort_24,
onClick = config.onSortByBalanceClick,
)
BackgroundActionButton(
config = ActionConfig(
text = stringResource(id = R.string.organize_tokens_group),
iconResId = R.drawable.ic_group_24,
onClick = config.onGroupByNetworkClick,
),
modifier = Modifier.weight(1f),
text = stringResource(id = R.string.organize_tokens_group),
iconResId = R.drawable.ic_group_24,
onClick = config.onGroupByNetworkClick,
)
}
}

View file

@ -0,0 +1,79 @@
package com.tangem.feature.wallet.presentation.wallet.state
import com.tangem.core.ui.components.buttons.actions.ActionConfig
import com.tangem.feature.wallet.impl.R
/**
* Wallet manage button state
*
* @param config action config
*
[REDACTED_AUTHOR]
*/
sealed class WalletManageButton(val config: ActionConfig) {
/**
* Buy
*
* @param onClick lambda be invoked when manage button is clicked
*/
data class Buy(val onClick: () -> Unit) : WalletManageButton(
config = ActionConfig(
text = "Buy",
iconResId = R.drawable.ic_plus_24,
onClick = onClick,
),
)
/**
* Send
*
* @param onClick lambda be invoked when manage button is clicked
*/
data class Send(val onClick: () -> Unit) : WalletManageButton(
config = ActionConfig(
text = "Send",
iconResId = R.drawable.ic_arrow_up_24,
onClick = onClick,
),
)
/**
* Receive
*
* @param onClick lambda be invoked when manage button is clicked
*/
data class Receive(val onClick: () -> Unit) : WalletManageButton(
config = ActionConfig(
text = "Receive",
iconResId = R.drawable.ic_arrow_down_24,
onClick = onClick,
),
)
/**
* Exchange
*
* @param onClick lambda be invoked when manage button is clicked
*/
data class Exchange(val onClick: () -> Unit) : WalletManageButton(
config = ActionConfig(
text = "Exchange",
iconResId = R.drawable.ic_exchange_vertical_24,
onClick = onClick,
),
)
/**
* Copy address
*
* @param onClick lambda be invoked when manage button is clicked
*/
data class CopyAddress(val onClick: () -> Unit) : WalletManageButton(
config = ActionConfig(
text = "Copy address",
iconResId = R.drawable.ic_copy_24,
onClick = onClick,
),
)
}

View file

@ -0,0 +1,64 @@
package com.tangem.feature.wallet.presentation.wallet.state
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.rememberScrollState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.key
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import com.tangem.core.ui.components.buttons.actions.ActionButton
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
import kotlinx.collections.immutable.ImmutableList
/**
* Wallet manage buttons
*
* @param buttons manage buttons
*
[REDACTED_AUTHOR]
*/
@Composable
internal fun WalletManageButtons(buttons: ImmutableList<WalletManageButton>) {
Row(
modifier = Modifier
.horizontalScroll(state = rememberScrollState())
.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing8),
) {
buttons.forEach { button ->
key(button.config.text) {
ActionButton(config = button.config)
}
}
}
}
@Preview
@Composable
private fun Preview_WalletManageButtons_Light(
@PreviewParameter(WalletManageButtonProvider::class) buttons: ImmutableList<WalletManageButton>,
) {
TangemTheme(isDark = false) {
WalletManageButtons(buttons = buttons)
}
}
@Preview
@Composable
private fun Preview_WalletManageButtons_Dark(
@PreviewParameter(WalletManageButtonProvider::class) buttons: ImmutableList<WalletManageButton>,
) {
TangemTheme(isDark = true) {
WalletManageButtons(buttons = buttons)
}
}
private class WalletManageButtonProvider : CollectionPreviewParameterProvider<ImmutableList<WalletManageButton>>(
collection = listOf(WalletPreviewData.manageButtons),
)

View file

@ -53,6 +53,7 @@ internal sealed class WalletStateHolder(
* @property wallets list of wallets states
* @property contentItems content items
* @property notifications notifications
* @property buttons manage buttons
*/
data class SingleCurrencyContent(
override val onBackClick: () -> Unit,
@ -61,5 +62,6 @@ internal sealed class WalletStateHolder(
override val wallets: ImmutableList<WalletCardState>,
override val contentItems: ImmutableList<WalletContentItemState.SingleCurrencyItem>,
override val notifications: ImmutableList<WalletNotification>,
val buttons: ImmutableList<WalletManageButton>,
) : WalletStateHolder(onBackClick, topBarConfig, selectedWallet, wallets, contentItems, notifications)
}

View file

@ -1,28 +1,26 @@
package com.tangem.feature.wallet.presentation.wallet.ui
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.Scaffold
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.composed
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import com.tangem.core.ui.components.RoundedActionButton
import com.tangem.core.ui.components.buttons.actions.ActionConfig
import com.tangem.core.ui.components.buttons.actions.RoundedActionButton
import com.tangem.core.ui.components.notifications.Notification
import com.tangem.core.ui.components.transactions.Transaction
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.wallet.impl.R
@ -30,9 +28,11 @@ import com.tangem.feature.wallet.presentation.common.WalletPreviewData
import com.tangem.feature.wallet.presentation.common.component.NetworkGroupItem
import com.tangem.feature.wallet.presentation.common.component.TokenItem
import com.tangem.feature.wallet.presentation.wallet.state.WalletContentItemState
import com.tangem.feature.wallet.presentation.wallet.state.WalletManageButtons
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder
import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletCardsList
import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletTopBar
import com.tangem.feature.wallet.presentation.wallet.ui.decorations.walletContentItemDecoration
/**
* Wallet screen
@ -49,15 +49,29 @@ internal fun WalletScreen(state: WalletStateHolder, modifier: Modifier = Modifie
topBar = { WalletTopBar(config = state.topBarConfig) },
containerColor = TangemTheme.colors.background.secondary,
) { scaffoldPaddings ->
val lastContentItemIndex = remember(state.contentItems) { state.contentItems.lastIndex }
LazyColumn(
modifier = modifier
.padding(scaffoldPaddings)
.padding(paddingValues = scaffoldPaddings)
.fillMaxSize(),
contentPadding = PaddingValues(
horizontal = TangemTheme.dimens.spacing16,
vertical = TangemTheme.dimens.spacing8,
),
horizontalAlignment = Alignment.CenterHorizontally,
) {
item { WalletCardsList(wallets = state.wallets) }
item {
WalletCardsList(
wallets = state.wallets,
modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing12),
)
}
if (state is WalletStateHolder.SingleCurrencyContent) {
item { WalletManageButtons(buttons = state.buttons) }
}
items(items = state.notifications, itemContent = { Notification(state = it.state) })
itemsIndexed(
items = state.contentItems,
@ -70,36 +84,19 @@ internal fun WalletScreen(state: WalletStateHolder, modifier: Modifier = Modifie
is WalletContentItemState.SingleCurrencyItem.Transaction -> index
}
},
) { index, item ->
val itemModifier = Modifier
.padding(horizontal = TangemTheme.dimens.spacing16)
.clipFirstAndLastItems(index, lastContentItemIndex)
when (item) {
is WalletContentItemState.MultiCurrencyItem.NetworkGroupTitle -> {
NetworkGroupItem(networkName = item.networkName, modifier = itemModifier)
}
is WalletContentItemState.MultiCurrencyItem.Token -> {
TokenItem(state = item.state, modifier = itemModifier)
}
is WalletContentItemState.SingleCurrencyItem.Title -> {
SingleCurrencyTitle(config = item, modifier = itemModifier)
}
is WalletContentItemState.SingleCurrencyItem.TransactionGroupTitle -> {
TransactionGroupTitle(config = item, modifier = itemModifier)
}
is WalletContentItemState.SingleCurrencyItem.Transaction -> {
Transaction(state = item.state, modifier = itemModifier)
}
}
}
itemContent = { index, item ->
ContentItem(currentIndex = index, lastIndex = state.contentItems.lastIndex, item = item)
},
)
if (state is WalletStateHolder.MultiCurrencyContent) {
item {
RoundedActionButton(
text = stringResource(id = R.string.organize_tokens_title),
iconResId = R.drawable.ic_filter_24,
onClick = state.onOrganizeTokensClick,
config = ActionConfig(
text = stringResource(id = R.string.organize_tokens_title),
iconResId = R.drawable.ic_filter_24,
onClick = state.onOrganizeTokensClick,
),
modifier = Modifier.padding(top = TangemTheme.dimens.spacing14),
)
}
@ -108,6 +105,29 @@ internal fun WalletScreen(state: WalletStateHolder, modifier: Modifier = Modifie
}
}
@Composable
private fun ContentItem(currentIndex: Int, lastIndex: Int, item: WalletContentItemState) {
val itemModifier = Modifier.walletContentItemDecoration(currentIndex, lastIndex)
when (item) {
is WalletContentItemState.MultiCurrencyItem.NetworkGroupTitle -> {
NetworkGroupItem(networkName = item.networkName, modifier = itemModifier)
}
is WalletContentItemState.MultiCurrencyItem.Token -> {
TokenItem(state = item.state, modifier = itemModifier)
}
is WalletContentItemState.SingleCurrencyItem.Title -> {
SingleCurrencyTitle(config = item, modifier = itemModifier)
}
is WalletContentItemState.SingleCurrencyItem.TransactionGroupTitle -> {
TransactionGroupTitle(config = item, modifier = itemModifier)
}
is WalletContentItemState.SingleCurrencyItem.Transaction -> {
Transaction(state = item.state, modifier = itemModifier)
}
}
}
@Composable
private fun SingleCurrencyTitle(
config: WalletContentItemState.SingleCurrencyItem.Title,
@ -166,31 +186,6 @@ private fun TransactionGroupTitle(
)
}
private fun Modifier.clipFirstAndLastItems(index: Int, lastItemIndex: Int): Modifier = composed {
when (index) {
0 -> {
this
.padding(top = TangemTheme.dimens.spacing14)
.clip(
RoundedCornerShape(
topStart = TangemTheme.dimens.radius16,
topEnd = TangemTheme.dimens.radius16,
),
)
}
lastItemIndex -> {
this
.clip(
RoundedCornerShape(
bottomStart = TangemTheme.dimens.radius16,
bottomEnd = TangemTheme.dimens.radius16,
),
)
}
else -> this
}
}
// region Preview
@Preview(showBackground = true, widthDp = 360)
@Composable

View file

@ -23,21 +23,21 @@ import kotlinx.collections.immutable.persistentListOf
/**
* Wallets list
*
* @param wallets list of wallet state
* @param wallets list of wallet state
* @param modifier modifier
*
[REDACTED_AUTHOR]
*/
@OptIn(ExperimentalFoundationApi::class)
@Composable
internal fun WalletCardsList(wallets: ImmutableList<WalletCardState>) {
internal fun WalletCardsList(wallets: ImmutableList<WalletCardState>, modifier: Modifier = Modifier) {
val horizontalCardPadding = TangemTheme.dimens.spacing16
val itemWidth = LocalConfiguration.current.screenWidthDp.dp - horizontalCardPadding * 2
val lazyListState = rememberLazyListState()
LazyRow(
modifier = Modifier.background(color = TangemTheme.colors.background.secondary),
modifier = modifier.background(color = TangemTheme.colors.background.secondary),
state = lazyListState,
contentPadding = PaddingValues(horizontal = TangemTheme.dimens.spacing16),
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
flingBehavior = rememberSnapFlingBehavior(lazyListState = lazyListState),
) {

View file

@ -0,0 +1,36 @@
package com.tangem.feature.wallet.presentation.wallet.ui.decorations
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.draw.clip
import com.tangem.core.ui.res.TangemTheme
/**
[REDACTED_AUTHOR]
*/
internal fun Modifier.walletContentItemDecoration(currentIndex: Int, lastItemIndex: Int): Modifier = composed {
when (currentIndex) {
0 -> {
this
.padding(top = TangemTheme.dimens.spacing14)
.clip(
RoundedCornerShape(
topStart = TangemTheme.dimens.radius16,
topEnd = TangemTheme.dimens.radius16,
),
)
}
lastItemIndex -> {
this
.clip(
RoundedCornerShape(
bottomStart = TangemTheme.dimens.radius16,
bottomEnd = TangemTheme.dimens.radius16,
),
)
}
else -> this
}
}