Updated on 2026-08-14

This commit is contained in:
Tangem 2025-10-02 20:46:41 +07:00
parent 82aae53d53
commit 38e82b9423
20 changed files with 198 additions and 142 deletions

View file

@ -78,10 +78,14 @@ internal class AccountCreateEditModel @Inject constructor(
isWarning = true,
onClick = { router.pop() },
)
val messageRes = when (params) {
is AccountCreateEditComponent.Params.Create -> R.string.account_unsaved_dialog_message_create
is AccountCreateEditComponent.Params.Edit -> R.string.account_unsaved_dialog_message_edit
}
messageSender.send(
DialogMessage(
title = resourceReference(R.string.account_unsaved_dialog_title),
message = resourceReference(R.string.account_unsaved_dialog_message_create),
message = resourceReference(messageRes),
firstActionBuilder = { firstAction },
secondActionBuilder = { secondAction },
),
@ -120,17 +124,15 @@ internal class AccountCreateEditModel @Inject constructor(
}
private fun handleAddAccountError(error: AddCryptoPortfolioUseCase.Error) {
if (error is AddCryptoPortfolioUseCase.Error.AccountListRequirementsNotMet &&
error.cause is AccountList.Error.DuplicateAccountNames
) {
// TODO("account") show alert that the account name already exists
return
val duplicateAccountNames = (error as? AddCryptoPortfolioUseCase.Error.AccountListRequirementsNotMet)
?.cause is AccountList.Error.DuplicateAccountNames
when {
duplicateAccountNames -> showAccountNameExist()
else -> {
showSomethingWrong()
logError(error = AccountFeatureError.CreateAccount.FailedToCreateAccount(cause = error))
}
}
// TODO: show alert https://www.figma.com/design/09KKG4ZVuFDZhj8WLv5rGJ/%F0%9F%9A%A7-App-experience?node-id=38882-113775&t=vk6TCy4MkYol1cPb-4
logError(
error = AccountFeatureError.CreateAccount.FailedToCreateAccount(cause = error),
)
}
private suspend fun editCryptoPortfolio(params: AccountCreateEditComponent.Params.Edit) {
@ -157,17 +159,15 @@ internal class AccountCreateEditModel @Inject constructor(
}
private fun handleEditAccountError(error: UpdateCryptoPortfolioUseCase.Error) {
if (error is UpdateCryptoPortfolioUseCase.Error.AccountListRequirementsNotMet &&
error.cause is AccountList.Error.DuplicateAccountNames
) {
// TODO("account") show alert that the account name already exists
return
val duplicateAccountNames = (error as? UpdateCryptoPortfolioUseCase.Error.AccountListRequirementsNotMet)
?.cause is AccountList.Error.DuplicateAccountNames
when {
duplicateAccountNames -> showAccountNameExist()
else -> {
showSomethingWrong()
logError(error = AccountFeatureError.EditAccount.FailedToEditAccount(cause = error))
}
}
// TODO: show alert like in create account flow
logError(
error = AccountFeatureError.EditAccount.FailedToEditAccount(cause = error),
)
}
private fun showMessage(@StringRes id: Int) {
@ -175,7 +175,10 @@ internal class AccountCreateEditModel @Inject constructor(
messageSender.send(ToastMessage(message = message))
}
private fun onCloseClick() = unsaveChangeDialog()
private fun onCloseClick() {
val showConfirmDialog = uiState.value.buttonState.isButtonEnabled
if (showConfirmDialog) unsaveChangeDialog() else router.pop()
}
private fun onIconSelect(icon: CryptoPortfolioIcon.Icon) {
uiState.value = uiState.value
@ -256,4 +259,20 @@ internal class AccountCreateEditModel @Inject constructor(
event = ExceptionAnalyticsEvent(exception = exception, params = params),
)
}
private fun showSomethingWrong() {
val dialogMessage = DialogMessage(
title = resourceReference(R.string.common_something_went_wrong),
message = resourceReference(R.string.account_could_not_create),
)
messageSender.send(dialogMessage)
}
private fun showAccountNameExist() {
val dialogMessage = DialogMessage(
title = resourceReference(R.string.common_something_went_wrong),
message = resourceReference(R.string.account_form_name_already_exist_error_description),
)
messageSender.send(dialogMessage)
}
}

View file

@ -19,6 +19,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
@ -30,8 +32,8 @@ import com.tangem.core.ui.components.PrimaryButton
import com.tangem.core.ui.components.SpacerH
import com.tangem.core.ui.components.SpacerH24
import com.tangem.core.ui.components.SpacerH8
import com.tangem.core.ui.components.appbar.AppBarWithBackButton
import com.tangem.core.ui.components.account.AccountIconSize
import com.tangem.core.ui.components.appbar.AppBarWithBackButton
import com.tangem.core.ui.components.fields.AutoSizeTextField
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.res.TangemTheme
@ -43,9 +45,11 @@ import kotlinx.collections.immutable.toImmutableList
@Composable
internal fun AccountCreateEditContent(state: AccountCreateEditUM, modifier: Modifier = Modifier) {
val keyboardController = LocalSoftwareKeyboardController.current
val focusManager = LocalFocusManager.current
Column(
modifier = modifier
.background(color = TangemTheme.colors.background.tertiary)
.background(color = TangemTheme.colors.background.secondary)
.fillMaxSize()
.imePadding()
.systemBarsPadding(),
@ -76,6 +80,10 @@ internal fun AccountCreateEditContent(state: AccountCreateEditUM, modifier: Modi
color = TangemTheme.colors.text.tertiary,
)
}
if (state.buttonState.showProgress) {
focusManager.clearFocus()
keyboardController?.hide()
}
PrimaryButton(
modifier = Modifier
.fillMaxWidth()
@ -161,6 +169,7 @@ private fun AccountColor(colorsState: AccountCreateEditUM.Colors) {
contentAlignment = Alignment.Center,
modifier = Modifier
.wrapContentSize()
.clip(CircleShape)
.clickable(onClick = { colorsState.onColorSelect(color) })
.size(48.dp),
) {
@ -208,6 +217,7 @@ private fun AccountIcons(iconsState: AccountCreateEditUM.Icons) {
contentAlignment = Alignment.Center,
modifier = Modifier
.wrapContentSize()
.clip(CircleShape)
.clickable(onClick = { iconsState.onIconSelect(icon) })
.size(52.dp),
) {

View file

@ -1,11 +1,9 @@
package com.tangem.features.account.fetcher
import arrow.core.getOrElse
import com.tangem.domain.account.models.AccountStatusList
import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer
import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.isMultiCurrency
@ -60,8 +58,8 @@ internal class DefaultPortfolioFetcher @AssistedInject constructor(
.map { it.filterWallets(mode) }
.distinctUntilChanged()
.flatMapLatest { wallets -> balancesForWallets(wallets) },
flow2 = appCurrencyFlow(),
flow3 = balanceHidingFlow(),
flow2 = getSelectedAppCurrencyUseCase.invokeOrDefault(),
flow3 = getBalanceHidingSettingsUseCase.isBalanceHidden(),
) { balances, appCurrency, isBalanceHiding ->
Data(
appCurrency = appCurrency,
@ -94,18 +92,6 @@ internal class DefaultPortfolioFetcher @AssistedInject constructor(
private fun accountStatusListFlow(wallet: UserWallet): Flow<AccountStatusList> =
singleAccountStatusListSupplier(SingleAccountStatusListProducer.Params(wallet.walletId))
private fun appCurrencyFlow(): Flow<AppCurrency> {
return getSelectedAppCurrencyUseCase()
.map { it.getOrElse { AppCurrency.Default } }
.distinctUntilChanged()
}
private fun balanceHidingFlow(): Flow<Boolean> {
return getBalanceHidingSettingsUseCase()
.map { it.isBalanceHidden }
.distinctUntilChanged()
}
@AssistedFactory
interface Factory : PortfolioFetcher.Factory {
override fun create(mode: Mode, scope: CoroutineScope): DefaultPortfolioFetcher