Просмотр исходного кода

fix: ensure :block/uuid never changes for any block

Previously, this happens when `DEL` in a block which followed by a
refed block.
Tienson Qin 2 лет назад
Родитель
Сommit
660ac318cf

+ 14 - 18
src/main/frontend/handler/editor.cljs

@@ -258,17 +258,12 @@
     (profile
      "Save block: "
      (let [original-block (db/entity (:db/id block))
-           original-uuid (:block/uuid original-block)
            original-props (:block/properties original-block)
-           uuid-changed? (not= (:block/uuid block) original-uuid)
            block' (-> (wrap-parse-block block)
                       ;; :block/uuid might be changed when backspace/delete
                       ;; a block that has been refed
                       (assoc :block/uuid (:block/uuid block)))
-           opts' (merge opts (cond-> {:outliner-op :save-block}
-                               uuid-changed?
-                               (assoc :uuid-changed {:from (:block/uuid block)
-                                                     :to original-uuid})))]
+           opts' (assoc opts :outliner-op :save-block)]
 
        (let [{:keys [tx-data]}
              (outliner-tx/transact!
@@ -809,7 +804,6 @@
                          (delete-block-fn prev-block)
                          (save-block! repo block new-content {:editor/op :delete})
                          (outliner-core/save-block! {:db/id (:db/id block)
-                                                     :block/uuid (:block/uuid block)
                                                      :block/parent (:db/id (:block/parent prev-block))
                                                      :block/left (or (:db/id (:block/left prev-block))
                                                                      (:db/id (:block/parent prev-block)))})
@@ -2694,22 +2688,24 @@
                                     (drawer/remove-logbook)))
                           (str value "" (:block/content next-block)))
             repo (state/get-current-repo)
-            edit-block' (if next-block-has-refs?
-                          (assoc edit-block
-                                 :block/uuid (:block/uuid next-block))
-                          edit-block)
-            new-properties (merge
-                            (:block/properties (db/entity (:db/id next-block)))
-                            (:block/properties (db/entity (:db/id edit-block))))]
+            delete-block (if next-block-has-refs? edit-block next-block)
+            keep-block (if next-block-has-refs? next-block edit-block)]
         (outliner-tx/transact!
          {:outliner-op :delete-blocks
           :concat-data {:last-edit-block (:block/uuid edit-block)
                         :end? true}}
-         (delete-block-aux! next-block false)
-         (save-block! repo edit-block' new-content {:editor/op :delete})
+         (delete-block-aux! delete-block false)
+         (save-block! repo keep-block new-content {:editor/op :delete})
+         (when next-block-has-refs?
+           (outliner-core/save-block! {:db/id (:db/id keep-block)
+                                       :block/left (:db/id (:block/left delete-block))}))
          (when db-based?
-           (outliner-core/save-block! {:db/id (:db/id edit-block)
-                                       :block/properties new-properties})))
+           (let [new-properties (merge
+                                 (:block/properties (db/entity (:db/id edit-block)))
+                                 (:block/properties (db/entity (:db/id next-block))))]
+             (when-not (= new-properties (:block/properties keep-block))
+               (outliner-core/save-block! {:db/id (:db/id keep-block)
+                                           :block/properties new-properties})))))
         (let [block (if next-block-has-refs? next-block edit-block)]
           (edit-block! block current-pos nil))))))
 

+ 14 - 2
src/main/frontend/modules/outliner/core.cljs

@@ -303,13 +303,25 @@
                 fix-tag-ids)
           repo (state/get-current-repo)
           db-based? (config/db-based-graph? repo)
-          eid (or (:db/id (:data this))
-                  (when-let [block-uuid (:block/uuid (:data this))] [:block/uuid block-uuid]))
+          db-id (:db/id (:data this))
+          block-uuid (:block/uuid (:data this))
+          eid (or db-id (when block-uuid [:block/uuid block-uuid]))
           block-entity (db/entity eid)
           tags-has-class? (and db-based?
                                (some (fn [tag]
                                        (contains? (:block/type (db/entity [:block/uuid (:block/uuid tag)])) "class"))
                                      (:block/tags m)))]
+
+      ;; Ensure block UUID never changes
+      (when (and db-id block-uuid)
+        (let [uuid-not-changed? (= block-uuid (:block/uuid (db/entity db-id)))]
+          (when-not uuid-not-changed?
+            (when config/dev?
+              (state/pub-event! [:notification/show
+                                {:content "Block UUID shouldn't be changed"
+                                 :status :error}])))
+          (assert uuid-not-changed? "Block UUID changed")))
+
       (when eid
         ;; Retract attributes to prepare for tx which rewrites block attributes
         (when (:block/content m)

+ 7 - 40
src/main/frontend/modules/outliner/datascript.cljs

@@ -80,39 +80,10 @@
   [tx-report]
   (get-in tx-report [:tempids :db/current-tx]))
 
-(defn update-block-refs
-  [txs opts]
-  (if-let [changed (:uuid-changed opts)]
-    (let [{:keys [from to]} changed
-          from-e (db/entity [:block/uuid from])
-          to-e (db/entity [:block/uuid to])
-          from-id (:db/id from-e)
-          to-id (:db/id to-e)
-          from-refs (:block/_refs from-e)
-          from-path-refs (:block/_path-refs from-e)
-          to-refs (:block/_refs to-e)
-          from-refs-txs (mapcat (fn [ref]
-                                  (let [id (:db/id ref)]
-                                    [[:db/retract id :block/refs from-id]
-                                     [:db/add id :block/refs to-id]])) from-refs)
-          from-path-refs-txs (mapcat (fn [ref]
-                                       (let [id (:db/id ref)]
-                                         [[:db/retract id :block/path-refs from-id]
-                                          [:db/add id :block/path-refs to-id]])) from-path-refs)
-          to-refs-txs (mapcat (fn [ref]
-                                (let [id (:db/id ref)
-                                      new-content (string/replace (:block/content ref)
-                                                                  (block-ref/->block-ref to)
-                                                                  (block-ref/->block-ref from))]
-                                  [[:db/add id :block/content new-content]])) to-refs)]
-      (concat txs from-refs-txs from-path-refs-txs to-refs-txs))
-    txs))
-
 (defn update-refs-and-macros
   "When a block is deleted, refs are updated and macros associated with the block are deleted"
   [txs repo opts]
-  (if (and (= :delete-blocks (:outliner-op opts))
-           (empty? (:uuid-changed opts)))
+  (if (= :delete-blocks (:outliner-op opts))
     (let [retracted-block-ids (->> (keep (fn [tx]
                                            (when (and (vector? tx)
                                                       (= :db.fn/retractEntity (first tx)))
@@ -146,9 +117,9 @@
           macros-tx (mapcat (fn [b]
                               ;; Only delete if last reference
                               (keep #(when (<= (count (:block/_macros (db/entity repo (:db/id %))))
-                                                   1)
-                                           (vector :db.fn/retractEntity (:db/id %)))
-                                        (:block/macros b)))
+                                               1)
+                                       (vector :db.fn/retractEntity (:db/id %)))
+                                    (:block/macros b)))
                             retracted-blocks)]
       (when (seq retracted-tx')
         (state/set-state! [:editor/last-replace-ref-content-tx (state/get-current-repo)]
@@ -179,16 +150,12 @@
         txs (map (fn [m]
                    (if (map? m)
                      (dissoc m :block/children :block/meta :block/top? :block/bottom? :block/anchor
-                               :block/title :block/body :block/level :block/container :db/other-tx
-                               :block/unordered)
+                             :block/title :block/body :block/level :block/container :db/other-tx
+                             :block/unordered)
                      m)) txs)
         txs (remove-nil-from-transaction txs)
         txs (cond-> txs
-              (:uuid-changed opts)
-              (update-block-refs opts)
-
-              (and (= :delete-blocks (:outliner-op opts))
-                   (empty? (:uuid-changed opts)))
+              (= :delete-blocks (:outliner-op opts))
               (update-refs-and-macros repo opts)
 
               true