Updated on 2026-08-14
This commit is contained in:
parent
1a5401519e
commit
e881eaa3de
17 changed files with 75 additions and 110 deletions
|
|
@ -3,29 +3,52 @@ package com.tangem.core.ui.components.bottomsheets
|
|||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ModalBottomSheet
|
||||
import androidx.compose.material3.SheetState
|
||||
import androidx.compose.material3.rememberModalBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
* Tangem bottom sheet with custom draggable header and config
|
||||
*
|
||||
* @param config data model containing logic and ui models
|
||||
* @param config data model containing logic and ui models
|
||||
* @param content custom bottom sheet content
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun TangemBottomSheet(
|
||||
inline fun <reified T : TangemBottomSheetConfigContent> TangemBottomSheet(
|
||||
config: TangemBottomSheetConfig,
|
||||
content: @Composable ColumnScope.(TangemBottomSheetConfigContent) -> Unit,
|
||||
crossinline content: @Composable ColumnScope.(T) -> Unit,
|
||||
) {
|
||||
ModalBottomSheet(
|
||||
onDismissRequest = config.onDismissRequest,
|
||||
sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true),
|
||||
containerColor = TangemTheme.colors.background.primary,
|
||||
shape = TangemTheme.shapes.bottomSheetLarge,
|
||||
dragHandle = { TangemBottomSheetDraggableHeader() },
|
||||
) {
|
||||
content(config.content)
|
||||
var isVisible by remember { mutableStateOf(value = config.isShow) }
|
||||
|
||||
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||
if (isVisible && config.content is T) {
|
||||
ModalBottomSheet(
|
||||
onDismissRequest = config.onDismissRequest,
|
||||
sheetState = sheetState,
|
||||
containerColor = TangemTheme.colors.background.primary,
|
||||
shape = TangemTheme.shapes.bottomSheetLarge,
|
||||
dragHandle = { TangemBottomSheetDraggableHeader() },
|
||||
) {
|
||||
content(config.content)
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(key1 = config.isShow) {
|
||||
if (config.isShow) {
|
||||
isVisible = true
|
||||
} else {
|
||||
sheetState.collapse { isVisible = false }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
suspend fun SheetState.collapse(onCollapsed: () -> Unit) {
|
||||
coroutineScope {
|
||||
launch { hide() }.invokeOnCompletion { onCollapsed() }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
package com.tangem.core.ui.components.bottomsheets
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
|
||||
/**
|
||||
* General interface for bottom sheet config model
|
||||
*/
|
||||
@Immutable
|
||||
interface TangemBottomSheetConfigContent
|
||||
|
|
@ -12,12 +12,8 @@ import com.tangem.core.ui.res.TangemTheme
|
|||
|
||||
@Composable
|
||||
fun ChooseAddressBottomSheet(config: TangemBottomSheetConfig) {
|
||||
if (config.content is ChooseAddressBottomSheetConfig && config.isShow) {
|
||||
TangemBottomSheet(config) { content ->
|
||||
ChooseAddressBottomSheetContent(
|
||||
content = content as ChooseAddressBottomSheetConfig,
|
||||
)
|
||||
}
|
||||
TangemBottomSheet(config) { content: ChooseAddressBottomSheetConfig ->
|
||||
ChooseAddressBottomSheetContent(content = content)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,9 @@ package com.tangem.core.ui.components.bottomsheets.chooseaddress
|
|||
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.core.ui.components.bottomsheets.tokenreceive.AddressModel
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
class ChooseAddressBottomSheetConfig(
|
||||
val addressModels: List<AddressModel>,
|
||||
val addressModels: ImmutableList<AddressModel>,
|
||||
val onClick: (AddressModel) -> Unit,
|
||||
) : TangemBottomSheetConfigContent
|
||||
|
|
@ -33,12 +33,8 @@ import com.tangem.core.ui.res.TangemTheme
|
|||
|
||||
@Composable
|
||||
fun TokenReceiveBottomSheet(config: TangemBottomSheetConfig) {
|
||||
if (config.content is TokenReceiveBottomSheetConfig && config.isShow) {
|
||||
TangemBottomSheet(config) { content ->
|
||||
TokenReceiveBottomSheetContent(
|
||||
content = content as TokenReceiveBottomSheetConfig,
|
||||
)
|
||||
}
|
||||
TangemBottomSheet(config) { content: TokenReceiveBottomSheetConfig ->
|
||||
TokenReceiveBottomSheetContent(content = content)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.state.component
|
|||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsLoadedTxHistoryConverter
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsLoadingTxHistoryConverter
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
|
|
@ -188,12 +189,14 @@ internal class TokenDetailsStateFactory(
|
|||
isShow = true,
|
||||
onDismissRequest = clickIntents::onDismissBottomSheet,
|
||||
content = ChooseAddressBottomSheetConfig(
|
||||
addressModels = addresses.map {
|
||||
AddressModel(
|
||||
value = it.value,
|
||||
type = AddressModel.Type.valueOf(it.type.name),
|
||||
)
|
||||
},
|
||||
addressModels = addresses
|
||||
.map { address ->
|
||||
AddressModel(
|
||||
value = address.value,
|
||||
type = AddressModel.Type.valueOf(address.type.name),
|
||||
)
|
||||
}
|
||||
.toImmutableList(),
|
||||
onClick = clickIntents::onAddressTypeSelected,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -308,8 +308,6 @@ internal object WalletPreviewData {
|
|||
}
|
||||
|
||||
val actionsBottomSheet = ActionsBottomSheetConfig(
|
||||
isShow = true,
|
||||
onDismissRequest = {},
|
||||
actions = listOf(
|
||||
TokenActionButtonConfig(
|
||||
text = TextReference.Str("Send"),
|
||||
|
|
@ -386,7 +384,6 @@ internal object WalletPreviewData {
|
|||
WalletNotification.Warning.NetworksUnreachable,
|
||||
),
|
||||
bottomSheetConfig = bottomSheet,
|
||||
tokenActionsBottomSheet = actionsBottomSheet,
|
||||
onManageTokensClick = {},
|
||||
event = consumedEvent(),
|
||||
isBalanceHidden = false,
|
||||
|
|
|
|||
|
|
@ -1,17 +1,13 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state
|
||||
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
/**
|
||||
* Config for the token actions bottom sheet
|
||||
*
|
||||
* @property isShow flag that determine if bottom sheet is shown
|
||||
* @property onDismissRequest lambda be invoked when bottom sheet is dismissed
|
||||
* @property actions actions
|
||||
*
|
||||
* @property actions actions
|
||||
*/
|
||||
internal data class ActionsBottomSheetConfig(
|
||||
val isShow: Boolean,
|
||||
val onDismissRequest: () -> Unit,
|
||||
val actions: ImmutableList<TokenActionButtonConfig>,
|
||||
)
|
||||
) : TangemBottomSheetConfigContent
|
||||
|
|
@ -28,7 +28,6 @@ internal sealed class WalletMultiCurrencyState : WalletState.ContentState() {
|
|||
override val event: StateEvent<WalletEvent> = consumedEvent(),
|
||||
override val isBalanceHidden: Boolean,
|
||||
val isManageTokensAvailable: Boolean = true,
|
||||
val tokenActionsBottomSheet: ActionsBottomSheetConfig?,
|
||||
val onManageTokensClick: () -> Unit,
|
||||
) : WalletMultiCurrencyState()
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ internal class WalletSkeletonStateConverter(
|
|||
tokensListState = WalletTokensListState.Loading(),
|
||||
notifications = persistentListOf(),
|
||||
bottomSheetConfig = null,
|
||||
tokenActionsBottomSheet = null,
|
||||
onManageTokensClick = clickIntents::onManageTokensClick,
|
||||
isBalanceHidden = isBalanceHiddenProvider(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -220,16 +220,9 @@ internal class WalletStateFactory(
|
|||
}
|
||||
|
||||
fun getStateWithTokenActionBottomSheet(tokenActions: TokenActionsState): WalletState {
|
||||
return when (val state = currentStateProvider() as WalletState.ContentState) {
|
||||
is WalletMultiCurrencyState.Content -> state.copy(
|
||||
tokenActionsBottomSheet = ActionsBottomSheetConfig(
|
||||
isShow = true,
|
||||
actions = tokenActionsProvider.provideActions(tokenActions),
|
||||
onDismissRequest = clickIntents::onDismissActionsBottomSheet,
|
||||
),
|
||||
)
|
||||
else -> state
|
||||
}
|
||||
return getStateWithOpenWalletBottomSheet(
|
||||
content = ActionsBottomSheetConfig(actions = tokenActionsProvider.provideActions(tokenActions)),
|
||||
)
|
||||
}
|
||||
|
||||
fun getLoadingTxHistoryState(itemsCountEither: Either<TxHistoryStateError, Int>): WalletState {
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ internal class WalletsUnlockStateConverter(
|
|||
tokensListState = WalletTokensListState.Loading(),
|
||||
notifications = persistentListOf(),
|
||||
bottomSheetConfig = null,
|
||||
tokenActionsBottomSheet = null,
|
||||
onManageTokensClick = clickIntents::onManageTokensClick,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -28,10 +28,7 @@ import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
|||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletAlertState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletMultiCurrencyState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletSingleCurrencyState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletBottomSheetConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletPullToRefreshConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletTokensListState
|
||||
|
|
@ -242,20 +239,11 @@ private fun ManageTokensButton(onManageTokensClick: () -> Unit) {
|
|||
@Composable
|
||||
private fun WalletBottomSheets(state: WalletState) {
|
||||
val bottomSheetConfig = (state as? WalletState.ContentState)?.bottomSheetConfig
|
||||
if (bottomSheetConfig != null && bottomSheetConfig.isShow) {
|
||||
if (bottomSheetConfig != null) {
|
||||
when (bottomSheetConfig.content) {
|
||||
is WalletBottomSheetConfig -> {
|
||||
WalletBottomSheet(config = bottomSheetConfig)
|
||||
}
|
||||
is TokenReceiveBottomSheetConfig -> {
|
||||
TokenReceiveBottomSheet(config = bottomSheetConfig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(state as? WalletMultiCurrencyState.Content)?.let { multiCurrencyState ->
|
||||
if (multiCurrencyState.tokenActionsBottomSheet != null && multiCurrencyState.tokenActionsBottomSheet.isShow) {
|
||||
TokenActionsBottomSheet(config = multiCurrencyState.tokenActionsBottomSheet)
|
||||
is WalletBottomSheetConfig -> WalletBottomSheet(config = bottomSheetConfig)
|
||||
is TokenReceiveBottomSheetConfig -> TokenReceiveBottomSheet(config = bottomSheetConfig)
|
||||
is ActionsBottomSheetConfig -> TokenActionsBottomSheet(config = bottomSheetConfig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,16 +2,14 @@ package com.tangem.feature.wallet.presentation.wallet.ui.components
|
|||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material3.BottomSheetDefaults
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ModalBottomSheet
|
||||
import androidx.compose.material3.rememberModalBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
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.SimpleSettingsRow
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
|
||||
|
|
@ -19,24 +17,16 @@ import com.tangem.feature.wallet.presentation.wallet.state.ActionsBottomSheetCon
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.TokenActionButtonConfig
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
internal fun TokenActionsBottomSheet(config: ActionsBottomSheetConfig) {
|
||||
ModalBottomSheet(
|
||||
onDismissRequest = config.onDismissRequest,
|
||||
sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true),
|
||||
containerColor = TangemTheme.colors.background.primary,
|
||||
dragHandle = { BottomSheetDefaults.DragHandle() },
|
||||
) {
|
||||
ActionsBottomSheetContent(config.actions)
|
||||
internal fun TokenActionsBottomSheet(config: TangemBottomSheetConfig) {
|
||||
TangemBottomSheet<ActionsBottomSheetConfig>(config = config) {
|
||||
ActionsBottomSheetContent(actions = it.actions)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ActionsBottomSheetContent(actions: ImmutableList<TokenActionButtonConfig>) {
|
||||
Column(
|
||||
modifier = Modifier.background(TangemTheme.colors.background.primary),
|
||||
) {
|
||||
Column(modifier = Modifier.background(TangemTheme.colors.background.primary)) {
|
||||
actions.forEach { action ->
|
||||
if (action.enabled) {
|
||||
SimpleSettingsRow(
|
||||
|
|
|
|||
|
|
@ -30,10 +30,8 @@ import com.tangem.feature.wallet.presentation.wallet.state.components.WalletBott
|
|||
*/
|
||||
@Composable
|
||||
internal fun WalletBottomSheet(config: TangemBottomSheetConfig) {
|
||||
TangemBottomSheet(config) { content ->
|
||||
BottomSheetContent(
|
||||
config = content as WalletBottomSheetConfig,
|
||||
)
|
||||
TangemBottomSheet(config) { content: WalletBottomSheetConfig ->
|
||||
BottomSheetContent(config = content)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,8 +41,6 @@ internal interface WalletClickIntents {
|
|||
|
||||
fun onTokenItemLongClick(cryptoCurrencyStatus: CryptoCurrencyStatus)
|
||||
|
||||
fun onDismissActionsBottomSheet()
|
||||
|
||||
fun onRenameClick(userWalletId: UserWalletId, name: String)
|
||||
|
||||
fun onDeleteBeforeConfirmationClick(userWalletId: UserWalletId)
|
||||
|
|
|
|||
|
|
@ -907,12 +907,8 @@ internal class WalletViewModel @Inject constructor(
|
|||
viewModelScope.launch(dispatchers.io) {
|
||||
removeCurrencyUseCase(userWallet.walletId, cryptoCurrencyStatus.currency)
|
||||
.fold(
|
||||
ifLeft = {
|
||||
showSnackbar(resourceReference(R.string.common_error))
|
||||
},
|
||||
ifRight = {
|
||||
onDismissActionsBottomSheet()
|
||||
},
|
||||
ifLeft = { showToast(resourceReference(R.string.common_error)) },
|
||||
ifRight = { uiState = stateFactory.getStateWithClosedBottomSheet() },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -937,16 +933,6 @@ internal class WalletViewModel @Inject constructor(
|
|||
uiState = stateFactory.getStateWithClosedBottomSheet()
|
||||
}
|
||||
|
||||
override fun onDismissActionsBottomSheet() {
|
||||
(uiState as? WalletMultiCurrencyState.Content)?.let { state ->
|
||||
uiState = state.copy(
|
||||
tokenActionsBottomSheet = state.tokenActionsBottomSheet?.copy(
|
||||
isShow = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTransactionClick(txHash: String) {
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
val wallet = getWallet(
|
||||
|
|
@ -1005,7 +991,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun showSnackbar(message: TextReference) {
|
||||
private fun showToast(message: TextReference) {
|
||||
uiState = stateFactory.getStateAndTriggerEvent(
|
||||
state = uiState,
|
||||
event = WalletEvent.ShowToast(message),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue