Updated on 2026-08-14

This commit is contained in:
Tangem 2024-11-09 08:43:41 +03:00
parent 25bae0ed98
commit e2b5e5b07b
12 changed files with 539 additions and 153 deletions

View file

@ -27,7 +27,7 @@ internal class DefaultRoutingComponent @AssistedInject constructor(
override val stack: Value<ChildStack<AppRoute, Child>> = childStack(
source = navigationProvider.getOrCreateTyped(),
serializer = AppRoute.serializer(),
serializer = AppRoute.serializer(), // TODO Maybe set this to null for AppRoute.Onboarding case. Need to check
initialConfiguration = getInitialRoute(),
handleBackButton = false,
childFactory = ::child,

View file

@ -38,6 +38,8 @@ class GetCardImageUseCase(private val verifier: OnlineCardVerifier = OnlineCardV
}
}
fun getDefaultFallbackUrl(): String = Artwork.DEFAULT_IMG_URL
private fun getFallbackArtworkUrl(cardId: String): String {
return when {
cardId.startsWith(Artwork.SERGIO_CARD_ID) -> Artwork.SERGIO_CARD_URL
@ -45,7 +47,7 @@ class GetCardImageUseCase(private val verifier: OnlineCardVerifier = OnlineCardV
else -> when (TwinsHelper.getTwinCardNumber(cardId)) {
TwinCardNumber.First -> Artwork.TWIN_CARD_1_URL
TwinCardNumber.Second -> Artwork.TWIN_CARD_2_URL
else -> Artwork.DEFAULT_IMG_URL
else -> getDefaultFallbackUrl()
}
}
}

View file

@ -29,6 +29,7 @@ dependencies {
implementation(projects.domain.feedback)
implementation(projects.domain.core)
implementation(projects.domain.card)
implementation(projects.domain.wallets)
/** Tangem libraries */
implementation(projects.libs.tangemSdkApi)

View file

@ -3,6 +3,7 @@ package com.tangem.features.onboarding.v2.multiwallet.impl
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.arkivanov.decompose.extensions.compose.jetpack.stack.Children
import com.arkivanov.decompose.extensions.compose.jetpack.stack.animation.slide
import com.arkivanov.decompose.extensions.compose.jetpack.stack.animation.stackAnimation
@ -21,6 +22,7 @@ import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.MultiWall
import com.tangem.features.onboarding.v2.multiwallet.impl.child.createwallet.MultiWalletCreateWalletComponent
import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletModel
import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState
import com.tangem.features.onboarding.v2.multiwallet.impl.ui.OnboardingMultiWallet
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@ -95,13 +97,20 @@ internal class DefaultOnboardingMultiWalletComponent @AssistedInject constructor
@Composable
override fun Content(modifier: Modifier) {
val stackState by childStack.subscribeAsState()
val state by model.uiState.collectAsStateWithLifecycle()
Children(
stack = stackState,
animation = stackAnimation(slide()),
) {
it.instance.Content(Modifier)
}
OnboardingMultiWallet(
state = state,
modifier = modifier,
childContent = { mdfr ->
Children(
stack = stackState,
animation = stackAnimation(slide()),
) {
it.instance.Content(mdfr)
}
},
)
}
@AssistedFactory

View file

@ -1,14 +1,10 @@
package com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
@ -26,22 +22,8 @@ fun MultiWalletBackup(state: MultiWalletBackupUM, modifier: Modifier = Modifier)
Column(
modifier = modifier
.fillMaxSize()
.navigationBarsPadding()
.verticalScroll(rememberScrollState()),
.navigationBarsPadding(),
) {
Box(
Modifier
.fillMaxWidth()
.weight(1f),
) {
Box(
Modifier
.align(Alignment.Center)
.size(100.dp)
.background(Color.Black),
)
}
when (state) {
is MultiWalletBackupUM.Wallet1 -> Wallet1Content(state)
is MultiWalletBackupUM.Wallet2 -> TODO()

View file

@ -1,21 +0,0 @@
package com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.res.TangemThemePreview
@Composable
fun Wallet1Artwork(modifier: Modifier = Modifier) {
Box(modifier) {
}
}
@Preview
@Composable
private fun Preview() {
TangemThemePreview {
Wallet1Artwork()
}
}

View file

@ -1,13 +1,8 @@
package com.tangem.features.onboarding.v2.multiwallet.impl.child.createwallet.ui
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@ -42,22 +37,9 @@ fun MultiWalletCreateWallet(state: MultiWalletCreateWalletUM, modifier: Modifier
Column(
modifier = modifier
.fillMaxSize()
.navigationBarsPadding()
.verticalScroll(rememberScrollState()),
.navigationBarsPadding(),
verticalArrangement = Arrangement.Bottom,
) {
Box(
Modifier
.fillMaxWidth()
.weight(1f),
) {
Box(
Modifier
.align(Alignment.Center)
.size(100.dp)
.background(Color.Black),
)
}
PrimaryButtonIconEnd(
modifier = Modifier
.padding(start = 16.dp, end = 16.dp, bottom = 12.dp)

View file

@ -1,16 +0,0 @@
package com.tangem.features.onboarding.v2.multiwallet.impl.model
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.features.onboarding.v2.impl.R
import com.tangem.features.onboarding.v2.multiwallet.impl.ui.state.OnboardingMultiWalletUM
internal fun resetCardDialog(onConfirm: () -> Unit, onDismiss: () -> Unit, onDismissButtonClick: () -> Unit) =
OnboardingMultiWalletUM.Dialog(
title = resourceReference(R.string.onboarding_activation_error_title),
description = resourceReference(R.string.onboarding_activation_error_message),
confirmButtonText = resourceReference(R.string.common_ok),
dismissButtonText = resourceReference(R.string.common_support),
onDismiss = onDismiss,
onConfirm = onConfirm,
onDismissButtonClick = onDismissButtonClick,
)

View file

@ -4,11 +4,11 @@ import com.tangem.core.decompose.di.ComponentScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.wallets.usecase.GetCardImageUseCase
import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent
import com.tangem.features.onboarding.v2.multiwallet.impl.ui.state.OnboardingMultiWalletUM
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import javax.inject.Inject
@ -17,8 +17,9 @@ internal class OnboardingMultiWalletModel @Inject constructor(
paramsContainer: ParamsContainer,
override val dispatchers: CoroutineDispatcherProvider,
) : Model() {
private val params = paramsContainer.require<OnboardingMultiWalletComponent.Params>()
private val getCardImageUseCase = GetCardImageUseCase()
private val _uiState = MutableStateFlow(OnboardingMultiWalletUM())
val state = MutableStateFlow(
OnboardingMultiWalletState(
@ -27,12 +28,15 @@ internal class OnboardingMultiWalletModel @Inject constructor(
),
)
val uiState = _uiState.asStateFlow()
init {
// TODO add analytics
// if (!manager.isActivationStarted(notNullCard.cardId)) {
// Analytics.send(Onboarding.Started())
// }
initScreenTitleSub()
loadCardArtwork()
}
private fun getInitialStep(): OnboardingMultiWalletState.Step {
@ -60,4 +64,17 @@ internal class OnboardingMultiWalletModel @Inject constructor(
}
}
}
private fun loadCardArtwork() {
modelScope.launch {
val artwork =
getCardImageUseCase.invoke(params.scanResponse.card.cardId, params.scanResponse.card.cardPublicKey)
if (artwork != getCardImageUseCase.getDefaultFallbackUrl()) {
_uiState.update {
it.copy(artworkUrl = artwork)
}
}
}
}
}

View file

@ -1,79 +1,63 @@
package com.tangem.features.onboarding.v2.multiwallet.impl.ui
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.BasicDialog
import com.tangem.core.ui.components.DialogButtonUM
import com.tangem.core.ui.components.PrimaryButtonIconEnd
import com.tangem.core.ui.components.SecondaryButton
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.onboarding.v2.impl.R
import com.tangem.features.onboarding.v2.multiwallet.impl.ui.state.OnboardingMultiWalletUM
@Composable
internal fun OnboardingMultiWallet(state: OnboardingMultiWalletUM, modifier: Modifier = Modifier) {
if (state.dialog != null) {
BasicDialog(
title = state.dialog.title.resolveReference(),
message = state.dialog.description.resolveReference(),
confirmButton = DialogButtonUM(
title = state.dialog.confirmButtonText.resolveReference(),
onClick = state.dialog.onConfirm,
),
dismissButton = DialogButtonUM(
title = state.dialog.dismissButtonText.resolveReference(),
onClick = state.dialog.onDismissButtonClick,
),
onDismissDialog = state.dialog.onDismiss,
)
}
@Suppress("MagicNumber")
internal fun OnboardingMultiWallet(
state: OnboardingMultiWalletUM,
modifier: Modifier = Modifier,
childContent: @Composable (Modifier) -> Unit = {},
) {
Column(
modifier = modifier
.fillMaxSize()
.navigationBarsPadding()
.verticalScroll(rememberScrollState()),
) {
Box(Modifier.weight(1f))
PrimaryButtonIconEnd(
WalletArtworks(
url = state.artworkUrl,
modifier = Modifier
.padding(start = 16.dp, end = 16.dp, bottom = 12.dp)
.weight(.56f)
.padding(horizontal = 34.dp)
.padding(top = 20.dp)
.fillMaxWidth(),
iconResId = R.drawable.ic_tangem_24,
text = stringResource(R.string.onboarding_create_wallet_button_create_wallet),
onClick = state.onCreateWalletClick,
state = WalletArtworksState.Folded,
)
SecondaryButton(
modifier = Modifier
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp)
.fillMaxWidth(),
text = stringResource(R.string.onboarding_create_wallet_options_button_options),
onClick = state.onOtherOptionsClick,
)
Box(
modifier = Modifier.weight(.44f),
contentAlignment = Alignment.BottomStart,
) {
childContent(Modifier)
}
}
}
@Preview
@Preview(showBackground = true, widthDp = 360, heightDp = 640)
@Composable
private fun Preview() {
TangemThemePreview {
OnboardingMultiWallet(
state = OnboardingMultiWalletUM(
onCreateWalletClick = {},
showSeedPhraseOption = true,
onBack = {},
onOtherOptionsClick = {},
dialog = null,
),
state = OnboardingMultiWalletUM(artworkUrl = null),
childContent = { md ->
Box(
modifier = md
.fillMaxWidth()
.height(200.dp)
.background(Color.DarkGray),
)
},
)
}
}

View file

@ -0,0 +1,462 @@
@file:Suppress("MagicNumber", "UnnecessaryParentheses", "CyclomaticComplexMethod", "LongMethod")
package com.tangem.features.onboarding.v2.multiwallet.impl.ui
import androidx.compose.animation.core.Transition
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.updateTransition
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastForEach
import androidx.compose.ui.zIndex
import coil.compose.AsyncImage
import coil.request.ImageRequest
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.onboarding.v2.impl.R
import kotlinx.coroutines.delay
import java.util.concurrent.TimeUnit
sealed class WalletArtworksState {
data object Folded : WalletArtworksState()
data object Fan : WalletArtworksState()
data class Stack(
val threeCards: Boolean = true,
) : WalletArtworksState()
data class Unfold(
val step: Step = Step.First,
) : WalletArtworksState() {
enum class Step {
First, Second, Third
}
}
data class Leapfrog(
val threeCards: Boolean = true,
val step: Step = Step.Second,
) : WalletArtworksState() {
enum class Step {
Second, Third
}
}
}
@Composable
fun WalletArtworks(url: String?, state: WalletArtworksState, modifier: Modifier = Modifier) {
BoxWithConstraints(
modifier
.heightIn(min = 180.dp)
.widthIn(max = 450.dp),
) {
val animationWidth = maxWidth
val density = LocalDensity.current.density
var animationState by remember {
mutableStateOf(
state.toTransitionSetState(
maxWidthDp = animationWidth.value,
density = density,
maxHeightDp = maxHeight.value,
).first(),
)
}
val transition1 = updateTransition(animationState.walletCard1, label = "transition")
val transition2 = updateTransition(animationState.walletCard2, label = "transition")
val transition3 = updateTransition(animationState.walletCard3, label = "transition")
LaunchedEffect(state) {
val animationSetState = state.toTransitionSetState(
maxWidthDp = animationWidth.value,
density = density,
maxHeightDp = maxHeight.value,
)
animationSetState.fastForEach {
animationState = it
val maxTime = maxOf(
transition1.totalDurationNanos,
transition2.totalDurationNanos,
transition3.totalDurationNanos,
)
delay(TimeUnit.NANOSECONDS.toMillis(maxTime))
}
}
AnimatedWalletCards(
url = url,
modifier = Modifier
.widthIn(max = 450.dp)
.matchParentSize(),
transition1 = transition1,
transition2 = transition2,
transition3 = transition3,
)
}
}
private data class CardsTransitionState(
val walletCard1: WalletCardTransitionState,
val walletCard2: WalletCardTransitionState,
val walletCard3: WalletCardTransitionState,
)
private data class WalletCardTransitionState(
val alpha: Float = 1f,
val xTranslation: Float = 0f,
val yTranslation: Float = 0f,
val xScale: Float = 1f,
val yScale: Float = 1f,
val rotation: Float = 0f,
val zIndex: Float = 0f,
)
@Composable
private fun AnimatedWalletCards(
url: String?,
transition1: Transition<WalletCardTransitionState>,
transition2: Transition<WalletCardTransitionState>,
transition3: Transition<WalletCardTransitionState>,
modifier: Modifier = Modifier,
) {
val alpha1 by transition1.animateFloat(label = "alpha1") { it.alpha }
val translationX1 by transition1.animateFloat(label = "translationX1") { it.xTranslation }
val translationY1 by transition1.animateFloat(label = "translationY1") { it.yTranslation }
val rotation1 by transition1.animateFloat(label = "rotation1") { it.rotation }
val scaleX1 by transition1.animateFloat(label = "scaleX1") { it.xScale }
val scaleY1 by transition1.animateFloat(label = "scaleY1") { it.yScale }
val zIndex1 = transition1.currentState.zIndex
val alpha2 by transition2.animateFloat(label = "alpha2") { it.alpha }
val translationX2 by transition2.animateFloat(label = "translationX2") { it.xTranslation }
val translationY2 by transition2.animateFloat(label = "translationY2") { it.yTranslation }
val rotation2 by transition2.animateFloat(label = "rotation2") { it.rotation }
val scaleX2 by transition2.animateFloat(label = "scaleX2") { it.xScale }
val scaleY2 by transition2.animateFloat(label = "scaleY2") { it.yScale }
val zIndex2 = transition2.currentState.zIndex
val alpha3 by transition3.animateFloat(label = "alpha3") { it.alpha }
val translationX3 by transition3.animateFloat(label = "translationX3") { it.xTranslation }
val translationY3 by transition3.animateFloat(label = "translationY3") { it.yTranslation }
val rotation3 by transition3.animateFloat(label = "rotation3") { it.rotation }
val scaleX3 by transition3.animateFloat(label = "scaleX3") { it.xScale }
val scaleY3 by transition3.animateFloat(label = "scaleY3") { it.yScale }
val zIndex3 = transition3.targetState.zIndex
Box(modifier) {
WalletCard(
modifier = Modifier
.zIndex(zIndex3)
.matchParentSize()
.graphicsLayer {
translationX = translationX3
translationY = translationY3
}
.graphicsLayer {
alpha = alpha3
scaleX = scaleX3
scaleY = scaleY3
rotationZ = rotation3
},
url = url,
)
WalletCard(
modifier = Modifier
.zIndex(zIndex2)
.matchParentSize()
.graphicsLayer {
translationX = translationX2
translationY = translationY2
}
.graphicsLayer {
alpha = alpha2
rotationZ = rotation2
scaleX = scaleX2
scaleY = scaleY2
},
url = url,
)
WalletCard(
modifier = Modifier
.zIndex(zIndex1)
.matchParentSize()
.graphicsLayer {
scaleX = scaleX1
scaleY = scaleY1
}
.graphicsLayer {
alpha = alpha1
translationX = translationX1
translationY = translationY1
rotationZ = rotation1
},
url = url,
)
}
}
@Composable
private fun WalletCard(url: String?, modifier: Modifier = Modifier) {
AsyncImage(
modifier = modifier,
model = ImageRequest.Builder(LocalContext.current)
.data(url)
.crossfade(true)
.build(),
placeholder = painterResource(R.drawable.card_placeholder_black),
error = painterResource(R.drawable.card_placeholder_black),
fallback = painterResource(R.drawable.card_placeholder_black),
contentDescription = null,
)
}
private fun WalletArtworksState.toTransitionSetState(maxWidthDp: Float, maxHeightDp: Float, density: Float) =
when (this) {
is WalletArtworksState.Folded -> listOf(
CardsTransitionState(
WalletCardTransitionState(),
WalletCardTransitionState(),
WalletCardTransitionState(),
),
)
is WalletArtworksState.Stack -> listOf(
CardsTransitionState(
walletCard1 = WalletCardTransitionState(),
walletCard2 = WalletCardTransitionState(),
walletCard3 = WalletCardTransitionState(),
),
CardsTransitionState(
walletCard1 = WalletCardTransitionState().copy(
alpha = 1f,
xTranslation = 0f,
yTranslation = 0f,
rotation = 0f,
xScale = 1f,
yScale = 1f,
),
walletCard2 = WalletCardTransitionState().copy(
alpha = 0.65f,
xTranslation = 0f,
yTranslation = ((maxHeightDp * (1 - 0.83f)) / 4 + 12) * density,
rotation = 0f,
xScale = 0.83f,
yScale = 0.83f,
),
walletCard3 = WalletCardTransitionState().copy(
alpha = if (threeCards) 0.55f else 0f,
xTranslation = 0f,
yTranslation = (maxHeightDp * (1 - 0.72f) / 4 + 24) * density,
rotation = 0f,
xScale = 0.72f,
yScale = 0.72f,
),
),
)
is WalletArtworksState.Unfold -> listOfNotNull(
CardsTransitionState(
walletCard1 = WalletCardTransitionState(),
walletCard2 = WalletCardTransitionState().copy(
alpha = 0.65f,
),
walletCard3 = WalletCardTransitionState().copy(
alpha = 0.55f,
),
).takeIf { step == WalletArtworksState.Unfold.Step.First },
CardsTransitionState(
walletCard1 = WalletCardTransitionState().copy(
rotation = 5f,
),
walletCard2 = WalletCardTransitionState().copy(
alpha = when (step) {
WalletArtworksState.Unfold.Step.First -> 0.65f
WalletArtworksState.Unfold.Step.Second -> 1f
WalletArtworksState.Unfold.Step.Third -> 1f
},
rotation = -6f,
xTranslation = 0f,
yTranslation = -(maxHeightDp * (1 - 0.88f) / 4) * density,
xScale = 0.88f,
yScale = 0.88f,
),
walletCard3 = WalletCardTransitionState().copy(
alpha = when (step) {
WalletArtworksState.Unfold.Step.First -> 0.55f
WalletArtworksState.Unfold.Step.Second -> 0.55f
WalletArtworksState.Unfold.Step.Third -> 1f
},
rotation = -16f,
xTranslation = 0f,
yTranslation = -(maxHeightDp * (1 - 0.81f) / 4 + 2) * density,
xScale = 0.81f,
yScale = 0.81f,
),
),
)
WalletArtworksState.Fan -> {
listOf(
CardsTransitionState(
walletCard1 = WalletCardTransitionState().copy(
xTranslation = maxWidthDp * 0.4f * density,
yTranslation = 35 * density,
rotation = 75f,
xScale = .85f,
yScale = .85f,
),
walletCard2 = WalletCardTransitionState().copy(
xTranslation = maxWidthDp * -0.4f * density,
yTranslation = -5 * density,
rotation = 75f,
xScale = .85f,
yScale = .85f,
),
walletCard3 = WalletCardTransitionState().copy(
rotation = 105f,
xScale = .85f,
yScale = .85f,
),
),
)
}
is WalletArtworksState.Leapfrog -> {
val translationY = -(maxHeightDp / 2) * density
val secondCardPlace = WalletCardTransitionState().copy(
alpha = 0.65f,
xTranslation = 0f,
yTranslation = ((maxHeightDp * (1 - 0.83f)) / 4 + 12) * density,
rotation = 0f,
xScale = 0.83f,
yScale = 0.83f,
)
val thirdCardPlace = WalletCardTransitionState().copy(
alpha = if (threeCards) 0.55f else 0f,
xTranslation = 0f,
yTranslation = (maxHeightDp * (1 - 0.72f) / 4 + 24) * density,
rotation = 0f,
xScale = 0.72f,
yScale = 0.72f,
)
if (step == WalletArtworksState.Leapfrog.Step.Second) {
listOf(
CardsTransitionState(
walletCard1 = WalletCardTransitionState(),
walletCard2 = secondCardPlace,
walletCard3 = thirdCardPlace,
),
CardsTransitionState(
walletCard1 = WalletCardTransitionState().copy(
yTranslation = translationY,
),
walletCard2 = WalletCardTransitionState().copy(
alpha = 1f,
zIndex = 4f,
),
walletCard3 = thirdCardPlace,
),
CardsTransitionState(
walletCard1 = WalletCardTransitionState().copy(
zIndex = 1f,
),
walletCard2 = WalletCardTransitionState().copy(
zIndex = 4f,
),
walletCard3 = secondCardPlace,
),
)
} else {
listOf(
CardsTransitionState(
walletCard1 = WalletCardTransitionState().copy(
zIndex = 2f,
),
walletCard2 = WalletCardTransitionState().copy(
zIndex = 3f,
),
walletCard3 = secondCardPlace,
),
CardsTransitionState(
walletCard1 = WalletCardTransitionState().copy(
yTranslation = translationY,
),
walletCard2 = WalletCardTransitionState().copy(
zIndex = 3f,
yTranslation = translationY,
),
walletCard3 = WalletCardTransitionState().copy(
alpha = 1f,
zIndex = 4f,
),
),
CardsTransitionState(
walletCard1 = WalletCardTransitionState().copy(
zIndex = 1f,
),
walletCard2 = WalletCardTransitionState().copy(
zIndex = 4f,
),
walletCard3 = WalletCardTransitionState().copy(
zIndex = 5f,
),
),
)
}
}
}
@Preview(showBackground = true, widthDp = 360, heightDp = 640)
@Composable
private fun Preview() {
TangemThemePreview {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
var state: WalletArtworksState by remember { mutableStateOf(WalletArtworksState.Folded) }
WalletArtworks(
url = null,
state = state,
modifier = Modifier.fillMaxWidth(),
)
var index by remember { mutableIntStateOf(0) }
Button(
modifier = Modifier
.zIndex(5f)
.align(Alignment.TopStart),
onClick = {
val list = listOf(
WalletArtworksState.Folded,
WalletArtworksState.Stack(),
WalletArtworksState.Fan,
WalletArtworksState.Unfold(step = WalletArtworksState.Unfold.Step.First),
WalletArtworksState.Unfold(step = WalletArtworksState.Unfold.Step.Second),
WalletArtworksState.Unfold(step = WalletArtworksState.Unfold.Step.Third),
WalletArtworksState.Stack(),
WalletArtworksState.Leapfrog(step = WalletArtworksState.Leapfrog.Step.Second),
WalletArtworksState.Leapfrog(step = WalletArtworksState.Leapfrog.Step.Third),
)
state = list[index % list.size]
index++
},
) {
Text("Animate")
}
}
}
}

View file

@ -1,21 +1,5 @@
package com.tangem.features.onboarding.v2.multiwallet.impl.ui.state
import com.tangem.core.ui.extensions.TextReference
internal data class OnboardingMultiWalletUM(
val onCreateWalletClick: () -> Unit,
val showSeedPhraseOption: Boolean,
val onOtherOptionsClick: () -> Unit,
val onBack: () -> Unit,
val dialog: Dialog?,
) {
data class Dialog(
val title: TextReference,
val description: TextReference,
val dismissButtonText: TextReference,
val confirmButtonText: TextReference,
val onConfirm: () -> Unit,
val onDismissButtonClick: () -> Unit,
val onDismiss: () -> Unit,
)
}
val artworkUrl: String? = null,
)