Updated on 2026-08-14
This commit is contained in:
parent
91d8932543
commit
3cf222aa32
7 changed files with 159 additions and 18 deletions
|
|
@ -3,12 +3,13 @@ package com.tangem.features.managetokens.component
|
|||
import com.tangem.core.decompose.factory.ComponentFactory
|
||||
import com.tangem.core.ui.decompose.ComposableDialogComponent
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.features.managetokens.entity.customtoken.SelectedDerivationPath
|
||||
|
||||
internal interface CustomTokenDerivationInputComponent : ComposableDialogComponent {
|
||||
|
||||
data class Params(
|
||||
val userWalletId: UserWalletId,
|
||||
val onConfirm: (String) -> Unit,
|
||||
val onConfirm: (SelectedDerivationPath) -> Unit,
|
||||
val onDismiss: () -> Unit,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,127 @@
|
|||
package com.tangem.features.managetokens.component.impl
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.managetokens.ValidateDerivationPathUseCase
|
||||
import com.tangem.domain.managetokens.model.exceptoin.DerivationPathValidationException
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.features.managetokens.component.CustomTokenDerivationInputComponent
|
||||
import com.tangem.features.managetokens.entity.customtoken.CustomDerivationInputUM
|
||||
import com.tangem.features.managetokens.entity.customtoken.SelectedDerivationPath
|
||||
import com.tangem.features.managetokens.impl.R
|
||||
import com.tangem.features.managetokens.ui.dialog.CustomDerivationInputDialog
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
internal class DefaultCustomTokenDerivationInputComponent @AssistedInject constructor(
|
||||
@Assisted context: AppComponentContext,
|
||||
@Assisted private val params: CustomTokenDerivationInputComponent.Params,
|
||||
private val validateDerivationPathUseCase: ValidateDerivationPathUseCase,
|
||||
) : CustomTokenDerivationInputComponent, AppComponentContext by context {
|
||||
|
||||
private val state: MutableStateFlow<CustomDerivationInputUM> = MutableStateFlow(
|
||||
value = getInitialState(),
|
||||
)
|
||||
|
||||
init {
|
||||
observeValueUpdates()
|
||||
}
|
||||
|
||||
override fun dismiss() {
|
||||
params.onDismiss()
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun Dialog() {
|
||||
val state by state.collectAsStateWithLifecycle()
|
||||
|
||||
CustomDerivationInputDialog(
|
||||
model = state,
|
||||
onDismiss = ::dismiss,
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
private fun observeValueUpdates() {
|
||||
state
|
||||
.map { it.value.text }
|
||||
.distinctUntilChanged()
|
||||
.sample(periodMillis = 1_000)
|
||||
.onEach(::validateValue)
|
||||
.launchIn(componentScope)
|
||||
}
|
||||
|
||||
private fun getInitialState(): CustomDerivationInputUM = CustomDerivationInputUM(
|
||||
value = TextFieldValue(),
|
||||
error = null,
|
||||
updateValue = ::updateValue,
|
||||
isConfirmEnabled = false,
|
||||
onConfirm = ::confirm,
|
||||
)
|
||||
|
||||
private fun validateValue(value: String) {
|
||||
validateDerivationPathUseCase(value).getOrElse { e ->
|
||||
updateWithValidationError(e)
|
||||
return
|
||||
}
|
||||
|
||||
state.update { state ->
|
||||
state.copy(
|
||||
error = null,
|
||||
isConfirmEnabled = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateWithValidationError(e: DerivationPathValidationException) {
|
||||
state.update { state ->
|
||||
state.copy(
|
||||
error = when (e) {
|
||||
DerivationPathValidationException.Empty -> null
|
||||
DerivationPathValidationException.Invalid -> {
|
||||
resourceReference(R.string.custom_token_invalid_derivation_path)
|
||||
}
|
||||
},
|
||||
isConfirmEnabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateValue(value: TextFieldValue) {
|
||||
state.update { state ->
|
||||
state.copy(value = value)
|
||||
}
|
||||
}
|
||||
|
||||
private fun confirm() {
|
||||
if (state.value.error != null && !state.value.isConfirmEnabled) {
|
||||
return
|
||||
}
|
||||
|
||||
val value = state.value.value.text
|
||||
val model = SelectedDerivationPath(
|
||||
id = null,
|
||||
value = Network.DerivationPath.Custom(value),
|
||||
networkName = stringReference(value = value),
|
||||
)
|
||||
|
||||
params.onConfirm(model)
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : CustomTokenDerivationInputComponent.Factory {
|
||||
override fun create(
|
||||
context: AppComponentContext,
|
||||
params: CustomTokenDerivationInputComponent.Params,
|
||||
): DefaultCustomTokenDerivationInputComponent
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ import com.tangem.core.decompose.model.getOrCreateModel
|
|||
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
||||
import com.tangem.features.managetokens.component.AddCustomTokenComponent
|
||||
import com.tangem.features.managetokens.component.ManageTokensComponent
|
||||
import com.tangem.features.managetokens.entity.managetokens.BottomSheetConfig
|
||||
import com.tangem.features.managetokens.entity.managetokens.ManageTokensBottomSheetConfig
|
||||
import com.tangem.features.managetokens.model.ManageTokensModel
|
||||
import com.tangem.features.managetokens.ui.ManageTokensScreen
|
||||
import dagger.assisted.Assisted
|
||||
|
|
@ -32,7 +32,7 @@ internal class DefaultManageTokensComponent @AssistedInject constructor(
|
|||
|
||||
private val bottomSheetSlot = childSlot(
|
||||
source = model.bottomSheetNavigation,
|
||||
serializer = BottomSheetConfig.serializer(),
|
||||
serializer = ManageTokensBottomSheetConfig.serializer(),
|
||||
handleBackButton = false,
|
||||
childFactory = ::bottomSheetChild,
|
||||
)
|
||||
|
|
@ -53,10 +53,10 @@ internal class DefaultManageTokensComponent @AssistedInject constructor(
|
|||
}
|
||||
|
||||
private fun bottomSheetChild(
|
||||
config: BottomSheetConfig,
|
||||
config: ManageTokensBottomSheetConfig,
|
||||
componentContext: ComponentContext,
|
||||
): ComposableBottomSheetComponent = when (config) {
|
||||
is BottomSheetConfig.AddCustomToken -> {
|
||||
is ManageTokensBottomSheetConfig.AddCustomToken -> {
|
||||
addCustomTokenComponentFactory.create(
|
||||
context = childByContext(componentContext),
|
||||
params = AddCustomTokenComponent.Params(
|
||||
|
|
|
|||
|
|
@ -1,13 +1,7 @@
|
|||
package com.tangem.features.managetokens.di
|
||||
|
||||
import com.tangem.features.managetokens.component.AddCustomTokenComponent
|
||||
import com.tangem.features.managetokens.component.CustomTokenFormComponent
|
||||
import com.tangem.features.managetokens.component.CustomTokenSelectorComponent
|
||||
import com.tangem.features.managetokens.component.ManageTokensComponent
|
||||
import com.tangem.features.managetokens.component.impl.DefaultAddCustomTokenComponent
|
||||
import com.tangem.features.managetokens.component.impl.DefaultCustomTokenFormComponent
|
||||
import com.tangem.features.managetokens.component.impl.DefaultCustomTokenSelectorComponent
|
||||
import com.tangem.features.managetokens.component.impl.DefaultManageTokensComponent
|
||||
import com.tangem.features.managetokens.component.*
|
||||
import com.tangem.features.managetokens.component.impl.*
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -39,4 +33,10 @@ internal interface ComponentModule {
|
|||
fun bindCustomTokenFormComponentFactory(
|
||||
factory: DefaultCustomTokenFormComponent.Factory,
|
||||
): CustomTokenFormComponent.Factory
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindCustomTokenDerivationInputComponentFactory(
|
||||
factory: DefaultCustomTokenDerivationInputComponent.Factory,
|
||||
): CustomTokenDerivationInputComponent.Factory
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.features.managetokens.entity.customtoken
|
||||
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
internal sealed class CustomTokenSelectorDialogConfig {
|
||||
|
||||
@Serializable
|
||||
data class CustomDerivationInput(
|
||||
val userWalletId: UserWalletId,
|
||||
) : CustomTokenSelectorDialogConfig()
|
||||
}
|
||||
|
|
@ -4,10 +4,10 @@ import com.tangem.domain.wallets.models.UserWalletId
|
|||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
internal sealed class BottomSheetConfig {
|
||||
internal sealed class ManageTokensBottomSheetConfig {
|
||||
|
||||
@Serializable
|
||||
data class AddCustomToken(
|
||||
val userWalletId: UserWalletId,
|
||||
) : BottomSheetConfig()
|
||||
) : ManageTokensBottomSheetConfig()
|
||||
}
|
||||
|
|
@ -18,7 +18,7 @@ import com.tangem.domain.managetokens.SaveManagedTokensUseCase
|
|||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.features.managetokens.component.ManageTokensComponent
|
||||
import com.tangem.features.managetokens.entity.item.CurrencyItemUM
|
||||
import com.tangem.features.managetokens.entity.managetokens.BottomSheetConfig
|
||||
import com.tangem.features.managetokens.entity.managetokens.ManageTokensBottomSheetConfig
|
||||
import com.tangem.features.managetokens.entity.managetokens.ManageTokensTopBarUM
|
||||
import com.tangem.features.managetokens.entity.managetokens.ManageTokensUM
|
||||
import com.tangem.features.managetokens.impl.R
|
||||
|
|
@ -47,7 +47,7 @@ internal class ManageTokensModel @Inject constructor(
|
|||
private val params: ManageTokensComponent.Params = paramsContainer.require()
|
||||
|
||||
val state: MutableStateFlow<ManageTokensUM> = MutableStateFlow(getInitialState(params.userWalletId))
|
||||
val bottomSheetNavigation: SlotNavigation<BottomSheetConfig> = SlotNavigation()
|
||||
val bottomSheetNavigation: SlotNavigation<ManageTokensBottomSheetConfig> = SlotNavigation()
|
||||
|
||||
init {
|
||||
manageTokensListManager.uiItems
|
||||
|
|
@ -228,7 +228,7 @@ internal class ManageTokensModel @Inject constructor(
|
|||
|
||||
private fun navigateToAddCustomToken() {
|
||||
params.userWalletId?.let {
|
||||
bottomSheetNavigation.activate(BottomSheetConfig.AddCustomToken(it))
|
||||
bottomSheetNavigation.activate(ManageTokensBottomSheetConfig.AddCustomToken(it))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue