Browse Source

fix: paste shapes with bindings

Peng Xiao 3 years ago
parent
commit
e39fe772bb

+ 33 - 5
tldraw/apps/tldraw-logseq/src/hooks/usePaste.ts

@@ -3,6 +3,7 @@ import {
   fileToBase64,
   fileToBase64,
   getSizeFromSrc,
   getSizeFromSrc,
   TLAsset,
   TLAsset,
+  TLBinding,
   TLShapeModel,
   TLShapeModel,
   uniqueId,
   uniqueId,
 } from '@tldraw/core'
 } from '@tldraw/core'
@@ -19,6 +20,7 @@ export function usePaste() {
 
 
     const assetsToCreate: ImageAsset[] = []
     const assetsToCreate: ImageAsset[] = []
     const shapesToCreate: TLShapeModel[] = []
     const shapesToCreate: TLShapeModel[] = []
+    const bindingsToCreate: TLBinding[] = []
 
 
     async function handleImage(item: ClipboardItem) {
     async function handleImage(item: ClipboardItem) {
       const firstImageType = item.types.find(type => type.startsWith('image'))
       const firstImageType = item.types.find(type => type.startsWith('image'))
@@ -62,10 +64,9 @@ export function usePaste() {
               maxY: (shape.point?.[1] ?? point[1]) + (shape.size?.[1] ?? 4),
               maxY: (shape.point?.[1] ?? point[1]) + (shape.size?.[1] ?? 4),
             }))
             }))
           )
           )
-          const clonedShape = data.shapes.map((shape: TLShapeModel) => {
+          const clonedShapes = shapes.map((shape: TLShapeModel) => {
             return {
             return {
               ...shape,
               ...shape,
-              handles: {}, // TODO: may add this later?
               id: uniqueId(),
               id: uniqueId(),
               parentId: app.currentPageId,
               parentId: app.currentPageId,
               point: [
               point: [
@@ -74,7 +75,34 @@ export function usePaste() {
               ],
               ],
             }
             }
           })
           })
-          shapesToCreate.push(...clonedShape)
+          shapesToCreate.push(...clonedShapes)
+
+          // Try to rebinding the shapes to the new assets
+          shapesToCreate.forEach((s, idx) => {
+            if (s.handles) {
+              Object.values(s.handles).forEach(h => {
+                if (h.bindingId) {
+                  // try to bind the new shape
+                  const binding = app.currentPage.bindings[h.bindingId]
+                  // if the copied binding from/to is in the source
+                  const oldFromIdx = shapes.findIndex(s => s.id === binding.fromId)
+                  const oldToIdx = shapes.findIndex(s => s.id === binding.toId)
+                  if (binding && oldFromIdx !== -1 && oldToIdx !== -1) {
+                    const newBinding: TLBinding = {
+                      ...binding,
+                      id: uniqueId(),
+                      fromId: shapesToCreate[oldFromIdx].id,
+                      toId: shapesToCreate[oldToIdx].id,
+                    }
+                    bindingsToCreate.push(newBinding)
+                    h.bindingId = newBinding.id
+                  } else {
+                    h.bindingId = undefined
+                  }
+                }
+              })
+            }
+          })
         }
         }
       }
       }
     }
     }
@@ -91,7 +119,7 @@ export function usePaste() {
       }
       }
     }
     }
 
 
-    const allShapesToAdd = [
+    const allShapesToAdd: TLShapeModel[] = [
       ...assetsToCreate.map((asset, i) => ({
       ...assetsToCreate.map((asset, i) => ({
         id: uniqueId(),
         id: uniqueId(),
         type: 'image',
         type: 'image',
@@ -103,9 +131,9 @@ export function usePaste() {
       })),
       })),
       ...shapesToCreate,
       ...shapesToCreate,
     ]
     ]
-
     app.createAssets(assetsToCreate)
     app.createAssets(assetsToCreate)
     app.createShapes(allShapesToAdd)
     app.createShapes(allShapesToAdd)
+    app.currentPage.updateBindings(Object.fromEntries(bindingsToCreate.map(b => [b.id, b])))
 
 
     app.setSelectedShapes(allShapesToAdd.map(s => s.id))
     app.setSelectedShapes(allShapesToAdd.map(s => s.id))
   }, [])
   }, [])

+ 7 - 1
tldraw/packages/core/src/lib/TLApp/TLApp.ts

@@ -2,7 +2,7 @@
 /* eslint-disable @typescript-eslint/no-non-null-assertion */
 /* eslint-disable @typescript-eslint/no-non-null-assertion */
 /* eslint-disable @typescript-eslint/no-explicit-any */
 /* eslint-disable @typescript-eslint/no-explicit-any */
 import { Vec } from '@tldraw/vec'
 import { Vec } from '@tldraw/vec'
-import { action, computed, makeObservable, observable } from 'mobx'
+import { action, computed, makeObservable, observable, toJS } from 'mobx'
 import { BoundsUtils, KeyUtils } from '~utils'
 import { BoundsUtils, KeyUtils } from '~utils'
 import {
 import {
   TLSelectTool,
   TLSelectTool,
@@ -470,6 +470,12 @@ export class TLApp<
     } else {
     } else {
       this.selectionRotation = 0
       this.selectionRotation = 0
     }
     }
+    if (process.env.NODE_ENV === 'development') {
+      console.log(
+        'setSelectedShapes',
+        newSelectedShapes.map(s => toJS(s.serialized))
+      )
+    }
     return this
     return this
   }
   }