Updated on 2026-08-14
This commit is contained in:
parent
e51453c99b
commit
9ab23a953d
21 changed files with 343 additions and 233 deletions
|
|
@ -0,0 +1,3 @@
|
|||
package com.tangem.features.hotwallet.accesscode
|
||||
|
||||
const val ACCESS_CODE_LENGTH = 6
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package com.tangem.features.hotwallet.accesscode.confirm
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.security.DisableScreenshotsDisposableEffect
|
||||
import com.tangem.features.hotwallet.accesscode.confirm.ui.SetAccessCodeConfirmContent
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
internal class ConfirmAccessCodeComponent @AssistedInject constructor(
|
||||
@Assisted private val context: AppComponentContext,
|
||||
@Assisted private val params: Params,
|
||||
) : ComposableContentComponent, AppComponentContext by context {
|
||||
|
||||
private val model: ConfirmAccessCodeModel = getOrCreateModel(params)
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val state by model.uiState.collectAsStateWithLifecycle()
|
||||
|
||||
DisableScreenshotsDisposableEffect()
|
||||
|
||||
SetAccessCodeConfirmContent(
|
||||
accessCode = state.accessCode,
|
||||
onAccessCodeChange = state.onAccessCodeChange,
|
||||
accessCodeLength = state.accessCodeLength,
|
||||
onConfirm = state.onConfirm,
|
||||
buttonEnabled = state.buttonEnabled,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
interface ModelCallbacks {
|
||||
fun onAccessCodeConfirmed()
|
||||
}
|
||||
|
||||
data class Params(
|
||||
val accessCodeToConfirm: String,
|
||||
val callbacks: ModelCallbacks,
|
||||
)
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(context: AppComponentContext, params: Params): ConfirmAccessCodeComponent
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package com.tangem.features.hotwallet.accesscode.confirm
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.features.hotwallet.accesscode.confirm.entity.ConfirmAccessCodeUM
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import javax.inject.Inject
|
||||
|
||||
@Stable
|
||||
@ModelScoped
|
||||
internal class ConfirmAccessCodeModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<ConfirmAccessCodeComponent.Params>()
|
||||
|
||||
internal val uiState: StateFlow<ConfirmAccessCodeUM>
|
||||
field = MutableStateFlow(getInitialState())
|
||||
|
||||
private fun getInitialState() = ConfirmAccessCodeUM(
|
||||
accessCode = "",
|
||||
onAccessCodeChange = ::onAccessCodeChange,
|
||||
buttonEnabled = false,
|
||||
onConfirm = ::onConfirm,
|
||||
)
|
||||
|
||||
private fun onAccessCodeChange(value: String) {
|
||||
uiState.update {
|
||||
it.copy(
|
||||
accessCode = value,
|
||||
buttonEnabled = value == params.accessCodeToConfirm,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onConfirm() {
|
||||
params.callbacks.onAccessCodeConfirmed()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.tangem.features.hotwallet.accesscode.confirm.entity
|
||||
|
||||
import com.tangem.features.hotwallet.accesscode.ACCESS_CODE_LENGTH
|
||||
|
||||
internal data class ConfirmAccessCodeUM(
|
||||
val accessCode: String,
|
||||
val onAccessCodeChange: (String) -> Unit,
|
||||
val buttonEnabled: Boolean,
|
||||
val onConfirm: () -> Unit,
|
||||
) {
|
||||
val accessCodeLength: Int = ACCESS_CODE_LENGTH
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package com.tangem.features.hotwallet.accesscode.confirm.ui
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.PrimaryButton
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.features.hotwallet.accesscode.ui.AccessCodeEnter
|
||||
import com.tangem.core.res.R
|
||||
|
||||
@Composable
|
||||
internal fun SetAccessCodeConfirmContent(
|
||||
accessCode: String,
|
||||
onAccessCodeChange: (String) -> Unit,
|
||||
accessCodeLength: Int,
|
||||
onConfirm: () -> Unit,
|
||||
buttonEnabled: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.navigationBarsPadding(),
|
||||
) {
|
||||
AccessCodeEnter(
|
||||
modifier = Modifier
|
||||
.padding(top = 16.dp)
|
||||
.weight(1f),
|
||||
accessCode = accessCode,
|
||||
onAccessCodeChange = onAccessCodeChange,
|
||||
accessCodeLength = accessCodeLength,
|
||||
reEnterAccessCodeState = true,
|
||||
)
|
||||
|
||||
PrimaryButton(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp)
|
||||
.imePadding(),
|
||||
text = stringResourceSafe(R.string.common_confirm),
|
||||
onClick = onConfirm,
|
||||
enabled = buttonEnabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
package com.tangem.features.hotwallet.setaccesscode.di
|
||||
package com.tangem.features.hotwallet.accesscode.di
|
||||
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.features.hotwallet.setaccesscode.SetAccessCodeModel
|
||||
import com.tangem.features.hotwallet.accesscode.confirm.ConfirmAccessCodeModel
|
||||
import com.tangem.features.hotwallet.accesscode.set.SetAccessCodeModel
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -11,10 +12,15 @@ import dagger.multibindings.IntoMap
|
|||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface SetAccessCodeModule {
|
||||
internal interface AccessCodeModule {
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(SetAccessCodeModel::class)
|
||||
fun bindSetAccessCodeModel(model: SetAccessCodeModel): Model
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(ConfirmAccessCodeModel::class)
|
||||
fun bindConfirmAccessCodeModel(model: ConfirmAccessCodeModel): Model
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.features.hotwallet.setaccesscode
|
||||
package com.tangem.features.hotwallet.accesscode.set
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
|
|
@ -8,8 +8,9 @@ import com.tangem.core.decompose.context.AppComponentContext
|
|||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.security.DisableScreenshotsDisposableEffect
|
||||
import com.tangem.features.hotwallet.setaccesscode.ui.SetAccessCodeContent
|
||||
import com.tangem.features.hotwallet.accesscode.set.ui.SetAccessCodeContent
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
internal class SetAccessCodeComponent @AssistedInject constructor(
|
||||
|
|
@ -23,21 +24,28 @@ internal class SetAccessCodeComponent @AssistedInject constructor(
|
|||
override fun Content(modifier: Modifier) {
|
||||
val state by model.uiState.collectAsStateWithLifecycle()
|
||||
|
||||
DisableScreenshotsDisposableEffect()
|
||||
|
||||
SetAccessCodeContent(
|
||||
state = state,
|
||||
onBack = { model.onBack() },
|
||||
accessCode = state.accessCode,
|
||||
onAccessCodeChange = state.onAccessCodeChange,
|
||||
accessCodeLength = state.accessCodeLength,
|
||||
onContinue = state.onContinue,
|
||||
buttonEnabled = state.buttonEnabled,
|
||||
modifier = modifier,
|
||||
)
|
||||
|
||||
DisableScreenshotsDisposableEffect()
|
||||
}
|
||||
|
||||
interface ModelCallbacks {
|
||||
fun onBackClick()
|
||||
fun onAccessCodeSet()
|
||||
fun onAccessCodeSet(accessCode: String)
|
||||
}
|
||||
|
||||
data class Params(
|
||||
val callbacks: ModelCallbacks,
|
||||
)
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(context: AppComponentContext, params: Params): SetAccessCodeComponent
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package com.tangem.features.hotwallet.accesscode.set
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.features.hotwallet.accesscode.set.entity.SetAccessCodeUM
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import javax.inject.Inject
|
||||
|
||||
@Stable
|
||||
@ModelScoped
|
||||
internal class SetAccessCodeModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<SetAccessCodeComponent.Params>()
|
||||
|
||||
internal val uiState: StateFlow<SetAccessCodeUM>
|
||||
field = MutableStateFlow(getInitialState())
|
||||
|
||||
private fun getInitialState() = SetAccessCodeUM(
|
||||
accessCode = "",
|
||||
onAccessCodeChange = ::onAccessCodeChange,
|
||||
buttonEnabled = false,
|
||||
onContinue = ::onContinue,
|
||||
)
|
||||
|
||||
private fun onAccessCodeChange(value: String) {
|
||||
uiState.update {
|
||||
it.copy(
|
||||
accessCode = value,
|
||||
buttonEnabled = value.length == uiState.value.accessCodeLength,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onContinue() {
|
||||
params.callbacks.onAccessCodeSet(uiState.value.accessCode)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.tangem.features.hotwallet.accesscode.set.entity
|
||||
|
||||
import com.tangem.features.hotwallet.accesscode.ACCESS_CODE_LENGTH
|
||||
|
||||
internal data class SetAccessCodeUM(
|
||||
val accessCode: String,
|
||||
val onAccessCodeChange: (String) -> Unit,
|
||||
val buttonEnabled: Boolean,
|
||||
val onContinue: () -> Unit,
|
||||
) {
|
||||
val accessCodeLength: Int = ACCESS_CODE_LENGTH
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package com.tangem.features.hotwallet.accesscode.set.ui
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.PrimaryButton
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.features.hotwallet.accesscode.ui.AccessCodeEnter
|
||||
import com.tangem.core.res.R
|
||||
|
||||
@Composable
|
||||
internal fun SetAccessCodeContent(
|
||||
accessCode: String,
|
||||
onAccessCodeChange: (String) -> Unit,
|
||||
accessCodeLength: Int,
|
||||
onContinue: () -> Unit,
|
||||
buttonEnabled: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.navigationBarsPadding(),
|
||||
) {
|
||||
AccessCodeEnter(
|
||||
modifier = Modifier
|
||||
.padding(top = 16.dp)
|
||||
.weight(1f),
|
||||
accessCode = accessCode,
|
||||
onAccessCodeChange = onAccessCodeChange,
|
||||
accessCodeLength = accessCodeLength,
|
||||
reEnterAccessCodeState = false,
|
||||
)
|
||||
|
||||
PrimaryButton(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp)
|
||||
.imePadding(),
|
||||
text = stringResourceSafe(R.string.common_continue),
|
||||
onClick = onContinue,
|
||||
enabled = buttonEnabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.features.hotwallet.setaccesscode.ui
|
||||
package com.tangem.features.hotwallet.accesscode.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
|
|
@ -15,11 +15,12 @@ import com.tangem.core.ui.components.fields.PinTextField
|
|||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.hotwallet.setaccesscode.entity.SetAccessCodeUM
|
||||
|
||||
@Composable
|
||||
internal fun SetAccessCodeEnter(
|
||||
state: SetAccessCodeUM,
|
||||
internal fun AccessCodeEnter(
|
||||
accessCode: String,
|
||||
onAccessCodeChange: (String) -> Unit,
|
||||
accessCodeLength: Int,
|
||||
reEnterAccessCodeState: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
|
|
@ -52,7 +53,7 @@ internal fun SetAccessCodeEnter(
|
|||
} else {
|
||||
stringResourceSafe(
|
||||
R.string.access_code_create_description,
|
||||
state.accessCodeLength,
|
||||
accessCodeLength,
|
||||
)
|
||||
},
|
||||
style = TangemTheme.typography.body1,
|
||||
|
|
@ -67,18 +68,10 @@ internal fun SetAccessCodeEnter(
|
|||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
PinTextField(
|
||||
length = state.accessCodeLength,
|
||||
length = accessCodeLength,
|
||||
isPasswordVisual = true,
|
||||
value = if (reEnterAccessCodeState) {
|
||||
state.accessCodeSecond
|
||||
} else {
|
||||
state.accessCodeFirst
|
||||
},
|
||||
onValueChange = if (reEnterAccessCodeState) {
|
||||
state.onAccessCodeSecondChange
|
||||
} else {
|
||||
state.onAccessCodeFirstChange
|
||||
},
|
||||
value = accessCode,
|
||||
onValueChange = onAccessCodeChange,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -89,37 +82,25 @@ internal fun SetAccessCodeEnter(
|
|||
@Composable
|
||||
private fun Preview() {
|
||||
TangemThemePreview {
|
||||
SetAccessCodeEnter(
|
||||
AccessCodeEnter(
|
||||
accessCode = "123456",
|
||||
onAccessCodeChange = {},
|
||||
accessCodeLength = 6,
|
||||
reEnterAccessCodeState = false,
|
||||
state = SetAccessCodeUM(
|
||||
step = SetAccessCodeUM.Step.AccessCode,
|
||||
accessCodeFirst = "",
|
||||
accessCodeSecond = "",
|
||||
onAccessCodeFirstChange = {},
|
||||
onAccessCodeSecondChange = {},
|
||||
buttonEnabled = false,
|
||||
onContinue = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun Preview2() {
|
||||
TangemThemePreview {
|
||||
SetAccessCodeEnter(
|
||||
AccessCodeEnter(
|
||||
accessCode = "123456",
|
||||
onAccessCodeChange = {},
|
||||
accessCodeLength = 6,
|
||||
reEnterAccessCodeState = true,
|
||||
state = SetAccessCodeUM(
|
||||
step = SetAccessCodeUM.Step.ConfirmAccessCode,
|
||||
accessCodeFirst = "",
|
||||
accessCodeSecond = "",
|
||||
onAccessCodeFirstChange = {},
|
||||
onAccessCodeSecondChange = {},
|
||||
buttonEnabled = false,
|
||||
onContinue = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -9,11 +9,12 @@ import com.tangem.core.decompose.di.ModelScoped
|
|||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.domain.settings.ShouldAskPermissionUseCase
|
||||
import com.tangem.features.hotwallet.setaccesscode.SetAccessCodeComponent
|
||||
import com.tangem.features.hotwallet.addexistingwallet.start.AddExistingWalletStartComponent
|
||||
import com.tangem.features.hotwallet.addexistingwallet.im.port.AddExistingWalletImportComponent
|
||||
import com.tangem.features.hotwallet.addexistingwallet.root.routing.AddExistingWalletRoute
|
||||
import com.tangem.features.hotwallet.addexistingwallet.start.AddExistingWalletStartComponent
|
||||
import com.tangem.features.hotwallet.manualbackup.completed.ManualBackupCompletedComponent
|
||||
import com.tangem.features.hotwallet.accesscode.confirm.ConfirmAccessCodeComponent
|
||||
import com.tangem.features.hotwallet.accesscode.set.SetAccessCodeComponent
|
||||
import com.tangem.features.hotwallet.setupfinished.MobileWalletSetupFinishedComponent
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsComponent
|
||||
import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
|
||||
|
|
@ -31,20 +32,22 @@ internal class AddExistingWalletModel @Inject constructor(
|
|||
val addExistingWalletStartModelCallbacks = AddExistingWalletStartModelCallbacks()
|
||||
val addExistingWalletImportModelCallbacks = AddExistingWalletImportModelCallbacks()
|
||||
val manualBackupCompletedComponentModelCallbacks = ManualBackupCompletedComponentModelCallbacks()
|
||||
val accessCodeModelCallbacks = AccessCodeModelCallbacks()
|
||||
val pushNotificationsComponentModelCallbacks = PushNotificationsComponentModelCallbacks()
|
||||
val setAccessCodeModelCallbacks = SetAccessCodeModelCallbacks()
|
||||
val confirmAccessCodeModelCallbacks = ConfirmAccessCodeModelCallbacks()
|
||||
val mobileWalletSetupFinishedComponentModelCallbacks = MobileWalletSetupFinishedComponentModelCallbacks()
|
||||
|
||||
val stackNavigation = StackNavigation<AddExistingWalletRoute>()
|
||||
|
||||
fun onChildBack(currentRoute: AddExistingWalletRoute) {
|
||||
when (currentRoute) {
|
||||
AddExistingWalletRoute.Import -> stackNavigation.pop()
|
||||
AddExistingWalletRoute.BackupCompleted -> Unit
|
||||
AddExistingWalletRoute.AccessCode -> stackNavigation.pop()
|
||||
AddExistingWalletRoute.PushNotifications -> Unit
|
||||
AddExistingWalletRoute.SetupFinished -> Unit
|
||||
AddExistingWalletRoute.Start -> Unit
|
||||
is AddExistingWalletRoute.Import -> stackNavigation.pop()
|
||||
is AddExistingWalletRoute.BackupCompleted -> Unit
|
||||
is AddExistingWalletRoute.ConfirmAccessCode -> stackNavigation.pop()
|
||||
is AddExistingWalletRoute.SetAccessCode -> stackNavigation.pop()
|
||||
is AddExistingWalletRoute.PushNotifications -> Unit
|
||||
is AddExistingWalletRoute.SetupFinished -> Unit
|
||||
is AddExistingWalletRoute.Start -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -66,16 +69,18 @@ internal class AddExistingWalletModel @Inject constructor(
|
|||
|
||||
inner class ManualBackupCompletedComponentModelCallbacks : ManualBackupCompletedComponent.ModelCallbacks {
|
||||
override fun onContinueClick() {
|
||||
stackNavigation.push(AddExistingWalletRoute.AccessCode)
|
||||
stackNavigation.push(AddExistingWalletRoute.SetAccessCode)
|
||||
}
|
||||
}
|
||||
|
||||
inner class AccessCodeModelCallbacks : SetAccessCodeComponent.ModelCallbacks {
|
||||
override fun onBackClick() {
|
||||
stackNavigation.pop()
|
||||
inner class SetAccessCodeModelCallbacks : SetAccessCodeComponent.ModelCallbacks {
|
||||
override fun onAccessCodeSet(accessCode: String) {
|
||||
stackNavigation.push(AddExistingWalletRoute.ConfirmAccessCode(accessCode))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAccessCodeSet() {
|
||||
inner class ConfirmAccessCodeModelCallbacks : ConfirmAccessCodeComponent.ModelCallbacks {
|
||||
override fun onAccessCodeConfirmed() {
|
||||
modelScope.launch {
|
||||
val shouldRequestPush = shouldAskPermissionUseCase(PUSH_PERMISSION)
|
||||
if (shouldRequestPush) {
|
||||
|
|
@ -95,7 +100,8 @@ internal class AddExistingWalletModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
inner class MobileWalletSetupFinishedComponentModelCallbacks : MobileWalletSetupFinishedComponent.ModelCallbacks {
|
||||
inner class MobileWalletSetupFinishedComponentModelCallbacks :
|
||||
MobileWalletSetupFinishedComponent.ModelCallbacks {
|
||||
override fun onContinueClick() {
|
||||
router.replaceAll(AppRoute.Wallet)
|
||||
}
|
||||
|
|
@ -2,7 +2,8 @@ package com.tangem.features.hotwallet.addexistingwallet.root.routing
|
|||
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.features.hotwallet.setaccesscode.SetAccessCodeComponent
|
||||
import com.tangem.features.hotwallet.accesscode.set.SetAccessCodeComponent
|
||||
import com.tangem.features.hotwallet.accesscode.confirm.ConfirmAccessCodeComponent
|
||||
import com.tangem.features.hotwallet.addexistingwallet.root.AddExistingWalletModel
|
||||
import com.tangem.features.hotwallet.addexistingwallet.start.AddExistingWalletStartComponent
|
||||
import com.tangem.features.hotwallet.addexistingwallet.im.port.AddExistingWalletImportComponent
|
||||
|
|
@ -13,6 +14,8 @@ import javax.inject.Inject
|
|||
|
||||
internal class AddExistingWalletChildFactory @Inject constructor(
|
||||
private val pushNotificationsComponent: PushNotificationsComponent.Factory,
|
||||
private val setAccessCodeSetComponentFactory: SetAccessCodeComponent.Factory,
|
||||
private val confirmAccessCodeComponentFactory: ConfirmAccessCodeComponent.Factory,
|
||||
) {
|
||||
|
||||
fun createChild(
|
||||
|
|
@ -39,10 +42,17 @@ internal class AddExistingWalletChildFactory @Inject constructor(
|
|||
callbacks = model.manualBackupCompletedComponentModelCallbacks,
|
||||
),
|
||||
)
|
||||
is AddExistingWalletRoute.AccessCode -> SetAccessCodeComponent(
|
||||
is AddExistingWalletRoute.SetAccessCode -> setAccessCodeSetComponentFactory.create(
|
||||
context = childContext,
|
||||
params = SetAccessCodeComponent.Params(
|
||||
callbacks = model.accessCodeModelCallbacks,
|
||||
callbacks = model.setAccessCodeModelCallbacks,
|
||||
),
|
||||
)
|
||||
is AddExistingWalletRoute.ConfirmAccessCode -> confirmAccessCodeComponentFactory.create(
|
||||
context = childContext,
|
||||
params = ConfirmAccessCodeComponent.Params(
|
||||
accessCodeToConfirm = route.accessCode,
|
||||
callbacks = model.confirmAccessCodeModelCallbacks,
|
||||
),
|
||||
)
|
||||
is AddExistingWalletRoute.PushNotifications -> pushNotificationsComponent.create(
|
||||
|
|
@ -51,7 +61,7 @@ internal class AddExistingWalletChildFactory @Inject constructor(
|
|||
callbacks = model.pushNotificationsComponentModelCallbacks,
|
||||
),
|
||||
)
|
||||
AddExistingWalletRoute.SetupFinished -> MobileWalletSetupFinishedComponent(
|
||||
is AddExistingWalletRoute.SetupFinished -> MobileWalletSetupFinishedComponent(
|
||||
context = childContext,
|
||||
params = MobileWalletSetupFinishedComponent.Params(
|
||||
callbacks = model.mobileWalletSetupFinishedComponentModelCallbacks,
|
||||
|
|
@ -15,7 +15,10 @@ internal sealed class AddExistingWalletRoute : Route {
|
|||
object BackupCompleted : AddExistingWalletRoute()
|
||||
|
||||
@Serializable
|
||||
object AccessCode : AddExistingWalletRoute()
|
||||
object SetAccessCode : AddExistingWalletRoute()
|
||||
|
||||
@Serializable
|
||||
data class ConfirmAccessCode(val accessCode: String) : AddExistingWalletRoute()
|
||||
|
||||
@Serializable
|
||||
object PushNotifications : AddExistingWalletRoute()
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
package com.tangem.features.hotwallet.setaccesscode
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.features.hotwallet.setaccesscode.entity.SetAccessCodeUM
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import javax.inject.Inject
|
||||
|
||||
@Stable
|
||||
@ModelScoped
|
||||
internal class SetAccessCodeModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<SetAccessCodeComponent.Params>()
|
||||
|
||||
internal val uiState: StateFlow<SetAccessCodeUM>
|
||||
field = MutableStateFlow(getInitialState())
|
||||
|
||||
fun onBack() {
|
||||
when (uiState.value.step) {
|
||||
SetAccessCodeUM.Step.AccessCode -> {
|
||||
params.callbacks.onBackClick()
|
||||
}
|
||||
SetAccessCodeUM.Step.ConfirmAccessCode -> {
|
||||
uiState.update {
|
||||
it.copy(
|
||||
step = SetAccessCodeUM.Step.AccessCode,
|
||||
accessCodeSecond = "",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getInitialState() = SetAccessCodeUM(
|
||||
step = SetAccessCodeUM.Step.AccessCode,
|
||||
accessCodeFirst = "",
|
||||
accessCodeSecond = "",
|
||||
onAccessCodeFirstChange = ::onAccessCodeFirstChange,
|
||||
onAccessCodeSecondChange = ::onAccessCodeSecondChange,
|
||||
buttonEnabled = false,
|
||||
onContinue = ::onContinue,
|
||||
)
|
||||
|
||||
private fun onAccessCodeFirstChange(value: String) {
|
||||
uiState.update {
|
||||
it.copy(
|
||||
accessCodeFirst = value,
|
||||
buttonEnabled = value.length == uiState.value.accessCodeLength,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onAccessCodeSecondChange(value: String) {
|
||||
uiState.update {
|
||||
it.copy(
|
||||
accessCodeSecond = value,
|
||||
buttonEnabled = uiState.value.accessCodeFirst == uiState.value.accessCodeSecond,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onContinue() {
|
||||
when (uiState.value.step) {
|
||||
SetAccessCodeUM.Step.AccessCode -> {
|
||||
uiState.update {
|
||||
it.copy(
|
||||
step = SetAccessCodeUM.Step.ConfirmAccessCode,
|
||||
)
|
||||
}
|
||||
}
|
||||
SetAccessCodeUM.Step.ConfirmAccessCode -> {
|
||||
params.callbacks.onAccessCodeSet()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
package com.tangem.features.hotwallet.setaccesscode.entity
|
||||
|
||||
internal data class SetAccessCodeUM(
|
||||
val step: Step,
|
||||
val accessCodeFirst: String,
|
||||
val accessCodeSecond: String,
|
||||
val onAccessCodeFirstChange: (String) -> Unit,
|
||||
val onAccessCodeSecondChange: (String) -> Unit,
|
||||
val buttonEnabled: Boolean,
|
||||
val onContinue: () -> Unit,
|
||||
) {
|
||||
val accessCodeLength: Int = ACCESS_CODE_LENGTH
|
||||
|
||||
enum class Step {
|
||||
AccessCode,
|
||||
ConfirmAccessCode,
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ACCESS_CODE_LENGTH = 6
|
||||
}
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
package com.tangem.features.hotwallet.setaccesscode.ui
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.PrimaryButton
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemAnimations
|
||||
import com.tangem.features.hotwallet.setaccesscode.entity.SetAccessCodeUM
|
||||
import com.tangem.features.hotwallet.setaccesscode.entity.SetAccessCodeUM.Step.*
|
||||
import com.tangem.core.res.R
|
||||
|
||||
@Composable
|
||||
internal fun SetAccessCodeContent(state: SetAccessCodeUM, onBack: () -> Unit, modifier: Modifier = Modifier) {
|
||||
BackHandler(onBack = onBack)
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.navigationBarsPadding(),
|
||||
) {
|
||||
AnimatedContent(
|
||||
modifier = Modifier.weight(1f),
|
||||
targetState = state.step,
|
||||
transitionSpec = TangemAnimations.AnimatedContent
|
||||
.slide { initial, target -> target.ordinal > initial.ordinal },
|
||||
label = "AnimatedContent",
|
||||
) { step ->
|
||||
when (step) {
|
||||
AccessCode -> SetAccessCodeEnter(
|
||||
modifier = Modifier.padding(top = 16.dp),
|
||||
state = state,
|
||||
reEnterAccessCodeState = false,
|
||||
)
|
||||
ConfirmAccessCode -> SetAccessCodeEnter(
|
||||
modifier = Modifier.padding(top = 16.dp),
|
||||
state = state,
|
||||
reEnterAccessCodeState = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
PrimaryButton(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp)
|
||||
.imePadding(),
|
||||
text = if (state.step == ConfirmAccessCode) {
|
||||
stringResourceSafe(R.string.common_confirm)
|
||||
} else {
|
||||
stringResourceSafe(R.string.common_continue)
|
||||
},
|
||||
onClick = state.onContinue,
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue