From b27149edaf51d2fc5e28124d47fb0230e1d05bf2 Mon Sep 17 00:00:00 2001 From: "Andres Gomez, Thomas (ITDV RL)" Date: Tue, 20 Aug 2024 14:54:32 +0200 Subject: [PATCH] Remove old drag&drop code. --- .../screens/character/CharacterSheetScreen.kt | 18 +- .../preview/rememberInventoryListState.kt | 176 --------- .../factory/InventoryItemUioFactory.kt | 19 - .../pages/inventory/InventoryPage.kt | 3 +- .../draggable/InventoryDragDropState.kt | 4 +- .../inventory/item_list/ItemListViewModel.kt | 1 + .../inventory_OLD/InventoryControllerOLD.kt | 145 -------- .../inventory_OLD/InventoryItemUioOLD.kt | 192 ---------- .../pages/inventory_OLD/InventoryPageOLD.kt | 260 ------------- .../inventory_OLD/InventoryViewModelOLD.kt | 127 ------- .../utilitary/LazyGrid+DragAndDrop.kt | 342 ------------------ .../detectDragGesturesAfterLongPress.kt | 55 --- 12 files changed, 18 insertions(+), 1324 deletions(-) delete mode 100644 app/src/main/java/com/pixelized/rplexicon/ui/screens/character/composable/preview/rememberInventoryListState.kt delete mode 100644 app/src/main/java/com/pixelized/rplexicon/ui/screens/character/factory/InventoryItemUioFactory.kt delete mode 100644 app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory_OLD/InventoryControllerOLD.kt delete mode 100644 app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory_OLD/InventoryItemUioOLD.kt delete mode 100644 app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory_OLD/InventoryPageOLD.kt delete mode 100644 app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory_OLD/InventoryViewModelOLD.kt delete mode 100644 app/src/main/java/com/pixelized/rplexicon/utilitary/LazyGrid+DragAndDrop.kt delete mode 100644 app/src/main/java/com/pixelized/rplexicon/utilitary/lazyGridDragAndDrop/detectDragGesturesAfterLongPress.kt diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/CharacterSheetScreen.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/CharacterSheetScreen.kt index 4a39699..c6f066c 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/CharacterSheetScreen.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/CharacterSheetScreen.kt @@ -59,7 +59,6 @@ import com.pixelized.rplexicon.NO_WINDOW_INSETS import com.pixelized.rplexicon.R import com.pixelized.rplexicon.ui.composable.KeepOnScreen import com.pixelized.rplexicon.ui.composable.Loader -import com.pixelized.rplexicon.ui.screens.rolls.RollResult import com.pixelized.rplexicon.ui.composable.Toolbar import com.pixelized.rplexicon.ui.composable.edit.HandleHitPointEditDialog import com.pixelized.rplexicon.ui.composable.edit.HandleSkillEditDialog @@ -84,12 +83,15 @@ import com.pixelized.rplexicon.ui.screens.character.pages.actions.SpellsViewMode import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationPage import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationPagePreview import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationViewModel -import com.pixelized.rplexicon.ui.screens.character.pages.inventory.InventoryPage2 +import com.pixelized.rplexicon.ui.screens.character.pages.inventory.InventoryPage import com.pixelized.rplexicon.ui.screens.character.pages.inventory.InventoryPreview -import com.pixelized.rplexicon.ui.screens.character.pages.inventory_OLD.InventoryViewModelOLD +import com.pixelized.rplexicon.ui.screens.character.pages.inventory.InventoryViewModel +import com.pixelized.rplexicon.ui.screens.character.pages.inventory.item_detail.ItemDetailViewModel +import com.pixelized.rplexicon.ui.screens.character.pages.inventory.item_list.ItemListViewModel import com.pixelized.rplexicon.ui.screens.character.pages.proficiency.ProficiencyPage import com.pixelized.rplexicon.ui.screens.character.pages.proficiency.ProficiencyPreview import com.pixelized.rplexicon.ui.screens.character.pages.proficiency.ProficiencyViewModel +import com.pixelized.rplexicon.ui.screens.rolls.RollResult import com.pixelized.rplexicon.ui.theme.LexiconTheme import com.pixelized.rplexicon.utilitary.extentions.modifier.lexiconShadow import kotlinx.coroutines.launch @@ -109,7 +111,9 @@ enum class CharacterTabUio(@StringRes val label: Int) { @Composable fun CharacterSheetScreen( viewModel: CharacterSheetViewModel = hiltViewModel(), - inventoryViewModel: InventoryViewModelOLD = hiltViewModel(), + inventoryViewModel: InventoryViewModel = hiltViewModel(), + itemListViewModel: ItemListViewModel = hiltViewModel(), + itemDetailViewModel: ItemDetailViewModel = hiltViewModel(), proficiencyViewModel: ProficiencyViewModel = hiltViewModel(), headerViewModel: HeaderViewModel = hiltViewModel(), attacksViewModel: AttacksViewModel = hiltViewModel(), @@ -202,7 +206,11 @@ fun CharacterSheetScreen( ) }, inventory = { - InventoryPage2() + InventoryPage( + inventoryViewModel = inventoryViewModel, + itemListViewModel = itemListViewModel, + itemDetailViewModel = itemDetailViewModel, + ) }, sheet = { SpellLevelChooser( diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/composable/preview/rememberInventoryListState.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/composable/preview/rememberInventoryListState.kt deleted file mode 100644 index 3b4fbe0..0000000 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/composable/preview/rememberInventoryListState.kt +++ /dev/null @@ -1,176 +0,0 @@ -package com.pixelized.rplexicon.ui.screens.character.composable.preview - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.Stable -import androidx.compose.runtime.State -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import com.pixelized.rplexicon.R -import com.pixelized.rplexicon.data.model.item.InventoryPath -import com.pixelized.rplexicon.ui.screens.character.pages.inventory_OLD.InventoryItemUioOLD - -@Composable -@Stable -fun rememberInventoryListState(): State> { - return remember { - var id = 0 - mutableStateOf( - listOf( - InventoryItemUioOLD( - id = "${id++}", - path = InventoryPath.ROOT, - name = "Pouch", - context = null, - amount = 1, - items = 3, - container = true, - usable = false, - icon = R.drawable.icbg_pouch_a_unfaded, - ), - InventoryItemUioOLD( - id = "${id++}", - path = InventoryPath.ROOT, - name = "Backpack", - context = null, - amount = 1, - items = 6, - container = true, - usable = false, - icon = R.drawable.icbg_backpack_a_unfaded, - ), - InventoryItemUioOLD( - id = "${id++}", - path = InventoryPath.ROOT, - name = "Scroll of blessing", - context = null, - amount = 1, - items = 0, - container = false, - usable = true, - icon = R.drawable.icbg_scroll_of_bless_unfaded, - ), - InventoryItemUioOLD( - id = "${id++}", - path = InventoryPath.ROOT, - name = "Scroll of spirit weapon", - context = null, - amount = 1, - items = 0, - container = false, - usable = true, - icon = R.drawable.icbg_book_signedtradebisa_unfaded, - ), - InventoryItemUioOLD( - id = "${id++}", - path = InventoryPath.ROOT, - name = "Potion of healing", - context = null, - amount = 2, - items = 0, - container = false, - usable = true, - icon = R.drawable.icbg_potion_of_superior_healing_unfaded, - ), - InventoryItemUioOLD( - id = "${id++}", - path = InventoryPath.ROOT, - name = "Potion of supĂ©rior healing", - context = null, - amount = 2, - items = 0, - container = false, - usable = true, - icon = R.drawable.icbg_pot_potion_of_healing_unfaded, - ), - InventoryItemUioOLD( - id = "${id++}", - path = InventoryPath.ROOT, - name = "Potion of holy water", - context = null, - amount = 2, - items = 0, - container = false, - usable = true, - icon = R.drawable.icbg_grn_holy_water_unfaded, - ), - InventoryItemUioOLD( - id = "${id++}", - path = InventoryPath.ROOT, - name = "Leather armor", - context = null, - amount = 1, - items = 0, - container = false, - usable = false, - icon = R.drawable.icbg_leather_armour_rogue_unfaded, - ), - InventoryItemUioOLD( - id = "${id++}", - path = InventoryPath.ROOT, - name = "Silver battleaxe", - context = null, - amount = 1, - items = 0, - container = false, - usable = false, - icon = R.drawable.icbg_battleaxe_plus_one_unfaded, - ), - InventoryItemUioOLD( - id = "${id++}", - path = InventoryPath.ROOT, - name = "Hand crossbow", - context = null, - amount = 1, - items = 0, - container = false, - usable = false, - icon = R.drawable.icbg_hand_crossbow_unfaded, - ), - InventoryItemUioOLD( - id = "${id++}", - path = InventoryPath.ROOT, - name = "Goodberry", - context = null, - amount = 1, - items = 0, - container = false, - usable = false, - icon = R.drawable.icbg_food_goodberry_unfaded, - ), - InventoryItemUioOLD( - id = "${id++}", - path = InventoryPath.ROOT, - name = "Wolf fang", - context = null, - amount = 1, - items = 0, - container = false, - usable = false, - icon = R.drawable.icbg_worg_fang_unfaded, - ), - InventoryItemUioOLD( - id = "${id++}", - path = InventoryPath.ROOT, - name = "Lantern of revealing", - context = null, - amount = 1, - items = 0, - container = false, - usable = false, - icon = R.drawable.ic_drive_lantern_of_revealing, - ), - InventoryItemUioOLD( - id = "${id++}", - path = InventoryPath.ROOT, - name = "Dust of disappearance", - context = null, - amount = 1, - items = 0, - container = false, - usable = false, - icon = R.drawable.icbg_haste_spore_grenade_unfaded, - ), - ) - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/factory/InventoryItemUioFactory.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/factory/InventoryItemUioFactory.kt deleted file mode 100644 index 5cc8248..0000000 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/factory/InventoryItemUioFactory.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.pixelized.rplexicon.ui.screens.character.factory - -import com.pixelized.rplexicon.data.model.item.InventoryPath -import com.pixelized.rplexicon.data.model.item.Item -import com.pixelized.rplexicon.data.network.FireItemDto -import com.pixelized.rplexicon.ui.screens.character.pages.inventory_OLD.InventoryItemUioOLD -import javax.inject.Inject - -class InventoryItemUioFactory @Inject constructor() { - - @Deprecated(message = "") - fun toUio( - items: Map, - fires: List, - path: InventoryPath, - ): List { - return emptyList() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/InventoryPage.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/InventoryPage.kt index 64f638a..cde397b 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/InventoryPage.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/InventoryPage.kt @@ -63,7 +63,7 @@ import kotlinx.coroutines.launch @Composable -fun InventoryPage2( +fun InventoryPage( inventoryViewModel: InventoryViewModel = hiltViewModel(), itemListViewModel: ItemListViewModel = hiltViewModel(), itemDetailViewModel: ItemDetailViewModel = hiltViewModel(), @@ -92,6 +92,7 @@ fun InventoryPage2( } }, ) + Surface( modifier = Modifier.fillMaxSize() ) { diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/composable/draggable/InventoryDragDropState.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/composable/draggable/InventoryDragDropState.kt index 8607d3e..d5e4b1c 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/composable/draggable/InventoryDragDropState.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/composable/draggable/InventoryDragDropState.kt @@ -2,6 +2,7 @@ package com.pixelized.rplexicon.ui.screens.character.pages.inventory.composable. import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.VectorConverter +import androidx.compose.foundation.gestures.detectDragGesturesAfterLongPress import androidx.compose.foundation.lazy.grid.LazyGridItemInfo import androidx.compose.foundation.lazy.grid.LazyGridLayoutInfo import androidx.compose.foundation.lazy.grid.LazyGridState @@ -22,7 +23,6 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.toOffset -import com.pixelized.rplexicon.utilitary.lazyGridDragAndDrop.detectDragGesturesAfterLongPress import kotlinx.coroutines.CoroutineScope @Composable @@ -193,7 +193,7 @@ class InventoryDragDropState internal constructor( } } - fun onDragEnd(offset: Offset) { + fun onDragEnd() { val draggedItemTargetOffset = draggedItemOffset() val draggedItemTargetType = type(offset = draggedItemTargetOffset) val layout = layoutInfo(type = draggedItemTargetType) diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/item_list/ItemListViewModel.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/item_list/ItemListViewModel.kt index f0af2c2..ab1fa30 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/item_list/ItemListViewModel.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/item_list/ItemListViewModel.kt @@ -74,6 +74,7 @@ class ItemListViewModel @Inject constructor( } fun show() { + filter.value = "" _display.value = true } diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory_OLD/InventoryControllerOLD.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory_OLD/InventoryControllerOLD.kt deleted file mode 100644 index 541bf4a..0000000 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory_OLD/InventoryControllerOLD.kt +++ /dev/null @@ -1,145 +0,0 @@ -package com.pixelized.rplexicon.ui.screens.character.pages.inventory_OLD - -import com.pixelized.rplexicon.data.model.item.InventoryPath -import com.pixelized.rplexicon.data.model.item.Item -import com.pixelized.rplexicon.data.network.FireItemDto -import com.pixelized.rplexicon.data.repository.character.ItemsRepository -import com.pixelized.rplexicon.data.repository.firebase.inventory.InventoryFireRepository -import com.pixelized.rplexicon.ui.screens.character.factory.InventoryItemUioFactory -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.emptyFlow -import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.launch - -@Deprecated(message = "to be removed") -class InventoryControllerOLD( - private val fireRepository: InventoryFireRepository, - private val itemFactory: InventoryItemUioFactory, - val scope: CoroutineScope, - val character: String, - val path: InventoryPath, - itemsRepository: ItemsRepository, -) { - private val fireCollectorJob: Job - - // Target the local indexes form specific ids (change locally to avoid flooding of firebase) - private val localIndex = MutableStateFlow>(hashMapOf()) - - // Item list flow. this is a the global list of all items. - private val itemsList: StateFlow> = itemsRepository.data - - // Inventory for a specific character in firebase for a specific inventory path. - // This is a flow of ItemDto from firebase and is the source of truth for the data. - private val fireInventory: StateFlow> = emptyFlow>() - // fireRepository.getInventory(character = character, path = path) - .stateIn( - scope = scope, - started = SharingStarted.Eagerly, - initialValue = emptyList(), - ) - - // Inventory for a specific character in firebase for a specific inventory path. - // This consume other flows to create on that is displayable. - // The goal of it is to avoid updating eagerly the firebase data. - val inventory = combine(itemsList, fireInventory, localIndex) { items, fire, indexes -> - itemFactory.toUio(items = items, fires = fire, path = path).sortedBy { indexes[it.id] } - }.stateIn( - scope = scope, - started = SharingStarted.Eagerly, - initialValue = emptyList(), - ) - - init { - fireCollectorJob = scope.launch { - launch(Dispatchers.IO) { -// fireRepository.getInventory(character = character, path = path).collect { items -> -// localIndex.value = items.mapNotNull { -// if (it.id != null) { -// it.id as String to items.indexOf(it) -// } else { -// null -// } -// }.toMap() -// } - } - } - } - - protected fun finalize() { - fireCollectorJob.cancel() - } - - fun onMove( - fromIndex: Int, - toIndex: Int, - ) { - // Item have been moved, need to update the local item index. - // This is call during a drag event to move item in the collection. - // We avoid updating firebase during the drag, we do so on the release (see onDrop(Int)) - localIndex.value = localIndex.value.toMutableMap().also { map -> - val fromId = map.firstNotNullOfOrNull { if (it.value == fromIndex) it.key else null } - val toId = map.firstNotNullOfOrNull { if (it.value == toIndex) it.key else null } - if (fromId != null && toId != null) { - map[fromId] = toIndex - map[toId] = fromIndex - } - } - } - - fun isMoveEnable(fromIndex: Int, toIndex: Int): Boolean { - val isSourceAContainer = inventory.value.getOrNull(fromIndex)?.container ?: false - val isReceiverAContainer = inventory.value.getOrNull(toIndex)?.container ?: false - return !(isSourceAContainer.not() && isReceiverAContainer) - } - - fun onDrop(index: Int) { -// val source = inventory.value.getOrNull(index) -// val fireIndex = fireInventory.value.indexOfFirst { it.id == source?.id } -// -// val inventory = fireInventory.value.toMutableList().also { fireInventory -> -// fireInventory.add(index, fireInventory.removeAt(fireIndex)) -// } - -// fireRepository.setInventory( -// character = character, -// path = path, -// inventory = inventory, -// ) - } - - fun onDropOver(fromIndex: Int, toIndex: Int) { -// val source = inventory.value.getOrNull(fromIndex) -// val receiver = inventory.value.getOrNull(toIndex) -// -// if (fromIndex != toIndex && receiver?.container == true) { -// val inventory = fireInventory.value.toMutableList().also { fireInventory -> -// val sourceIndex = fireInventory.indexOfFirst { it.id == source?.id } -// val receiverIndex = fireInventory.indexOfFirst { it.id == receiver.id } -// val sourceFireItem = fireInventory.getOrNull(sourceIndex) -// val receiverFireItem = fireInventory.getOrNull(receiverIndex) -// if (sourceFireItem != null && receiverFireItem != null) { -// fireInventory.set( -// index = receiverIndex, -// element = receiverFireItem.copy( -// children = receiverFireItem.children.toMutableList().also { -// it.add(sourceFireItem) -// }, -// ), -// ) -// fireInventory.remove(element = sourceFireItem) -// } -// } -// fireRepository.setInventory( -// character = character, -// path = path, -// inventory = inventory, -// ) -// } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory_OLD/InventoryItemUioOLD.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory_OLD/InventoryItemUioOLD.kt deleted file mode 100644 index 1c3c65b..0000000 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory_OLD/InventoryItemUioOLD.kt +++ /dev/null @@ -1,192 +0,0 @@ -package com.pixelized.rplexicon.ui.screens.character.pages.inventory_OLD - -import android.content.res.Configuration -import androidx.compose.animation.AnimatedContent -import androidx.compose.animation.SizeTransform -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.animation.slideInVertically -import androidx.compose.animation.slideOutVertically -import androidx.compose.animation.togetherWith -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.aspectRatio -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.offset -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.Stable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.tooling.preview.PreviewParameter -import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import androidx.compose.ui.unit.dp -import com.pixelized.rplexicon.R -import com.pixelized.rplexicon.data.model.item.InventoryPath -import com.pixelized.rplexicon.ui.composable.images.AsyncImage -import com.pixelized.rplexicon.ui.theme.LexiconTheme - -@Stable -@Deprecated(message = "to be removed") -data class InventoryItemUioOLD( - val id: String, - val path: InventoryPath, - val name: String, - val context: String?, - val amount: Int, - val items: Int, - val container: Boolean, - val usable: Boolean, - val icon: Any? = R.drawable.icbg_generic_darkness_icon, -) - -@Composable -@Deprecated(message = "to be removed") -fun InventoryItem( - modifier: Modifier = Modifier, - item: InventoryItemUioOLD, -) { - Box( - modifier = Modifier - .then(other = modifier) - .aspectRatio(ratio = 1f), - ) { - AsyncImage( - modifier = Modifier.matchParentSize(), - model = item.icon, - contentScale = ContentScale.Fit, - ) - AnimatedContent( - modifier = Modifier - .align(alignment = Alignment.TopEnd) - .offset(x = 0.dp, y = (-4).dp) - .padding(horizontal = 2.dp), - targetState = item.items, - transitionSpec = { - // Compare the incoming number with the previous number. - if (targetState > initialState) { - // If the target number is larger, it slides up and fades in - // while the initial (smaller) number slides up and fades out. - slideInVertically { height -> height / 2 } + fadeIn() togetherWith slideOutVertically { height -> -height / 2 } + fadeOut() - } else { - // If the target number is smaller, it slides down and fades in - // while the initial number slides down and fades out. - slideInVertically { height -> -height / 2 } + fadeIn() togetherWith slideOutVertically { height -> height / 2 } + fadeOut() - }.using( - // Disable clipping since the faded slide-in/out should - // be displayed out of bounds. - SizeTransform(clip = false) - ) - }, - label = "Container count size", - ) { items -> - Text( - modifier = Modifier.fillMaxWidth(), - maxLines = 1, - overflow = TextOverflow.Ellipsis, - style = MaterialTheme.typography.bodyLarge, - fontWeight = FontWeight.Bold, - textAlign = TextAlign.End, - text = items.takeIf { it > 0 }?.let { "$it" } ?: " ", //   - ) - } - AnimatedContent( - modifier = Modifier - .align(alignment = Alignment.BottomEnd) - .offset(x = 0.dp, y = 4.dp) - .padding(horizontal = 2.dp), - targetState = item.amount, - transitionSpec = { - // Compare the incoming number with the previous number. - if (targetState > initialState) { - // If the target number is larger, it slides up and fades in - // while the initial (smaller) number slides up and fades out. - slideInVertically { height -> height / 2 } + fadeIn() togetherWith slideOutVertically { height -> -height / 2 } + fadeOut() - } else { - // If the target number is smaller, it slides down and fades in - // while the initial number slides down and fades out. - slideInVertically { height -> -height / 2 } + fadeIn() togetherWith slideOutVertically { height -> height / 2 } + fadeOut() - }.using( - // Disable clipping since the faded slide-in/out should - // be displayed out of bounds. - SizeTransform(clip = false) - ) - }, - label = "Container count size", - ) { amount -> - Text( - modifier = Modifier - .fillMaxWidth() - .graphicsLayer { this.alpha = if (amount == 1) 0f else 1f }, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - style = MaterialTheme.typography.bodyLarge, - fontWeight = FontWeight.Bold, - textAlign = TextAlign.End, - text = amount.takeIf { it > 1 }?.let { "$it" } ?: " ", //   - ) - } - } -} - - -@Composable -@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO, widthDp = 64) -@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, widthDp = 64) -private fun InventoryItemPreview( - @PreviewParameter(ClassInventoryItemProvider::class) preview: InventoryItemUioOLD, -) { - LexiconTheme { - Surface { - InventoryItem( - item = preview, - ) - } - } -} - -private class ClassInventoryItemProvider : PreviewParameterProvider { - override val values: Sequence = sequenceOf( - InventoryItemUioOLD( - id = "0", - path = InventoryPath.ROOT, - name = "Pouch", - context = null, - amount = 1, - items = 1, - usable = false, - container = true, - icon = R.drawable.icbg_pouch_a_unfaded, - ), - InventoryItemUioOLD( - id = "1", - path = InventoryPath.ROOT, - name = "Scroll of blessing", - context = null, - amount = 1, - items = 0, - container = false, - usable = false, - icon = R.drawable.icbg_scroll_of_bless_unfaded, - ), - InventoryItemUioOLD( - id = "2", - path = InventoryPath.ROOT, - name = "Potion of blessing", - context = null, - amount = 2, - items = 0, - container = false, - usable = false, - icon = R.drawable.icbg_pot_potion_of_healing_unfaded, - ), - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory_OLD/InventoryPageOLD.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory_OLD/InventoryPageOLD.kt deleted file mode 100644 index 739957d..0000000 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory_OLD/InventoryPageOLD.kt +++ /dev/null @@ -1,260 +0,0 @@ -package com.pixelized.rplexicon.ui.screens.character.pages.inventory_OLD - -import android.content.res.Configuration.UI_MODE_NIGHT_NO -import android.content.res.Configuration.UI_MODE_NIGHT_YES -import androidx.compose.animation.animateColor -import androidx.compose.animation.core.updateTransition -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.grid.GridCells -import androidx.compose.foundation.lazy.grid.LazyVerticalGrid -import androidx.compose.foundation.lazy.grid.itemsIndexed -import androidx.compose.foundation.lazy.grid.rememberLazyGridState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Add -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.material3.surfaceColorAtElevation -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.compositeOver -import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.pixelized.rplexicon.LocalRollOverlay -import com.pixelized.rplexicon.LocalSnack -import com.pixelized.rplexicon.R -import com.pixelized.rplexicon.data.model.item.InventoryPath -import com.pixelized.rplexicon.ui.composable.FloatingActionButton -import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberInventoryListState -import com.pixelized.rplexicon.ui.screens.character.pages.inventory.item_detail.ItemDetailDialog -import com.pixelized.rplexicon.ui.screens.character.pages.inventory.item_detail.ItemDetailViewModel -import com.pixelized.rplexicon.ui.screens.character.pages.inventory.item_list.ItemListDialog -import com.pixelized.rplexicon.ui.screens.character.pages.inventory.item_list.ItemListViewModel -import com.pixelized.rplexicon.ui.screens.character.pages.inventory.item_list.ItemUio -import com.pixelized.rplexicon.ui.theme.LexiconTheme -import com.pixelized.rplexicon.utilitary.DraggableItem -import com.pixelized.rplexicon.utilitary.dragContainer -import com.pixelized.rplexicon.utilitary.extentions.lexicon -import com.pixelized.rplexicon.utilitary.extentions.modifier.doubleBorder -import com.pixelized.rplexicon.utilitary.rememberGridDragDropState -import kotlinx.coroutines.launch - -@Composable -@Deprecated(message = "to be removed") -fun InventoryPageOLD( - viewModel: InventoryViewModelOLD = hiltViewModel(), - itemViewModel: ItemListViewModel = hiltViewModel(), - detailViewModel: ItemDetailViewModel = hiltViewModel(), -) { - val overlay = LocalRollOverlay.current - val snack = LocalSnack.current - val scope = rememberCoroutineScope() - val path = remember { InventoryPath.ROOT } - val controller = viewModel.controller(path = path) - val rootInventory = viewModel.inventory(controller = controller) - - InventoryPageContent( - modifier = Modifier.fillMaxSize(), - inventory = rootInventory, - onAddItem = itemViewModel::show, - onInventoryItemClick = { item: InventoryItemUioOLD -> -// detailViewModel.show( //TODO -// detail = viewModel.getItemDetail(item = item) -// ) - }, - onInventoryItemMove = controller::onMove, - onInventoryIsMoveEnable = controller::isMoveEnable, - onInventoryItemDrop = controller::onDrop, - onInventoryItemDropOver = controller::onDropOver, - ) - - ItemListDialog( - viewModel = itemViewModel, - onItem = { item: ItemUio -> -// detailViewModel.show( -// detail = viewModel.getItemDetail(item = item) -// ) - }, - onDismissRequest = itemViewModel::hide, - ) - - ItemDetailDialog( - viewModel = detailViewModel, -// onItem = { item -> -// detailViewModel.show( -// detail = viewModel.getItemDetail(item = item) -// ) -// }, - onDismissRequest = { -// viewModel.changeItemQuantity( -// id = detail.id, -// path = detail.path, -// quantity = detail.quantity ?: 0 -// ) -// detailViewModel.hide(detail) - }, - onUse = { detail -> -// detailViewModel.hide(detail) - viewModel.onUse(itemId = detail.id)?.let { diceThrow -> - scope.launch { - overlay.showOverlay(diceThrow = diceThrow) - } - } - } - ) - - LaunchedEffect(key1 = "InventorySnack") { - viewModel.snack.collect { message -> - message?.let { - scope.launch { snack.showSnackbar(message = it) } - } - } - } -} - -@Composable -private fun InventoryPageContent( - modifier: Modifier = Modifier, - inventory: State>, - onAddItem: () -> Unit, - onInventoryItemClick: (InventoryItemUioOLD) -> Unit, - onInventoryItemMove: (Int, Int) -> Unit, - onInventoryIsMoveEnable: (Int, Int) -> Boolean, - onInventoryItemDrop: (Int) -> Unit, - onInventoryItemDropOver: (Int, Int) -> Unit, -) { - val contentPadding = remember { PaddingValues(16.dp) } - val gridState = rememberLazyGridState() - val dragDropState = rememberGridDragDropState( - contentPadding = contentPadding, - gridState = gridState, - onMove = onInventoryItemMove, - isMoveEnable = onInventoryIsMoveEnable, - onDragRelease = onInventoryItemDrop, - onDropReleaseOver = onInventoryItemDropOver, - ) - Box( - modifier = modifier, - ) { - LazyVerticalGrid( - columns = GridCells.Fixed(5), - modifier = Modifier - .graphicsLayer { this.clip = false } - .dragContainer(dragDropState) - .fillMaxSize(), - state = gridState, - contentPadding = contentPadding, - verticalArrangement = Arrangement.spacedBy(8.dp), - horizontalArrangement = Arrangement.spacedBy(8.dp), - ) { - itemsIndexed( - items = inventory.value, - key = { _, item -> item.id }, - ) { index, item -> - DraggableItem( - dragDropState = dragDropState, - index = index - ) { isDragging, isOvering -> - val colorScheme = MaterialTheme.lexicon.colorScheme - val transition = updateTransition( - targetState = isDragging || isOvering, - label = "Dragging transition", - ) - val backgroundColor = transition.animateColor( - label = "Draggable item background color", - ) { - val surface = colorScheme.base.surfaceColorAtElevation(2.dp) - when (it) { - true -> colorScheme.base.primary.copy(alpha = 0.15f) - .compositeOver(surface) - - else -> surface - } - } - val outlineColor = transition.animateColor( - label = "Draggable item outline color", - ) { - when (it) { - true -> colorScheme.base.primary - else -> colorScheme.characterSheet.outlineBorder - } - } - val innerColor = transition.animateColor( - label = "Draggable item inline color", - ) { - when (it) { - true -> colorScheme.base.primary - else -> colorScheme.characterSheet.innerBorder - } - } - Box( - modifier = Modifier.doubleBorder( - backgroundColor = backgroundColor.value, - outline = remember { RoundedCornerShape(8.dp) }, - outlineColor = outlineColor.value, - inner = remember { RoundedCornerShape(6.dp) }, - innerColor = innerColor.value, - ) - ) { - InventoryItem( - modifier = Modifier.clickable { onInventoryItemClick(item) }, - item = item, - ) - } - } - } - } - - FloatingActionButton( - modifier = Modifier - .align(alignment = Alignment.BottomEnd) - .padding(all = 16.dp), - onClick = onAddItem, - expended = true, - icon = { - Icon( - imageVector = Icons.Default.Add, - contentDescription = null, - ) - }, - text = { - Text(text = stringResource(id = R.string.character_sheet__inventory__edit_items_action)) - } - ) - } -} - -@Composable -@Preview(uiMode = UI_MODE_NIGHT_NO) -@Preview(uiMode = UI_MODE_NIGHT_YES) -fun InventoryPagePreview() { - LexiconTheme { - Surface { - InventoryPageContent( - modifier = Modifier.fillMaxSize(), - inventory = rememberInventoryListState(), - onAddItem = { }, - onInventoryItemClick = { }, - onInventoryItemMove = { _, _ -> }, - onInventoryIsMoveEnable = { _, _ -> true }, - onInventoryItemDrop = { _ -> }, - onInventoryItemDropOver = { _, _ -> } - ) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory_OLD/InventoryViewModelOLD.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory_OLD/InventoryViewModelOLD.kt deleted file mode 100644 index 9fd19c8..0000000 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory_OLD/InventoryViewModelOLD.kt +++ /dev/null @@ -1,127 +0,0 @@ -package com.pixelized.rplexicon.ui.screens.character.pages.inventory_OLD - -import android.app.Application -import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect -import androidx.compose.runtime.Stable -import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.remember -import androidx.lifecycle.AndroidViewModel -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.viewModelScope -import com.pixelized.rplexicon.data.model.DiceThrow -import com.pixelized.rplexicon.data.model.item.InventoryPath -import com.pixelized.rplexicon.data.repository.character.DescriptionRepository -import com.pixelized.rplexicon.data.repository.character.ItemsRepository -import com.pixelized.rplexicon.data.repository.firebase.inventory.InventoryFireRepository -import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument -import com.pixelized.rplexicon.ui.screens.character.factory.InventoryItemUioFactory -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.SharedFlow -import javax.inject.Inject - -@HiltViewModel -@Deprecated("to be removed") -class InventoryViewModelOLD @Inject constructor( - private val descriptionRepository: DescriptionRepository, - private val fireRepository: InventoryFireRepository, - private val itemFactory: InventoryItemUioFactory, - private val itemsRepository: ItemsRepository, - savedStateHandle: SavedStateHandle, - application: Application -) : AndroidViewModel(application) { - private val character = savedStateHandle.characterSheetArgument.name - private val controllers = hashMapOf() - - private val _snack = MutableSharedFlow() - val snack: SharedFlow get() = _snack - - @Composable - @Stable - fun controller( - path: InventoryPath, - ): InventoryControllerOLD { - val controller = remember(path) { - InventoryControllerOLD( - fireRepository = fireRepository, - itemsRepository = itemsRepository, - itemFactory = itemFactory, - scope = viewModelScope, - character = character, - path = path, - ) - } - DisposableEffect(key1 = path) { - controllers[path] = controller - onDispose { - controllers.remove(path) - } - } - return controller - } - - // UI data, merge the firebase inventory full data and with the local index and transform it into UIO. - @Composable - @Stable - fun inventory( - controller: InventoryControllerOLD, - ): State> { - return controller.inventory.collectAsState(initial = emptyList()) - } - - fun onUse(itemId: String): DiceThrow? { - val item = itemsRepository.find(id = itemId) - return item?.let { - DiceThrow.Object( - character = character, - itemId = item.id, - itemName = item.name, - ) - } - } - - fun changeItemQuantity( - id: String, - path: InventoryPath?, - quantity: Int, - ) { -// if (path != null) { -// // if path != null then we target an item that is already in the inventory. -// if (quantity > 0) { -// // if the quantity is > 0 then only adjust it. -// fireRepository.setItemQuantity( -// character = character, -// path = path, -// id = id, -// quantity = quantity, -// ) -// } else { -// // need to remove the item from the list & update the position of every elements. -// val root = fireRepository.getInventorySnapshot(character = character) -// val item = root.getItem(path = path) -// val parent = root.getItem(path = path.parent()) -// -// val updatedInventory = (parent?.children ?: root).toMutableList().also { -// it.removeAt(it.indexOf(item)) -// } -// fireRepository.setInventory( -// character = character, -// path = path.parent(), // indexPath.joinToString(separator = "") { "$it/${ItemDto.CHILDREN}/" }, -// inventory = updatedInventory, -// ) -// } -// } else if (quantity > 0) { -// val root = fireRepository.getInventorySnapshot(character = character) -// // path is null, we target an item that is NOT in the list. -// // retrieve the last element of the list and add one after. -// fireRepository.setItemQuantity( -// character = character, -// path = InventoryPath.ROOT.add(root.lastIndex + 1), -// id = id, -// quantity = quantity, -// ) -// } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/rplexicon/utilitary/LazyGrid+DragAndDrop.kt b/app/src/main/java/com/pixelized/rplexicon/utilitary/LazyGrid+DragAndDrop.kt deleted file mode 100644 index ed973c4..0000000 --- a/app/src/main/java/com/pixelized/rplexicon/utilitary/LazyGrid+DragAndDrop.kt +++ /dev/null @@ -1,342 +0,0 @@ -package com.pixelized.rplexicon.utilitary - -import androidx.compose.animation.core.Animatable -import androidx.compose.animation.core.Spring -import androidx.compose.animation.core.VectorConverter -import androidx.compose.animation.core.VisibilityThreshold -import androidx.compose.animation.core.spring -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.gestures.scrollBy -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.lazy.grid.LazyGridItemInfo -import androidx.compose.foundation.lazy.grid.LazyGridItemScope -import androidx.compose.foundation.lazy.grid.LazyGridState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.derivedStateOf -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.rememberUpdatedState -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.geometry.Size -import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.platform.LocalLayoutDirection -import androidx.compose.ui.unit.IntOffset -import androidx.compose.ui.unit.IntSize -import androidx.compose.ui.unit.toOffset -import androidx.compose.ui.unit.toSize -import androidx.compose.ui.zIndex -import com.pixelized.rplexicon.utilitary.lazyGridDragAndDrop.detectDragGesturesAfterLongPress -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.isActive -import kotlinx.coroutines.launch - -/*** - * https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/LazyGridDragAndDropDemo.kt - */ -@Composable -fun rememberGridDragDropState( - contentPadding: PaddingValues, - gridState: LazyGridState, - onMove: (Int, Int) -> Unit, - isMoveEnable: (Int, Int) -> Boolean, - onDragRelease: (Int) -> Unit, - onDropReleaseOver: (Int, Int) -> Unit, -): GridDragDropState { - val density = LocalDensity.current - val layoutDirection = LocalLayoutDirection.current - val scope = rememberCoroutineScope() - val currentOnMove = rememberUpdatedState(newValue = onMove) - val currentIsMoveEnable = rememberUpdatedState(newValue = isMoveEnable) - val currentOnDragRelease = rememberUpdatedState(newValue = onDragRelease) - val currentOnDropReleaseOver = rememberUpdatedState(newValue = onDropReleaseOver) - - val state = remember(gridState, scope, currentOnMove) { - GridDragDropState( - contentOffset = with(density) { - Offset( - contentPadding.calculateTopPadding().toPx(), - contentPadding.calculateLeftPadding(layoutDirection).toPx() - ) - }, - scope = scope, - state = gridState, - onMove = currentOnMove.value, - isMoveEnable = currentIsMoveEnable.value, - onDragRelease = currentOnDragRelease.value, - onDropReleaseOver = currentOnDropReleaseOver.value, - ) - } - - LaunchedEffect(state) { - while (isActive) { - val diff = state.scrollChannel.receive() - gridState.scrollBy(diff) - } - } - - return state -} - -class GridDragDropState internal constructor( - private val contentOffset: Offset, - private val scope: CoroutineScope, - private val state: LazyGridState, - private val onMove: (Int, Int) -> Unit, - private val isMoveEnable: (Int, Int) -> Boolean, - private val onDragRelease: (Int) -> Unit, - private val onDropReleaseOver: (Int, Int) -> Unit, -) { - internal val scrollChannel = Channel() - - var overItemIndex by mutableStateOf(null) - private set - - private var previousItemIndex by mutableStateOf(null) - - var draggingItemIndex by mutableStateOf(null) - private set - - internal var draggingItemLingeringIndex by mutableStateOf(null) - private set - - private var draggingItemInitialOffset by mutableStateOf(Offset.Zero) - - private var draggingItemDraggedDelta by mutableStateOf(Offset.Zero) - - private val draggingItemLayoutInfo: LazyGridItemInfo? - get() = state.layoutInfo.visibleItemsInfo - .firstOrNull { it.index == draggingItemIndex } - - internal val draggingItemOffset: Offset - get() = draggingItemLayoutInfo - ?.let { item -> draggingItemInitialOffset + draggingItemDraggedDelta - item.offset.toOffset() } - ?: Offset.Zero - - internal var draggingItemSetIntoPositionAnimation = - Animatable(initialValue = Offset.Zero, typeConverter = Offset.VectorConverter) - private set - - internal fun onDragStart(offset: Offset) { - state.layoutInfo.visibleItemsInfo - .firstItemWithOffsetOrNull(offset = offset) - ?.let { - draggingItemIndex = it.index - draggingItemInitialOffset = it.offset.toOffset() - } - } - - internal fun onDrag(offset: Offset) { - draggingItemDraggedDelta += offset - - val draggingItem = draggingItemLayoutInfo ?: return - val startOffset = draggingItem.offset.toOffset() + draggingItemOffset - val endOffset = startOffset + draggingItem.size.toSize() - - val middleOffset = startOffset + (endOffset - startOffset) / 2f - val middleXOffset = middleOffset.x.toInt() - val middleYOffset = middleOffset.y.toInt() - - val targetItem = state.layoutInfo.visibleItemsInfo.find { item -> - draggingItem.index != item.index && - item.offset.x <= middleXOffset && middleXOffset <= item.offsetEnd.x && - item.offset.y <= middleYOffset && middleYOffset <= item.offsetEnd.y - } - if (targetItem != null) { - if (isMoveEnable.invoke(draggingItem.index, targetItem.index)) { - onMove.invoke(draggingItem.index, targetItem.index) - previousItemIndex = draggingItemIndex - draggingItemIndex = targetItem.index - } else { - previousItemIndex = null - overItemIndex = targetItem.index - } - } else { - overItemIndex = null - val overscroll = when { - draggingItemDraggedDelta.y > 0 -> - (endOffset.y - state.layoutInfo.viewportEndOffset).coerceAtLeast(0f) - - draggingItemDraggedDelta.y < 0 -> - (startOffset.y - state.layoutInfo.viewportStartOffset).coerceAtMost(0f) - - else -> 0f - } - if (overscroll != 0f) { - scrollChannel.trySend(overscroll) - } - } - } - - internal fun onDragInterrupted(offset: Offset) { - val localDraggingItemIndex = draggingItemIndex - - if (localDraggingItemIndex != null) { - val target = state.layoutInfo.visibleItemsInfo.firstItemWithOffsetOrNull(offset) - when { - target == null && previousItemIndex != draggingItemIndex -> { - // release have occur on the current place of the item but outside of range - onDragRelease(localDraggingItemIndex) - // play a animation so the item fit in place. - draggingItemLingeringIndex = draggingItemIndex - val startOffset = draggingItemOffset - scope.launch { - draggingItemSetIntoPositionAnimation.snapTo(targetValue = startOffset) - draggingItemSetIntoPositionAnimation.animateTo( - targetValue = Offset.Zero, - animationSpec = spring( - stiffness = Spring.StiffnessMediumLow, - visibilityThreshold = Offset.VisibilityThreshold - ) - ) - draggingItemLingeringIndex = null - } - } - - target == null -> { - // release have occur outside valid range. play and animation the make the item go back in place. - draggingItemLingeringIndex = draggingItemIndex - val startOffset = draggingItemOffset - scope.launch { - draggingItemSetIntoPositionAnimation.snapTo(targetValue = startOffset) - draggingItemSetIntoPositionAnimation.animateTo( - targetValue = Offset.Zero, - animationSpec = spring( - stiffness = Spring.StiffnessMediumLow, - visibilityThreshold = Offset.VisibilityThreshold - ) - ) - draggingItemLingeringIndex = null - } - } - - target.index == localDraggingItemIndex -> { - // release have occur on the current place of the item - onDragRelease(localDraggingItemIndex) - // play a animation so the item fit in place. - draggingItemLingeringIndex = draggingItemIndex - val startOffset = draggingItemOffset - scope.launch { - draggingItemSetIntoPositionAnimation.snapTo(targetValue = startOffset) - draggingItemSetIntoPositionAnimation.animateTo( - targetValue = Offset.Zero, - animationSpec = spring( - stiffness = Spring.StiffnessMediumLow, - visibilityThreshold = Offset.VisibilityThreshold - ) - ) - draggingItemLingeringIndex = null - } - } - - target.index != localDraggingItemIndex -> { - onDropReleaseOver(localDraggingItemIndex, target.index) - } - } - } - previousItemIndex = null - overItemIndex = null - draggingItemDraggedDelta = Offset.Zero - draggingItemIndex = null - draggingItemInitialOffset = Offset.Zero - } - - private fun List.firstItemWithOffsetOrNull( - offset: Offset, - ): LazyGridItemInfo? { - val offsetX = offset.x.toInt() - contentOffset.x.toInt() - val offsetY = offset.y.toInt() - contentOffset.y.toInt() - return this.firstOrNull { item -> - item.offset.x <= offsetX && offsetX <= item.offsetEnd.x && - item.offset.y <= offsetY && offsetY <= item.offsetEnd.y - } - } - - private val LazyGridItemInfo.offsetEnd: IntOffset - get() = this.offset + this.size -} - -private operator fun IntOffset.plus(size: IntSize): IntOffset { - return IntOffset(x + size.width, y + size.height) -} - -private operator fun Offset.plus(size: Size): Offset { - return Offset(x + size.width, y + size.height) -} - -fun Modifier.dragContainer(dragDropState: GridDragDropState): Modifier { - return this then Modifier.pointerInput(dragDropState) { - detectDragGesturesAfterLongPress( - onDrag = { change, offset -> - change.consume() - dragDropState.onDrag(offset = offset) - }, - onDragStart = { offset -> - dragDropState.onDragStart(offset) - }, - onDragEnd = { offset -> - dragDropState.onDragInterrupted(offset) - }, - onDragCancel = { - dragDropState.onDragInterrupted(Offset.Zero) - } - ) - } -} - -@OptIn(ExperimentalFoundationApi::class) -@Composable -fun LazyGridItemScope.DraggableItem( - dragDropState: GridDragDropState, - index: Int, - modifier: Modifier = Modifier, - content: @Composable (isDragging: Boolean, isOver: Boolean) -> Unit -) { - val dragging by remember(index, dragDropState) { - derivedStateOf { - index == dragDropState.draggingItemIndex - } - } - val overing by remember(index, dragDropState) { - derivedStateOf { - index == dragDropState.overItemIndex - } - } - val draggingModifier = when { - dragging -> { - Modifier - .zIndex(1f) - .graphicsLayer { - translationX = dragDropState.draggingItemOffset.x - translationY = dragDropState.draggingItemOffset.y - } - } - - index == dragDropState.draggingItemLingeringIndex -> { - Modifier - .zIndex(1f) - .graphicsLayer { - translationX = dragDropState.draggingItemSetIntoPositionAnimation.value.x - translationY = dragDropState.draggingItemSetIntoPositionAnimation.value.y - } - } - - else -> { - Modifier.animateItemPlacement() - } - } - Box( - modifier = modifier.then(draggingModifier), - propagateMinConstraints = true, - ) { - content(dragging, overing) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/rplexicon/utilitary/lazyGridDragAndDrop/detectDragGesturesAfterLongPress.kt b/app/src/main/java/com/pixelized/rplexicon/utilitary/lazyGridDragAndDrop/detectDragGesturesAfterLongPress.kt deleted file mode 100644 index 8fc447c..0000000 --- a/app/src/main/java/com/pixelized/rplexicon/utilitary/lazyGridDragAndDrop/detectDragGesturesAfterLongPress.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.pixelized.rplexicon.utilitary.lazyGridDragAndDrop - -import androidx.compose.foundation.gestures.awaitEachGesture -import androidx.compose.foundation.gestures.awaitFirstDown -import androidx.compose.foundation.gestures.awaitLongPressOrCancellation -import androidx.compose.foundation.gestures.drag -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.input.pointer.PointerInputChange -import androidx.compose.ui.input.pointer.PointerInputScope -import androidx.compose.ui.input.pointer.changedToUp -import androidx.compose.ui.input.pointer.positionChange -import androidx.compose.ui.util.fastForEach -import kotlinx.coroutines.CancellationException - -suspend fun PointerInputScope.detectDragGesturesAfterLongPress( - onDragStart: (Offset) -> Unit = { }, - onDragEnd: (Offset) -> Unit = { }, - onDragCancel: () -> Unit = { }, - onDrag: (change: PointerInputChange, dragAmount: Offset) -> Unit -) { - awaitEachGesture { - try { - // await for a press - val down = awaitFirstDown(requireUnconsumed = false) - // await for a long press or a cancellation - val drag = awaitLongPressOrCancellation(pointerId = down.id) - // if the user did a long press - if (drag != null) { - // callback onDragStart with the initial position. - onDragStart.invoke(drag.position) - var lastDragInput: PointerInputChange = drag - val dragEnded = drag( - pointerId = drag.id, - onDrag = { input -> - lastDragInput = input - onDrag(input, input.positionChange()) - input.consume() - } - ) - if (dragEnded) { - // consume up if we quit drag gracefully with the up - currentEvent.changes.fastForEach { - if (it.changedToUp()) it.consume() - } - onDragEnd(lastDragInput.position) - } else { - onDragCancel() - } - } - } catch (c: CancellationException) { - onDragCancel() - throw c - } - } -} \ No newline at end of file