Updated on 2026-08-14
This commit is contained in:
parent
cf308447a8
commit
74ae074402
7 changed files with 110 additions and 14 deletions
|
|
@ -0,0 +1,30 @@
|
|||
package com.tangem.core.ui.extensions
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
|
||||
private typealias Action = () -> Unit
|
||||
|
||||
/**
|
||||
* Returns action with Haptic Feedback
|
||||
*
|
||||
* @param state of the content
|
||||
* @param hapticType haptic effect
|
||||
* @param onAction action that needs haptic feedback
|
||||
*/
|
||||
@Composable
|
||||
fun rememberHapticFeedback(
|
||||
state: Any,
|
||||
onAction: () -> Unit,
|
||||
hapticType: HapticFeedbackType = HapticFeedbackType.LongPress,
|
||||
): Action {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
return remember(state) {
|
||||
{
|
||||
hapticFeedback.performHapticFeedback(hapticType)
|
||||
onAction.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -182,6 +182,17 @@ internal object WalletPreviewData {
|
|||
id = UUID.randomUUID().toString(),
|
||||
icon = tokenIconState,
|
||||
name = "Polygon",
|
||||
onItemClick = {},
|
||||
onItemLongClick = {},
|
||||
)
|
||||
}
|
||||
|
||||
val tokenItemNoAddressState by lazy {
|
||||
TokenItemState.NoAddress(
|
||||
id = UUID.randomUUID().toString(),
|
||||
icon = tokenIconState,
|
||||
name = "Polygon",
|
||||
onItemLongClick = {},
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,8 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.composed
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||
|
|
@ -21,6 +18,7 @@ import androidx.constraintlayout.compose.ConstrainedLayoutReference
|
|||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.constraintlayout.compose.ConstraintLayoutScope
|
||||
import androidx.constraintlayout.compose.Dimension
|
||||
import com.tangem.core.ui.extensions.rememberHapticFeedback
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
|
||||
import com.tangem.feature.wallet.presentation.common.component.token.TokenCryptoInfoBlock
|
||||
|
|
@ -102,21 +100,36 @@ private fun Modifier.constrainAsOptionsItem(scope: ConstraintLayoutScope, ref: C
|
|||
private fun Modifier.tokenClickable(state: TokenItemState): Modifier = composed {
|
||||
when (state) {
|
||||
is TokenItemState.Content -> {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
val onLongClick = remember(state) {
|
||||
{
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
state.onItemLongClick()
|
||||
}
|
||||
}
|
||||
|
||||
val onLongClick = rememberHapticFeedback(
|
||||
state = state,
|
||||
onAction = state.onItemLongClick,
|
||||
)
|
||||
this.combinedClickable(
|
||||
onClick = state.onItemClick,
|
||||
onLongClick = onLongClick,
|
||||
)
|
||||
}
|
||||
is TokenItemState.Unreachable -> {
|
||||
val onLongClick = rememberHapticFeedback(
|
||||
state = state,
|
||||
onAction = state.onItemLongClick,
|
||||
)
|
||||
this.combinedClickable(
|
||||
onClick = state.onItemClick,
|
||||
onLongClick = onLongClick,
|
||||
)
|
||||
}
|
||||
is TokenItemState.NoAddress -> {
|
||||
val onLongClick = rememberHapticFeedback(
|
||||
state = state,
|
||||
onAction = state.onItemLongClick,
|
||||
)
|
||||
this.combinedClickable(
|
||||
onClick = {},
|
||||
onLongClick = onLongClick,
|
||||
)
|
||||
}
|
||||
is TokenItemState.Draggable,
|
||||
is TokenItemState.Unreachable,
|
||||
is TokenItemState.Loading,
|
||||
is TokenItemState.Locked,
|
||||
-> this
|
||||
|
|
@ -144,6 +157,7 @@ private class TokenConfigProvider : CollectionPreviewParameterProvider<TokenItem
|
|||
collection = listOf(
|
||||
WalletPreviewData.tokenItemVisibleState,
|
||||
WalletPreviewData.tokenItemUnreachableState,
|
||||
WalletPreviewData.tokenItemNoAddressState,
|
||||
WalletPreviewData.tokenItemDragState,
|
||||
WalletPreviewData.tokenItemHiddenState,
|
||||
WalletPreviewData.loadingTokenItemState,
|
||||
|
|
|
|||
|
|
@ -41,7 +41,9 @@ private fun ContentBlock(state: TokenItemState.ContentState, modifier: Modifier
|
|||
amount = when (state) {
|
||||
is TokenItemState.Content -> if (state.tokenOptions.isBalanceHidden) STARS else state.amount
|
||||
is TokenItemState.Draggable -> state.info.resolveReference()
|
||||
is TokenItemState.Unreachable -> null
|
||||
is TokenItemState.Unreachable,
|
||||
is TokenItemState.NoAddress,
|
||||
-> null
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ internal fun TokenFiatInfoBlock(
|
|||
)
|
||||
}
|
||||
is TokenItemState.Unreachable -> UnreachableBlock(modifier = modifier)
|
||||
is TokenItemState.NoAddress -> NoAddressBlock(modifier = modifier)
|
||||
is TokenItemState.Loading -> LoadingBlock(modifier = modifier)
|
||||
is TokenItemState.Locked -> LockedBlock(modifier = modifier)
|
||||
}
|
||||
|
|
@ -154,6 +155,16 @@ private fun UnreachableBlock(modifier: Modifier = Modifier) {
|
|||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun NoAddressBlock(modifier: Modifier = Modifier) {
|
||||
Text(
|
||||
modifier = modifier,
|
||||
text = stringResource(id = R.string.common_no_address),
|
||||
style = TangemTypography.body2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LoadingBlock(modifier: Modifier = Modifier) {
|
||||
NonContentContainer(modifier = modifier) {
|
||||
|
|
|
|||
|
|
@ -71,11 +71,30 @@ internal sealed interface TokenItemState {
|
|||
* @property id token id
|
||||
* @property icon token icon state
|
||||
* @property name token name
|
||||
* @property onItemClick callback which will be called when an item is clicked
|
||||
* @property onItemLongClick callback which will be called when an item is long clicked
|
||||
*/
|
||||
data class Unreachable(
|
||||
override val id: String,
|
||||
override val icon: IconState,
|
||||
override val name: String,
|
||||
val onItemClick: () -> Unit,
|
||||
val onItemLongClick: () -> Unit,
|
||||
) : ContentState()
|
||||
|
||||
/**
|
||||
* No derivation address state
|
||||
*
|
||||
* @property id token id
|
||||
* @property icon token icon state
|
||||
* @property name token name
|
||||
* @property onItemLongClick callback which will be called when an item is long clicked
|
||||
*/
|
||||
data class NoAddress(
|
||||
override val id: String,
|
||||
override val icon: IconState,
|
||||
override val name: String,
|
||||
val onItemLongClick: () -> Unit,
|
||||
) : ContentState()
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ internal class CryptoCurrencyStatusToTokenItemConverter(
|
|||
is CryptoCurrencyStatus.NoQuote,
|
||||
is CryptoCurrencyStatus.NoAccount,
|
||||
-> value.mapToTokenItemState()
|
||||
is CryptoCurrencyStatus.MissedDerivation -> value.mapToNoAddressTokenItemState()
|
||||
// TODO: Add other token item states, currently not designed
|
||||
is CryptoCurrencyStatus.MissedDerivation,
|
||||
is CryptoCurrencyStatus.Unreachable,
|
||||
is CryptoCurrencyStatus.NoAmount,
|
||||
-> value.mapToUnreachableTokenItemState()
|
||||
|
|
@ -69,6 +69,15 @@ internal class CryptoCurrencyStatusToTokenItemConverter(
|
|||
id = currency.id.value,
|
||||
name = currency.name,
|
||||
icon = iconStateConverter.convert(value = this),
|
||||
onItemClick = { clickIntents.onTokenItemClick(currency) },
|
||||
onItemLongClick = { clickIntents.onTokenItemLongClick(cryptoCurrencyStatus = this) },
|
||||
)
|
||||
|
||||
private fun CryptoCurrencyStatus.mapToNoAddressTokenItemState() = TokenItemState.NoAddress(
|
||||
id = currency.id.value,
|
||||
name = currency.name,
|
||||
icon = iconStateConverter.convert(this),
|
||||
onItemLongClick = { clickIntents.onTokenItemLongClick(cryptoCurrencyStatus = this) },
|
||||
)
|
||||
|
||||
private fun CryptoCurrencyStatus.getPriceChangeConfig(): PriceChangeConfig {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue