瀏覽代碼

Fix (Whiteboards): Shape index and arrow binding issue (#8885)

* fix: shape index and bindings

* fix: indexv updating
Konstantinos 2 年之前
父節點
當前提交
5913d81e6f

+ 42 - 1
e2e-tests/whiteboards.spec.ts

@@ -16,8 +16,9 @@ test('enable whiteboards', async ({ page }) => {
 })
 })
 
 
 test('should display onboarding tour', async ({ page }) => {
 test('should display onboarding tour', async ({ page }) => {
+  // ensure onboarding tour is going to be triggered locally
+  await page.evaluate(`window.localStorage.removeItem('whiteboard-onboarding-tour?')`)
   await page.click('.nav-header .whiteboard')
   await page.click('.nav-header .whiteboard')
-  await page.waitForTimeout(1000)
 
 
   await expect(page.locator('.cp__whiteboard-welcome')).toBeVisible()
   await expect(page.locator('.cp__whiteboard-welcome')).toBeVisible()
   await page.click('.cp__whiteboard-welcome button.bg-gray-600')
   await page.click('.cp__whiteboard-welcome button.bg-gray-600')
@@ -138,10 +139,50 @@ test('connect rectangles with an arrow', async ({ page }) => {
   await page.mouse.up()
   await page.mouse.up()
   await page.keyboard.press('Escape')
   await page.keyboard.press('Escape')
 
 
+  await expect(page.locator('.logseq-tldraw .tl-line-container')).toHaveCount(1)
+})
+
+test('delete the first rectangle', async ({ page }) => {
+  await page.keyboard.press('Escape')
+  await page.waitForTimeout(1000)
+  await page.click('.logseq-tldraw .tl-box-container:first-of-type')
+  await page.keyboard.press('Delete')
+
+  await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(1)
+  await expect(page.locator('.logseq-tldraw .tl-line-container')).toHaveCount(0)
+})
 
 
+test('undo the delete action', async ({ page }) => {
+  await page.keyboard.press(modKey + '+z')
+
+  await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(2)
   await expect(page.locator('.logseq-tldraw .tl-line-container')).toHaveCount(1)
   await expect(page.locator('.logseq-tldraw .tl-line-container')).toHaveCount(1)
 })
 })
 
 
+test('move arrow to back', async ({ page }) => {
+  await page.keyboard.press('Escape')
+  await page.waitForTimeout(1000)
+  await page.click('.logseq-tldraw .tl-line-container')
+  await page.keyboard.press('Shift+[')
+
+  await expect(page.locator('.logseq-tldraw .tl-canvas .tl-layer > div:first-of-type > div:first-of-type')).toHaveClass('tl-line-container')
+})
+
+test('move arrow to front', async ({ page }) => {
+  await page.keyboard.press('Escape')
+  await page.waitForTimeout(1000)
+  await page.click('.logseq-tldraw .tl-line-container')
+  await page.keyboard.press('Shift+]')
+
+  await expect(page.locator('.logseq-tldraw .tl-canvas .tl-layer > div:first-of-type > div:first-of-type')).not.toHaveClass('tl-line-container')
+})
+
+test('undo the move action', async ({ page }) => {
+  await page.keyboard.press(modKey + '+z')
+
+  await expect(page.locator('.logseq-tldraw .tl-canvas .tl-layer > div:first-of-type > div:first-of-type')).toHaveClass('tl-line-container')
+})
+
 test('cleanup the shapes', async ({ page }) => {
 test('cleanup the shapes', async ({ page }) => {
   await page.keyboard.press(`${modKey}+a`)
   await page.keyboard.press(`${modKey}+a`)
   await page.keyboard.press('Delete')
   await page.keyboard.press('Delete')

+ 1 - 1
src/main/frontend/components/whiteboard.css

@@ -165,7 +165,7 @@ input.tl-text-input {
     width: calc(100% - 20px);
     width: calc(100% - 20px);
 
 
     > .title {
     > .title {
-      @apply whitespace-nowrap min-w-[80px];
+      @apply whitespace-nowrap min-w-[100px];
     }
     }
   }
   }
 
 

+ 23 - 7
src/main/frontend/handler/whiteboard.cljs

@@ -92,7 +92,8 @@
         upsert-shapes (->> (set/difference new-id-nonces db-id-nonces)
         upsert-shapes (->> (set/difference new-id-nonces db-id-nonces)
                            (map (fn [{:keys [id]}]
                            (map (fn [{:keys [id]}]
                                   (-> (.-serialized ^js (.getShapeById tl-page id))
                                   (-> (.-serialized ^js (.getShapeById tl-page id))
-                                      js->clj-keywordize)))
+                                      js->clj-keywordize
+                                      (assoc :index (.indexOf shapes-index id)))))
                            (set))
                            (set))
         old-ids (set (map :id db-id-nonces))
         old-ids (set (map :id db-id-nonces))
         new-ids (set (map :id new-id-nonces))
         new-ids (set (map :id new-id-nonces))
@@ -133,9 +134,13 @@
 (defn transact-tldr-delta! [page-name ^js app replace?]
 (defn transact-tldr-delta! [page-name ^js app replace?]
   (let [tl-page ^js (second (first (.-pages app)))
   (let [tl-page ^js (second (first (.-pages app)))
         shapes (.-shapes ^js tl-page)
         shapes (.-shapes ^js tl-page)
+        shapes-index (map #(gobj/get % "id") shapes)
         new-id-nonces (set (map (fn [shape]
         new-id-nonces (set (map (fn [shape]
-                                  {:id (.-id shape)
-                                   :nonce (.-nonce shape)}) shapes))
+                                  (let [id (.-id shape)]
+                                   {:id id
+                                    :nonce (if (= shape.id (.indexOf shapes-index id))
+                                             (.-nonce shape)
+                                             (.getTime (js/Date.)))})) shapes))
         repo (state/get-current-repo)
         repo (state/get-current-repo)
         db-id-nonces (or
         db-id-nonces (or
                       (get-in @*last-shapes-nonce [repo page-name])
                       (get-in @*last-shapes-nonce [repo page-name])
@@ -156,7 +161,7 @@
 
 
                     ;; arrow
                     ;; arrow
                     (some #(and (= "line" (:type %))
                     (some #(and (= "line" (:type %))
-                                (= "arrow "(:end (:decorations %)))) new-shapes)
+                                (= "arrow " (:end (:decorations %)))) new-shapes)
 
 
                     (assoc metadata :whiteboard/op :new-arrow)
                     (assoc metadata :whiteboard/op :new-arrow)
                     :else
                     :else
@@ -358,15 +363,25 @@
       (when (seq bindings)
       (when (seq bindings)
         (.updateBindings tl-page (bean/->js bindings))))))
         (.updateBindings tl-page (bean/->js bindings))))))
 
 
+(defn update-shapes-index!
+  [^js tl-page page-name]
+  (when-let [page (db/entity [:block/name page-name])]
+    (let [shapes-index (get-in page [:block/properties :logseq.tldraw.page :shapes-index])]
+      (when (seq shapes-index)
+        (.updateShapesIndex tl-page (bean/->js shapes-index))))))
+
 (defn undo!
 (defn undo!
   [{:keys [tx-meta]}]
   [{:keys [tx-meta]}]
   (history/pause-listener!)
   (history/pause-listener!)
   (try
   (try
     (when-let [app (state/active-tldraw-app)]
     (when-let [app (state/active-tldraw-app)]
-      (let [{:keys [deleted-shapes new-shapes changed-shapes prev-changed-blocks]} (:data tx-meta)
+      (let [{:keys [page-name deleted-shapes new-shapes changed-shapes prev-changed-blocks]} (:data tx-meta)
             whiteboard-op (:whiteboard/op tx-meta)
             whiteboard-op (:whiteboard/op tx-meta)
-            ^js api (.-api app)]
+            ^js api (.-api app)
+            tl-page ^js (second (first (.-pages app)))]
         (when api
         (when api
+          (update-bindings! tl-page page-name)
+          (update-shapes-index! tl-page page-name)
           (case whiteboard-op
           (case whiteboard-op
             :group
             :group
             (do
             (do
@@ -383,7 +398,7 @@
                 (delete-shapes! api new-shapes))
                 (delete-shapes! api new-shapes))
               (when (seq changed-shapes)
               (when (seq changed-shapes)
                 (let [prev-shapes (map (fn [b] (get-in b [:block/properties :logseq.tldraw.shape]))
                 (let [prev-shapes (map (fn [b] (get-in b [:block/properties :logseq.tldraw.shape]))
-                                    prev-changed-blocks)]
+                                       prev-changed-blocks)]
                   (update-shapes! api prev-shapes))))))))
                   (update-shapes! api prev-shapes))))))))
     (catch :default e
     (catch :default e
       (js/console.error e)))
       (js/console.error e)))
@@ -400,6 +415,7 @@
             tl-page ^js (second (first (.-pages app)))]
             tl-page ^js (second (first (.-pages app)))]
         (when api
         (when api
           (update-bindings! tl-page page-name)
           (update-bindings! tl-page page-name)
+          (update-shapes-index! tl-page page-name)
           (case whiteboard-op
           (case whiteboard-op
             :group
             :group
             (do
             (do

+ 0 - 1
tldraw/packages/core/src/lib/TLHistory.ts

@@ -32,7 +32,6 @@ export class TLHistory<S extends TLShape = TLShape, K extends TLEventMap = TLEve
 
 
   @action persist = (replace = false) => {
   @action persist = (replace = false) => {
     if (this.isPaused || this.creating) return
     if (this.isPaused || this.creating) return
-    this.app.pages.forEach(page => page.bump()) // Is it ok here?
     this.app.notify('persist', {replace})
     this.app.notify('persist', {replace})
   }
   }
 
 

+ 5 - 5
tldraw/packages/core/src/lib/TLPage/TLPage.ts

@@ -91,10 +91,6 @@ export class TLPage<S extends TLShape = TLShape, E extends TLEventMap = TLEventM
 
 
   @observable nonce = 0
   @observable nonce = 0
 
 
-  @action bump = () => {
-    // this.nonce++
-  }
-
   @action update(props: Partial<TLPageProps<S>>) {
   @action update(props: Partial<TLPageProps<S>>) {
     Object.assign(this, props)
     Object.assign(this, props)
     return this
     return this
@@ -105,6 +101,11 @@ export class TLPage<S extends TLShape = TLShape, E extends TLEventMap = TLEventM
     return this
     return this
   }
   }
 
 
+  @action updateShapesIndex(shapesIndex: string[]) {
+    this.shapes.sort((a,b) => shapesIndex.indexOf(a.id) - shapesIndex.indexOf(b.id))
+    return this
+  }
+
   @action addShapes(...shapes: S[] | TLShapeModel[]) {
   @action addShapes(...shapes: S[] | TLShapeModel[]) {
     if (shapes.length === 0) return
     if (shapes.length === 0) return
     const shapeInstances =
     const shapeInstances =
@@ -115,7 +116,6 @@ export class TLPage<S extends TLShape = TLShape, E extends TLEventMap = TLEventM
             return new ShapeClass(shape)
             return new ShapeClass(shape)
           })
           })
     this.shapes.push(...shapeInstances)
     this.shapes.push(...shapeInstances)
-    this.bump()
     return shapeInstances
     return shapeInstances
   }
   }