From 69eafb868c1b662790c9453c083d6b87100b0bcf Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Thu, 27 May 2021 17:19:36 +1000 Subject: [PATCH] Ensure order of selected tiles is kept when moving them --- src/components/map/MapTiles.js | 1 - src/components/tile/SortableTiles.js | 34 ++++++++++----------- src/components/tile/TilesContainer.js | 4 +-- src/components/tile/TilesOverlay.js | 8 +++-- src/components/token/TokenTiles.js | 3 +- src/helpers/group.js | 43 ++++++++++++++++++++++----- src/modals/SelectMapModal.js | 6 ++-- src/modals/SelectTokensModal.js | 6 ++-- 8 files changed, 64 insertions(+), 41 deletions(-) diff --git a/src/components/map/MapTiles.js b/src/components/map/MapTiles.js index b528686..4cb4be3 100644 --- a/src/components/map/MapTiles.js +++ b/src/components/map/MapTiles.js @@ -66,7 +66,6 @@ function MapTiles({ maps, onMapEdit, onMapSelect, subgroup, columns }) { onTileSelect={onGroupSelect} disableGrouping={subgroup} openGroupId={openGroupId} - columns={columns} /> ); } diff --git a/src/components/tile/SortableTiles.js b/src/components/tile/SortableTiles.js index 1c2095a..0ced96b 100644 --- a/src/components/tile/SortableTiles.js +++ b/src/components/tile/SortableTiles.js @@ -9,11 +9,11 @@ import { useSensors, closestCenter, } from "@dnd-kit/core"; -import { SortableContext, arrayMove } from "@dnd-kit/sortable"; +import { SortableContext } from "@dnd-kit/sortable"; import { animated, useSpring, config } from "react-spring"; import { Badge } from "theme-ui"; -import { moveGroups } from "../../helpers/group"; +import { moveGroupsInto, moveGroups } from "../../helpers/group"; import { keyBy } from "../../helpers/shared"; import Vector2 from "../../helpers/Vector2"; @@ -27,7 +27,6 @@ function SortableTiles({ onTileSelect, disableGrouping, openGroupId, - columns, }) { const mouseSensor = useSensor(MouseSensor, { activationConstraint: { delay: 250, tolerance: 5 }, @@ -60,29 +59,28 @@ function SortableTiles({ return; } + let selectedIndices = selectedGroupIds.map((groupId) => + groups.findIndex((group) => group.id === groupId) + ); + // Maintain current group sorting + selectedIndices = selectedIndices.sort((a, b) => a - b); + if (over.id.startsWith("__group__")) { const overId = over.id.slice(9); if (overId === active.id) { return; } - let newGroups = groups; const overGroupIndex = groups.findIndex((group) => group.id === overId); - const selectedGroupIndices = selectedGroupIds.map((groupId) => - groups.findIndex((group) => group.id === groupId) - ); - onGroupChange( - moveGroups(newGroups, overGroupIndex, selectedGroupIndices) - ); + onGroupChange(moveGroupsInto(groups, overGroupIndex, selectedIndices)); onTileSelect(); - } else if (active.id !== over.id) { - let newGroups = groups; - for (let groupId of selectedGroupIds) { - const oldIndex = newGroups.findIndex((group) => group.id === groupId); - const newIndex = newGroups.findIndex((group) => group.id === over.id); - newGroups = arrayMove(newGroups, oldIndex, newIndex); + } else { + if (active.id === over.id) { + return; } - onGroupChange(newGroups); + + const overGroupIndex = groups.findIndex((group) => group.id === over.id); + onGroupChange(moveGroups(groups, overGroupIndex, selectedIndices)); } } @@ -98,7 +96,7 @@ function SortableTiles({ function renderSortableGroup(group, selectedGroups) { if (overGroupId === group.id && dragId && group.id !== dragId) { // If dragging over a group render a preview of that group - const previewGroup = moveGroups( + const previewGroup = moveGroupsInto( [group, ...selectedGroups], 0, selectedGroups.map((_, i) => i + 1) diff --git a/src/components/tile/TilesContainer.js b/src/components/tile/TilesContainer.js index d5728a2..097c565 100644 --- a/src/components/tile/TilesContainer.js +++ b/src/components/tile/TilesContainer.js @@ -6,7 +6,7 @@ import { useGroup } from "../../contexts/GroupContext"; import useResponsiveLayout from "../../hooks/useResponsiveLayout"; -function TilesContainer({ columns, children }) { +function TilesContainer({ children }) { const { onGroupSelect } = useGroup(); const layout = useResponsiveLayout(); @@ -31,7 +31,7 @@ function TilesContainer({ columns, children }) { overflow: "hidden", }} gap={2} - columns={`repeat(${columns}, 1fr)`} + columns={`repeat(${layout.tileGridColumns}, 1fr)`} > {children} diff --git a/src/components/tile/TilesOverlay.js b/src/components/tile/TilesOverlay.js index 24e35e3..b71ea18 100644 --- a/src/components/tile/TilesOverlay.js +++ b/src/components/tile/TilesOverlay.js @@ -6,9 +6,13 @@ import SimpleBar from "simplebar-react"; import { useGroup } from "../../contexts/GroupContext"; -function TilesOverlay({ columns, children }) { +import useResponsiveLayout from "../../hooks/useResponsiveLayout"; + +function TilesOverlay({ children }) { const { openGroupId, onGroupClose, onGroupSelect } = useGroup(); + const layout = useResponsiveLayout(); + const openAnimation = useSpring({ opacity: openGroupId ? 1 : 0, transform: openGroupId ? "scale(1)" : "scale(0.99)", @@ -88,7 +92,7 @@ function TilesOverlay({ columns, children }) { overflow: "hidden", }} gap={2} - columns={`repeat(${columns}, 1fr)`} + columns={`repeat(${layout.groupGridColumns}, 1fr)`} px={3} > {children} diff --git a/src/components/token/TokenTiles.js b/src/components/token/TokenTiles.js index 6172708..445a44c 100644 --- a/src/components/token/TokenTiles.js +++ b/src/components/token/TokenTiles.js @@ -9,7 +9,7 @@ import { getGroupItems } from "../../helpers/group"; import { useGroup } from "../../contexts/GroupContext"; -function TokenTiles({ tokens, onTokenEdit, subgroup, columns }) { +function TokenTiles({ tokens, onTokenEdit, subgroup }) { const { groups, selectedGroupIds, @@ -71,7 +71,6 @@ function TokenTiles({ tokens, onTokenEdit, subgroup, columns }) { onTileSelect={onGroupSelect} disableGrouping={subgroup} openGroupId={openGroupId} - columns={columns} /> ); } diff --git a/src/helpers/group.js b/src/helpers/group.js index 12345f8..d6a86f0 100644 --- a/src/helpers/group.js +++ b/src/helpers/group.js @@ -99,28 +99,28 @@ export function combineGroups(a, b) { } /** - * Immutably move group at indices `from` into index `to` + * Immutably move group at indices `indices` into group at index `into` * @param {Group[]} groups - * @param {number} to - * @param {number[]} from + * @param {number} into + * @param {number[]} indices * @returns {Group[]} */ -export function moveGroups(groups, to, from) { +export function moveGroupsInto(groups, into, indices) { const newGroups = cloneDeep(groups); - const toGroup = newGroups[to]; + const intoGroup = newGroups[into]; let fromGroups = []; - for (let i of from) { + for (let i of indices) { fromGroups.push(newGroups[i]); } - let combined = toGroup; + let combined = intoGroup; for (let fromGroup of fromGroups) { combined = combineGroups(combined, fromGroup); } // Replace and remove old groups - newGroups[to] = combined; + newGroups[into] = combined; for (let fromGroup of fromGroups) { const i = newGroups.findIndex((group) => group.id === fromGroup.id); newGroups.splice(i, 1); @@ -129,6 +129,33 @@ export function moveGroups(groups, to, from) { return newGroups; } +/** + * Immutably move group at indices `indices` to index `to` + * @param {Group[]} groups + * @param {number} into + * @param {number[]} indices + * @returns {Group[]} + */ +export function moveGroups(groups, to, indices) { + const newGroups = cloneDeep(groups); + + let fromGroups = []; + for (let i of indices) { + fromGroups.push(newGroups[i]); + } + + // Remove old groups + for (let fromGroup of fromGroups) { + const i = newGroups.findIndex((group) => group.id === fromGroup.id); + newGroups.splice(i, 1); + } + + // Add back at new index + newGroups.splice(to, 0, ...fromGroups); + + return newGroups; +} + /** * Recursively find a group within a group array * @param {Group[]} groups diff --git a/src/modals/SelectMapModal.js b/src/modals/SelectMapModal.js index d2ef530..00e3d92 100644 --- a/src/modals/SelectMapModal.js +++ b/src/modals/SelectMapModal.js @@ -259,21 +259,19 @@ function SelectMapModal({ onGroupsSelect={setSelectedGroupIds} disabled={!isOpen} > - + setIsEditModalOpen(true)} onMapSelect={handleMapSelect} - columns={layout.tileGridColumns} /> - + setIsEditModalOpen(true)} onMapSelect={handleMapSelect} subgroup - columns={layout.groupGridColumns} /> diff --git a/src/modals/SelectTokensModal.js b/src/modals/SelectTokensModal.js index 4e7dc40..a515214 100644 --- a/src/modals/SelectTokensModal.js +++ b/src/modals/SelectTokensModal.js @@ -200,19 +200,17 @@ function SelectTokensModal({ isOpen, onRequestClose }) { onGroupsSelect={setSelectedGroupIds} disabled={!isOpen} > - + setIsEditModalOpen(true)} - columns={layout.tileGridColumns} /> - + setIsEditModalOpen(true)} subgroup - columns={layout.groupGridColumns} />