| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- import { Data, GroupShape, Shape, ShapeType } from 'types'
- import * as vec from 'utils/vec'
- import BaseSession from './base-session'
- import commands from 'state/commands'
- import { current } from 'immer'
- import { v4 as uuid } from 'uuid'
- import {
- getChildIndexAbove,
- getPage,
- getSelectedShapes,
- updateParents,
- } from 'utils/utils'
- import { getShapeUtils } from 'lib/shape-utils'
-
- export default class TranslateSession extends BaseSession {
- delta = [0, 0]
- origin: number[]
- snapshot: TranslateSnapshot
- isCloning = false
-
- constructor(data: Data, point: number[]) {
- super(data)
- this.origin = point
- this.snapshot = getTranslateSnapshot(data)
- }
-
- update(data: Data, point: number[], isAligned: boolean, isCloning: boolean) {
- const { currentPageId, clones, initialShapes, initialParents } =
- this.snapshot
- const { shapes } = getPage(data, currentPageId)
-
- const delta = vec.vec(this.origin, point)
-
- if (isAligned) {
- if (Math.abs(delta[0]) < Math.abs(delta[1])) {
- delta[0] = 0
- } else {
- delta[1] = 0
- }
- }
-
- if (isCloning) {
- if (!this.isCloning) {
- this.isCloning = true
- data.selectedIds.clear()
-
- for (const { id, point } of initialShapes) {
- const shape = shapes[id]
- getShapeUtils(shape).translateTo(shape, point)
- }
-
- data.selectedIds.clear()
-
- for (const clone of clones) {
- data.selectedIds.add(clone.id)
- shapes[clone.id] = { ...clone }
- const parent = shapes[clone.parentId]
- if (!parent) continue
- getShapeUtils(parent).setProperty(parent, 'children', [
- ...parent.children,
- clone.id,
- ])
- }
- }
-
- for (const { id, point } of clones) {
- const shape = shapes[id]
- getShapeUtils(shape).translateTo(shape, vec.add(point, delta))
- }
-
- updateParents(
- data,
- clones.map((c) => c.id)
- )
- } else {
- if (this.isCloning) {
- this.isCloning = false
- data.selectedIds.clear()
-
- for (const { id } of initialShapes) {
- data.selectedIds.add(id)
- }
-
- for (const clone of clones) {
- delete shapes[clone.id]
- }
-
- initialParents.forEach(
- (parent) =>
- ((shapes[parent.id] as GroupShape).children = parent.children)
- )
- }
-
- for (const initialShape of initialShapes) {
- const shape = shapes[initialShape.id]
- const next = vec.add(initialShape.point, delta)
- const deltaForShape = vec.sub(next, shape.point)
- getShapeUtils(shape).translateTo(shape, next)
-
- if (shape.type === ShapeType.Group) {
- for (let childId of shape.children) {
- const childShape = shapes[childId]
- getShapeUtils(childShape).translateBy(childShape, deltaForShape)
- }
- }
- }
-
- updateParents(
- data,
- initialShapes.map((s) => s.id)
- )
- }
- }
-
- cancel(data: Data) {
- const { initialShapes, initialParents, clones, currentPageId } =
- this.snapshot
- const { shapes } = getPage(data, currentPageId)
-
- for (const { id, point } of initialShapes) {
- const shape = shapes[id]
- const deltaForShape = vec.sub(point, shape.point)
- getShapeUtils(shape).translateTo(shape, point)
-
- if (shape.type === ShapeType.Group) {
- for (let childId of shape.children) {
- const childShape = shapes[childId]
- getShapeUtils(childShape).translateBy(childShape, deltaForShape)
- }
- }
- }
-
- for (const { id } of clones) {
- delete shapes[id]
- }
-
- initialParents.forEach(({ id, children }) => {
- const shape = shapes[id]
- getShapeUtils(shape).setProperty(shape, 'children', children)
- })
-
- updateParents(
- data,
- initialShapes.map((s) => s.id)
- )
- }
-
- complete(data: Data) {
- if (!this.snapshot.hasUnlockedShapes) return
-
- commands.translate(
- data,
- this.snapshot,
- getTranslateSnapshot(data),
- this.isCloning
- )
- }
- }
-
- export function getTranslateSnapshot(data: Data) {
- const cData = current(data)
- const page = getPage(cData)
- const selectedShapes = getSelectedShapes(cData).filter(
- (shape) => !shape.isLocked
- )
-
- const hasUnlockedShapes = selectedShapes.length > 0
-
- const parents = Array.from(
- new Set(selectedShapes.map((s) => s.parentId)).values()
- )
- .filter((id) => id !== data.currentPageId)
- .map((id) => page.shapes[id])
-
- return {
- hasUnlockedShapes,
- currentPageId: data.currentPageId,
- initialParents: parents.map(({ id, children }) => ({ id, children })),
- initialShapes: selectedShapes.map(({ id, point, parentId }) => ({
- id,
- point,
- parentId,
- })),
- clones: selectedShapes
- .filter((shape) => shape.type !== ShapeType.Group)
- .flatMap((shape) => {
- const clone = {
- ...shape,
- id: uuid(),
- parentId: shape.parentId,
- childIndex: getChildIndexAbove(cData, shape.id),
- }
-
- return clone
-
- // cloneGroup(cData, {
- // ...shape,
- // id: uuid(),
- // parentId: shape.parentId,
- // childIndex: getChildIndexAbove(cData, shape.id),
- // })
- }),
- }
- }
-
- export type TranslateSnapshot = ReturnType<typeof getTranslateSnapshot>
-
- function cloneGroup(data: Data, clone: Shape): Shape[] {
- if (clone.type !== ShapeType.Group) {
- return [clone]
- }
-
- const page = getPage(data)
- const childClones = clone.children.flatMap((id) => {
- const newId = uuid()
- const source = page.shapes[id]
- const next = { ...source, id: newId, parentId: clone.id }
-
- if (next.type === ShapeType.Group) {
- return [next, ...cloneGroup(data, next)]
- }
-
- return [next]
- })
-
- return [clone, ...childClones]
- }
|