Browse Source

fix: paste nested blocks

Tienson Qin 2 years ago
parent
commit
81f22da35d

+ 26 - 8
src/main/frontend/handler/editor.cljs

@@ -1907,6 +1907,11 @@
          (edit-block! last-block' :max (:block/uuid last-block')))))
    0))
 
+(defn- nested-blocks
+  [blocks]
+  (let [ids (set (map :db/id blocks))]
+    (some? (some #(ids (:db/id (:block/parent %))) blocks))))
+
 (defn paste-blocks
   "Given a vec of blocks, insert them into the target page.
    keep-uuid?: if true, keep the uuid provided in the block structure."
@@ -1926,12 +1931,25 @@
         block (db/entity (:db/id target-block))
         page (if (:block/name block) block
                  (when target-block (:block/page (db/entity (:db/id target-block)))))
-        target-block (or target-block editing-block)
+        empty-target? (string/blank? (:block/content target-block))
+        paste-nested-blocks? (nested-blocks blocks)
+        target-block-has-children? (db/has-children? (:block/uuid target-block))
+        replace-empty-target? (if (and paste-nested-blocks? empty-target?
+                                       target-block-has-children?)
+                                false
+                                true)
+        target-block' (if replace-empty-target? target-block
+                          (db/pull (:db/id (:block/left target-block))))
         sibling? (cond
+                   (and paste-nested-blocks? empty-target?)
+                   (if (= (:block/parent target-block') (:block/parent target-block))
+                     true
+                     false)
+
                    (some? sibling?)
                    sibling?
 
-                   (db/has-children? (:block/uuid target-block))
+                   target-block-has-children?
                    false
 
                    :else
@@ -1944,15 +1962,15 @@
 
     (outliner-tx/transact!
       {:outliner-op :insert-blocks}
-      (when target-block
-        (let [format (or (:block/format target-block) (state/get-preferred-format))
+      (when target-block'
+        (let [format (or (:block/format target-block') (state/get-preferred-format))
               blocks' (map (fn [block]
                              (paste-block-cleanup block page exclude-properties format content-update-fn))
                            blocks)
-              result (outliner-core/insert-blocks! blocks' target-block {:sibling? sibling?
-                                                                         :outliner-op :paste
-                                                                         :replace-empty-target? true
-                                                                         :keep-uuid? keep-uuid?})]
+              result (outliner-core/insert-blocks! blocks' target-block' {:sibling? sibling?
+                                                                          :outliner-op :paste
+                                                                          :replace-empty-target? replace-empty-target?
+                                                                          :keep-uuid? keep-uuid?})]
           (edit-last-block-after-inserted! result))))))
 
 (defn- block-tree->blocks

+ 4 - 6
src/main/frontend/modules/outliner/core.cljs

@@ -280,15 +280,13 @@
     x))
 
 (defn- compute-block-parent
-  [block parent target-block prev-hop top-level? sibling? get-new-id outliner-op]
+  [block parent target-block prev-hop top-level? sibling? get-new-id outliner-op replace-empty-target? idx]
   (cond
     ;; replace existing block
     (and (= outliner-op :paste)
+         replace-empty-target?
          (string/blank? (:block/content target-block))
-         (= (get-id (:block/parent target-block))
-            (get-id (:block/parent block)))
-         (= (get-id (:block/left target-block))
-            (get-id (:block/left block))))
+         (zero? idx))
     (get-id (:block/parent target-block))
 
     prev-hop
@@ -476,7 +474,7 @@
                                                  (not= (:block/parent block) (:block/parent target-block)))
                            prev-hop (if outdented-block? (find-outdented-block-prev-hop block blocks) nil)
                            left-exists-in-blocks? (contains? ids (:db/id (:block/left block)))
-                           parent (compute-block-parent block parent target-block prev-hop top-level? sibling? get-new-id outliner-op)
+                           parent (compute-block-parent block parent target-block prev-hop top-level? sibling? get-new-id outliner-op replace-empty-target? idx)
                            left (compute-block-left blocks block left target-block prev-hop idx replace-empty-target? left-exists-in-blocks? get-new-id)]
                        (cond->
                          (merge block {:block/uuid uuid

+ 32 - 1
src/test/frontend/modules/outliner/core_test.cljs

@@ -330,6 +330,37 @@
 
       (is (= [19 20] (get-children 18))))))
 
+(deftest test-paste-into-empty-block
+  (testing "
+    Paste a block into the first block (its content is empty)
+    [[22 [[2 [[3 [[4]
+                [5]]]
+            [6 [[7 [[8]]]]]
+            [9 [[10]
+                [11]]]]]
+        [12 [[13]
+             [14]
+             [15]]]
+        [16 [[17]]]]]]
+ "
+    (transact-tree! tree)
+    (db/transact! test-db [{:block/uuid 22
+                            :block/content ""}])
+    (let [target-block (get-block 22)]
+      (outliner-tx/transact!
+        {:graph test-db}
+        (outliner-core/insert-blocks! [{:block/left [:block/uuid 1]
+                                        :block/content "test"
+                                        :block/parent [:block/uuid 1]
+                                        :block/page 1}]
+                                      target-block
+                                      {:sibling? false
+                                       :outliner-op :paste
+                                       :replace-empty-target? true}))
+      (is (= "test" (:block/content (get-block 22))))
+      (is (= [22] (get-children 1)))
+      (is (= [2 12 16] (get-children 22))))))
+
 (deftest test-batch-transact
   (testing "add 4, 5 after 2 and delete 3"
     (let [tree [[1 [[2] [3]]]]]
@@ -691,6 +722,6 @@
 
   (do
     (frontend.test.fixtures/reset-datascript test-db)
-    (cljs.test/test-vars [#'random-deletes]))
+    (cljs.test/test-vars [#'test-paste-first-empty-block]))
 
   )