diff --git a/deps/outliner/src/logseq/outliner/core.cljs b/deps/outliner/src/logseq/outliner/core.cljs index 3f5d50b81d..355a35060b 100644 --- a/deps/outliner/src/logseq/outliner/core.cljs +++ b/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)) diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index 9fc142154f..c8a0063af1 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/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? diff --git a/src/main/frontend/handler/paste.cljs b/src/main/frontend/handler/paste.cljs index 70b597bd9f..9de7bdf8c2 100644 --- a/src/main/frontend/handler/paste.cljs +++ b/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! diff --git a/src/main/frontend/worker/db_sync.cljs b/src/main/frontend/worker/db_sync.cljs index e21f66774d..2ac44464fa 100644 --- a/src/main/frontend/worker/db_sync.cljs +++ b/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 (aes-key assoc repo aes-key) diff --git a/src/test/frontend/modules/outliner/core_test.cljs b/src/test/frontend/modules/outliner/core_test.cljs index 14803e4e51..3f59bc8246 100644 --- a/src/test/frontend/modules/outliner/core_test.cljs +++ b/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}]}]}))))) \ No newline at end of file + :block/level 3}]}]})))))