瀏覽代碼

fix: move-blocks when multiple same embedded blocks

Tienson Qin 2 年之前
父節點
當前提交
9fba34dd22

+ 13 - 9
src/main/frontend/components/block.cljs

@@ -20,7 +20,6 @@
             [frontend.components.svg :as svg]
             [frontend.components.query :as query]
             [frontend.components.property :as property-component]
-            [frontend.components.property.value :as property-value]
             [frontend.config :as config]
             [frontend.context.i18n :refer [t]]
             [frontend.date :as date]
@@ -2661,7 +2660,7 @@
    (editor-handler/unhighlight-blocks!)))
 
 (defn- block-drop
-  [^js event uuid target-block *move-to]
+  [^js event uuid target-block original-block *move-to]
   (util/stop event)
   (when-not (dnd-same-block? uuid)
     (let [block-uuids (state/get-selection-block-ids)
@@ -2677,7 +2676,7 @@
             :edit-block? false
             :sibling?    (= @*move-to :sibling)
             :before?     (= @*move-to :top)}))
-        (dnd/move-blocks event blocks target-block @*move-to))))
+        (dnd/move-blocks event blocks target-block original-block @*move-to))))
   (block-drag-end event *move-to))
 
 (defn- block-mouse-over
@@ -2707,13 +2706,13 @@
     (state/into-selection-mode!)))
 
 (defn- on-drag-and-mouse-attrs
-  [block uuid top? block-id *move-to]
+  [block original-block uuid top? block-id *move-to]
   {:on-drag-over (fn [event]
                    (block-drag-over event uuid top? block-id *move-to))
    :on-drag-leave (fn [_event]
                     (block-drag-leave *move-to))
    :on-drop (fn [event]
-              (block-drop event uuid block *move-to))
+              (block-drop event uuid block original-block *move-to))
    :on-drag-end (fn [event]
                   (block-drag-end event *move-to))})
 
@@ -2811,7 +2810,8 @@
         block-id (str "ls-block-" blocks-container-id "-" uuid)
         has-child? (first (:block/_parent (db/entity (:db/id block))))
         top? (zero? (:idx config))
-        attrs (on-drag-and-mouse-attrs block uuid top? block-id *move-to)
+        original-block (:original-block config)
+        attrs (on-drag-and-mouse-attrs block original-block uuid top? block-id *move-to)
         children-refs (get-children-refs block)
         data-refs (build-refs-data-value children-refs)
         data-refs-self (build-refs-data-value refs)
@@ -2820,7 +2820,8 @@
         own-number-list? (:own-order-number-list? config)
         order-list? (boolean own-number-list?)
         selected? (when-not slide?
-                    (state/sub-block-selected? blocks-container-id uuid))]
+                    (state/sub-block-selected? blocks-container-id uuid))
+        config (dissoc config :original-block)]
     [:div.ls-block
      (cond->
       {:id block-id
@@ -2836,6 +2837,9 @@
        :blockid (str uuid)
        :haschild (str (boolean has-child?))}
 
+       original-block
+       (assoc :originalblockid (str (:block/uuid original-block)))
+
        level
        (assoc :level level)
 
@@ -3354,10 +3358,10 @@
                       :idx idx)
         config' (if linked-block
                   (let [new-container-id (state/next-blocks-container-id)]
-                    (prn {:new-container-id new-container-id})
                     (assoc config
                            :original-block original-block
-                           :blocks-container-id new-container-id))
+                           ;; :blocks-container-id new-container-id
+                           ))
                   config)]
     (rum/with-key (block-container config' item)
       (str (:blocks-container-id config') "-" (:block/uuid item)))))

+ 1 - 2
src/main/frontend/db/fix.cljs

@@ -8,8 +8,7 @@
             [frontend.db.model :as db-model]
             [frontend.util :as util]
             [frontend.state :as state]
-            [frontend.handler.notification :as notification]
-            [clojure.set :as set]))
+            [frontend.handler.notification :as notification]))
 
 (defn- fix-parent-broken-chain
   [db parent-id]

+ 2 - 2
src/main/frontend/handler/dnd.cljs

@@ -10,7 +10,7 @@
             [frontend.db :as db]))
 
 (defn move-blocks
-  [^js event blocks target-block move-to]
+  [^js event blocks target-block original-block move-to]
   (let [blocks' (map #(db/pull (:db/id %)) blocks)
         first-block (first blocks')
         top? (= move-to :top)
@@ -19,7 +19,7 @@
         current-format (:block/format first-block)
         target-format (:block/format target-block)
         target-block (if nested? target-block
-                         (or (first (:block/_link (db/entity (:db/id target-block)))) target-block))]
+                         (or original-block target-block))]
     (cond
       ;; alt pressed, make a block-ref
       (and alt-key? (= (count blocks) 1))

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

@@ -1674,15 +1674,9 @@
     (save-current-block!)
     (let [edit-block-id (:block/uuid (state/get-edit-block))
           move-nodes (fn [blocks]
-                       (let [top-level-blocks (->> (outliner-core/get-top-level-blocks blocks)
-                                                   (map (fn [b]
-                                                          (let [original-block (first (:block/_link (db/entity (:db/id b))))]
-                                                            (or (and original-block
-                                                                     (db/pull (:db/id original-block)))
-                                                                b)))))]
-                         (outliner-tx/transact!
-                          {:outliner-op :move-blocks}
-                          (outliner-core/move-blocks-up-down! top-level-blocks up?)))
+                       (outliner-tx/transact!
+                        {:outliner-op :move-blocks}
+                        (outliner-core/move-blocks-up-down! blocks up?))
                        (when-let [block-node (util/get-first-block-by-id (:block/uuid (first blocks)))]
                          (.scrollIntoView block-node #js {:behavior "smooth" :block "nearest"})))]
       (if edit-block-id
@@ -3645,8 +3639,8 @@
   ([select?]
    (when (state/editing?)
      (if select?
-       (->> (:block/uuid (state/get-edit-block))
-            select-block!)
+       (when-let [node (some-> (state/get-input) (util/rec-get-node "ls-block"))]
+         (state/exit-editing-and-set-selected-blocks! [node]))
        (state/clear-edit!)))))
 
 (defn replace-block-reference-with-content-at-point

+ 80 - 79
src/main/frontend/modules/outliner/core.cljs

@@ -19,7 +19,9 @@
             [frontend.handler.file-based.property.util :as property-util]
             [frontend.handler.property.util :as pu]
             [frontend.db.rtc.op :as rtc-op]
-            [frontend.format.mldoc :as mldoc]))
+            [frontend.format.mldoc :as mldoc]
+            [dommy.core :as dom]
+            [goog.object :as gobj]))
 
 (s/def ::block-map (s/keys :opt [:db/id :block/uuid :block/page :block/left :block/parent]))
 
@@ -498,12 +500,44 @@
               m' (vec (conj m block))]
           (recur m' (rest blocks)))))))
 
+(defn- get-original-block-by-dom
+  [node]
+  (when-let [id (some-> node
+                        (gobj/get "parentNode")
+                        (util/rec-get-node "ls-block")
+                        (dom/attr "originalblockid")
+                        uuid)]
+    (db/entity [:block/uuid id])))
+
+(defn get-original-block
+  "Get the original block from the current editing block or selected blocks"
+  [linked-block]
+  (cond
+    (and
+     (= (:block/uuid linked-block)
+        (:block/uuid (state/get-edit-block)))
+     (state/get-input)) ; editing block
+    (get-original-block-by-dom (state/get-input))
+
+    (seq (state/get-selection-blocks))
+    (->> (state/get-selection-blocks)
+         (remove nil?)
+         (keep #(when-let [id (dom/attr % "blockid")]
+                  (when (= (uuid id) (:block/uuid linked-block))
+                    (when-let [original-id (some-> (dom/attr % "originalblockid") uuid)]
+                      (db/entity [:block/uuid original-id])))))
+         ;; FIXME: what if there're multiple same blocks in the selection
+         first)))
+
 (defn get-top-level-blocks
   "Get only the top level blocks."
   [blocks]
   {:pre [(seq blocks)]}
   (let [level-blocks (blocks-with-level blocks)]
-    (filter (fn [b] (= 1 (:block/level b))) level-blocks)))
+    (->> (filter (fn [b] (= 1 (:block/level b))) level-blocks)
+         (map (fn [b]
+                (let [original (get-original-block b)]
+                  (or (and original (db/pull (:db/id original))) b)))))))
 
 (defn- get-right-siblings
   "Get `node`'s right siblings."
@@ -844,10 +878,6 @@
                 (:db/id target-block))
              sibling?)))
 
-(defn get-original-block
-  [linked-block]
-  (first (:block/_link (db/entity (:db/id linked-block)))))
-
 (defn move-blocks
   "Move `blocks` to `target-block` as siblings or children."
   [blocks target-block {:keys [_sibling? _up? outliner-op _indent?]
@@ -855,6 +885,7 @@
   [:pre [(seq blocks)
          (s/valid? ::block-map-or-entity target-block)]]
   (let [blocks (map (fn [b] (db/pull [:block/uuid (:block/uuid b)])) blocks)
+        blocks (get-top-level-blocks blocks)
         [target-block sibling?] (get-target-block target-block opts)
         non-consecutive-blocks? (seq (db-model/get-non-consecutive-blocks blocks))
         original-position? (move-to-original-position? blocks target-block sibling? non-consecutive-blocks?)]
@@ -865,12 +896,7 @@
                          (set))
             move-parents-to-child? (some parents (map :db/id blocks))]
         (when-not move-parents-to-child?
-          (let [blocks (->> (get-top-level-blocks blocks)
-                            (map (fn [b]
-                                   (let [original (get-original-block b)
-                                         original' (when original (db/pull (:db/id original)))]
-                                     (or original' b)))))
-                first-block (first blocks)
+          (let [first-block (first blocks)
                 {:keys [tx-data]} (insert-blocks blocks target-block {:sibling? sibling?
                                                                       :outliner-op (or outliner-op :move-blocks)})]
             (when (seq tx-data)
@@ -905,27 +931,9 @@
         first-block (db/entity (:db/id (first top-level-blocks)))
         first-block-parent (:block/parent first-block)
         left (:block/left first-block)
-        left-original (first (:block/_link left))
         left-left (:block/left left)
-        left-left-linked (:block/link left-left)
-        last-top-block (last top-level-blocks)
-        last-top-block-parent (:block/parent last-top-block)
-        right (get-right-sibling (:db/id last-top-block))
         opts {:outliner-op :move-blocks-up-down}]
     (cond
-      (and up? left-left-linked (not= (:db/id first-block-parent)
-                                      (:db/id (:block/parent left-left))))
-      (let [[target sibling?] (get-last-child-or-self left-left-linked)]
-        (move-blocks top-level-blocks target (merge opts {:sibling? sibling?
-                                                          :up? up?})))
-
-      (and up? left-original (:block/left left-original))
-      (let [left-left-original (:block/left left-original)
-            block (or (:block/link left-left-original) left-left-original)
-            [target sibling?] (get-last-child-or-self block)]
-        (move-blocks top-level-blocks target (merge opts {:sibling? sibling?
-                                                          :up? up?})))
-
       (and up? left-left)
       (cond
         (= (:block/parent left-left) first-block-parent)
@@ -950,48 +958,44 @@
         nil)
 
       (not up?)
-      (let [original-block (when last-top-block-parent (first (:block/_link (db/entity (:db/id last-top-block-parent)))))
-            original-block-right (when original-block (get-right-sibling (:db/id original-block)))]
-        (cond
-          right
+      (let [last-top-block (last top-level-blocks)
+            last-top-block-parent (:block/parent last-top-block)
+            right (get-right-sibling (:db/id last-top-block))]
+        (if right
           (move-blocks blocks right (merge opts {:sibling? true
                                                  :up? up?}))
-
-          original-block-right
-          (move-blocks blocks original-block-right (merge opts {:sibling? false
-                                                                :up? up?}))
-
-          :else
           (when last-top-block-parent
             (when-let [parent-right (get-right-sibling (:db/id last-top-block-parent))]
-              (if-let [linked-block (:block/link parent-right)]
-                (move-blocks blocks linked-block (merge opts {:sibling? false
-                                                              :up? up?}))
-                (move-blocks blocks parent-right (merge opts {:sibling? false
-                                                              :up? up?})))))))
+              (move-blocks blocks parent-right (merge opts {:sibling? false
+                                                            :up? up?}))))))
 
       :else
       nil)))
 
+(defn- get-first-block-original
+  []
+  (if-let [input (state/get-input)]
+    (get-original-block-by-dom (util/rec-get-node input "ls-block"))
+    (when-let [node (some-> (first (state/get-selection-blocks)))]
+      (get-original-block-by-dom node))))
+
 (defn indent-outdent-blocks
   "Indent or outdent `blocks`."
   [blocks indent?]
   {:pre [(seq blocks) (boolean? indent?)]}
-  (let [non-consecutive-blocks (db-model/get-non-consecutive-blocks blocks)]
+  (let [top-level-blocks (get-top-level-blocks blocks)
+        non-consecutive-blocks (db-model/get-non-consecutive-blocks top-level-blocks)]
     (when (empty? non-consecutive-blocks)
-      (let [first-block (db/entity (:db/id (first blocks)))
+      (let [first-block (db/entity (:db/id (first top-level-blocks)))
             left (db/entity (:db/id (:block/left first-block)))
             parent (:block/parent first-block)
             db (db/get-db)
-            top-level-blocks (get-top-level-blocks blocks)
             concat-tx-fn (fn [& results]
                            {:tx-data (->> (map :tx-data results)
                                           (apply util/concat-without-nil))
                             :tx-meta (:tx-meta (first results))})
-            opts {:outliner-op :indent-outdent-blocks}
-            parent-original (first (:block/_link parent))]
-        (cond
-          indent?
+            opts {:outliner-op :indent-outdent-blocks}]
+        (if indent?
           (when (and left (not (page-first-child? first-block)))
             (let [last-direct-child-id (db-model/get-block-last-direct-child db (:db/id left) false)
                   blocks' (drop-while (fn [b]
@@ -1010,35 +1014,33 @@
                     (concat-tx-fn result collapsed-tx))
                   (move-blocks blocks' left (merge opts {:sibling? false
                                                          :indent? true}))))))
-
-          (and parent-original (not indent?))
-          (let [blocks' (take-while (fn [b]
-                                      (not= (:db/id (:block/parent b))
-                                            (:db/id (:block/parent parent))))
-                                    top-level-blocks)]
-            (move-blocks blocks' parent-original (merge opts {:outliner-op :indent-outdent-blocks
-                                                              :sibling? true
-                                                              :indent? false})))
-
-          :else
-          (when (and parent (not (page-block? (db/entity (:db/id parent)))))
+          (if-let [parent-original (get-first-block-original)]
             (let [blocks' (take-while (fn [b]
                                         (not= (:db/id (:block/parent b))
                                               (:db/id (:block/parent parent))))
-                                      top-level-blocks)
-                  result (move-blocks blocks' parent (merge opts {:sibling? true}))]
-              (if (state/logical-outdenting?)
-                result
-                ;; direct outdenting (default behavior)
-                (let [last-top-block (db/pull (:db/id (last blocks')))
-                      right-siblings (->> (get-right-siblings (block last-top-block))
-                                          (map :data))]
-                  (if (seq right-siblings)
-                    (let [result2 (if-let [last-direct-child-id (db-model/get-block-last-direct-child db (:db/id last-top-block) false)]
-                                    (move-blocks right-siblings (db/entity last-direct-child-id) (merge opts {:sibling? true}))
-                                    (move-blocks right-siblings last-top-block (merge opts {:sibling? false})))]
-                      (concat-tx-fn result result2))
-                    result))))))))))
+                                      top-level-blocks)]
+              (move-blocks blocks' parent-original (merge opts {:outliner-op :indent-outdent-blocks
+                                                                :sibling? true
+                                                                :indent? false})))
+
+            (when (and parent (not (page-block? (db/entity (:db/id parent)))))
+              (let [blocks' (take-while (fn [b]
+                                          (not= (:db/id (:block/parent b))
+                                                (:db/id (:block/parent parent))))
+                                        top-level-blocks)
+                    result (move-blocks blocks' parent (merge opts {:sibling? true}))]
+                (if (state/logical-outdenting?)
+                  result
+                  ;; direct outdenting (default behavior)
+                  (let [last-top-block (db/pull (:db/id (last blocks')))
+                        right-siblings (->> (get-right-siblings (block last-top-block))
+                                            (map :data))]
+                    (if (seq right-siblings)
+                      (let [result2 (if-let [last-direct-child-id (db-model/get-block-last-direct-child db (:db/id last-top-block) false)]
+                                      (move-blocks right-siblings (db/entity last-direct-child-id) (merge opts {:sibling? true}))
+                                      (move-blocks right-siblings last-top-block (merge opts {:sibling? false})))]
+                        (concat-tx-fn result result2))
+                      result)))))))))))
 
 ;;; ### write-operations have side-effects (do transactions) ;;;;;;;;;;;;;;;;
 
@@ -1098,7 +1100,6 @@
       (rtc-op/<move-blocks-op! repo (keep :block/uuid blocks))))
   (op-transact! #'move-blocks blocks target-block {:sibling? sibling?
                                                    :outliner-op :move-blocks}))
-
 (defn move-blocks-up-down!
   [blocks up?]
   (let [repo (:repo *transaction-args*)

+ 10 - 8
src/main/frontend/util.cljc

@@ -780,20 +780,22 @@
             (rec-get-tippy-container (gobj/get node "parentNode"))))))
 
 #?(:cljs
-   (defn rec-get-blocks-container
-     [node]
-     (if (and node (d/has-class? node "blocks-container"))
+   (defn rec-get-node
+     [node class]
+     (if (and node (d/has-class? node class))
        node
        (and node
-            (rec-get-blocks-container (gobj/get node "parentNode"))))))
+            (rec-get-node (gobj/get node "parentNode") class)))))
+
+#?(:cljs
+   (defn rec-get-blocks-container
+     [node]
+     (rec-get-node node "blocks-container")))
 
 #?(:cljs
    (defn rec-get-blocks-content-section
      [node]
-     (if (and node (d/has-class? node "content"))
-       node
-       (and node
-            (rec-get-blocks-content-section (gobj/get node "parentNode"))))))
+     (rec-get-node node "content")))
 
 #?(:cljs
    (defn get-blocks-noncollapse

+ 1 - 1
src/main/logseq/api.cljs

@@ -674,7 +674,7 @@
                          nil)
           src-block    (db-model/query-block-by-uuid (sdk-utils/uuid-or-throw-error src-block-uuid))
           target-block (db-model/query-block-by-uuid (sdk-utils/uuid-or-throw-error target-block-uuid))]
-      (editor-dnd-handler/move-blocks nil [src-block] target-block move-to) nil)))
+      (editor-dnd-handler/move-blocks nil [src-block] target-block nil move-to) nil)))
 
 (def ^:export get_block api-block/get_block)