Updated on 2026-08-14

This commit is contained in:
Tangem 2024-07-17 17:53:37 +04:00
parent da1d75b51d
commit bccd93464f
8 changed files with 67 additions and 57 deletions

View file

@ -6,7 +6,7 @@ import androidx.compose.runtime.Stable
@Stable
interface ComposableDialogComponent {
val doOnDismiss: () -> Unit
fun dismiss()
@Composable
fun Dialog()

View file

@ -2,7 +2,7 @@ package com.tangem.domain.wallets.models
sealed interface UpdateWalletError {
data object DataError : UpdateWalletError
data object NameAlreadyExists : UpdateWalletError
data class DataError(val cause: Throwable) : UpdateWalletError
}

View file

@ -1,11 +1,9 @@
package com.tangem.domain.wallets.usecase
import arrow.core.Either
import arrow.core.left
import arrow.core.raise.either
import arrow.core.right
import com.tangem.common.doOnFailure
import com.tangem.common.doOnSuccess
import arrow.core.raise.ensure
import com.tangem.common.CompletionResult
import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.domain.wallets.models.UpdateWalletError
import com.tangem.domain.wallets.models.UserWallet
@ -18,19 +16,17 @@ import com.tangem.domain.wallets.models.UserWalletId
*/
class RenameWalletUseCase(private val userWalletsListManager: UserWalletsListManager) {
suspend operator fun invoke(userWalletId: UserWalletId, name: String): Either<UpdateWalletError, UserWallet> {
val existingNames = userWalletsListManager.userWalletsSync
suspend operator fun invoke(userWalletId: UserWalletId, name: String): Either<UpdateWalletError, UserWallet> =
either {
val existingNames = userWalletsListManager.userWalletsSync
if (existingNames.any { it.name == name && it.walletId != userWalletId }) {
return UpdateWalletError.NameAlreadyExists.left()
ensure(existingNames.none { it.name == name && it.walletId != userWalletId }) {
UpdateWalletError.NameAlreadyExists
}
when (val result = userWalletsListManager.update(userWalletId) { it.copy(name = name) }) {
is CompletionResult.Failure -> raise(UpdateWalletError.DataError(result.error))
is CompletionResult.Success -> result.data
}
}
return either {
userWalletsListManager.update(userWalletId) { it.copy(name = name) }
.doOnSuccess { return it.right() }
.doOnFailure { return UpdateWalletError.DataError.left() }
return UpdateWalletError.DataError.left()
}
}
}

View file

@ -1,11 +1,8 @@
package com.tangem.domain.wallets.usecase
import arrow.core.Either
import arrow.core.left
import arrow.core.raise.either
import arrow.core.right
import com.tangem.common.doOnFailure
import com.tangem.common.doOnSuccess
import com.tangem.common.CompletionResult
import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.domain.wallets.models.UpdateWalletError
import com.tangem.domain.wallets.models.UserWallet
@ -23,13 +20,10 @@ class UpdateWalletUseCase(private val userWalletsListManager: UserWalletsListMan
suspend operator fun invoke(
userWalletId: UserWalletId,
update: suspend (UserWallet) -> UserWallet,
): Either<UpdateWalletError, UserWallet> {
return either {
userWalletsListManager.update(userWalletId, update)
.doOnSuccess { return it.right() }
.doOnFailure { return UpdateWalletError.DataError.left() }
return UpdateWalletError.DataError.left()
): Either<UpdateWalletError, UserWallet> = either {
when (val result = userWalletsListManager.update(userWalletId, update)) {
is CompletionResult.Failure -> raise(UpdateWalletError.DataError(result.error))
is CompletionResult.Success -> result.data
}
}
}

View file

@ -21,18 +21,16 @@ import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import timber.log.Timber
internal class DefaultRenameWalletComponent @AssistedInject constructor(
@Assisted context: AppComponentContext,
@Assisted params: RenameWalletComponent.Params,
@Assisted private val params: RenameWalletComponent.Params,
private val renameWalletUseCase: RenameWalletUseCase,
) : RenameWalletComponent, AppComponentContext by context {
private val userWalletId = params.userWalletId
private val currentWalletName = params.currentName
override val doOnDismiss: () -> Unit = params.onDismiss
private val stateFlow: MutableStateFlow<RenameWalletUM> = MutableStateFlow(
value = RenameWalletUM(
walletNameValue = TextFieldValue(text = params.currentName),
@ -42,13 +40,17 @@ internal class DefaultRenameWalletComponent @AssistedInject constructor(
),
)
override fun dismiss() {
params.onDismiss()
}
@Composable
override fun Dialog() {
val model by stateFlow.collectAsStateWithLifecycle()
RenameWalletDialog(
model = model,
onDismiss = doOnDismiss,
onDismiss = ::dismiss,
)
}
@ -66,11 +68,13 @@ internal class DefaultRenameWalletComponent @AssistedInject constructor(
val maybeError = renameWalletUseCase(userWalletId, newName.text).leftOrNull()
if (maybeError != null) {
Timber.e("Unable to rename wallet: $maybeError")
val message = when (maybeError) {
UpdateWalletError.DataError -> resourceReference(
is UpdateWalletError.DataError -> resourceReference(
id = R.string.common_unknown_error,
)
UpdateWalletError.NameAlreadyExists -> resourceReference(
is UpdateWalletError.NameAlreadyExists -> resourceReference(
id = R.string.user_wallet_list_rename_popup_error_already_exists,
formatArgs = wrappedList(newName),
)
@ -79,7 +83,7 @@ internal class DefaultRenameWalletComponent @AssistedInject constructor(
messageSender.send(message = SnackbarMessage(message))
}
doOnDismiss()
dismiss()
}
@AssistedFactory

View file

@ -15,7 +15,7 @@ internal class PreviewRenameWalletComponent : RenameWalletComponent {
onConfirm = {},
)
override val doOnDismiss: () -> Unit = {}
override fun dismiss() {}
@Composable
override fun Dialog() {

View file

@ -1,5 +1,6 @@
package com.tangem.feature.walletsettings.model
import androidx.compose.ui.res.stringResource
import arrow.core.getOrElse
import com.arkivanov.decompose.router.slot.SlotNavigation
import com.arkivanov.decompose.router.slot.activate
@ -9,11 +10,13 @@ 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.decompose.ui.UiMessageSender
import com.tangem.core.ui.components.BasicDialog
import com.tangem.core.ui.components.DialogButton
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.message.ContentMessage
import com.tangem.core.ui.message.SnackbarMessage
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.domain.wallets.usecase.DeleteWalletUseCase
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.feature.walletsettings.component.WalletSettingsComponent
@ -27,6 +30,7 @@ import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
@Suppress("LongParameterList")
@ -55,15 +59,7 @@ internal class WalletSettingsModel @Inject constructor(
getWalletUseCase.invokeFlow(params.userWalletId)
.distinctUntilChanged()
.onEach { maybeWallet ->
val wallet = maybeWallet.getOrElse { error ->
error(
"""
Failed to get user wallet
|- User wallet ID: $params
|- Cause: $error
""".trimIndent(),
)
}
val wallet = maybeWallet.getOrNull() ?: return@onEach
state.update { value ->
value.copy(items = buildItems(wallet, dialogNavigation))
@ -80,7 +76,28 @@ internal class WalletSettingsModel @Inject constructor(
userWalletName = userWallet.name,
isReferralAvailable = userWallet.cardTypesResolver.isTangemWallet(),
renameWallet = { openRenameWalletDialog(userWallet, dialogNavigation) },
forgetWallet = { forgetWallet(userWallet.walletId) },
forgetWallet = {
messageSender.send(
ContentMessage { onDismiss ->
BasicDialog(
message = stringResource(R.string.user_wallet_list_delete_prompt),
onDismissDialog = onDismiss,
confirmButton = DialogButton(
title = stringResource(R.string.common_delete),
warning = true,
onClick = {
forgetWallet()
onDismiss()
},
),
dismissButton = DialogButton(
title = stringResource(R.string.common_cancel),
onClick = onDismiss,
),
)
},
)
},
)
private fun openRenameWalletDialog(userWallet: UserWallet, dialogNavigation: SlotNavigation<DialogConfig>) {
@ -92,8 +109,10 @@ internal class WalletSettingsModel @Inject constructor(
dialogNavigation.activate(config)
}
private fun forgetWallet(userWalletId: UserWalletId) = modelScope.launch {
val hasUserWallets = deleteWalletUseCase(userWalletId).getOrElse {
private fun forgetWallet() = modelScope.launch {
val hasUserWallets = deleteWalletUseCase(params.userWalletId).getOrElse {
Timber.e("Unable to delete wallet: $it")
messageSender.send(
message = SnackbarMessage(resourceReference(R.string.common_unknown_error)),
)

View file

@ -24,10 +24,7 @@ internal fun RenameWalletDialog(model: RenameWalletUM, onDismiss: () -> Unit) {
confirmButton = DialogButton(
title = stringResource(id = R.string.common_ok),
enabled = model.isNameCorrect,
onClick = {
model.onConfirm()
onDismiss()
},
onClick = model.onConfirm,
),
dismissButton = DialogButton(
title = stringResource(id = R.string.common_cancel),