Updated on 2026-08-14
This commit is contained in:
parent
12146c8981
commit
3e48a9ce0e
20 changed files with 402 additions and 17 deletions
|
|
@ -272,6 +272,7 @@ class OnboardingWalletFragment :
|
|||
onboardingManageTokensComponent = onboardingManageTokensComponentFactory.create(
|
||||
context = onboardingComponentContext,
|
||||
params = OnboardingManageTokensComponent.Params(userWalletId = userWalletId),
|
||||
onDone = {},
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ dependencies {
|
|||
/** AndroidX libraries */
|
||||
implementation(deps.androidx.fragment.ktx)
|
||||
implementation(deps.androidx.paging.runtime)
|
||||
implementation(deps.lifecycle.runtime.ktx)
|
||||
implementation(deps.androidx.palette)
|
||||
implementation(deps.androidx.windowManager) {
|
||||
exclude(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,123 @@
|
|||
package com.tangem.core.ui.components
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.graphics.PixelFormat
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.platform.AbstractComposeView
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.lifecycle.findViewTreeLifecycleOwner
|
||||
import androidx.lifecycle.findViewTreeViewModelStoreOwner
|
||||
import androidx.lifecycle.setViewTreeLifecycleOwner
|
||||
import androidx.lifecycle.setViewTreeViewModelStoreOwner
|
||||
import androidx.savedstate.findViewTreeSavedStateRegistryOwner
|
||||
import androidx.savedstate.setViewTreeSavedStateRegistryOwner
|
||||
import java.util.UUID
|
||||
|
||||
@Composable
|
||||
fun FullScreen(notTouchable: Boolean = false, content: @Composable (() -> Unit) -> Unit) {
|
||||
val view = LocalView.current
|
||||
val parentComposition = rememberCompositionContext()
|
||||
val currentContent by rememberUpdatedState(content)
|
||||
val id = rememberSaveable { UUID.randomUUID() }
|
||||
|
||||
val fullScreenLayout = remember {
|
||||
FullScreenLayout(
|
||||
notTouchable = notTouchable,
|
||||
composeView = view,
|
||||
uniqueId = id,
|
||||
).apply {
|
||||
setContent(parentComposition) {
|
||||
currentContent(::dismiss)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DisposableEffect(fullScreenLayout) {
|
||||
fullScreenLayout.show()
|
||||
onDispose { fullScreenLayout.dispose() }
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ViewConstructor", "ClickableViewAccessibility")
|
||||
private class FullScreenLayout(
|
||||
private val notTouchable: Boolean,
|
||||
private val composeView: View,
|
||||
uniqueId: UUID,
|
||||
) : AbstractComposeView(composeView.context) {
|
||||
|
||||
private val windowManager =
|
||||
composeView.context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
|
||||
|
||||
private val params = createLayoutParams()
|
||||
|
||||
override var shouldCreateCompositionOnAttachedToWindow: Boolean = false
|
||||
private set
|
||||
|
||||
private var viewShowing = false
|
||||
|
||||
init {
|
||||
if (notTouchable) {
|
||||
setOnTouchListener { _, _ -> false }
|
||||
}
|
||||
|
||||
id = android.R.id.content
|
||||
setTag(androidx.compose.ui.R.id.compose_view_saveable_id_tag, "CustomLayout:$uniqueId")
|
||||
setViewTreeLifecycleOwner(composeView.findViewTreeLifecycleOwner())
|
||||
setViewTreeSavedStateRegistryOwner(composeView.findViewTreeSavedStateRegistryOwner())
|
||||
setViewTreeViewModelStoreOwner(composeView.findViewTreeViewModelStoreOwner())
|
||||
}
|
||||
|
||||
private var content: @Composable () -> Unit by mutableStateOf({})
|
||||
|
||||
@Composable
|
||||
override fun Content() {
|
||||
content()
|
||||
}
|
||||
|
||||
fun setContent(parent: CompositionContext, content: @Composable () -> Unit) {
|
||||
setParentCompositionContext(parent)
|
||||
this.content = content
|
||||
shouldCreateCompositionOnAttachedToWindow = true
|
||||
}
|
||||
|
||||
private fun createLayoutParams(): WindowManager.LayoutParams = WindowManager.LayoutParams().apply {
|
||||
type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL
|
||||
token = composeView.applicationWindowToken
|
||||
width = WindowManager.LayoutParams.MATCH_PARENT
|
||||
height = WindowManager.LayoutParams.MATCH_PARENT
|
||||
format = PixelFormat.TRANSLUCENT
|
||||
flags = WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or
|
||||
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
|
||||
}
|
||||
|
||||
fun show() {
|
||||
if (viewShowing) dismiss()
|
||||
windowManager.addView(this, params)
|
||||
params.flags = params.flags or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
|
||||
if (notTouchable) {
|
||||
params.flags = params.flags or WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
|
||||
}
|
||||
|
||||
windowManager.updateViewLayout(this, params)
|
||||
viewShowing = true
|
||||
}
|
||||
|
||||
fun dismiss() {
|
||||
if (!viewShowing) return
|
||||
disposeComposition()
|
||||
windowManager.removeViewImmediate(this)
|
||||
viewShowing = false
|
||||
}
|
||||
|
||||
fun dispose() {
|
||||
dismiss()
|
||||
setViewTreeSavedStateRegistryOwner(null)
|
||||
setViewTreeSavedStateRegistryOwner(null)
|
||||
setViewTreeViewModelStoreOwner(null)
|
||||
}
|
||||
}
|
||||
24
core/ui/src/main/res/drawable/ic_success_blue_76.xml
Normal file
24
core/ui/src/main/res/drawable/ic_success_blue_76.xml
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="76dp"
|
||||
android:height="76dp"
|
||||
android:viewportWidth="76"
|
||||
android:viewportHeight="76">
|
||||
<path
|
||||
android:pathData="M38,16.571C32.317,16.571 26.866,18.829 22.848,22.848C18.829,26.866 16.571,32.317 16.571,38C16.571,43.683 18.829,49.134 22.848,53.152C26.866,57.171 32.317,59.429 38,59.429C43.683,59.429 49.134,57.171 53.152,53.152C57.171,49.134 59.429,43.683 59.429,38C59.429,32.317 57.171,26.866 53.152,22.848C49.134,18.829 43.683,16.571 38,16.571ZM16.787,16.787C22.413,11.161 30.044,8 38,8C45.957,8 53.587,11.161 59.213,16.787C64.839,22.413 68,30.044 68,38C68,45.957 64.839,53.587 59.213,59.213C53.587,64.839 45.957,68 38,68C30.044,68 22.413,64.839 16.787,59.213C11.161,53.587 8,45.957 8,38C8,30.044 11.161,22.413 16.787,16.787Z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#0099FF"
|
||||
android:fillType="evenOdd"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M21.029,21.029C25.53,16.529 31.635,14 38,14C44.365,14 50.47,16.529 54.971,21.029C59.471,25.53 62,31.635 62,38C62,44.365 59.471,50.47 54.971,54.971C50.47,59.471 44.365,62 38,62C31.635,62 25.53,59.471 21.029,54.971C16.529,50.47 14,44.365 14,38C14,31.635 16.529,25.53 21.029,21.029ZM38,16.697C32.35,16.697 26.931,18.941 22.936,22.936C18.941,26.931 16.697,32.35 16.697,38C16.697,43.65 18.941,49.069 22.936,53.064C26.931,57.059 32.35,59.303 38,59.303C43.65,59.303 49.069,57.059 53.064,53.064C57.059,49.069 59.303,43.65 59.303,38C59.303,32.35 57.059,26.931 53.064,22.936C49.069,18.941 43.65,16.697 38,16.697Z"
|
||||
android:fillColor="#0099FF"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M50.816,31.398C51.347,31.929 51.347,32.79 50.816,33.321L35.973,48.163L27.398,39.588C26.867,39.057 26.867,38.196 27.398,37.665C27.929,37.134 28.79,37.134 29.321,37.665L35.973,44.318L48.894,31.398C49.424,30.867 50.285,30.867 50.816,31.398Z"
|
||||
android:fillColor="#0099FF"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M12.082,4.354C11.999,3.882 11.321,3.882 11.239,4.354L10.886,6.378C10.855,6.555 10.715,6.695 10.538,6.726L8.515,7.078C8.042,7.161 8.042,7.839 8.515,7.922L10.538,8.274C10.715,8.305 10.855,8.445 10.886,8.622L11.239,10.646C11.321,11.118 11.999,11.118 12.082,10.646L12.434,8.622C12.465,8.445 12.605,8.305 12.783,8.274L14.806,7.922C15.278,7.839 15.278,7.161 14.806,7.078L12.783,6.726C12.605,6.695 12.465,6.555 12.434,6.378L12.082,4.354ZM64.555,4.444C64.452,3.852 63.601,3.852 63.498,4.444L63.056,6.982C63.017,7.205 62.842,7.379 62.619,7.418L60.082,7.861C59.489,7.964 59.489,8.815 60.082,8.918L62.619,9.36C62.842,9.399 63.017,9.574 63.056,9.797L63.498,12.334C63.601,12.927 64.452,12.927 64.555,12.334L64.998,9.797C65.037,9.574 65.211,9.399 65.434,9.36L67.972,8.918C68.564,8.815 68.564,7.964 67.972,7.861L65.434,7.418C65.211,7.379 65.037,7.205 64.998,6.982L64.555,4.444ZM70.422,16.354C70.339,15.882 69.661,15.882 69.578,16.354L69.226,18.378C69.195,18.555 69.055,18.695 68.878,18.726L66.854,19.078C66.382,19.161 66.382,19.839 66.854,19.922L68.878,20.274C69.055,20.305 69.195,20.445 69.226,20.622L69.578,22.646C69.661,23.118 70.339,23.118 70.422,22.646L70.774,20.622C70.805,20.445 70.945,20.305 71.122,20.274L73.146,19.922C73.618,19.839 73.618,19.161 73.146,19.078L71.122,18.726C70.945,18.695 70.805,18.555 70.774,18.378L70.422,16.354ZM69.578,56.354C69.661,55.882 70.339,55.882 70.422,56.354L70.774,58.378C70.805,58.555 70.945,58.695 71.122,58.726L73.146,59.078C73.618,59.161 73.618,59.839 73.146,59.922L71.122,60.274C70.945,60.305 70.805,60.445 70.774,60.622L70.422,62.646C70.339,63.118 69.661,63.118 69.578,62.646L69.226,60.622C69.195,60.445 69.055,60.305 68.878,60.274L66.854,59.922C66.382,59.839 66.382,59.161 66.854,59.078L68.878,58.726C69.055,58.695 69.195,58.555 69.226,58.378L69.578,56.354Z"
|
||||
android:fillColor="#0099FF"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
1
core/ui/src/main/res/raw/anim_confetti.json
Normal file
1
core/ui/src/main/res/raw/anim_confetti.json
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.features.managetokens.component
|
||||
|
||||
import com.tangem.core.decompose.factory.ComponentFactory
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
|
|
@ -8,5 +8,7 @@ interface OnboardingManageTokensComponent : ComposableContentComponent {
|
|||
|
||||
data class Params(val userWalletId: UserWalletId)
|
||||
|
||||
interface Factory : ComponentFactory<Params, OnboardingManageTokensComponent>
|
||||
interface Factory {
|
||||
fun create(context: AppComponentContext, params: Params, onDone: () -> Unit): OnboardingManageTokensComponent
|
||||
}
|
||||
}
|
||||
|
|
@ -12,14 +12,22 @@ import com.tangem.features.managetokens.ui.OnboardingManageTokensContent
|
|||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
internal class DefaultOnboardingManageTokensComponent @AssistedInject constructor(
|
||||
@Assisted context: AppComponentContext,
|
||||
@Assisted params: OnboardingManageTokensComponent.Params,
|
||||
@Assisted onDone: () -> Unit,
|
||||
) : OnboardingManageTokensComponent, AppComponentContext by context {
|
||||
|
||||
private val model: OnboardingManageTokensModel = getOrCreateModel(params)
|
||||
|
||||
init {
|
||||
componentScope.launch {
|
||||
model.returnToParentComponentFlow.collect { onDone() }
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val state by model.state.collectAsStateWithLifecycle()
|
||||
|
|
@ -32,6 +40,7 @@ internal class DefaultOnboardingManageTokensComponent @AssistedInject constructo
|
|||
override fun create(
|
||||
context: AppComponentContext,
|
||||
params: OnboardingManageTokensComponent.Params,
|
||||
onDone: () -> Unit,
|
||||
): DefaultOnboardingManageTokensComponent
|
||||
}
|
||||
}
|
||||
|
|
@ -51,6 +51,7 @@ internal class OnboardingManageTokensModel @Inject constructor(
|
|||
|
||||
private val params: OnboardingManageTokensComponent.Params = paramsContainer.require()
|
||||
val state: MutableStateFlow<OnboardingManageTokensUM> = MutableStateFlow(getInitialState())
|
||||
val returnToParentComponentFlow = MutableSharedFlow<Unit>()
|
||||
|
||||
init {
|
||||
manageTokensListManager.uiItems
|
||||
|
|
@ -261,7 +262,7 @@ internal class OnboardingManageTokensModel @Inject constructor(
|
|||
return@resource
|
||||
}
|
||||
|
||||
reduxStateHolder.dispatch(OnboardingManageTokensAction.CurrenciesSaved)
|
||||
returnToParentComponent()
|
||||
}
|
||||
|
||||
private fun onLaterClick() = resource(
|
||||
|
|
@ -287,7 +288,17 @@ internal class OnboardingManageTokensModel @Inject constructor(
|
|||
return@resource
|
||||
}
|
||||
|
||||
returnToParentComponent()
|
||||
}
|
||||
|
||||
private fun returnToParentComponent() {
|
||||
// old onboarding
|
||||
reduxStateHolder.dispatch(OnboardingManageTokensAction.CurrenciesSaved)
|
||||
|
||||
// new one
|
||||
modelScope.launch {
|
||||
returnToParentComponentFlow.emit(Unit)
|
||||
}
|
||||
}
|
||||
|
||||
private fun searchCurrencies(query: String) {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
package com.tangem.features.managetokens.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material3.FabPosition
|
||||
import androidx.compose.material3.Scaffold
|
||||
|
|
@ -71,7 +68,9 @@ internal fun OnboardingManageTokensContent(state: OnboardingManageTokensUM, modi
|
|||
},
|
||||
snackbarHost = {
|
||||
TangemSnackbarHost(
|
||||
modifier = Modifier.padding(all = TangemTheme.dimens.spacing16),
|
||||
modifier = Modifier
|
||||
.padding(all = TangemTheme.dimens.spacing16)
|
||||
.navigationBarsPadding(),
|
||||
hostState = LocalSnackbarHostState.current,
|
||||
)
|
||||
},
|
||||
|
|
@ -80,7 +79,8 @@ internal fun OnboardingManageTokensContent(state: OnboardingManageTokensUM, modi
|
|||
FloatingActionButton(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16)
|
||||
.fillMaxWidth(),
|
||||
.fillMaxWidth()
|
||||
.navigationBarsPadding(),
|
||||
config = state.actionButtonConfig,
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ dependencies {
|
|||
|
||||
/** Common */
|
||||
implementation(projects.common.ui)
|
||||
implementation(projects.common.routing)
|
||||
|
||||
/** Domain */
|
||||
implementation(projects.domain.models)
|
||||
|
|
@ -37,6 +38,7 @@ dependencies {
|
|||
implementation(projects.domain.wallets)
|
||||
implementation(projects.domain.wallets.models)
|
||||
implementation(projects.domain.legacy)
|
||||
implementation(projects.domain.settings)
|
||||
|
||||
/** Tangem libraries */
|
||||
implementation(projects.libs.tangemSdkApi)
|
||||
|
|
@ -57,6 +59,7 @@ dependencies {
|
|||
implementation(deps.compose.ui)
|
||||
implementation(deps.compose.ui.tooling)
|
||||
implementation(deps.compose.coil)
|
||||
implementation(deps.lottie.compose)
|
||||
implementation(deps.decompose.ext.compose)
|
||||
implementation(deps.androidx.activity.compose)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
package com.tangem.features.onboarding.v2.done.api
|
||||
|
||||
import com.tangem.core.decompose.factory.ComponentFactory
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
|
||||
interface OnboardingDoneComponent : ComposableContentComponent {
|
||||
|
||||
data class Params(val onDone: () -> Unit)
|
||||
|
||||
interface Factory : ComponentFactory<Params, OnboardingDoneComponent>
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package com.tangem.features.onboarding.v2.done.impl
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.features.onboarding.v2.done.api.OnboardingDoneComponent
|
||||
import com.tangem.features.onboarding.v2.done.impl.ui.OnboardingDone
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
internal class DefaultOnboardingDoneComponent @AssistedInject constructor(
|
||||
@Assisted context: AppComponentContext,
|
||||
@Assisted private val params: OnboardingDoneComponent.Params,
|
||||
) : OnboardingDoneComponent, AppComponentContext by context {
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
OnboardingDone(
|
||||
onContinueClick = remember(this) { params.onDone },
|
||||
)
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : OnboardingDoneComponent.Factory {
|
||||
override fun create(
|
||||
context: AppComponentContext,
|
||||
params: OnboardingDoneComponent.Params,
|
||||
): DefaultOnboardingDoneComponent
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.features.onboarding.v2.done.impl.di
|
||||
|
||||
import com.tangem.features.onboarding.v2.done.api.OnboardingDoneComponent
|
||||
import com.tangem.features.onboarding.v2.done.impl.DefaultOnboardingDoneComponent
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface ComponentModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun componentFactory(factory: DefaultOnboardingDoneComponent.Factory): OnboardingDoneComponent.Factory
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
package com.tangem.features.onboarding.v2.done.impl.ui
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.airbnb.lottie.compose.LottieAnimation
|
||||
import com.airbnb.lottie.compose.LottieCompositionSpec
|
||||
import com.airbnb.lottie.compose.animateLottieCompositionAsState
|
||||
import com.airbnb.lottie.compose.rememberLottieComposition
|
||||
import com.tangem.core.ui.components.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.onboarding.v2.impl.R
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
@Composable
|
||||
internal fun OnboardingDone(onContinueClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||
val composition by rememberLottieComposition(spec = LottieCompositionSpec.RawRes(R.raw.anim_confetti))
|
||||
val progress by animateLottieCompositionAsState(composition)
|
||||
var showConfetti by remember { mutableStateOf(false) }
|
||||
|
||||
Column(
|
||||
modifier
|
||||
.fillMaxSize(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_success_blue_76),
|
||||
tint = Color.Unspecified,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.size(76.dp),
|
||||
)
|
||||
SpacerH32()
|
||||
Text(
|
||||
modifier = Modifier.padding(horizontal = 32.dp),
|
||||
text = stringResource(R.string.onboarding_done_header),
|
||||
style = TangemTheme.typography.h2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
SpacerH12()
|
||||
Text(
|
||||
modifier = Modifier.padding(horizontal = 32.dp),
|
||||
text = stringResource(R.string.onboarding_subtitle_success_tangem_wallet_onboarding),
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
SpacerH(72.dp)
|
||||
}
|
||||
|
||||
PrimaryButton(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp)
|
||||
.padding(bottom = 16.dp)
|
||||
.navigationBarsPadding(),
|
||||
text = stringResource(R.string.onboarding_button_continue_wallet),
|
||||
onClick = onContinueClick,
|
||||
)
|
||||
}
|
||||
|
||||
if (showConfetti) {
|
||||
FullScreen(notTouchable = true) {
|
||||
LottieAnimation(
|
||||
composition = composition,
|
||||
progress = { progress },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
delay(timeMillis = 500)
|
||||
showConfetti = true
|
||||
}
|
||||
|
||||
LaunchedEffect(progress == 1f) {
|
||||
if (progress == 1f) {
|
||||
showConfetti = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
private fun Preview() {
|
||||
TangemThemePreview {
|
||||
OnboardingDone(onContinueClick = {})
|
||||
}
|
||||
}
|
||||
|
|
@ -65,6 +65,7 @@ internal class DefaultOnboardingEntryComponent @AssistedInject constructor(
|
|||
onboardingChildFactory.createChild(
|
||||
route = configuration,
|
||||
childContext = childByContext(factoryContext),
|
||||
onManageTokensDone = model::onManageTokensDone,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,25 +2,35 @@ package com.tangem.features.onboarding.v2.entry.impl.model
|
|||
|
||||
import com.arkivanov.decompose.router.stack.StackNavigation
|
||||
import com.arkivanov.decompose.router.stack.navigate
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.decompose.di.ComponentScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.models.scan.ProductType
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.settings.repositories.SettingsRepository
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.features.onboarding.v2.TitleProvider
|
||||
import com.tangem.features.onboarding.v2.entry.OnboardingEntryComponent
|
||||
import com.tangem.features.onboarding.v2.entry.impl.routing.OnboardingRoute
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.NonCancellable
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@ComponentScoped
|
||||
internal class OnboardingEntryModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val router: Router,
|
||||
private val tangemSdkManager: TangemSdkManager,
|
||||
private val settingsRepository: SettingsRepository,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<OnboardingEntryComponent.Params>()
|
||||
|
|
@ -63,4 +73,20 @@ internal class OnboardingEntryModel @Inject constructor(
|
|||
listOf(OnboardingRoute.ManageTokens(userWallet))
|
||||
}
|
||||
}
|
||||
|
||||
fun onManageTokensDone() {
|
||||
stackNavigation.navigate {
|
||||
listOf(OnboardingRoute.Done(onDone = ::navigateToWalletScreen))
|
||||
}
|
||||
}
|
||||
|
||||
private fun navigateToWalletScreen() {
|
||||
modelScope.launch(NonCancellable) {
|
||||
router.replaceAll(AppRoute.Wallet)
|
||||
if (tangemSdkManager.checkCanUseBiometry() && settingsRepository.shouldShowSaveUserWalletScreen()) {
|
||||
delay(timeMillis = 1_800)
|
||||
router.push(AppRoute.SaveWallet)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +1,18 @@
|
|||
package com.tangem.features.onboarding.v2.entry.impl.routing
|
||||
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.features.managetokens.component.ManageTokensComponent
|
||||
import com.tangem.features.managetokens.component.ManageTokensSource
|
||||
import com.tangem.features.managetokens.component.OnboardingManageTokensComponent
|
||||
import com.tangem.features.onboarding.v2.done.api.OnboardingDoneComponent
|
||||
import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class OnboardingChildFactory @Inject constructor(
|
||||
private val multiWalletComponentFactory: OnboardingMultiWalletComponent.Factory,
|
||||
private val manageTokensComponentFactory: ManageTokensComponent.Factory,
|
||||
private val onboardingManageTokensComponentFactory: OnboardingManageTokensComponent.Factory,
|
||||
private val onboardingDoneComponentFactory: OnboardingDoneComponent.Factory,
|
||||
) {
|
||||
|
||||
fun createChild(route: OnboardingRoute, childContext: AppComponentContext): Any {
|
||||
fun createChild(route: OnboardingRoute, childContext: AppComponentContext, onManageTokensDone: () -> Unit): Any {
|
||||
return when (route) {
|
||||
is OnboardingRoute.MultiWallet -> multiWalletComponentFactory.create(
|
||||
context = childContext,
|
||||
|
|
@ -22,11 +23,17 @@ internal class OnboardingChildFactory @Inject constructor(
|
|||
onDone = route.onDone,
|
||||
),
|
||||
)
|
||||
is OnboardingRoute.ManageTokens -> manageTokensComponentFactory.create( // TODO replace with wrapper
|
||||
is OnboardingRoute.ManageTokens -> onboardingManageTokensComponentFactory.create(
|
||||
context = childContext,
|
||||
params = ManageTokensComponent.Params(
|
||||
params = OnboardingManageTokensComponent.Params(
|
||||
userWalletId = route.userWallet.walletId,
|
||||
source = ManageTokensSource.ONBOARDING,
|
||||
),
|
||||
onDone = onManageTokensDone,
|
||||
)
|
||||
is OnboardingRoute.Done -> onboardingDoneComponentFactory.create(
|
||||
context = childContext,
|
||||
params = OnboardingDoneComponent.Params(
|
||||
onDone = route.onDone,
|
||||
),
|
||||
)
|
||||
else -> Unit
|
||||
|
|
|
|||
|
|
@ -19,4 +19,8 @@ sealed class OnboardingRoute : Route {
|
|||
data class ManageTokens(
|
||||
val userWallet: UserWallet,
|
||||
) : OnboardingRoute()
|
||||
|
||||
data class Done(
|
||||
val onDone: () -> Unit,
|
||||
) : OnboardingRoute()
|
||||
}
|
||||
|
|
@ -42,6 +42,11 @@ internal inline fun OnboardingEntry(
|
|||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
is OnboardingRoute.Done -> {
|
||||
(it.instance as ComposableContentComponent).Content(
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
OnboardingRoute.None -> {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ jodatime = "2.12.1"
|
|||
kotlin-immutable-collections = "0.3.5"
|
||||
kotsonGsonExt = "2.5.0"
|
||||
lottie = "3.4.0"
|
||||
lottie-compose = "6.6.0"
|
||||
moshi = "1.12.0"
|
||||
okhttp = "4.9.3"
|
||||
rekotlin = "1.0.4"
|
||||
|
|
@ -228,10 +229,10 @@ googlePlay-services-wallet = { module = "com.google.android.gms:play-services-wa
|
|||
hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" }
|
||||
hilt-core = { module = "com.google.dagger:hilt-core", version.ref = "hilt" }
|
||||
hilt-kapt = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt" }
|
||||
hilt-navigation = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt" }
|
||||
jodatime = { module = "joda-time:joda-time", version.ref = "jodatime" }
|
||||
kotsonGson = { module = "com.github.salomonbrys.kotson:kotson", version.ref = "kotsonGsonExt" }
|
||||
lottie = { module = "com.airbnb.android:lottie", version.ref = "lottie" }
|
||||
lottie-compose = { module = "com.airbnb.android:lottie-compose", version.ref = "lottie-compose" }
|
||||
material = { module = "com.google.android.material:material", version.ref = "googleMaterialComponent" }
|
||||
moshi = { module = "com.squareup.moshi:moshi", version.ref = "moshi" }
|
||||
moshi-kotlin = { module = "com.squareup.moshi:moshi-kotlin", version.ref = "moshi" }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue