Updated on 2026-08-14
This commit is contained in:
parent
dd9d7f2e45
commit
544c243291
16 changed files with 270 additions and 129 deletions
|
|
@ -7,29 +7,19 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material.SnackbarHost
|
import androidx.compose.material.SnackbarHost
|
||||||
import androidx.compose.material.SnackbarHostState
|
import androidx.compose.material.SnackbarHostState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.rememberUpdatedState
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
|
import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import com.tangem.core.analytics.Analytics
|
import com.tangem.core.analytics.Analytics
|
||||||
|
import com.tangem.core.ui.components.wallets.RenameWalletDialogContent
|
||||||
import com.tangem.core.ui.fragments.ComposeBottomSheetFragment
|
import com.tangem.core.ui.fragments.ComposeBottomSheetFragment
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.tap.common.analytics.events.MyWallets
|
import com.tangem.tap.common.analytics.events.MyWallets
|
||||||
import com.tangem.tap.features.details.ui.cardsettings.resolveReference
|
import com.tangem.tap.features.details.ui.cardsettings.resolveReference
|
||||||
import com.tangem.tap.features.walletSelector.ui.components.BiometricsDisabledWarningContent
|
import com.tangem.tap.features.walletSelector.ui.components.*
|
||||||
import com.tangem.tap.features.walletSelector.ui.components.BiometricsLockoutWarningContent
|
|
||||||
import com.tangem.tap.features.walletSelector.ui.components.KeyInvalidatedWarningContent
|
|
||||||
import com.tangem.tap.features.walletSelector.ui.components.RemoveWalletDialogContent
|
|
||||||
import com.tangem.tap.features.walletSelector.ui.components.RenameWalletDialogContent
|
|
||||||
import com.tangem.tap.features.walletSelector.ui.components.WalletSelectorScreenContent
|
|
||||||
import com.tangem.tap.features.walletSelector.ui.model.DialogModel
|
import com.tangem.tap.features.walletSelector.ui.model.DialogModel
|
||||||
import com.tangem.tap.features.walletSelector.ui.model.WarningModel
|
import com.tangem.tap.features.walletSelector.ui.model.WarningModel
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
@ -90,7 +80,13 @@ internal class WalletSelectorBottomSheetFragment : ComposeBottomSheetFragment<Wa
|
||||||
if (dialog == null) return
|
if (dialog == null) return
|
||||||
when (dialog) {
|
when (dialog) {
|
||||||
is DialogModel.RemoveWalletDialog -> RemoveWalletDialogContent(dialog)
|
is DialogModel.RemoveWalletDialog -> RemoveWalletDialogContent(dialog)
|
||||||
is DialogModel.RenameWalletDialog -> RenameWalletDialogContent(dialog)
|
is DialogModel.RenameWalletDialog -> {
|
||||||
|
RenameWalletDialogContent(
|
||||||
|
name = dialog.currentName,
|
||||||
|
onConfirm = dialog.onConfirm,
|
||||||
|
onDismiss = dialog.onDismiss,
|
||||||
|
)
|
||||||
|
}
|
||||||
is WarningModel.BiometricsLockoutWarning -> BiometricsLockoutWarningContent(dialog)
|
is WarningModel.BiometricsLockoutWarning -> BiometricsLockoutWarningContent(dialog)
|
||||||
is WarningModel.KeyInvalidatedWarning -> KeyInvalidatedWarningContent(dialog)
|
is WarningModel.KeyInvalidatedWarning -> KeyInvalidatedWarningContent(dialog)
|
||||||
is WarningModel.BiometricsDisabledWarning -> BiometricsDisabledWarningContent(dialog)
|
is WarningModel.BiometricsDisabledWarning -> BiometricsDisabledWarningContent(dialog)
|
||||||
|
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
package com.tangem.tap.features.walletSelector.ui.components
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.runtime.*
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import com.tangem.core.ui.components.AdditionalTextInputDialogParams
|
|
||||||
import com.tangem.core.ui.components.DialogButton
|
|
||||||
import com.tangem.core.ui.components.TextInputDialog
|
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
|
||||||
import com.tangem.tap.features.walletSelector.ui.model.DialogModel
|
|
||||||
import com.tangem.wallet.R
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
internal fun RenameWalletDialogContent(dialog: DialogModel.RenameWalletDialog) {
|
|
||||||
var value by remember {
|
|
||||||
mutableStateOf(TextFieldValue(text = dialog.currentName))
|
|
||||||
}
|
|
||||||
|
|
||||||
TextInputDialog(
|
|
||||||
fieldValue = value,
|
|
||||||
confirmButton = DialogButton(
|
|
||||||
title = stringResource(id = R.string.common_ok),
|
|
||||||
enabled = value.text.isNotEmpty() && value.text != dialog.currentName,
|
|
||||||
onClick = { dialog.onConfirm(value.text) },
|
|
||||||
),
|
|
||||||
onDismissDialog = dialog.onDismiss,
|
|
||||||
onValueChange = { newValue ->
|
|
||||||
value = newValue
|
|
||||||
},
|
|
||||||
title = stringResource(R.string.user_wallet_list_rename_popup_title),
|
|
||||||
dismissButton = DialogButton(
|
|
||||||
title = stringResource(id = R.string.common_cancel),
|
|
||||||
onClick = dialog.onDismiss,
|
|
||||||
),
|
|
||||||
textFieldParams = AdditionalTextInputDialogParams(
|
|
||||||
label = stringResource(R.string.user_wallet_list_rename_popup_placeholder),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// region Preview
|
|
||||||
@Composable
|
|
||||||
private fun RenameWalletDialogContentSample(modifier: Modifier = Modifier) {
|
|
||||||
Column(
|
|
||||||
modifier = modifier,
|
|
||||||
) {
|
|
||||||
RenameWalletDialogContent(dialog = DialogModel.RenameWalletDialog("", {}, {}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Preview(showBackground = true, widthDp = 360)
|
|
||||||
@Composable
|
|
||||||
private fun RenameWalletDialogContentPreview_Light() {
|
|
||||||
TangemTheme {
|
|
||||||
RenameWalletDialogContentSample()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Preview(showBackground = true, widthDp = 360)
|
|
||||||
@Composable
|
|
||||||
private fun RenameWalletDialogContentPreview_Dark() {
|
|
||||||
TangemTheme(isDark = true) {
|
|
||||||
RenameWalletDialogContentSample()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// endregion Preview
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
package com.tangem.core.ui.components.wallets
|
||||||
|
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import com.tangem.core.ui.R
|
||||||
|
import com.tangem.core.ui.components.AdditionalTextInputDialogParams
|
||||||
|
import com.tangem.core.ui.components.DialogButton
|
||||||
|
import com.tangem.core.ui.components.TextInputDialog
|
||||||
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rename a wallet dialog
|
||||||
|
*
|
||||||
|
* @param name wallet name
|
||||||
|
* @param onConfirm lambda be invoked when Confirm button is clicked
|
||||||
|
* @param onDismiss lambda be invoked when dialog is dismissed
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun RenameWalletDialogContent(name: String, onConfirm: (newName: String) -> Unit, onDismiss: () -> Unit) {
|
||||||
|
var value by remember { mutableStateOf(TextFieldValue(text = name)) }
|
||||||
|
|
||||||
|
TextInputDialog(
|
||||||
|
fieldValue = value,
|
||||||
|
confirmButton = DialogButton(
|
||||||
|
title = stringResource(id = R.string.common_ok),
|
||||||
|
enabled = value.text.isNotEmpty() && value.text != name,
|
||||||
|
onClick = { onConfirm(value.text) },
|
||||||
|
),
|
||||||
|
onDismissDialog = onDismiss,
|
||||||
|
onValueChange = { value = it },
|
||||||
|
title = stringResource(R.string.user_wallet_list_rename_popup_title),
|
||||||
|
dismissButton = DialogButton(title = stringResource(id = R.string.common_cancel), onClick = onDismiss),
|
||||||
|
textFieldParams = AdditionalTextInputDialogParams(
|
||||||
|
label = stringResource(R.string.user_wallet_list_rename_popup_placeholder),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// region Preview
|
||||||
|
|
||||||
|
@Preview(showBackground = true, widthDp = 360)
|
||||||
|
@Composable
|
||||||
|
private fun RenameWalletDialogContentPreview_Light() {
|
||||||
|
TangemTheme(isDark = false) {
|
||||||
|
RenameWalletDialogContent(name = "", onConfirm = {}, onDismiss = {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview(showBackground = true, widthDp = 360)
|
||||||
|
@Composable
|
||||||
|
private fun RenameWalletDialogContentPreview_Dark() {
|
||||||
|
TangemTheme(isDark = true) {
|
||||||
|
RenameWalletDialogContent(name = "", onConfirm = {}, onDismiss = {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// endregion Preview
|
||||||
|
|
@ -35,7 +35,8 @@ internal object WalletPreviewData {
|
||||||
balance = "8923,05 $",
|
balance = "8923,05 $",
|
||||||
additionalInfo = TextReference.Str("3 cards • Seed phrase"),
|
additionalInfo = TextReference.Str("3 cards • Seed phrase"),
|
||||||
imageResId = R.drawable.ill_businessman_3d,
|
imageResId = R.drawable.ill_businessman_3d,
|
||||||
onClick = null,
|
onRenameClick = { _, _ -> },
|
||||||
|
onDeleteClick = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,7 +45,8 @@ internal object WalletPreviewData {
|
||||||
id = UserWalletId("321"),
|
id = UserWalletId("321"),
|
||||||
title = "Wallet 1",
|
title = "Wallet 1",
|
||||||
imageResId = R.drawable.ill_businessman_3d,
|
imageResId = R.drawable.ill_businessman_3d,
|
||||||
onClick = null,
|
onRenameClick = { _, _ -> },
|
||||||
|
onDeleteClick = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,7 +55,8 @@ internal object WalletPreviewData {
|
||||||
id = UserWalletId("42"),
|
id = UserWalletId("42"),
|
||||||
title = "Wallet 1",
|
title = "Wallet 1",
|
||||||
imageResId = R.drawable.ill_businessman_3d,
|
imageResId = R.drawable.ill_businessman_3d,
|
||||||
onClick = null,
|
onRenameClick = { _, _ -> },
|
||||||
|
onDeleteClick = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -62,7 +65,8 @@ internal object WalletPreviewData {
|
||||||
id = UserWalletId("24"),
|
id = UserWalletId("24"),
|
||||||
title = "Wallet 1",
|
title = "Wallet 1",
|
||||||
imageResId = R.drawable.ill_businessman_3d,
|
imageResId = R.drawable.ill_businessman_3d,
|
||||||
onClick = null,
|
onRenameClick = { _, _ -> },
|
||||||
|
onDeleteClick = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,10 @@ internal class DefaultWalletRouter(private val navigationStateHolder: Navigation
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun openStoriesScreen() {
|
||||||
|
navigationStateHolder.navigate(action = NavigationAction.NavigateTo(screen = AppScreen.Home))
|
||||||
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
const val BACKSTACK_ENTRY_COUNT_TO_CLOSE_WALLET_SCREEN = 2
|
const val BACKSTACK_ENTRY_COUNT_TO_CLOSE_WALLET_SCREEN = 2
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,4 +44,7 @@ internal interface InnerWalletRouter : WalletRouter {
|
||||||
|
|
||||||
/** Open token details screen */
|
/** Open token details screen */
|
||||||
fun openTokenDetails(currency: CryptoCurrency)
|
fun openTokenDetails(currency: CryptoCurrency)
|
||||||
|
|
||||||
|
/** Open stories screen */
|
||||||
|
fun openStoriesScreen()
|
||||||
}
|
}
|
||||||
|
|
@ -22,8 +22,11 @@ internal sealed interface WalletCardState {
|
||||||
@get:DrawableRes
|
@get:DrawableRes
|
||||||
val imageResId: Int?
|
val imageResId: Int?
|
||||||
|
|
||||||
/** Lambda be invoked when card is clicked */
|
/** Lambda be invoked when Rename button is clicked */
|
||||||
val onClick: (() -> Unit)?
|
val onRenameClick: (UserWalletId, String) -> Unit
|
||||||
|
|
||||||
|
/** Lambda be invoked when Delete button is clicked */
|
||||||
|
val onDeleteClick: (UserWalletId) -> Unit
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wallet card content state
|
* Wallet card content state
|
||||||
|
|
@ -32,7 +35,8 @@ internal sealed interface WalletCardState {
|
||||||
* @property title wallet name
|
* @property title wallet name
|
||||||
* @property additionalInfo wallet additional info
|
* @property additionalInfo wallet additional info
|
||||||
* @property imageResId wallet image resource id
|
* @property imageResId wallet image resource id
|
||||||
* @property onClick lambda be invoked when wallet card is clicked
|
* @property onRenameClick lambda be invoked when Rename button is clicked
|
||||||
|
* @property onDeleteClick lambda be invoked when Delete button is clicked
|
||||||
* @property balance wallet balance
|
* @property balance wallet balance
|
||||||
*/
|
*/
|
||||||
data class Content(
|
data class Content(
|
||||||
|
|
@ -40,7 +44,8 @@ internal sealed interface WalletCardState {
|
||||||
override val title: String,
|
override val title: String,
|
||||||
override val additionalInfo: TextReference,
|
override val additionalInfo: TextReference,
|
||||||
override val imageResId: Int?,
|
override val imageResId: Int?,
|
||||||
override val onClick: (() -> Unit)? = null,
|
override val onRenameClick: (UserWalletId, String) -> Unit,
|
||||||
|
override val onDeleteClick: (UserWalletId) -> Unit,
|
||||||
val balance: String,
|
val balance: String,
|
||||||
) : WalletCardState
|
) : WalletCardState
|
||||||
|
|
||||||
|
|
@ -51,14 +56,16 @@ internal sealed interface WalletCardState {
|
||||||
* @property title wallet name
|
* @property title wallet name
|
||||||
* @property additionalInfo wallet additional info
|
* @property additionalInfo wallet additional info
|
||||||
* @property imageResId wallet image resource id
|
* @property imageResId wallet image resource id
|
||||||
* @property onClick lambda be invoked when wallet card is clicked
|
* @property onRenameClick lambda be invoked when Rename button is clicked
|
||||||
|
* @property onDeleteClick lambda be invoked when Delete button is clicked
|
||||||
*/
|
*/
|
||||||
data class HiddenContent(
|
data class HiddenContent(
|
||||||
override val id: UserWalletId,
|
override val id: UserWalletId,
|
||||||
override val title: String,
|
override val title: String,
|
||||||
override val additionalInfo: TextReference = HIDDEN_BALANCE_TEXT,
|
override val additionalInfo: TextReference = HIDDEN_BALANCE_TEXT,
|
||||||
override val imageResId: Int?,
|
override val imageResId: Int?,
|
||||||
override val onClick: (() -> Unit)?,
|
override val onRenameClick: (UserWalletId, String) -> Unit,
|
||||||
|
override val onDeleteClick: (UserWalletId) -> Unit,
|
||||||
) : WalletCardState
|
) : WalletCardState
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -68,14 +75,16 @@ internal sealed interface WalletCardState {
|
||||||
* @property title wallet name
|
* @property title wallet name
|
||||||
* @property additionalInfo wallet additional info
|
* @property additionalInfo wallet additional info
|
||||||
* @property imageResId wallet image resource id
|
* @property imageResId wallet image resource id
|
||||||
* @property onClick lambda be invoked when wallet card is clicked
|
* @property onRenameClick lambda be invoked when Rename button is clicked
|
||||||
|
* @property onDeleteClick lambda be invoked when Delete button is clicked
|
||||||
*/
|
*/
|
||||||
data class LockedContent(
|
data class LockedContent(
|
||||||
override val id: UserWalletId,
|
override val id: UserWalletId,
|
||||||
override val title: String,
|
override val title: String,
|
||||||
override val additionalInfo: TextReference? = null,
|
override val additionalInfo: TextReference? = null,
|
||||||
override val imageResId: Int?,
|
override val imageResId: Int?,
|
||||||
override val onClick: (() -> Unit)?,
|
override val onRenameClick: (UserWalletId, String) -> Unit,
|
||||||
|
override val onDeleteClick: (UserWalletId) -> Unit,
|
||||||
) : WalletCardState
|
) : WalletCardState
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -85,14 +94,16 @@ internal sealed interface WalletCardState {
|
||||||
* @property title wallet name
|
* @property title wallet name
|
||||||
* @property additionalInfo wallet additional info
|
* @property additionalInfo wallet additional info
|
||||||
* @property imageResId wallet image resource id
|
* @property imageResId wallet image resource id
|
||||||
* @property onClick lambda be invoked when wallet card is clicked
|
* @property onRenameClick lambda be invoked when Rename button is clicked
|
||||||
|
* @property onDeleteClick lambda be invoked when Delete button is clicked
|
||||||
*/
|
*/
|
||||||
data class Error(
|
data class Error(
|
||||||
override val id: UserWalletId,
|
override val id: UserWalletId,
|
||||||
override val title: String,
|
override val title: String,
|
||||||
override val additionalInfo: TextReference = EMPTY_BALANCE_TEXT,
|
override val additionalInfo: TextReference = EMPTY_BALANCE_TEXT,
|
||||||
override val imageResId: Int?,
|
override val imageResId: Int?,
|
||||||
override val onClick: (() -> Unit)?,
|
override val onRenameClick: (UserWalletId, String) -> Unit,
|
||||||
|
override val onDeleteClick: (UserWalletId) -> Unit,
|
||||||
) : WalletCardState
|
) : WalletCardState
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -102,16 +113,28 @@ internal sealed interface WalletCardState {
|
||||||
* @property title wallet name
|
* @property title wallet name
|
||||||
* @property additionalInfo wallet additional info
|
* @property additionalInfo wallet additional info
|
||||||
* @property imageResId wallet image resource id
|
* @property imageResId wallet image resource id
|
||||||
* @property onClick lambda be invoked when wallet card is clicked
|
* @property onRenameClick lambda be invoked when Rename button is clicked
|
||||||
|
* @property onDeleteClick lambda be invoked when Delete button is clicked
|
||||||
*/
|
*/
|
||||||
data class Loading(
|
data class Loading(
|
||||||
override val id: UserWalletId,
|
override val id: UserWalletId,
|
||||||
override val title: String,
|
override val title: String,
|
||||||
override val additionalInfo: TextReference? = null,
|
override val additionalInfo: TextReference? = null,
|
||||||
override val imageResId: Int?,
|
override val imageResId: Int?,
|
||||||
override val onClick: (() -> Unit)? = null,
|
override val onRenameClick: (UserWalletId, String) -> Unit,
|
||||||
|
override val onDeleteClick: (UserWalletId) -> Unit,
|
||||||
) : WalletCardState
|
) : WalletCardState
|
||||||
|
|
||||||
|
fun copySealed(title: String = this.title): WalletCardState {
|
||||||
|
return when (this) {
|
||||||
|
is Content -> copy(title = title)
|
||||||
|
is Error -> copy(title = title)
|
||||||
|
is HiddenContent -> copy(title = title)
|
||||||
|
is Loading -> copy(title = title)
|
||||||
|
is LockedContent -> copy(title = title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val HIDDEN_BALANCE_TEXT by lazy { TextReference.Str(value = "•••") }
|
val HIDDEN_BALANCE_TEXT by lazy { TextReference.Str(value = "•••") }
|
||||||
val EMPTY_BALANCE_TEXT by lazy { TextReference.Str(value = "—") }
|
val EMPTY_BALANCE_TEXT by lazy { TextReference.Str(value = "—") }
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ internal class WalletLoadedTokensListConverter(
|
||||||
cardTypeResolverProvider: Provider<CardTypesResolver>,
|
cardTypeResolverProvider: Provider<CardTypesResolver>,
|
||||||
currentWalletProvider: Provider<UserWallet>,
|
currentWalletProvider: Provider<UserWallet>,
|
||||||
clickIntents: WalletClickIntents,
|
clickIntents: WalletClickIntents,
|
||||||
) : Converter<LoadedTokensListModel, WalletMultiCurrencyState.Content> {
|
) : Converter<LoadedTokensListModel, WalletState> {
|
||||||
|
|
||||||
private val tokenListStateConverter = TokenListToWalletStateConverter(
|
private val tokenListStateConverter = TokenListToWalletStateConverter(
|
||||||
currentStateProvider = currentStateProvider,
|
currentStateProvider = currentStateProvider,
|
||||||
|
|
@ -46,7 +46,7 @@ internal class WalletLoadedTokensListConverter(
|
||||||
currentStateProvider = currentStateProvider,
|
currentStateProvider = currentStateProvider,
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun convert(value: LoadedTokensListModel): WalletMultiCurrencyState.Content {
|
override fun convert(value: LoadedTokensListModel): WalletState {
|
||||||
return value.tokenListEither.fold(
|
return value.tokenListEither.fold(
|
||||||
ifLeft = tokenListErrorStateConverter::convert,
|
ifLeft = tokenListErrorStateConverter::convert,
|
||||||
ifRight = {
|
ifRight = {
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,8 @@ internal class WalletRefreshStateConverter(
|
||||||
title = selectedWallet.title,
|
title = selectedWallet.title,
|
||||||
additionalInfo = additionalInfo,
|
additionalInfo = additionalInfo,
|
||||||
imageResId = selectedWallet.imageResId,
|
imageResId = selectedWallet.imageResId,
|
||||||
|
onRenameClick = selectedWallet.onRenameClick,
|
||||||
|
onDeleteClick = selectedWallet.onDeleteClick,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,8 @@ internal class WalletSingleCurrencyLoadedBalanceConverter(
|
||||||
currencyAmount = status.amount,
|
currencyAmount = status.amount,
|
||||||
),
|
),
|
||||||
imageResId = selectedWallet.imageResId,
|
imageResId = selectedWallet.imageResId,
|
||||||
onClick = selectedWallet.onClick,
|
onRenameClick = selectedWallet.onRenameClick,
|
||||||
|
onDeleteClick = selectedWallet.onDeleteClick,
|
||||||
balance = formatFiatAmount(status = status, appCurrency = appCurrencyProvider()),
|
balance = formatFiatAmount(status = status, appCurrency = appCurrencyProvider()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -104,7 +105,8 @@ internal class WalletSingleCurrencyLoadedBalanceConverter(
|
||||||
id = selectedWallet.id,
|
id = selectedWallet.id,
|
||||||
title = selectedWallet.title,
|
title = selectedWallet.title,
|
||||||
imageResId = selectedWallet.imageResId,
|
imageResId = selectedWallet.imageResId,
|
||||||
onClick = selectedWallet.onClick,
|
onRenameClick = selectedWallet.onRenameClick,
|
||||||
|
onDeleteClick = selectedWallet.onDeleteClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is CryptoCurrencyStatus.MissedDerivation,
|
is CryptoCurrencyStatus.MissedDerivation,
|
||||||
|
|
@ -116,7 +118,8 @@ internal class WalletSingleCurrencyLoadedBalanceConverter(
|
||||||
id = selectedWallet.id,
|
id = selectedWallet.id,
|
||||||
title = selectedWallet.title,
|
title = selectedWallet.title,
|
||||||
imageResId = selectedWallet.imageResId,
|
imageResId = selectedWallet.imageResId,
|
||||||
onClick = selectedWallet.onClick,
|
onRenameClick = selectedWallet.onRenameClick,
|
||||||
|
onDeleteClick = selectedWallet.onDeleteClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ internal class WalletSkeletonStateConverter(
|
||||||
|
|
||||||
// If wallet is initialized, return it, otherwise return loading state
|
// If wallet is initialized, return it, otherwise return loading state
|
||||||
if (initializedWallet !is WalletCardState.Loading) {
|
if (initializedWallet !is WalletCardState.Loading) {
|
||||||
initializedWallet
|
initializedWallet.copySealed(title = wallet.name)
|
||||||
} else {
|
} else {
|
||||||
createWalletLoadingState(wallet)
|
createWalletLoadingState(wallet)
|
||||||
}
|
}
|
||||||
|
|
@ -118,6 +118,8 @@ internal class WalletSkeletonStateConverter(
|
||||||
null
|
null
|
||||||
},
|
},
|
||||||
imageResId = WalletImageResolver.resolve(cardTypesResolver = cardTypeResolver),
|
imageResId = WalletImageResolver.resolve(cardTypesResolver = cardTypeResolver),
|
||||||
|
onRenameClick = clickIntents::onRenameClick,
|
||||||
|
onDeleteClick = clickIntents::onDeleteClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -200,11 +200,12 @@ internal class WalletStateFactory(
|
||||||
id = walletCardState.id,
|
id = walletCardState.id,
|
||||||
title = walletCardState.title,
|
title = walletCardState.title,
|
||||||
imageResId = walletCardState.imageResId,
|
imageResId = walletCardState.imageResId,
|
||||||
onClick = walletCardState.onClick,
|
|
||||||
additionalInfo = WalletAdditionalInfoFactory.resolve(
|
additionalInfo = WalletAdditionalInfoFactory.resolve(
|
||||||
cardTypesResolver = cardTypeResolver,
|
cardTypesResolver = cardTypeResolver,
|
||||||
wallet = currentWalletProvider(),
|
wallet = currentWalletProvider(),
|
||||||
),
|
),
|
||||||
|
onRenameClick = walletCardState.onRenameClick,
|
||||||
|
onDeleteClick = walletCardState.onDeleteClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.toImmutableList(),
|
.toImmutableList(),
|
||||||
|
|
@ -227,7 +228,8 @@ internal class WalletStateFactory(
|
||||||
id = walletCardState.id,
|
id = walletCardState.id,
|
||||||
title = walletCardState.title,
|
title = walletCardState.title,
|
||||||
imageResId = walletCardState.imageResId,
|
imageResId = walletCardState.imageResId,
|
||||||
onClick = walletCardState.onClick,
|
onRenameClick = walletCardState.onRenameClick,
|
||||||
|
onDeleteClick = walletCardState.onDeleteClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.toImmutableList(),
|
.toImmutableList(),
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,38 @@
|
||||||
package com.tangem.feature.wallet.presentation.wallet.ui.components.common
|
package com.tangem.feature.wallet.presentation.wallet.ui.components.common
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.animation.AnimatedContent
|
import androidx.compose.animation.AnimatedContent
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.ExperimentalAnimationApi
|
import androidx.compose.animation.ExperimentalAnimationApi
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.*
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.gestures.detectTapGestures
|
||||||
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
|
import androidx.compose.foundation.interaction.PressInteraction
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material.icons.outlined.Delete
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material.icons.outlined.Edit
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.material3.*
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||||
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.layout.onSizeChanged
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||||
|
import androidx.compose.ui.unit.DpOffset
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.constraintlayout.compose.ConstraintLayout
|
import androidx.constraintlayout.compose.ConstraintLayout
|
||||||
import androidx.constraintlayout.compose.ConstraintLayoutScope
|
import androidx.constraintlayout.compose.ConstraintLayoutScope
|
||||||
|
|
@ -25,8 +40,10 @@ import androidx.constraintlayout.compose.Dimension
|
||||||
import com.tangem.core.ui.components.FontSizeRange
|
import com.tangem.core.ui.components.FontSizeRange
|
||||||
import com.tangem.core.ui.components.RectangleShimmer
|
import com.tangem.core.ui.components.RectangleShimmer
|
||||||
import com.tangem.core.ui.components.ResizableText
|
import com.tangem.core.ui.components.ResizableText
|
||||||
|
import com.tangem.core.ui.components.wallets.RenameWalletDialogContent
|
||||||
import com.tangem.core.ui.extensions.TextReference
|
import com.tangem.core.ui.extensions.TextReference
|
||||||
import com.tangem.core.ui.extensions.resolveReference
|
import com.tangem.core.ui.extensions.resolveReference
|
||||||
|
import com.tangem.core.ui.res.TangemColorPalette
|
||||||
import com.tangem.core.ui.res.TangemDimens
|
import com.tangem.core.ui.res.TangemDimens
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.feature.wallet.impl.R
|
import com.tangem.feature.wallet.impl.R
|
||||||
|
|
@ -44,7 +61,12 @@ import com.tangem.feature.wallet.presentation.wallet.state.components.WalletCard
|
||||||
@Composable
|
@Composable
|
||||||
internal fun WalletCard(state: WalletCardState, modifier: Modifier = Modifier) {
|
internal fun WalletCard(state: WalletCardState, modifier: Modifier = Modifier) {
|
||||||
@Suppress("DestructuringDeclarationWithTooManyEntries")
|
@Suppress("DestructuringDeclarationWithTooManyEntries")
|
||||||
CardContainer(onClick = state.onClick, modifier = modifier) {
|
CardContainer(
|
||||||
|
name = state.title,
|
||||||
|
onDeleteClick = { state.onDeleteClick(state.id) },
|
||||||
|
onRenameClick = { state.onRenameClick(state.id, it) },
|
||||||
|
modifier = modifier,
|
||||||
|
) {
|
||||||
val (title, balance, additionalText, image) = createRefs()
|
val (title, balance, additionalText, image) = createRefs()
|
||||||
|
|
||||||
val contentVerticalMargin = TangemTheme.dimens.spacing12
|
val contentVerticalMargin = TangemTheme.dimens.spacing12
|
||||||
|
|
@ -92,16 +114,43 @@ internal fun WalletCard(state: WalletCardState, modifier: Modifier = Modifier) {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun CardContainer(
|
private fun CardContainer(
|
||||||
onClick: (() -> Unit)?,
|
name: String,
|
||||||
|
onDeleteClick: () -> Unit,
|
||||||
|
onRenameClick: (String) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
content: @Composable ConstraintLayoutScope.() -> Unit,
|
content: @Composable (ConstraintLayoutScope.() -> Unit),
|
||||||
) {
|
) {
|
||||||
|
var isMenuVisible by rememberSaveable { mutableStateOf(value = false) }
|
||||||
|
var pressOffset by remember { mutableStateOf(value = DpOffset.Zero) }
|
||||||
|
var itemHeight by remember { mutableStateOf(value = 0.dp) }
|
||||||
|
|
||||||
|
val density = LocalDensity.current
|
||||||
|
val interactionSource = remember { MutableInteractionSource() }
|
||||||
|
val haptic = LocalHapticFeedback.current
|
||||||
|
|
||||||
Surface(
|
Surface(
|
||||||
modifier = modifier.defaultMinSize(minHeight = TangemTheme.dimens.size108),
|
modifier = modifier
|
||||||
|
.defaultMinSize(minHeight = TangemTheme.dimens.size108)
|
||||||
|
.onSizeChanged { itemHeight = with(density) { it.height.toDp() } }
|
||||||
|
.clip(shape = TangemTheme.shapes.roundedCornersXMedium)
|
||||||
|
.indication(interactionSource = interactionSource, indication = LocalIndication.current)
|
||||||
|
.pointerInput(true) {
|
||||||
|
detectTapGestures(
|
||||||
|
onLongPress = {
|
||||||
|
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||||
|
isMenuVisible = true
|
||||||
|
pressOffset = DpOffset(x = it.x.toDp(), y = it.y.toDp())
|
||||||
|
},
|
||||||
|
onPress = {
|
||||||
|
val press = PressInteraction.Press(it)
|
||||||
|
interactionSource.emit(press)
|
||||||
|
tryAwaitRelease()
|
||||||
|
interactionSource.emit(PressInteraction.Release(press))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
shape = TangemTheme.shapes.roundedCornersXMedium,
|
shape = TangemTheme.shapes.roundedCornersXMedium,
|
||||||
color = TangemTheme.colors.background.primary,
|
color = TangemTheme.colors.background.primary,
|
||||||
onClick = onClick ?: {},
|
|
||||||
enabled = onClick != null,
|
|
||||||
) {
|
) {
|
||||||
ConstraintLayout(
|
ConstraintLayout(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
@ -111,6 +160,50 @@ private fun CardContainer(
|
||||||
content()
|
content()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isRenameWalletDialogVisible by rememberSaveable { mutableStateOf(value = false) }
|
||||||
|
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = isMenuVisible,
|
||||||
|
onDismissRequest = { isMenuVisible = false },
|
||||||
|
modifier = Modifier.background(color = TangemTheme.colors.background.secondary),
|
||||||
|
offset = pressOffset.copy(y = pressOffset.y - itemHeight),
|
||||||
|
) {
|
||||||
|
MenuItem(
|
||||||
|
textResId = R.string.common_rename,
|
||||||
|
imageVector = Icons.Outlined.Edit,
|
||||||
|
onClick = {
|
||||||
|
isMenuVisible = false
|
||||||
|
isRenameWalletDialogVisible = true
|
||||||
|
},
|
||||||
|
)
|
||||||
|
MenuItem(textResId = R.string.common_delete, imageVector = Icons.Outlined.Delete, onClick = onDeleteClick)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRenameWalletDialogVisible) {
|
||||||
|
RenameWalletDialogContent(
|
||||||
|
name = name,
|
||||||
|
onConfirm = {
|
||||||
|
onRenameClick(it)
|
||||||
|
isRenameWalletDialogVisible = false
|
||||||
|
},
|
||||||
|
onDismiss = { isRenameWalletDialogVisible = false },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun MenuItem(@StringRes textResId: Int, imageVector: ImageVector, onClick: () -> Unit) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(text = stringResource(id = textResId), style = TangemTheme.typography.subtitle2) },
|
||||||
|
modifier = Modifier.background(color = TangemTheme.colors.background.secondary),
|
||||||
|
trailingIcon = { Icon(imageVector = imageVector, contentDescription = null) },
|
||||||
|
onClick = onClick,
|
||||||
|
colors = MenuDefaults.itemColors(
|
||||||
|
textColor = TangemTheme.colors.text.primary1,
|
||||||
|
trailingIconColor = TangemColorPalette.Dark6,
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ internal class FiatBalanceToWalletCardConverter(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun WalletCardState.toLoadingWalletCardState(): WalletCardState {
|
private fun WalletCardState.toLoadingWalletCardState(): WalletCardState {
|
||||||
return WalletCardState.Loading(id, title, additionalInfo, imageResId, onClick)
|
return WalletCardState.Loading(id, title, additionalInfo, imageResId, onRenameClick, onDeleteClick)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun WalletCardState.toErrorWalletCardState(): WalletCardState {
|
private fun WalletCardState.toErrorWalletCardState(): WalletCardState {
|
||||||
|
|
@ -35,7 +35,8 @@ internal class FiatBalanceToWalletCardConverter(
|
||||||
id = id,
|
id = id,
|
||||||
title = title,
|
title = title,
|
||||||
imageResId = imageResId,
|
imageResId = imageResId,
|
||||||
onClick = onClick,
|
onDeleteClick = onDeleteClick,
|
||||||
|
onRenameClick = onRenameClick,
|
||||||
additionalInfo = WalletAdditionalInfoFactory.resolve(
|
additionalInfo = WalletAdditionalInfoFactory.resolve(
|
||||||
cardTypesResolver = cardTypeResolverProvider(),
|
cardTypesResolver = cardTypeResolverProvider(),
|
||||||
wallet = currentWalletProvider(),
|
wallet = currentWalletProvider(),
|
||||||
|
|
@ -50,7 +51,8 @@ internal class FiatBalanceToWalletCardConverter(
|
||||||
title = currentState.title,
|
title = currentState.title,
|
||||||
additionalInfo = currentState.additionalInfo ?: WalletCardState.HIDDEN_BALANCE_TEXT,
|
additionalInfo = currentState.additionalInfo ?: WalletCardState.HIDDEN_BALANCE_TEXT,
|
||||||
imageResId = currentState.imageResId,
|
imageResId = currentState.imageResId,
|
||||||
onClick = currentState.onClick,
|
onRenameClick = currentState.onRenameClick,
|
||||||
|
onDeleteClick = currentState.onDeleteClick,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val appCurrency = appCurrencyProvider()
|
val appCurrency = appCurrencyProvider()
|
||||||
|
|
@ -63,7 +65,8 @@ internal class FiatBalanceToWalletCardConverter(
|
||||||
wallet = currentWalletProvider(),
|
wallet = currentWalletProvider(),
|
||||||
),
|
),
|
||||||
imageResId = currentState.imageResId,
|
imageResId = currentState.imageResId,
|
||||||
onClick = currentState.onClick,
|
onRenameClick = currentState.onRenameClick,
|
||||||
|
onDeleteClick = currentState.onDeleteClick,
|
||||||
balance = formatFiatAmount(
|
balance = formatFiatAmount(
|
||||||
fiatAmount = this.amount,
|
fiatAmount = this.amount,
|
||||||
fiatCurrencyCode = appCurrency.code,
|
fiatCurrencyCode = appCurrency.code,
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.utils
|
||||||
import com.tangem.common.Provider
|
import com.tangem.common.Provider
|
||||||
import com.tangem.domain.tokens.error.TokenListError
|
import com.tangem.domain.tokens.error.TokenListError
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletMultiCurrencyState
|
import com.tangem.feature.wallet.presentation.wallet.state.WalletMultiCurrencyState
|
||||||
|
import com.tangem.feature.wallet.presentation.wallet.state.WalletSingleCurrencyState
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletState
|
import com.tangem.feature.wallet.presentation.wallet.state.WalletState
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletTokensListState
|
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletTokensListState
|
||||||
import com.tangem.utils.converter.Converter
|
import com.tangem.utils.converter.Converter
|
||||||
|
|
@ -10,11 +11,23 @@ import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
||||||
internal class TokenListErrorConverter(
|
internal class TokenListErrorConverter(
|
||||||
private val currentStateProvider: Provider<WalletState>,
|
private val currentStateProvider: Provider<WalletState>,
|
||||||
) : Converter<TokenListError, WalletMultiCurrencyState.Content> {
|
) : Converter<TokenListError, WalletState> {
|
||||||
|
|
||||||
override fun convert(value: TokenListError): WalletMultiCurrencyState.Content {
|
override fun convert(value: TokenListError): WalletState {
|
||||||
return requireNotNull(currentStateProvider() as? WalletMultiCurrencyState.Content).copy(
|
return when (val state = currentStateProvider()) {
|
||||||
tokensListState = WalletTokensListState.Content(items = persistentListOf(), onOrganizeTokensClick = null),
|
is WalletMultiCurrencyState.Content -> {
|
||||||
)
|
state.copy(
|
||||||
|
tokensListState = WalletTokensListState.Content(
|
||||||
|
items = persistentListOf(),
|
||||||
|
onOrganizeTokensClick = null,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is WalletMultiCurrencyState.Locked,
|
||||||
|
is WalletSingleCurrencyState.Content,
|
||||||
|
is WalletSingleCurrencyState.Locked,
|
||||||
|
is WalletState.Initial,
|
||||||
|
-> state
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -471,7 +471,10 @@ internal class WalletViewModel @Inject constructor(
|
||||||
|
|
||||||
override fun onDeleteClick(userWalletId: UserWalletId) {
|
override fun onDeleteClick(userWalletId: UserWalletId) {
|
||||||
viewModelScope.launch(dispatchers.io) {
|
viewModelScope.launch(dispatchers.io) {
|
||||||
deleteWalletUseCase(userWalletId)
|
val either = deleteWalletUseCase(userWalletId)
|
||||||
|
|
||||||
|
val state = requireNotNull(uiState as? WalletState.ContentState)
|
||||||
|
if (state.walletsListConfig.wallets.size <= 1 && either.isRight()) router.openStoriesScreen()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue