Updated on 2026-08-14
This commit is contained in:
commit
11bd3bc722
8 changed files with 70 additions and 10 deletions
|
|
@ -27,6 +27,7 @@ import kotlinx.coroutines.flow.update
|
|||
|
||||
internal class PreviewManageTokensComponent(
|
||||
private val isLoading: Boolean,
|
||||
private val showTangemIcon: Boolean,
|
||||
params: ManageTokensComponent.Params,
|
||||
) : ManageTokensComponent {
|
||||
|
||||
|
|
@ -65,6 +66,7 @@ internal class PreviewManageTokensComponent(
|
|||
loadMore = { false },
|
||||
saveChanges = {},
|
||||
isSavingInProgress = false,
|
||||
needToAddDerivations = showTangemIcon,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ internal data class CustomTokenFormUM(
|
|||
val notifications: PersistentList<NotificationUM> = persistentListOf(),
|
||||
val canAddToken: Boolean = false,
|
||||
val isValidating: Boolean = false,
|
||||
val needToAddDerivation: Boolean = false,
|
||||
val saveToken: () -> Unit,
|
||||
) {
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ internal sealed class ManageTokensUM {
|
|||
val saveChanges: () -> Unit,
|
||||
val hasChanges: Boolean,
|
||||
val isSavingInProgress: Boolean,
|
||||
val needToAddDerivations: Boolean,
|
||||
) : ManageTokensUM()
|
||||
|
||||
fun copySealed(
|
||||
|
|
@ -52,6 +53,7 @@ internal sealed class ManageTokensUM {
|
|||
isNextBatchLoading: Boolean = this.isNextBatchLoading,
|
||||
isSavingInProgress: Boolean = this is ManageContent && this.isSavingInProgress,
|
||||
scrollToTop: StateEvent<Unit> = this.scrollToTop,
|
||||
needToAddDerivations: Boolean = this is ManageContent && this.needToAddDerivations,
|
||||
): ManageTokensUM {
|
||||
return when (this) {
|
||||
is ManageContent -> copy(
|
||||
|
|
@ -62,6 +64,7 @@ internal sealed class ManageTokensUM {
|
|||
isNextBatchLoading = isNextBatchLoading,
|
||||
isSavingInProgress = isSavingInProgress,
|
||||
scrollToTop = scrollToTop,
|
||||
needToAddDerivations = needToAddDerivations,
|
||||
)
|
||||
is ReadContent -> copy(
|
||||
search = search,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.tangem.core.ui.extensions.resourceReference
|
|||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.message.ContentMessage
|
||||
import com.tangem.domain.card.DerivePublicKeysUseCase
|
||||
import com.tangem.domain.card.HasMissedDerivationsUseCase
|
||||
import com.tangem.domain.managetokens.model.exceptoin.CustomTokenFormValidationException
|
||||
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
|
|
@ -43,6 +44,7 @@ internal class CustomTokenFormModel @Inject constructor(
|
|||
private val customCurrencyValidator: CustomCurrencyValidator,
|
||||
private val addCryptoCurrenciesUseCase: AddCryptoCurrenciesUseCase,
|
||||
private val derivePublicKeysUseCase: DerivePublicKeysUseCase,
|
||||
private val hasMissedDerivationsUseCase: HasMissedDerivationsUseCase,
|
||||
private val messageSender: UiMessageSender,
|
||||
private val customTokenFormManager: CustomCurrencyFormBuilder,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
|
|
@ -156,7 +158,12 @@ internal class CustomTokenFormModel @Inject constructor(
|
|||
fillForm: Boolean,
|
||||
isAlreadyAdded: Boolean,
|
||||
isCustom: Boolean,
|
||||
) {
|
||||
) = modelScope.launch {
|
||||
val needToAddDerivation = hasMissedDerivationsUseCase(
|
||||
userWalletId = params.userWalletId,
|
||||
networksWithDerivationPath = mapOf(currency.network.backendId to getDerivationPath().value),
|
||||
)
|
||||
|
||||
state.update { state ->
|
||||
var updatedState = state
|
||||
.updateWithProgress(
|
||||
|
|
@ -166,6 +173,7 @@ internal class CustomTokenFormModel @Inject constructor(
|
|||
clearNotifications = true,
|
||||
clearFieldErrors = true,
|
||||
disableSecondaryFields = !isCustom,
|
||||
needToAddDerivation = needToAddDerivation,
|
||||
)
|
||||
|
||||
if (fillForm) {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import com.tangem.core.ui.event.triggeredEvent
|
|||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.domain.card.HasMissedDerivationsUseCase
|
||||
import com.tangem.domain.managetokens.SaveManagedTokensUseCase
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.features.managetokens.analytics.CustomTokenAnalyticsEvent
|
||||
|
|
@ -47,6 +48,7 @@ internal class ManageTokensModel @Inject constructor(
|
|||
private val router: Router,
|
||||
private val manageTokensListManager: ManageTokensListManager,
|
||||
private val messageSender: UiMessageSender,
|
||||
private val hasMissedDerivationsUseCase: HasMissedDerivationsUseCase,
|
||||
private val saveManagedTokensUseCase: SaveManagedTokensUseCase,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
paramsContainer: ParamsContainer,
|
||||
|
|
@ -140,6 +142,7 @@ internal class ManageTokensModel @Inject constructor(
|
|||
hasChanges = false,
|
||||
saveChanges = ::saveChanges,
|
||||
loadMore = ::loadMoreItems,
|
||||
needToAddDerivations = false,
|
||||
isSavingInProgress = false,
|
||||
)
|
||||
}
|
||||
|
|
@ -255,10 +258,22 @@ internal class ManageTokensModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun updateChangedItems(currenciesToAdd: ChangedCurrencies, currenciesToRemove: ChangedCurrencies) {
|
||||
state.update { state ->
|
||||
state.copySealed(
|
||||
hasChanges = currenciesToAdd.isNotEmpty() || currenciesToRemove.isNotEmpty(),
|
||||
)
|
||||
modelScope.launch {
|
||||
val hasMissedDerivations = params.userWalletId?.let { walletId ->
|
||||
val networks = currenciesToAdd.values
|
||||
.flatten()
|
||||
.toSet()
|
||||
.associate { it.backendId to null }
|
||||
|
||||
hasMissedDerivationsUseCase(walletId, networks)
|
||||
}
|
||||
|
||||
state.update { state ->
|
||||
state.copySealed(
|
||||
hasChanges = currenciesToAdd.isNotEmpty() || currenciesToRemove.isNotEmpty(),
|
||||
needToAddDerivations = hasMissedDerivations ?: false,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,9 +22,11 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
|
|||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import com.tangem.core.ui.components.PrimaryButton
|
||||
import com.tangem.core.ui.components.block.information.InformationBlock
|
||||
import com.tangem.core.ui.components.bottomFade
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButton
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonsDefaults
|
||||
import com.tangem.core.ui.components.fields.SimpleTextField
|
||||
import com.tangem.core.ui.components.isOpened
|
||||
import com.tangem.core.ui.components.keyboardAsState
|
||||
|
|
@ -82,14 +84,22 @@ internal fun CustomTokenFormContent(model: CustomTokenFormUM, modifier: Modifier
|
|||
}
|
||||
}
|
||||
|
||||
PrimaryButton(
|
||||
TangemButton(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.padding(bottom = TangemTheme.dimens.spacing16 + bottomBarHeight)
|
||||
.fillMaxWidth(),
|
||||
text = stringResource(id = R.string.custom_token_add_token),
|
||||
colors = TangemButtonsDefaults.primaryButtonColors,
|
||||
enabled = model.canAddToken,
|
||||
showProgress = model.isValidating,
|
||||
animateContentChange = true,
|
||||
icon = if (model.needToAddDerivation) {
|
||||
TangemButtonIconPosition.End(R.drawable.ic_tangem_24)
|
||||
} else {
|
||||
TangemButtonIconPosition.None
|
||||
},
|
||||
textStyle = TangemTheme.typography.subtitle1,
|
||||
onClick = model.saveToken,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,11 +33,17 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
|
|||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEachIndexed
|
||||
import com.tangem.core.ui.components.*
|
||||
import com.tangem.core.ui.components.BottomFade
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.TangemSwitch
|
||||
import com.tangem.core.ui.components.TextShimmer
|
||||
import com.tangem.core.ui.components.appbar.TangemTopAppBar
|
||||
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
|
||||
import com.tangem.core.ui.components.buttons.SecondarySmallButton
|
||||
import com.tangem.core.ui.components.buttons.SmallButtonConfig
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButton
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonsDefaults
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIcon
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.components.fields.SearchBar
|
||||
|
|
@ -122,6 +128,7 @@ internal fun ManageTokensScreen(state: ManageTokensUM, modifier: Modifier = Modi
|
|||
.fillMaxWidth(),
|
||||
isVisible = state.hasChanges,
|
||||
showProgress = state.isSavingInProgress,
|
||||
showIcon = state.needToAddDerivations,
|
||||
onClick = state.saveChanges,
|
||||
)
|
||||
}
|
||||
|
|
@ -158,6 +165,7 @@ private fun ManageTokensTopBar(topBar: ManageTokensTopBarUM?, search: SearchBarU
|
|||
private fun SaveChangesButton(
|
||||
isVisible: Boolean,
|
||||
showProgress: Boolean,
|
||||
showIcon: Boolean,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
|
|
@ -168,10 +176,18 @@ private fun SaveChangesButton(
|
|||
exit = fadeOut(),
|
||||
label = "save_button_visibility",
|
||||
) {
|
||||
PrimaryButtonIconEnd(
|
||||
TangemButton(
|
||||
text = stringResource(id = R.string.common_save),
|
||||
iconResId = R.drawable.ic_tangem_24,
|
||||
icon = if (showIcon) {
|
||||
TangemButtonIconPosition.End(R.drawable.ic_tangem_24)
|
||||
} else {
|
||||
TangemButtonIconPosition.None
|
||||
},
|
||||
showProgress = showProgress,
|
||||
colors = TangemButtonsDefaults.primaryButtonColors,
|
||||
textStyle = TangemTheme.typography.subtitle1,
|
||||
enabled = true,
|
||||
animateContentChange = true,
|
||||
onClick = onClick,
|
||||
)
|
||||
}
|
||||
|
|
@ -472,6 +488,7 @@ private class PreviewManageTokensComponentProvider : PreviewParameterProvider<Ma
|
|||
get() = sequenceOf(
|
||||
PreviewManageTokensComponent(
|
||||
isLoading = true,
|
||||
showTangemIcon = true,
|
||||
params = ManageTokensComponent.Params(
|
||||
source = ManageTokensSource.ONBOARDING,
|
||||
userWalletId = UserWalletId("wallet_id"),
|
||||
|
|
@ -479,10 +496,12 @@ private class PreviewManageTokensComponentProvider : PreviewParameterProvider<Ma
|
|||
),
|
||||
PreviewManageTokensComponent(
|
||||
isLoading = false,
|
||||
showTangemIcon = true,
|
||||
params = ManageTokensComponent.Params(source = ManageTokensSource.ONBOARDING, userWalletId = null),
|
||||
),
|
||||
PreviewManageTokensComponent(
|
||||
isLoading = false,
|
||||
showTangemIcon = false,
|
||||
params = ManageTokensComponent.Params(
|
||||
source = ManageTokensSource.ONBOARDING,
|
||||
userWalletId = UserWalletId("wallet_id"),
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ internal fun CustomTokenFormUM.updateWithProgress(
|
|||
showProgress: Boolean,
|
||||
isWasFilled: Boolean = this.tokenForm?.wasFilled ?: false,
|
||||
canAddToken: Boolean = this.canAddToken,
|
||||
needToAddDerivation: Boolean = false,
|
||||
clearNotifications: Boolean = false,
|
||||
clearFieldErrors: Boolean = false,
|
||||
disableSecondaryFields: Boolean = false,
|
||||
|
|
@ -34,6 +35,7 @@ internal fun CustomTokenFormUM.updateWithProgress(
|
|||
return copy(
|
||||
isValidating = showProgress,
|
||||
canAddToken = canAddToken,
|
||||
needToAddDerivation = needToAddDerivation,
|
||||
notifications = if (clearNotifications) persistentListOf() else notifications,
|
||||
).updateTokenForm {
|
||||
val updatedFields = fields.mapValues { (key, field) ->
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue