tldraw/state/commands/move-to-page.ts

154 lines
4.4 KiB
TypeScript
Raw Normal View History

2021-06-10 09:49:16 +00:00
import Command from './command'
import history from '../history'
import { Data } from 'types'
import {
getDocumentBranch,
getPage,
getPageState,
getSelectedIds,
setToArray,
uniqueArray,
} from 'utils/utils'
2021-06-21 21:35:28 +00:00
import { getShapeUtils } from 'state/shape-utils'
2021-06-10 09:49:16 +00:00
import storage from 'state/storage'
2021-06-21 21:35:28 +00:00
export default function moveToPageCommand(data: Data, newPageId: string): void {
2021-06-10 10:33:24 +00:00
const { currentPageId: oldPageId } = data
const oldPage = getPage(data)
2021-06-10 09:49:16 +00:00
const selectedIds = setToArray(getSelectedIds(data))
2021-06-10 10:33:24 +00:00
const idsToMove = uniqueArray(
...selectedIds.flatMap((id) => getDocumentBranch(data, id))
2021-06-10 09:49:16 +00:00
)
2021-06-10 10:33:24 +00:00
const oldParentIds = Object.fromEntries(
idsToMove.map((id) => [id, oldPage.shapes[id].parentId])
)
// const selectedParents = uniqueArray(
// ...selectedIds.map((id) => getTopParentId(data, id))
// )
2021-06-10 09:49:16 +00:00
history.execute(
data,
new Command({
2021-06-19 17:22:46 +00:00
name: 'move_to_page',
2021-06-10 09:49:16 +00:00
category: 'canvas',
manualSelection: true,
do(data) {
2021-06-10 10:33:24 +00:00
const fromPageId = oldPageId
const toPageId = newPageId
2021-06-10 09:49:16 +00:00
const fromPage = getPage(data, fromPageId)
// Get all of the selected shapes and their descendents
2021-06-10 10:33:24 +00:00
const shapesToMove = idsToMove.map((id) => fromPage.shapes[id])
shapesToMove.forEach((shape) => {
// If the shape is a parent of a group that isn't selected,
// remove the shape's id from its parent's children.
if (
shape.parentId !== fromPageId &&
!idsToMove.includes(shape.parentId)
) {
const parent = fromPage.shapes[shape.parentId]
getShapeUtils(parent).setProperty(
parent,
'children',
parent.children.filter((id) => id !== shape.id)
)
}
2021-06-10 09:49:16 +00:00
2021-06-10 10:33:24 +00:00
// Delete the shapes from the "from" page
delete fromPage.shapes[shape.id]
})
2021-06-10 09:49:16 +00:00
// Clear the current page state's selected ids
getPageState(data, fromPageId).selectedIds.clear()
// Save the "from" page
storage.savePage(data, data.document.id, fromPageId)
2021-06-10 09:49:16 +00:00
// Load the "to" page
storage.loadPage(data, toPageId)
// The page we're moving the shapes to
const toPage = getPage(data, toPageId)
2021-06-10 10:33:24 +00:00
// Add all of the selected shapes to the "from" page.
2021-06-10 09:49:16 +00:00
shapesToMove.forEach((shape) => {
toPage.shapes[shape.id] = shape
2021-06-10 10:33:24 +00:00
})
// If a shape's parent isn't in the document, re-parent to the page.
shapesToMove.forEach((shape) => {
if (!toPage.shapes[shape.parentId]) {
2021-06-10 09:49:16 +00:00
getShapeUtils(shape).setProperty(shape, 'parentId', toPageId)
}
})
// Select the selected ids on the new page
getPageState(data, toPageId).selectedIds = new Set(selectedIds)
// Move to the new page
data.currentPageId = toPageId
},
undo(data) {
2021-06-10 10:33:24 +00:00
const fromPageId = newPageId
const toPageId = oldPageId
2021-06-10 09:49:16 +00:00
2021-06-10 10:33:24 +00:00
const fromPage = getPage(data, fromPageId)
2021-06-10 09:49:16 +00:00
2021-06-10 10:33:24 +00:00
const shapesToMove = idsToMove.map((id) => fromPage.shapes[id])
2021-06-10 09:49:16 +00:00
2021-06-10 10:33:24 +00:00
shapesToMove.forEach((shape) => {
if (
shape.parentId !== fromPageId &&
!idsToMove.includes(shape.parentId)
) {
const parent = fromPage.shapes[shape.parentId]
getShapeUtils(parent).setProperty(
parent,
'children',
parent.children.filter((id) => id !== shape.id)
)
}
2021-06-10 09:49:16 +00:00
2021-06-10 10:33:24 +00:00
delete fromPage.shapes[shape.id]
})
2021-06-10 09:49:16 +00:00
2021-06-10 10:33:24 +00:00
getPageState(data, fromPageId).selectedIds.clear()
2021-06-10 09:49:16 +00:00
storage.savePage(data, data.document.id, fromPageId)
2021-06-10 10:33:24 +00:00
storage.loadPage(data, toPageId)
const toPage = getPage(data, toPageId)
2021-06-10 09:49:16 +00:00
shapesToMove.forEach((shape) => {
2021-06-10 10:33:24 +00:00
toPage.shapes[shape.id] = shape
// Move shapes back to their old parent
const parentId = oldParentIds[shape.id]
getShapeUtils(shape).setProperty(shape, 'parentId', parentId)
// And add the shape back to the parent's children
if (parentId !== toPageId) {
const parent = toPage.shapes[parentId]
getShapeUtils(parent).setProperty(parent, 'children', [
...parent.children,
shape.id,
])
2021-06-10 09:49:16 +00:00
}
})
2021-06-10 10:33:24 +00:00
getPageState(data, toPageId).selectedIds = new Set(selectedIds)
2021-06-10 09:49:16 +00:00
2021-06-10 10:33:24 +00:00
data.currentPageId = toPageId
2021-06-10 09:49:16 +00:00
},
})
)
}