You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import Command from './command'
  2. import history from '../history'
  3. import { Data, Shape } from 'types'
  4. import {
  5. getChildIndexAbove,
  6. getCommonBounds,
  7. getCurrentCamera,
  8. getPage,
  9. getSelectedIds,
  10. getSelectedShapes,
  11. getViewport,
  12. screenToWorld,
  13. setSelectedIds,
  14. setToArray,
  15. } from 'utils/utils'
  16. import { uniqueId } from 'utils/utils'
  17. import { current } from 'immer'
  18. import vec from 'utils/vec'
  19. import { getShapeUtils } from 'lib/shape-utils'
  20. import state from 'state/state'
  21. export default function pasteCommand(data: Data, initialShapes: Shape[]) {
  22. const { currentPageId } = data
  23. const center = screenToWorld(
  24. [window.innerWidth / 2, window.innerHeight / 2],
  25. data
  26. )
  27. const bounds = getCommonBounds(
  28. ...initialShapes.map((shape) =>
  29. getShapeUtils(shape).getRotatedBounds(shape)
  30. )
  31. )
  32. const topLeft = vec.sub(center, [bounds.width / 2, bounds.height / 2])
  33. const newIdMap = Object.fromEntries(
  34. initialShapes.map((shape) => [shape.id, uniqueId()])
  35. )
  36. const oldSelectedIds = setToArray(getSelectedIds(data))
  37. history.execute(
  38. data,
  39. new Command({
  40. name: 'paste_new_shapes',
  41. category: 'canvas',
  42. manualSelection: true,
  43. do(data) {
  44. const { shapes } = getPage(data, currentPageId)
  45. let childIndex =
  46. (state.values.currentShapes[state.values.currentShapes.length - 1]
  47. ?.childIndex || 0) + 1
  48. for (const shape of initialShapes) {
  49. const topLeftOffset = vec.sub(shape.point, [bounds.minX, bounds.minY])
  50. const newId = newIdMap[shape.id]
  51. shapes[newId] = {
  52. ...shape,
  53. id: newId,
  54. parentId: oldSelectedIds[shape.parentId] || data.currentPageId,
  55. childIndex: childIndex++,
  56. point: vec.add(topLeft, topLeftOffset),
  57. }
  58. }
  59. setSelectedIds(data, Object.values(newIdMap))
  60. },
  61. undo(data) {
  62. const { shapes } = getPage(data, currentPageId)
  63. Object.values(newIdMap).forEach((id) => delete shapes[id])
  64. setSelectedIds(data, oldSelectedIds)
  65. },
  66. })
  67. )
  68. }