Updated on 2026-08-14
This commit is contained in:
parent
7551148abe
commit
6d73ea6b3c
6 changed files with 314 additions and 85 deletions
|
|
@ -106,11 +106,17 @@ internal object WalletPreviewData {
|
|||
val draggableItems = List(networksSize) { it }
|
||||
.flatMap { index ->
|
||||
val lastNetworkIndex = networksSize - 1
|
||||
val lastTokenIndex = tokensSize - 1
|
||||
val networkNumber = index + 1
|
||||
|
||||
val group = DraggableItem.GroupHeader(
|
||||
id = "group_$networkNumber",
|
||||
networkName = "$networkNumber",
|
||||
roundingMode = when (index) {
|
||||
0 -> DraggableItem.RoundingMode.Top()
|
||||
lastNetworkIndex -> DraggableItem.RoundingMode.Bottom()
|
||||
else -> DraggableItem.RoundingMode.None
|
||||
},
|
||||
)
|
||||
|
||||
val tokens: MutableList<DraggableItem.Token> = mutableListOf()
|
||||
|
|
@ -120,10 +126,14 @@ internal object WalletPreviewData {
|
|||
DraggableItem.Token(
|
||||
tokenItemState = tokenItemDragState.copy(
|
||||
id = "${group.id}_token_$tokenNumber",
|
||||
name = "Token $tokenNumber",
|
||||
name = "Token $tokenNumber from $networkNumber network",
|
||||
networkIconResId = R.drawable.img_eth_22.takeIf { i != 0 },
|
||||
),
|
||||
groupId = group.id,
|
||||
roundingMode = when {
|
||||
i == lastTokenIndex && index == lastNetworkIndex -> DraggableItem.RoundingMode.Bottom()
|
||||
else -> DraggableItem.RoundingMode.None
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -142,6 +152,10 @@ internal object WalletPreviewData {
|
|||
|
||||
val draggableTokens = draggableItems
|
||||
.filterIsInstance<DraggableItem.Token>()
|
||||
.toMutableList()
|
||||
.also {
|
||||
it[0] = it[0].copy(roundingMode = DraggableItem.RoundingMode.Top())
|
||||
}
|
||||
.toPersistentList()
|
||||
|
||||
val groupedOrganizeTokensState = OrganizeTokensStateHolder(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens
|
||||
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.animation.core.*
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.*
|
||||
|
|
@ -13,10 +13,10 @@ import androidx.compose.runtime.*
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.composed
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
|
|
@ -30,10 +30,7 @@ import com.tangem.feature.wallet.impl.R
|
|||
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
|
||||
import com.tangem.feature.wallet.presentation.common.component.DraggableNetworkGroupItem
|
||||
import com.tangem.feature.wallet.presentation.common.component.DraggableTokenItem
|
||||
import org.burnoutcrew.reorderable.ReorderableItem
|
||||
import org.burnoutcrew.reorderable.ReorderableLazyListState
|
||||
import org.burnoutcrew.reorderable.rememberReorderableLazyListState
|
||||
import org.burnoutcrew.reorderable.reorderable
|
||||
import org.burnoutcrew.reorderable.*
|
||||
|
||||
@Composable
|
||||
internal fun OrganizeTokensScreen(state: OrganizeTokensStateHolder, modifier: Modifier = Modifier) {
|
||||
|
|
@ -60,7 +57,6 @@ internal fun OrganizeTokensScreen(state: OrganizeTokensStateHolder, modifier: Mo
|
|||
)
|
||||
}
|
||||
|
||||
// TODO: Fix list animations
|
||||
@Composable
|
||||
private fun TokenList(
|
||||
listState: LazyListState,
|
||||
|
|
@ -76,7 +72,6 @@ private fun TokenList(
|
|||
onDragEnd = { _, _ -> dragConfig.onItemDragEnd() },
|
||||
)
|
||||
val items = state.items
|
||||
val lastItemIndex = items.lastIndex
|
||||
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
|
|
@ -99,9 +94,8 @@ private fun TokenList(
|
|||
}
|
||||
|
||||
DraggableItem(
|
||||
item = item,
|
||||
index = index,
|
||||
lastItemIndex = lastItemIndex,
|
||||
item = item,
|
||||
reorderableState = reorderableListState,
|
||||
onDragStart = onDragStart,
|
||||
)
|
||||
|
|
@ -121,7 +115,6 @@ private fun TokenList(
|
|||
private fun LazyItemScope.DraggableItem(
|
||||
index: Int,
|
||||
item: DraggableItem,
|
||||
lastItemIndex: Int,
|
||||
reorderableState: ReorderableLazyListState,
|
||||
onDragStart: () -> Unit,
|
||||
) {
|
||||
|
|
@ -135,8 +128,7 @@ private fun LazyItemScope.DraggableItem(
|
|||
onDragStart()
|
||||
}
|
||||
|
||||
val itemModifier = Modifier
|
||||
.clipFirstLastAndDraggingItems(index, lastItemIndex, isDragging)
|
||||
val itemModifier = Modifier.applyShapeAndShadow(item.roundingMode, item.showShadow)
|
||||
|
||||
when (item) {
|
||||
is DraggableItem.GroupHeader -> DraggableNetworkGroupItem(
|
||||
|
|
@ -256,35 +248,56 @@ private fun Actions(config: OrganizeTokensStateHolder.ActionsConfig, modifier: M
|
|||
}
|
||||
}
|
||||
|
||||
private fun Modifier.clipFirstLastAndDraggingItems(index: Int, lastItemIndex: Int, isDragging: Boolean): Modifier =
|
||||
private fun Modifier.applyShapeAndShadow(roundingMode: DraggableItem.RoundingMode, showShadow: Boolean): Modifier =
|
||||
composed {
|
||||
when {
|
||||
isDragging -> {
|
||||
val elevation by animateDpAsState(
|
||||
targetValue = TangemTheme.dimens.elevation12,
|
||||
label = "dragging_item_shadow_elevation",
|
||||
)
|
||||
|
||||
this.shadow(elevation, shape = TangemTheme.shapes.roundedCornersXMedium)
|
||||
}
|
||||
index == 0 -> {
|
||||
this.clip(
|
||||
RoundedCornerShape(
|
||||
topStart = TangemTheme.dimens.radius16,
|
||||
topEnd = TangemTheme.dimens.radius16,
|
||||
),
|
||||
)
|
||||
}
|
||||
index == lastItemIndex -> {
|
||||
this.clip(
|
||||
RoundedCornerShape(
|
||||
bottomStart = TangemTheme.dimens.radius16,
|
||||
bottomEnd = TangemTheme.dimens.radius16,
|
||||
),
|
||||
)
|
||||
}
|
||||
else -> this
|
||||
val radius by animateDpAsState(
|
||||
targetValue = if (roundingMode !is DraggableItem.RoundingMode.None) {
|
||||
TangemTheme.dimens.radius16
|
||||
} else {
|
||||
TangemTheme.dimens.radius0
|
||||
},
|
||||
label = "item_shape_radius",
|
||||
)
|
||||
val shape = when (roundingMode) {
|
||||
is DraggableItem.RoundingMode.None -> RectangleShape
|
||||
is DraggableItem.RoundingMode.Top -> RoundedCornerShape(
|
||||
topStart = radius,
|
||||
topEnd = radius,
|
||||
)
|
||||
is DraggableItem.RoundingMode.Bottom -> RoundedCornerShape(
|
||||
bottomStart = radius,
|
||||
bottomEnd = radius,
|
||||
)
|
||||
is DraggableItem.RoundingMode.All -> RoundedCornerShape(
|
||||
size = radius,
|
||||
)
|
||||
}
|
||||
|
||||
val paddingValue = TangemTheme.dimens.spacing4
|
||||
val padding = if (roundingMode.showGap) {
|
||||
when (roundingMode) {
|
||||
is DraggableItem.RoundingMode.None -> null
|
||||
is DraggableItem.RoundingMode.All -> PaddingValues(vertical = paddingValue)
|
||||
is DraggableItem.RoundingMode.Top -> PaddingValues(top = paddingValue)
|
||||
is DraggableItem.RoundingMode.Bottom -> PaddingValues(bottom = paddingValue)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
this
|
||||
.let {
|
||||
if (padding != null) {
|
||||
it.padding(padding)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
.shadow(
|
||||
elevation = if (showShadow) TangemTheme.dimens.elevation12 else TangemTheme.dimens.elevation0,
|
||||
shape = shape,
|
||||
clip = true,
|
||||
)
|
||||
}
|
||||
|
||||
// region Preview
|
||||
|
|
|
|||
|
|
@ -58,20 +58,28 @@ internal sealed interface OrganizeTokensListState {
|
|||
* Helper class for the DND list items
|
||||
*
|
||||
* @property id ID of the item
|
||||
* @property roundingMode item [RoundingMode]
|
||||
* @property showShadow if true then item should be elevated
|
||||
* */
|
||||
@Immutable
|
||||
internal sealed interface DraggableItem {
|
||||
val id: String
|
||||
val roundingMode: RoundingMode
|
||||
val showShadow: Boolean
|
||||
|
||||
/**
|
||||
* Item for network group header.
|
||||
*
|
||||
* @property id ID of the network group
|
||||
* @property networkName network group name
|
||||
* @property roundingMode item [RoundingMode]
|
||||
* @property showShadow if true then item should be elevated
|
||||
* */
|
||||
data class GroupHeader(
|
||||
override val id: String,
|
||||
val networkName: String,
|
||||
override val roundingMode: RoundingMode = RoundingMode.None,
|
||||
override val showShadow: Boolean = false,
|
||||
) : DraggableItem
|
||||
|
||||
/**
|
||||
|
|
@ -80,10 +88,14 @@ internal sealed interface DraggableItem {
|
|||
* @property tokenItemState state of the token item
|
||||
* @property groupId ID of the network group which contains this token
|
||||
* @property id ID of the token
|
||||
* @property roundingMode item [RoundingMode]
|
||||
* @property showShadow if true then item should be elevated
|
||||
* */
|
||||
data class Token(
|
||||
val tokenItemState: TokenItemState.Draggable,
|
||||
val groupId: String,
|
||||
override val showShadow: Boolean = false,
|
||||
override val roundingMode: RoundingMode = RoundingMode.None,
|
||||
) : DraggableItem {
|
||||
override val id: String = tokenItemState.id
|
||||
}
|
||||
|
|
@ -96,5 +108,72 @@ internal sealed interface DraggableItem {
|
|||
* */
|
||||
data class GroupPlaceholder(
|
||||
override val id: String,
|
||||
) : DraggableItem
|
||||
) : DraggableItem {
|
||||
override val showShadow: Boolean = false
|
||||
override val roundingMode: RoundingMode = RoundingMode.None
|
||||
}
|
||||
|
||||
/**
|
||||
* Update item [RoundingMode]
|
||||
*
|
||||
* @param mode new [RoundingMode]
|
||||
*
|
||||
* @return updated [DraggableItem]
|
||||
* */
|
||||
fun roundingMode(mode: RoundingMode): DraggableItem = when (this) {
|
||||
is GroupPlaceholder -> this
|
||||
is GroupHeader -> this.copy(roundingMode = mode)
|
||||
is Token -> this.copy(roundingMode = mode)
|
||||
}
|
||||
|
||||
/**
|
||||
* Update item shadow visibility
|
||||
*
|
||||
* @param show if true then item should be elevated
|
||||
*
|
||||
* @return updated [DraggableItem]
|
||||
* */
|
||||
fun showShadow(show: Boolean): DraggableItem = when (this) {
|
||||
is GroupPlaceholder -> this
|
||||
is GroupHeader -> this.copy(showShadow = show)
|
||||
is Token -> this.copy(showShadow = show)
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounding mode of the [DraggableItem]
|
||||
*
|
||||
* @property showGap if true then item should have padding on rounded side
|
||||
* */
|
||||
@Immutable
|
||||
sealed interface RoundingMode {
|
||||
val showGap: Boolean
|
||||
|
||||
/**
|
||||
* In this mode, item is not rounded
|
||||
* */
|
||||
object None : RoundingMode {
|
||||
override val showGap: Boolean = false
|
||||
}
|
||||
|
||||
/**
|
||||
* In this mode, item should have a rounded top side
|
||||
*
|
||||
* @property showGap if true then item should have top padding
|
||||
* */
|
||||
data class Top(override val showGap: Boolean = false) : RoundingMode
|
||||
|
||||
/**
|
||||
* In this mode, item should have a rounded bottom side
|
||||
*
|
||||
* @property showGap if true then item should have bottom padding
|
||||
* */
|
||||
data class Bottom(override val showGap: Boolean = false) : RoundingMode
|
||||
|
||||
/**
|
||||
* In this mode, item should have a rounded all sides
|
||||
*
|
||||
* @property showGap if true then item should have top and bottom padding
|
||||
* */
|
||||
data class All(override val showGap: Boolean = false) : RoundingMode
|
||||
}
|
||||
}
|
||||
|
|
@ -4,16 +4,16 @@ import androidx.compose.runtime.getValue
|
|||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensStateHolder.DragConfig
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensStateHolder.HeaderConfig
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.checkCanMoveHeaderOver
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.checkCanMoveTokenOver
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.findItemsToMove
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.moveItem
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.*
|
||||
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.burnoutcrew.reorderable.ItemPosition
|
||||
import javax.inject.Inject
|
||||
import kotlin.properties.Delegates
|
||||
|
|
@ -22,9 +22,8 @@ import kotlin.properties.Delegates
|
|||
@HiltViewModel
|
||||
internal class OrganizeTokensViewModel @Inject constructor() : ViewModel() {
|
||||
|
||||
// TODO: Move to domain
|
||||
@Volatile
|
||||
private var groupIdToTokens: Map<String, List<DraggableItem.Token>>? = null
|
||||
private var movingItem: DraggableItem? = null
|
||||
|
||||
var router: InnerWalletRouter by Delegates.notNull()
|
||||
|
||||
|
|
@ -38,8 +37,8 @@ internal class OrganizeTokensViewModel @Inject constructor() : ViewModel() {
|
|||
dragConfig = DragConfig(
|
||||
onItemDragged = this::moveItem,
|
||||
canDragItemOver = this::checkCanMoveItemOver,
|
||||
onItemDragEnd = this::expandGroups,
|
||||
onDragStart = this::collapseGroup,
|
||||
onItemDragEnd = this::endMoving,
|
||||
onDragStart = this::startMoving,
|
||||
),
|
||||
header = HeaderConfig(
|
||||
onSortByBalanceClick = { /* no-op */ },
|
||||
|
|
@ -78,46 +77,42 @@ internal class OrganizeTokensViewModel @Inject constructor() : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun collapseGroup(item: DraggableItem) {
|
||||
if (!groupIdToTokens.isNullOrEmpty() || item is DraggableItem.Token) return
|
||||
private fun startMoving(movingItem: DraggableItem) = viewModelScope.launch(Dispatchers.Default) {
|
||||
if (this@OrganizeTokensViewModel.movingItem != null) return@launch
|
||||
this@OrganizeTokensViewModel.movingItem = movingItem
|
||||
|
||||
val itemsState = uiState.itemsState as? OrganizeTokensListState.GroupedByNetwork ?: return
|
||||
groupIdToTokens = itemsState.items
|
||||
.asSequence()
|
||||
.filterIsInstance<DraggableItem.Token>()
|
||||
.groupBy(DraggableItem.Token::groupId)
|
||||
|
||||
uiState = uiState.copy(
|
||||
itemsState = itemsState.updateItems { items ->
|
||||
items.filterNot { it is DraggableItem.Token && it.groupId == item.id }
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun expandGroups() {
|
||||
if (groupIdToTokens.isNullOrEmpty()) return
|
||||
|
||||
val itemsState = uiState.itemsState as? OrganizeTokensListState.GroupedByNetwork ?: return
|
||||
val currentGroups = itemsState.items.filterIsInstance<DraggableItem.GroupHeader>()
|
||||
val newItems = currentGroups
|
||||
.flatMapIndexed { index, group ->
|
||||
mutableListOf<DraggableItem>(group)
|
||||
.also { it.addAll(groupIdToTokens?.get(group.id).orEmpty()) }
|
||||
.also {
|
||||
if (index != currentGroups.lastIndex) {
|
||||
it.add(DraggableItem.GroupPlaceholder(id = "group_divider_$index"))
|
||||
}
|
||||
}
|
||||
val updatedItemsState = uiState.itemsState.updateItems { items ->
|
||||
when (movingItem) {
|
||||
is DraggableItem.GroupHeader -> items.collapseGroup(movingItem)
|
||||
is DraggableItem.Token -> when (uiState.itemsState) {
|
||||
is OrganizeTokensListState.GroupedByNetwork -> items.divideGroups(movingItem)
|
||||
is OrganizeTokensListState.Ungrouped -> items.divideItems(movingItem)
|
||||
}
|
||||
is DraggableItem.GroupPlaceholder -> items
|
||||
}
|
||||
}
|
||||
|
||||
uiState = uiState.copy(
|
||||
itemsState = itemsState.updateItems { newItems },
|
||||
)
|
||||
|
||||
groupIdToTokens = null
|
||||
uiState = uiState.copy(itemsState = updatedItemsState)
|
||||
}
|
||||
|
||||
private fun moveItem(from: ItemPosition, to: ItemPosition) {
|
||||
private fun endMoving() = viewModelScope.launch(Dispatchers.Default) {
|
||||
if (movingItem == null) return@launch
|
||||
|
||||
val updatedItemsState = uiState.itemsState.updateItems { items ->
|
||||
when (movingItem) {
|
||||
is DraggableItem.GroupHeader -> items.expandGroups()
|
||||
is DraggableItem.Token -> items.uniteItems()
|
||||
is DraggableItem.GroupPlaceholder,
|
||||
null,
|
||||
-> items
|
||||
}
|
||||
}
|
||||
|
||||
uiState = uiState.copy(itemsState = updatedItemsState)
|
||||
movingItem = null
|
||||
}
|
||||
|
||||
private fun moveItem(from: ItemPosition, to: ItemPosition) = viewModelScope.launch(Dispatchers.Default) {
|
||||
uiState = uiState.copy(
|
||||
itemsState = uiState.itemsState.updateItems {
|
||||
it.moveItem(from.index, to.index)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ internal fun checkCanMoveHeaderOver(
|
|||
moveOverItem: DraggableItem,
|
||||
lastItemIndex: Int,
|
||||
): Boolean {
|
||||
// Group item can be moved only to group divider or to ages of the items list
|
||||
return when {
|
||||
moveOverItemPosition.index == 0 -> true
|
||||
moveOverItemPosition.index == lastItemIndex -> true
|
||||
|
|
@ -40,6 +41,7 @@ internal fun checkCanMoveHeaderOver(
|
|||
}
|
||||
|
||||
internal fun checkCanMoveTokenOver(item: DraggableItem.Token, moveOverItem: DraggableItem): Boolean {
|
||||
// Token item can be moved only in its group
|
||||
return when (moveOverItem) {
|
||||
is DraggableItem.GroupHeader -> false // Token item can not be moved to group item
|
||||
is DraggableItem.Token -> item.groupId == moveOverItem.groupId // Token item can not be moved over its group
|
||||
|
|
@ -52,4 +54,129 @@ internal fun PersistentList<DraggableItem>.moveItem(fromIndex: Int, toIndex: Int
|
|||
return this
|
||||
.removeAt(fromIndex)
|
||||
.add(toIndex, fromItem)
|
||||
}
|
||||
|
||||
internal fun List<DraggableItem>.divideItems(movingItem: DraggableItem): List<DraggableItem> {
|
||||
return this.map {
|
||||
it
|
||||
.roundingMode(DraggableItem.RoundingMode.All(showGap = true))
|
||||
.showShadow(show = it.id == movingItem.id)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun List<DraggableItem>.uniteItems(): List<DraggableItem> {
|
||||
val lastItemIndex = this.lastIndex
|
||||
return this.mapIndexed { index, item ->
|
||||
val mode = when (index) {
|
||||
0 -> DraggableItem.RoundingMode.Top()
|
||||
lastItemIndex -> DraggableItem.RoundingMode.Bottom()
|
||||
else -> DraggableItem.RoundingMode.None
|
||||
}
|
||||
|
||||
item
|
||||
.roundingMode(mode)
|
||||
.showShadow(show = false)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Move to domain
|
||||
@Volatile
|
||||
private var groupIdToTokens: Map<String, List<DraggableItem.Token>>? = null
|
||||
|
||||
internal fun List<DraggableItem>.collapseGroup(group: DraggableItem.GroupHeader): List<DraggableItem> {
|
||||
if (!groupIdToTokens.isNullOrEmpty()) return this
|
||||
|
||||
groupIdToTokens = this
|
||||
.asSequence()
|
||||
.filterIsInstance<DraggableItem.Token>()
|
||||
.groupBy { it.groupId }
|
||||
|
||||
return this
|
||||
.filterNot { it is DraggableItem.Token && it.groupId == group.id }
|
||||
.divideGroups(group)
|
||||
}
|
||||
|
||||
internal fun List<DraggableItem>.expandGroups(): List<DraggableItem> {
|
||||
if (groupIdToTokens.isNullOrEmpty()) return this
|
||||
|
||||
val currentGroups = this.filterIsInstance<DraggableItem.GroupHeader>()
|
||||
val lastGroupIndex = currentGroups.lastIndex
|
||||
|
||||
return currentGroups
|
||||
.flatMapIndexed { index, group ->
|
||||
buildList {
|
||||
add(group)
|
||||
addAll(groupIdToTokens?.get(group.id).orEmpty())
|
||||
if (index != lastGroupIndex) {
|
||||
add(DraggableItem.GroupPlaceholder(id = "group_divider_$index"))
|
||||
}
|
||||
}
|
||||
}
|
||||
.uniteItems()
|
||||
.also { groupIdToTokens = null }
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the correct [DraggableItem.RoundingMode] and shadow status to each item in the list,
|
||||
* based on the relationship of each item to the [movingItem] and its position in the list.
|
||||
*
|
||||
* @param movingItem The item that is being dragged/moved.
|
||||
* @return A list of [DraggableItem]s with updated rounding modes and shadow statuses.
|
||||
*/
|
||||
internal fun List<DraggableItem>.divideGroups(movingItem: DraggableItem): List<DraggableItem> {
|
||||
val lastItemIndex = this.lastIndex
|
||||
|
||||
return this.mapIndexed { index, item ->
|
||||
when {
|
||||
// Case when current item is the moving item
|
||||
item.id == movingItem.id -> {
|
||||
item
|
||||
.roundingMode(DraggableItem.RoundingMode.All(showGap = true))
|
||||
.showShadow(show = true)
|
||||
}
|
||||
// Case when moving item is a token and current item is the group of the moving token
|
||||
movingItem is DraggableItem.Token && item.id == movingItem.groupId -> {
|
||||
item
|
||||
.roundingMode(DraggableItem.RoundingMode.All(showGap = true))
|
||||
.showShadow(show = true)
|
||||
}
|
||||
// Case when both moving item and current item are tokens and belong to the same group
|
||||
movingItem is DraggableItem.Token &&
|
||||
item is DraggableItem.Token && item.groupId == movingItem.groupId -> {
|
||||
item
|
||||
.roundingMode(DraggableItem.RoundingMode.All(showGap = true))
|
||||
.showShadow(show = false)
|
||||
}
|
||||
// Case when current item is the first item in the list
|
||||
index == 0 -> {
|
||||
item
|
||||
.roundingMode(DraggableItem.RoundingMode.Top())
|
||||
.showShadow(show = false)
|
||||
}
|
||||
// Case when current item is the last item in the list
|
||||
index == lastItemIndex -> {
|
||||
item
|
||||
.roundingMode(DraggableItem.RoundingMode.Bottom())
|
||||
.showShadow(show = false)
|
||||
}
|
||||
// Case when previous item is a GroupPlaceholder
|
||||
this[index - 1] is DraggableItem.GroupPlaceholder -> {
|
||||
item
|
||||
.roundingMode(DraggableItem.RoundingMode.Top(showGap = true))
|
||||
.showShadow(show = false)
|
||||
}
|
||||
// Case when next item is a GroupPlaceholder
|
||||
this[index + 1] is DraggableItem.GroupPlaceholder -> {
|
||||
item
|
||||
.roundingMode(DraggableItem.RoundingMode.Bottom(showGap = true))
|
||||
.showShadow(show = false)
|
||||
}
|
||||
// Default case when none of the above conditions are met
|
||||
else -> {
|
||||
item
|
||||
.roundingMode(DraggableItem.RoundingMode.None)
|
||||
.showShadow(show = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue