Ensure order of selected tiles is kept when moving them

This commit is contained in:
Mitchell McCaffrey 2021-05-27 17:19:36 +10:00
parent dd130a008e
commit 69eafb868c
8 changed files with 64 additions and 41 deletions

View File

@ -66,7 +66,6 @@ function MapTiles({ maps, onMapEdit, onMapSelect, subgroup, columns }) {
onTileSelect={onGroupSelect}
disableGrouping={subgroup}
openGroupId={openGroupId}
columns={columns}
/>
);
}

View File

@ -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)

View File

@ -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}
</Grid>

View File

@ -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}

View File

@ -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}
/>
);
}

View File

@ -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

View File

@ -259,21 +259,19 @@ function SelectMapModal({
onGroupsSelect={setSelectedGroupIds}
disabled={!isOpen}
>
<TilesContainer columns={layout.tileGridColumns}>
<TilesContainer>
<MapTiles
maps={maps}
onMapEdit={() => setIsEditModalOpen(true)}
onMapSelect={handleMapSelect}
columns={layout.tileGridColumns}
/>
</TilesContainer>
<TilesOverlay columns={layout.groupGridColumns}>
<TilesOverlay>
<MapTiles
maps={maps}
onMapEdit={() => setIsEditModalOpen(true)}
onMapSelect={handleMapSelect}
subgroup
columns={layout.groupGridColumns}
/>
</TilesOverlay>
</GroupProvider>

View File

@ -200,19 +200,17 @@ function SelectTokensModal({ isOpen, onRequestClose }) {
onGroupsSelect={setSelectedGroupIds}
disabled={!isOpen}
>
<TilesContainer columns={layout.tileGridColumns}>
<TilesContainer>
<TokenTiles
tokens={tokens}
onTokenEdit={() => setIsEditModalOpen(true)}
columns={layout.tileGridColumns}
/>
</TilesContainer>
<TilesOverlay columns={layout.groupGridColumns}>
<TilesOverlay>
<TokenTiles
tokens={tokens}
onTokenEdit={() => setIsEditModalOpen(true)}
subgroup
columns={layout.groupGridColumns}
/>
</TilesOverlay>
</GroupProvider>