瀏覽代碼

feat(whiteboard): onboarding whiteboard

Peng Xiao 3 年之前
父節點
當前提交
e8d1c1baa7

文件差異過大導致無法顯示
+ 0 - 0
resources/whiteboard/onboarding.edn


文件差異過大導致無法顯示
+ 0 - 0
resources/whiteboard/onboarding.template


+ 4 - 1
src/main/frontend/extensions/tldraw.cljs

@@ -79,10 +79,13 @@
   [name block-id]
   (let [data (whiteboard-handler/page-name->tldr! name block-id)
         [tln set-tln] (rum/use-state nil)]
-    (rum/use-layout-effect!
+    (rum/use-effect!
      (fn []
        (when (and tln name)
          (when-let [^js api (gobj/get tln "api")]
+           (when (and (not (state/get-onboarding-whiteboard?))
+                      (= 0 (.. tln -shapes -length)))
+             (whiteboard-handler/populate-onboarding-whiteboard api))
            (when (and block-id (parse-uuid block-id))
              (. api selectShapes block-id)
              (. api zoomToSelection))))

+ 34 - 1
src/main/frontend/handler/whiteboard.cljs

@@ -4,13 +4,15 @@
             [dommy.core :as dom]
             [frontend.db.model :as model]
             [frontend.db.utils :as db-utils]
+            [frontend.handler.editor :as editor-handler]
             [frontend.handler.route :as route-handler]
             [frontend.modules.outliner.core :as outliner]
             [frontend.modules.outliner.file :as outliner-file]
             [frontend.state :as state]
             [frontend.util :as util]
+            [logseq.graph-parser.util :as gp-util]
             [logseq.graph-parser.whiteboard :as gp-whiteboard]
-            [frontend.handler.editor :as editor-handler]))
+            [promesa.core :as p]))
 
 (defn shape->block [shape page-name idx]
   (let [properties {:ls-type :whiteboard-shape
@@ -216,3 +218,34 @@
   [target]
   (when-let [shape-el (dom/closest target "[data-shape-id]")]
     (.getAttribute shape-el "data-shape-id")))
+
+(defn get-onboard-whiteboard-edn
+  []
+  (p/let [^js res (js/fetch "./whiteboard/onboarding.edn") ;; do we need to cache it?
+          text (.text res)
+          edn (gp-util/safe-read-string text)]
+    edn))
+
+(defn clone-whiteboard-from-edn
+  "Given a tldr, clone the whiteboard page into current active whiteboard"
+  ([edn]
+   (when-let [app (state/active-tldraw-app)]
+     (clone-whiteboard-from-edn edn (.-api app))))
+  ([{:keys [pages blocks]} api]
+   (let [page-block (first pages)
+         shapes (->> blocks
+                     (filter gp-whiteboard/shape-block?)
+                     (map gp-whiteboard/block->shape)
+                     (sort-by :index))
+         tldr-page (gp-whiteboard/page-block->tldr-page page-block)
+         assets (:assets tldr-page)
+         bindings (:bindings tldr-page)]
+     (.cloneShapesIntoCurrentPage ^js api (clj->js {:shapes shapes
+                                                    :assets assets
+                                                    :bindings bindings})))))
+(defn populate-onboarding-whiteboard
+  [api]
+  (when (some? api)
+    (p/let [edn (get-onboard-whiteboard-edn)]
+      (clone-whiteboard-from-edn edn api)
+      (state/set-onboarding-whiteboard! true))))

+ 11 - 0
src/main/frontend/state.cljs

@@ -263,6 +263,8 @@
      :ui/find-in-page                       nil
      :graph/importing                       nil
      :graph/importing-state                 {}
+
+     :whiteboard/onboarding-whiteboard?     (or (storage/get :ls-onboarding-whiteboard?) false)
      })))
 
 ;; Block ast state
@@ -1916,3 +1918,12 @@ Similar to re-frame subscriptions"
   {:pre [(map? v)
          (= #{:repo :old-path :new-path} (set (keys v)))]}
   (async/offer! (get-file-rename-event-chan) v))
+
+(defn set-onboarding-whiteboard!
+  [v]
+  (set-state! :whiteboard/onboarding-whiteboard? v)
+  (storage/set :ls-onboarding-whiteboard? v))
+
+(defn get-onboarding-whiteboard?
+  []
+  (get-in @state [:whiteboard/onboarding-whiteboard?]))

文件差異過大導致無法顯示
+ 0 - 0
templates/onboarding-whiteboard.json


+ 30 - 10
tldraw/packages/core/src/lib/TLApi/TLApi.ts

@@ -201,7 +201,7 @@ export class TLApi<S extends TLShape = TLShape, K extends TLEventMap = TLEventMa
     shapes,
     assets,
     bindings,
-    point,
+    point = [0, 0],
   }: {
     shapes: TLShapeModel[]
     point: number[]
@@ -307,18 +307,38 @@ export class TLApi<S extends TLShape = TLShape, K extends TLEventMap = TLEventMa
     return null
   }
 
+  cloneShapesIntoCurrentPage = (opts: {
+    shapes: TLShapeModel[]
+    point: number[]
+    // assets & bindings are the context for creating shapes
+    assets: TLAsset[]
+    bindings: Record<string, TLBinding>
+  }) => {
+    const data = this.cloneShapes(opts)
+    if (data) {
+      this.addClonedShapes(data)
+    }
+    return this
+  }
+
+  addClonedShapes = (opts: ReturnType<TLApi['cloneShapes']>) => {
+    const { shapes, assets, bindings } = opts
+    if (assets.length > 0) {
+      this.app.createAssets(assets)
+    }
+    if (shapes.length > 0) {
+      this.app.createShapes(shapes)
+    }
+    this.app.currentPage.updateBindings(Object.fromEntries(bindings.map(b => [b.id, b])))
+    this.app.selectedTool.transition('idle') // clears possible editing states
+    return this
+  }
+
   addClonedShapesFromTldrString = (text: string, point: number[]) => {
     const data = this.getClonedShapesFromTldrString(text, point)
     if (data) {
-      const { shapes, bindings, assets } = data
-      if (assets.length > 0) {
-        this.app.createAssets(assets)
-      }
-      if (shapes.length > 0) {
-        this.app.createShapes(shapes)
-      }
-      this.app.currentPage.updateBindings(Object.fromEntries(bindings.map(b => [b.id, b])))
-      this.app.selectedTool.transition('idle') // clears possible editing states
+      this.addClonedShapes(data)
     }
+    return this
   }
 }

部分文件因文件數量過多而無法顯示