diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index 04e7b37c3a..a36ec4218a 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -737,23 +737,27 @@ :tail-len tail-len}))))))))) (state/set-editor-op! nil)))) -;; Must be siblings? +(defn- get-end-block-parent + [end-block blocks] + (if-let [parent (let [id (:db/id (:block/parent end-block))] + (some (fn [block] (when (= (:db/id block) id) block)) blocks))] + (recur parent blocks) + end-block)) + (defn delete-blocks! [repo block-uuids] (when (seq block-uuids) (let [lookup-refs (map (fn [id] [:block/uuid id]) block-uuids) - blocks (db/pull-many repo '[*] lookup-refs) - parent (:block/parent (first blocks)) - top-level-blocks (filter #(= parent (:block/parent %)) blocks)] - (if (= 1 (count top-level-blocks)) - (delete-block-aux! (first blocks) false) - (let [start-node (outliner-core/block (first top-level-blocks)) - end-node (outliner-core/block (last top-level-blocks))] - (outliner-core/delete-nodes start-node end-node lookup-refs) - (let [opts {:key :block/change - :data blocks}] - (db/refresh repo opts)) - (repo-handler/push-if-auto-enabled! repo)))))) + blocks (db/pull-many repo '[*] lookup-refs)] + (let [start-node (outliner-core/block (first blocks)) + end-block (last blocks) + end-block-parent (get-end-block-parent end-block blocks) + end-node (outliner-core/block end-block-parent)] + (outliner-core/delete-nodes start-node end-node lookup-refs) + (let [opts {:key :block/change + :data blocks}] + (db/refresh repo opts)) + (repo-handler/push-if-auto-enabled! repo))))) (defn remove-block-property! [block-id key] diff --git a/src/main/frontend/modules/outliner/core.cljs b/src/main/frontend/modules/outliner/core.cljs index ddcc41daf6..7a106b1ccf 100644 --- a/src/main/frontend/modules/outliner/core.cljs +++ b/src/main/frontend/modules/outliner/core.cljs @@ -223,21 +223,52 @@ ;; Pipeline after outliner operation (outliner-file/sync-to-file node))) +(defn get-left-nodes + [node limit] + (let [parent (tree/-get-parent node)] + (loop [node node + limit limit + result []] + (if (zero? limit) + result + (if-let [left (tree/-get-left node)] + (if-not (= left parent) + (recur left (dec limit) (conj result (tree/-get-id left))) + result) + result))))) + +(defn get-node-parents + [node limit] + (loop [node node + limit limit + result []] + (if (zero? limit) + result + (if-let [parent (tree/-get-parent node)] + (recur parent (dec limit) (conj result (tree/-get-id parent))) + result)))) + (defn delete-nodes "Delete nodes from the tree, start-node and end-node must be siblings." [start-node end-node block-ids] {:pre [(tree/satisfied-inode? start-node) (tree/satisfied-inode? end-node)]} - (when (= (tree/-get-parent-id start-node) - (tree/-get-parent-id end-node)) + (if (= start-node end-node) + (delete-node start-node) (let [right-node (tree/-get-right end-node) - conn (conn/get-conn false)] - (db-outliner/del-blocks conn block-ids) - (when (tree/satisfied-inode? right-node) - (let [left-node (tree/-get-left start-node) - new-right-node (tree/-set-left-id right-node (tree/-get-id left-node))] - (tree/-save new-right-node))) - (outliner-file/sync-to-file start-node)))) + conn (conn/get-conn false) + end-node-left-nodes (get-left-nodes end-node (count block-ids)) + start-node-parents-with-self (conj (get-node-parents start-node 1000) (tree/-get-id start-node))] + (when (tree/satisfied-inode? right-node) + (let [cross-node-id (first (set/intersection (set end-node-left-nodes) (set start-node-parents-with-self))) + cross-node (get-block-by-id cross-node-id) + new-left-id (if (= cross-node start-node) + (tree/-get-left-id cross-node) + cross-node-id) + new-right-node (tree/-set-left-id right-node new-left-id)] + (tree/-save new-right-node))) + (db-outliner/del-blocks conn block-ids) + (outliner-file/sync-to-file start-node)))) (defn move-subtree* "Move subtree to a destination position in the relation tree.