Updated on 2026-08-14
This commit is contained in:
parent
25bae0ed98
commit
e2b5e5b07b
12 changed files with 539 additions and 153 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue