Browse Source

fix: can't paste block with children to empty target

Tienson Qin 1 month ago
parent
commit
8116067f85

+ 6 - 30
deps/outliner/src/logseq/outliner/core.cljs

@@ -354,7 +354,7 @@
   (assoc-level-aux tree-vec children-key 1))
 
 (defn- assign-temp-id
-  [db blocks target-block replace-empty-target? keep-uuid?]
+  [blocks target-block replace-empty-target?]
   (->> blocks
        (map-indexed
         (fn [idx block]
@@ -363,34 +363,10 @@
                             (:db/id block))
                           (dec (- idx)))]
             (if replacing-block?
-              (let [block' (assoc block
-                                  :db/id (:db/id target-block)
-                                  :block/uuid (:block/uuid target-block))]
-                (if (seq (:block/_parent target-block)) ; target-block has children
-                  [block']
-                  (let [old-property-values (d/q
-                                             '[:find ?b ?a
-                                               :in $ ?v
-                                               :where
-                                               [?b ?a ?v]
-                                               [?v :block/uuid]]
-                                             db
-                                             (:db/id target-block))
-                        from-property (:logseq.property/created-from-property target-block)
-                        db-id (dec (- idx))]
-                    (concat
-                     [[:db/retractEntity (:db/id target-block)] ; retract target-block first
-                      (cond-> (assoc block
-                                     :db/id db-id
-                                     :block/uuid (if keep-uuid?
-                                                   (or (:block/uuid block)
-                                                       (common-uuid/gen-uuid))
-                                                   (common-uuid/gen-uuid)))
-                        from-property
-                        (assoc :logseq.property/created-from-property (:db/id from-property)))]
-                     (map (fn [[b a]]
-                            [:db/add b a db-id])
-                          old-property-values)))))
+              [(assoc block
+                      :db/id (:db/id target-block)
+                      :block/uuid (:block/uuid target-block)
+                      :block/order (:block/order target-block))]
               [(assoc block :db/id db-id)]))))
        (apply concat)))
 
@@ -763,7 +739,7 @@
                            :tx (vec blocks-tx)
                            :blocks (vec blocks)
                            :target-block target-block}))
-          (let [tx (assign-temp-id db blocks-tx target-block replace-empty-target? keep-uuid?)
+          (let [tx (assign-temp-id blocks-tx target-block replace-empty-target?)
                 old-db-id-blocks (->> (filter :block.temp/use-old-db-id? tx)
                                       (map :block/uuid)
                                       (set))

+ 11 - 5
src/main/frontend/handler/editor.cljs

@@ -63,6 +63,7 @@
             [logseq.shui.dialog.core :as shui-dialog]
             [logseq.shui.popup.core :as shui-popup]
             [logseq.shui.ui :as shui]
+            [medley.core :as medley]
             [promesa.core :as p]
             [rum.core :as rum]))
 
@@ -1319,7 +1320,7 @@
         (fs/write-plain-text-file! repo dir file-rpath content nil)))))
 
 (defn- new-asset-block
-  [repo ^js file {:keys [repo-dir asset-dir-rpath external-url]}]
+  [repo ^js file {:keys [repo-dir asset-dir-rpath external-url] :as opts}]
   ;; WARN file name maybe fully qualified path when paste file
   (p/let [[file title] (if (map? file) [(:src file) (:title file)] [file nil])
           [file external-url] (if (string? file) [nil file] [file external-url])
@@ -1339,7 +1340,7 @@
                             false)
         nil)
       ;; new asset block
-      (let [block-id (ldb/new-block-id)
+      (let [block-id (or (:block/uuid opts) (ldb/new-block-id))
             ext (when file-name (db-asset/asset-path->type file-name))
             _ (when (string/blank? ext)
                 (throw (ex-info "File doesn't have a valid ext."
@@ -1375,13 +1376,18 @@
           today-page (if (nil? today-page-e)
                        (state/pub-event! [:page/create today-page-name])
                        today-page-e)
+          edit-block (or (state/get-edit-block) last-edit-block)
+          empty-target? (if (state/get-edit-block)
+                          (string/blank? (state/get-edit-content))
+                          (string/blank? (:block/title last-edit-block)))
           blocks* (p/all
-                   (for [^js file files]
+                   (for [^js [idx file] (medley/indexed files)]
                      (new-asset-block repo file
                                       {:repo-dir repo-dir
-                                       :asset-dir-rpath asset-dir-rpath})))
+                                       :asset-dir-rpath asset-dir-rpath
+                                       :block/uuid (when (and (zero? idx) empty-target?)
+                                                     (:block/uuid edit-block))})))
           blocks (remove nil? blocks*)
-          edit-block (or (state/get-edit-block) last-edit-block)
           insert-to-current-block-page? (and (:block/uuid edit-block) (not pdf-area?))
           target (cond
                    insert-to-current-block-page?

+ 5 - 3
src/main/frontend/handler/paste.cljs

@@ -224,9 +224,11 @@
   (when id
     (let [clipboard-data (gobj/get e "clipboardData")
           files (.-files clipboard-data)]
-      (editor-handler/upload-asset! id files
-                                    (get (state/get-edit-block) :block/format :markdown)
-                                    editor-handler/*asset-uploading? true)
+      (p/let [blocks (editor-handler/upload-asset! id files
+                                                   (get (state/get-edit-block) :block/format :markdown)
+                                                   editor-handler/*asset-uploading? true)]
+        (when-let [asset (first blocks)]
+          (editor-handler/edit-block! asset :max {})))
       (util/stop e))))
 
 (defn editor-on-paste!

+ 5 - 9
src/main/frontend/worker/db_sync.cljs

@@ -485,15 +485,11 @@
       (when-not (and (string? public-key) (string? encrypted-private-key))
         (fail-fast :db-sync/missing-field {:graph-id graph-id :field :user-rsa-key-pair}))
       (p/let [private-key (<decrypt-private-key encrypted-private-key)
-              local-encrypted (<get-item (graph-encrypted-aes-key-idb-key graph-id))
-              remote-encrypted (when (nil? local-encrypted)
-                                 (p/let [resp (<fetch-graph-encrypted-aes-key-raw base graph-id)]
-                                   (when-let [encrypted-aes-key (:encrypted-aes-key resp)]
-                                     (ldb/read-transit-str encrypted-aes-key))))
-              encrypted-aes-key (or local-encrypted remote-encrypted)]
-        (when-not encrypted-aes-key
-          (fail-fast :db-sync/missing-field {:graph-id graph-id :field :encrypted-aes-key}))
-        (when (and encrypted-aes-key (nil? local-encrypted))
+              encrypted-aes-key (p/let [resp (<fetch-graph-encrypted-aes-key-raw base graph-id)]
+                                  (when-let [encrypted-aes-key (:encrypted-aes-key resp)]
+                                    (ldb/read-transit-str encrypted-aes-key)))]
+        (if-not encrypted-aes-key
+          (fail-fast :db-sync/missing-field {:graph-id graph-id :field :encrypted-aes-key})
           (<set-item! aes-key-k encrypted-aes-key))
         (p/let [aes-key (crypt/<decrypt-aes-key private-key encrypted-aes-key)]
           (swap! *repo->aes-key assoc repo aes-key)

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

@@ -428,6 +428,55 @@
       (is (= [22] (get-children 1)))
       (is (= [2 12 16] (get-children 22))))))
 
+(deftest test-paste-multiple-blocks-into-empty-block
+  (testing "
+    Page starts with:
+    - 1
+      - 2
+    - 3
+    - (empty)
+
+    Copy 1,2,3 and paste into the empty block with :replace-empty-target? true
+ "
+    (transact-tree! [[22 [[23]]] [24] [25]])
+    (db/transact! test-db [{:block/uuid 22
+                            :block/title "1"}
+                           {:block/uuid 23
+                            :block/title "2"}
+                           {:block/uuid 24
+                            :block/title "3"}
+                           {:block/uuid 25
+                            :block/title ""}])
+    (let [target-block (get-block 25)
+          copied-blocks (->> (build-blocks [[101 [[102]]] [103]])
+                             (map (fn [block]
+                                    (case (:block/uuid block)
+                                      101 (assoc block :block/title "1")
+                                      102 (assoc block :block/title "2")
+                                      103 (assoc block :block/title "3")
+                                      block))))]
+      (outliner-tx/transact!
+       (transact-opts)
+       (outliner-core/insert-blocks! (db/get-db test-db false)
+                                     copied-blocks
+                                     target-block
+                                     {:sibling? true
+                                      :outliner-op :paste
+                                      :replace-empty-target? true}))
+      (let [top-level (get-children 1)
+            new-top-level (remove #{22 24 25} top-level)
+            replaced (get-block 25)]
+        (is (= 4 (count top-level)))
+        (is (= [22 24] (take 2 top-level)))
+        (is (= 1 (count new-top-level)))
+        (is (= "1" (:block/title replaced)))
+        (is (= [23] (get-children 22)))
+        (let [replaced-children (get-children 25)]
+          (is (= 1 (count replaced-children)))
+          (is (not= 23 (first replaced-children)))
+          (is (= "2" (:block/title (get-block (first replaced-children))))))
+        (is (= "3" (:block/title (get-block (first new-top-level)))))))))
+
 (deftest test-batch-transact
   (testing "add 4, 5 after 2 and delete 3"
     (let [tree' [[10 [[2] [3]]]]]
@@ -788,4 +837,4 @@
                :block/uuid #uuid "62f4b8c6-072e-4133-90e2-0591021a7fea",
                :block/parent #:db{:id 2333},
                :block/page #:db{:id 2313},
-               :block/level 3}]}]})))))
+               :block/level 3}]}]})))))