From 2d96a9a2479aa6f07426d09b8a17b993f58afc5c Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 7 Nov 2025 10:41:10 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../wallet-settings/impl/build.gradle.kts | 1 + .../preview/PreviewWalletSettingsComponent.kt | 6 ++ .../walletsettings/entity/WalletSettingsUM.kt | 7 ++ .../model/WalletSettingsModel.kt | 26 ++++++++ .../walletsettings/ui/WalletSettingsScreen.kt | 66 +++++++++++++++---- gradle/dependencies.toml | 2 + 6 files changed, 97 insertions(+), 11 deletions(-) diff --git a/features/wallet-settings/impl/build.gradle.kts b/features/wallet-settings/impl/build.gradle.kts index e34be56eb8..91c5e3db22 100644 --- a/features/wallet-settings/impl/build.gradle.kts +++ b/features/wallet-settings/impl/build.gradle.kts @@ -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) diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/preview/PreviewWalletSettingsComponent.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/preview/PreviewWalletSettingsComponent.kt index ad1e46ea60..67df3940fa 100644 --- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/preview/PreviewWalletSettingsComponent.kt +++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/preview/PreviewWalletSettingsComponent.kt @@ -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 { diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/entity/WalletSettingsUM.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/entity/WalletSettingsUM.kt index 04014e4662..cb71750ba1 100644 --- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/entity/WalletSettingsUM.kt +++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/entity/WalletSettingsUM.kt @@ -9,6 +9,13 @@ internal data class WalletSettingsUM( val items: PersistentList, 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, ) \ No newline at end of file diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt index 9c9ea5d91d..31185e6adf 100644 --- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt +++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt @@ -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) { diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/ui/WalletSettingsScreen.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/ui/WalletSettingsScreen.kt index 3ddb2e4aa9..b3a5218d38 100644 --- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/ui/WalletSettingsScreen.kt +++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/ui/WalletSettingsScreen.kt @@ -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 diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 48a0dc4f7c..028cf3611c 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -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