Browse Source

feat: create on dnd

Konstantinos Kaloutas 3 years ago
parent
commit
f60c606c68

+ 3 - 3
tldraw/apps/tldraw-logseq/src/app.tsx

@@ -12,7 +12,7 @@ import * as React from 'react'
 import { AppUI } from './components/AppUI'
 import { ContextBar } from './components/ContextBar'
 import { ContextMenu } from './components/ContextMenu'
-import { useFileDrop } from './hooks/useFileDrop'
+import { useDrop } from './hooks/useDrop'
 import { usePaste } from './hooks/usePaste'
 import { useQuickAdd } from './hooks/useQuickAdd'
 import {
@@ -80,7 +80,7 @@ export const App = function App({
     handlers: handlers,
   }
 
-  const onFileDrop = useFileDrop(contextValue)
+  const onDrop = useDrop(contextValue)
   const onPaste = usePaste(contextValue)
   const onQuickAdd = useQuickAdd()
   const ref = React.useRef<HTMLDivElement>(null)
@@ -99,7 +99,7 @@ export const App = function App({
       <AppProvider
         Shapes={shapes}
         Tools={tools}
-        onFileDrop={onFileDrop}
+        onDrop={onDrop}
         onPaste={onPaste}
         onCanvasDBClick={onQuickAdd}
         onPersist={onPersistOnDiff}

+ 3 - 3
tldraw/apps/tldraw-logseq/src/hooks/useFileDrop.ts → tldraw/apps/tldraw-logseq/src/hooks/useDrop.ts

@@ -4,9 +4,9 @@ import type { Shape } from '../lib'
 import type { LogseqContextValue } from '../lib/logseq-context'
 import { usePaste } from './usePaste'
 
-export function useFileDrop(context: LogseqContextValue) {
+export function useDrop(context: LogseqContextValue) {
   const handlePaste = usePaste(context)
-  return React.useCallback<TLReactCallbacks<Shape>['onFileDrop']>(async (app, { files, point }) => {
-    handlePaste(app, { point, shiftKey: false, files })
+  return React.useCallback<TLReactCallbacks<Shape>['onDrop']>(async (app, { dataTransfer, point }) => {
+    handlePaste(app, { point, shiftKey: false, dataTransfer })
   }, [])
 }

+ 50 - 12
tldraw/apps/tldraw-logseq/src/hooks/usePaste.ts

@@ -1,3 +1,4 @@
+import { Label } from '@radix-ui/react-select'
 import {
   BoundsUtils,
   getSizeFromSrc,
@@ -18,6 +19,7 @@ import {
   YouTubeShape,
   LogseqPortalShape,
   VideoShape,
+  LineShape,
   ImageShape,
   IFrameShape,
 } from '../lib'
@@ -48,7 +50,7 @@ export function usePaste(context: LogseqContextValue) {
   const { handlers } = context
 
   return React.useCallback<TLReactCallbacks<Shape>['onPaste']>(
-    async (app, { point, shiftKey, files }) => {
+    async (app, { point, shiftKey, dataTransfer }) => {
       interface VideoImageAsset extends TLAsset {
         size: number[]
       }
@@ -115,6 +117,35 @@ export function usePaste(context: LogseqContextValue) {
         return added
       }
 
+      async function handleItems(items: any) {
+        for (const item of items) {
+          if (await handleText(item.text)) {
+            // const lineId = uniqueId()
+            // shapesToCreate.push({
+            //   ...LineShape.defaultProps,
+            //   id: lineId,
+            //   handles: {
+            //     start: { id: 'start', canBind: true, point: app.selectedShapesArray[0].getCenter() },
+            //     end: { id: 'end', canBind: true, point: [point[0], point[1]] },
+            //   }
+            // })
+            return true
+          }
+        }
+        return false
+      }
+
+      async function handleTransfer(dataTransfer: DataTransfer) {
+        let added = false
+
+        if ((dataTransfer.files?.length && await handleFiles(Array.from(dataTransfer.files))) ||
+            (dataTransfer.items?.length && await handleItems(Array.from(dataTransfer.items).map((item: any) => ({type: item.type, text: dataTransfer.getData(item.type)}))))  ) {
+          added = true
+        }
+
+        return added
+      }
+
       async function handleHTML(item: ClipboardItem) {
         if (item.types.includes('text/html')) {
           const blob = await item.getType('text/html')
@@ -130,25 +161,32 @@ export function usePaste(context: LogseqContextValue) {
         return false
       }
 
-      async function handleTextPlain(item: ClipboardItem) {
-        if (item.types.includes('text/plain')) {
-          const blob = await item.getType('text/plain')
-          const rawText = (await blob.text()).trim()
-
-          if (await handleURL(rawText)) {
+      async function handleText(text: string ) {
+          if (await handleURL(text)) {
             return true
           }
 
-          if (handleIframe(rawText)) {
+          if (handleIframe(text)) {
             return true
           }
 
-          if (handleTldrawShapes(rawText)) {
+          if (handleTldrawShapes(text)) {
             return true
           }
-          if (await handleLogseqPortalShapes(rawText)) {
+
+          if (await handleLogseqPortalShapes(text)) {
             return true
           }
+
+          return false
+      }
+
+      async function handleTextPlain(item: ClipboardItem) {
+        if (item.types.includes('text/plain')) {
+          const blob = await item.getType('text/plain')
+          const rawText = (await blob.text()).trim()
+
+          return handleText(rawText)
         }
 
         return false
@@ -313,8 +351,8 @@ export function usePaste(context: LogseqContextValue) {
       app.cursors.setCursor(TLCursor.Progress)
 
       try {
-        if (files && files.length > 0) {
-          await handleFiles(files)
+        if (dataTransfer) {
+          await handleTransfer(dataTransfer)
         } else {
           for (const item of await navigator.clipboard.read()) {
             let handled = !shiftKey ? await handleHTML(item) : false

+ 4 - 5
tldraw/packages/core/src/lib/TLApp/TLApp.ts

@@ -436,11 +436,10 @@ export class TLApp<
 
   paste = (e?: ClipboardEvent, shiftKey?: boolean) => {
     if (!this.editingShape) {
-      const fileList = e?.clipboardData?.files
       this.notify('paste', {
         point: this.inputs.currentPoint,
         shiftKey: !!shiftKey,
-        files: fileList ? Array.from(fileList) : undefined,
+        dataTransfer: e?.clipboardData,
       })
     }
   }
@@ -450,9 +449,9 @@ export class TLApp<
     this.api.deleteShapes()
   }
 
-  dropFiles = (files: FileList, point?: number[]) => {
-    this.notify('drop-files', {
-      files: Array.from(files),
+  drop = (dataTransfer: DataTransfer, point?: number[]) => {
+    this.notify('drop', {
+      dataTransfer,
       point: point
         ? this.viewport.getPagePoint(point)
         : BoundsUtils.getBoundsCenter(this.viewport.currentView),

+ 3 - 3
tldraw/packages/core/src/types/types.ts

@@ -153,12 +153,12 @@ export type TLSubscriptionEvent =
       info: TLShape[]
     }
   | {
-      event: 'drop-files'
-      info: { files: File[]; point: number[] }
+      event: 'drop'
+      info: { dataTransfer: DataTransfer; point: number[] }
     }
   | {
       event: 'paste'
-      info: { point: number[]; shiftKey: boolean; files?: File[] }
+      info: { point: number[]; shiftKey: boolean; dataTransfer?: DataTransfer }
     }
   | {
       event: 'create-assets'

+ 1 - 8
tldraw/packages/react/src/hooks/useCanvasEvents.ts

@@ -52,16 +52,9 @@ export function useCanvasEvents() {
 
     const onDrop = async (e: React.DragEvent<Element>) => {
       e.preventDefault()
-      Array.from(e.dataTransfer.items).forEach(item => {
-        const type = item.type
-        item.getAsString(s => {
-          console.log(type, ":", s)
-        })
-      })
 
-      if (!e.dataTransfer.files?.length) return
       const point = [e.clientX, e.clientY]
-      app.dropFiles(e.dataTransfer.files, point)
+      app.drop(e.dataTransfer, point)
     }
 
     const onDragOver = (e: React.DragEvent<Element>) => {

+ 2 - 2
tldraw/packages/react/src/hooks/useSetup.ts

@@ -18,7 +18,7 @@ export function useSetup<
     onCreateShapes,
     onDeleteAssets,
     onDeleteShapes,
-    onFileDrop,
+    onDrop,
     onPaste,
     onCanvasDBClick,
   } = props
@@ -45,7 +45,7 @@ export function useSetup<
     if (onCreateAssets) unsubs.push(app.subscribe('create-assets', onCreateAssets))
     if (onDeleteShapes) unsubs.push(app.subscribe('delete-shapes', onDeleteShapes))
     if (onDeleteAssets) unsubs.push(app.subscribe('delete-assets', onDeleteAssets))
-    if (onFileDrop) unsubs.push(app.subscribe('drop-files', onFileDrop))
+    if (onDrop) unsubs.push(app.subscribe('drop', onDrop))
     if (onPaste) unsubs.push(app.subscribe('paste', onPaste))
     if (onCanvasDBClick) unsubs.push(app.subscribe('canvas-dbclick', onCanvasDBClick))
     // Kind of unusual, is this the right pattern?

+ 1 - 1
tldraw/packages/react/src/types/TLReactSubscriptions.tsx

@@ -38,7 +38,7 @@ export interface TLReactCallbacks<
   onCreateAssets: TLReactCallback<S, R, 'create-assets'>
   onDeleteShapes: TLReactCallback<S, R, 'delete-shapes'>
   onDeleteAssets: TLReactCallback<S, R, 'delete-assets'>
-  onFileDrop: TLReactCallback<S, R, 'drop-files'>
+  onDrop: TLReactCallback<S, R, 'drop'>
   onCanvasDBClick: TLReactCallback<S, R, 'canvas-dbclick'>
   onPaste: TLReactCallback<S, R, 'paste'>
 }