Updated on 2026-08-14

This commit is contained in:
Tangem 2025-11-07 10:41:10 +05:00
parent 96e28b2d1f
commit 2d96a9a247
6 changed files with 97 additions and 11 deletions

View file

@ -62,6 +62,7 @@ dependencies {
implementation(deps.compose.material3)
implementation(deps.compose.shimmer)
implementation(deps.decompose.ext.compose)
implementation(deps.compose.reorderableV2)
/* DI */
implementation(deps.hilt.android)

View file

@ -12,6 +12,7 @@ import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.feature.walletsettings.component.WalletSettingsComponent
import com.tangem.feature.walletsettings.entity.AccountReorderUM
import com.tangem.feature.walletsettings.entity.WalletSettingsAccountsUM
import com.tangem.feature.walletsettings.entity.WalletSettingsAccountsUM.Footer.AddAccountUM
import com.tangem.feature.walletsettings.entity.WalletSettingsItemUM
@ -75,6 +76,11 @@ internal class PreviewWalletSettingsComponent : WalletSettingsComponent {
),
requestPushNotificationsPermission = false,
onPushNotificationPermissionGranted = {},
accountReorderUM = AccountReorderUM(
isDragEnabled = true,
onMove = { _, _ -> },
onDragStopped = {},
),
)
private fun previewAccounts() = buildList {

View file

@ -9,6 +9,13 @@ internal data class WalletSettingsUM(
val items: PersistentList<WalletSettingsItemUM>,
val requestPushNotificationsPermission: Boolean = false,
val onPushNotificationPermissionGranted: (Boolean) -> Unit,
val accountReorderUM: AccountReorderUM,
val isWalletBackedUp: Boolean = true,
val walletUpgradeDismissed: Boolean = false,
)
internal data class AccountReorderUM(
val isDragEnabled: Boolean,
val onMove: (fromIndex: Int, toIndex: Int) -> Unit,
val onDragStopped: () -> Unit,
)

View file

@ -50,6 +50,7 @@ import com.tangem.features.pushnotifications.api.analytics.PushNotificationAnaly
import com.tangem.hot.sdk.model.HotWalletId
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.mutate
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*
@ -100,6 +101,11 @@ internal class WalletSettingsModel @Inject constructor(
onPushNotificationPermissionGranted = ::onPushNotificationPermissionGranted,
isWalletBackedUp = true,
walletUpgradeDismissed = false,
accountReorderUM = AccountReorderUM(
isDragEnabled = false,
onMove = ::onAccountReorder,
onDragStopped = ::onAccountDragStopped,
),
),
)
@ -130,6 +136,12 @@ internal class WalletSettingsModel @Inject constructor(
isUpgradeNotificationEnabled = isUpgradeNotificationEnabled,
accountList = accountList,
),
accountReorderUM = AccountReorderUM(
isDragEnabled = accountsFeatureToggles.isFeatureEnabled &&
accountList.count { it is WalletSettingsAccountsUM.Account } > 1,
onMove = ::onAccountReorder,
onDragStopped = ::onAccountDragStopped,
),
isWalletBackedUp = isWalletBackedUp,
)
}
@ -416,6 +428,20 @@ internal class WalletSettingsModel @Inject constructor(
}
}
private fun onAccountReorder(fromIndex: Int, toIndex: Int) {
state.update { prevState ->
prevState.copy(
items = prevState.items.mutate {
it.add(toIndex - 1, it.removeAt(fromIndex - 1))
},
)
}
}
private fun onAccountDragStopped() {
// TODO() Implement saving the new order of accounts
}
// TODO actualize strings [REDACTED_TASK_KEY] and remove MaximumLineLength
@Suppress("LongMethod", "MaximumLineLength")
private fun onForgetWalletClick(userWallet: UserWallet) {

View file

@ -2,20 +2,23 @@ package com.tangem.feature.walletsettings.ui
import android.content.res.Configuration
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyItemScope
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.testTag
@ -45,10 +48,14 @@ import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.test.WalletSettingsScreenTestTags
import com.tangem.feature.walletsettings.component.preview.PreviewWalletSettingsComponent
import com.tangem.feature.walletsettings.entity.AccountReorderUM
import com.tangem.feature.walletsettings.entity.WalletSettingsAccountsUM
import com.tangem.feature.walletsettings.entity.WalletSettingsItemUM
import com.tangem.feature.walletsettings.entity.WalletSettingsUM
import com.tangem.feature.walletsettings.impl.R
import sh.calvin.reorderable.ReorderableItem
import sh.calvin.reorderable.ReorderableLazyListState
import sh.calvin.reorderable.rememberReorderableLazyListState
@Composable
internal fun WalletSettingsScreen(
@ -80,9 +87,16 @@ internal fun WalletSettingsScreen(
)
}
@Suppress("LongMethod")
@Composable
private fun Content(state: WalletSettingsUM, modifier: Modifier = Modifier) {
val listState = rememberLazyListState()
val reorderableListState = rememberReorderableLazyListState(
lazyListState = listState,
onMove = { from, to -> state.accountReorderUM.onMove(from.index, to.index) },
)
LazyColumn(
state = listState,
modifier = modifier,
contentPadding = PaddingValues(
top = TangemTheme.dimens.spacing16,
@ -143,7 +157,12 @@ private fun Content(state: WalletSettingsUM, modifier: Modifier = Modifier) {
model = item,
)
is WalletSettingsAccountsUM.Header -> AccountsHeader(item, itemModifier)
is WalletSettingsAccountsUM.Account -> AccountItem(item, itemModifier)
is WalletSettingsAccountsUM.Account -> AccountItem(
model = item,
reorderableListState = reorderableListState,
accountReorderUM = state.accountReorderUM,
modifier = itemModifier,
)
is WalletSettingsAccountsUM.Footer -> AccountsFooter(item, itemModifier)
}
}
@ -305,13 +324,38 @@ private fun AccountsHeader(model: WalletSettingsAccountsUM.Header, modifier: Mod
)
}
@Suppress("MagicNumber")
@Composable
private fun AccountItem(model: WalletSettingsAccountsUM.Account, modifier: Modifier = Modifier) {
UserWalletItem(
state = model.state,
modifier = modifier
.background(color = TangemTheme.colors.background.primary),
)
private fun LazyItemScope.AccountItem(
model: WalletSettingsAccountsUM.Account,
reorderableListState: ReorderableLazyListState,
accountReorderUM: AccountReorderUM,
modifier: Modifier = Modifier,
) {
ReorderableItem(
state = reorderableListState,
key = model.id,
) { isDragging ->
val elevation by animateDpAsState(if (isDragging) 9.dp else 0.dp)
val scale by animateFloatAsState(if (isDragging) 1.04f else 1f)
val shapeRadius by animateDpAsState(if (isDragging) 16.dp else 0.dp)
Surface(
shape = RoundedCornerShape(shapeRadius),
shadowElevation = elevation,
modifier = modifier.scale(scale),
) {
UserWalletItem(
state = model.state,
modifier = Modifier
.longPressDraggableHandle(
enabled = accountReorderUM.isDragEnabled,
onDragStopped = accountReorderUM.onDragStopped,
)
.background(color = TangemTheme.colors.background.primary),
)
}
}
}
@Composable

View file

@ -41,6 +41,7 @@ compose-navigation = "2.7.7"
compose-accompanist = "0.30.1"
compose-paging = "3.2.1"
compose-reorderable = "0.9.6"
compose-reorderable-v2 = "3.0.0"
compose-lifecycle-runtime = "2.7.0"
# endregion Compose
@ -186,6 +187,7 @@ compose-accompanist-webView = { module = "com.google.accompanist:accompanist-web
compose-accompanist-permission = { module = "com.google.accompanist:accompanist-permissions", version.ref = "compose-accompanist" }
compose-paging = { module = "androidx.paging:paging-compose", version.ref = "compose-paging" }
compose-reorderable = { module = "org.burnoutcrew.composereorderable:reorderable", version.ref = "compose-reorderable" }
compose-reorderableV2 = { module = "sh.calvin.reorderable:reorderable", version.ref = "compose-reorderable-v2" }
# endregion Compose
# region Firebase