Browse Source

fix(rtc): lost first block's rtc-ops when paste multiple blocks

rcmerci 2 months ago
parent
commit
208e3df662

+ 40 - 1
src/main/frontend/worker/rtc/gen_client_op.cljs

@@ -6,13 +6,52 @@
             [logseq.db :as ldb]
             [logseq.db.frontend.property :as db-property]))
 
+(defn remove-conflict-same-block-datoms
+  "remove conflict entity-datoms for same-block(same block/uuid) in same-entity-datoms-coll.
+  merge
+  [[[182 :block/uuid block-uuid1 1 false], ...]
+   [[183 :block/uuid block-uuid1 1 true], ...]]
+  into
+  [[[183 :block/uuid block-uuid1 1 true], ...]]
+"
+  [same-entity-datoms-coll]
+  (let [entity-info (map (fn [datoms]
+                           (let [first-datom (first datoms)
+                                 e           (nth first-datom 0)
+                                 t           (nth first-datom 3)
+                                 uuid        (some (fn [d]
+                                                     (when (keyword-identical? :block/uuid (nth d 1))
+                                                       (nth d 2)))
+                                                   datoms)]
+                             {:e e :t t :uuid uuid :datoms datoms}))
+                         same-entity-datoms-coll)
+        uuid-groups (group-by :uuid (filter :uuid entity-info))
+        loser-eids  (reduce
+                     (fn [acc [_uuid infos]]
+                       (let [t-groups (group-by :t infos)]
+                         (reduce
+                          (fn [acc* [_t infos*]]
+                            (if (> (count infos*) 1)
+                              (let [sorted-infos (sort-by :e > infos*)
+                                    losers       (rest sorted-infos)]
+                                (into acc* (map :e losers)))
+                              acc*))
+                          acc
+                          t-groups)))
+                     #{}
+                     uuid-groups)]
+    (if (seq loser-eids)
+      (map :datoms (remove #(contains? loser-eids (:e %)) entity-info))
+      same-entity-datoms-coll)))
+
 (defn group-datoms-by-entity
   "Groups transaction datoms by entity and returns a map of entity-id to datoms."
   [tx-data]
   (let [datom-vec-coll (map vec tx-data)
         id->same-entity-datoms (group-by first datom-vec-coll)
         id-order (distinct (map first datom-vec-coll))
-        same-entity-datoms-coll (map id->same-entity-datoms id-order)]
+        same-entity-datoms-coll (map id->same-entity-datoms id-order)
+        same-entity-datoms-coll (remove-conflict-same-block-datoms same-entity-datoms-coll)]
     {:same-entity-datoms-coll same-entity-datoms-coll
      :id->same-entity-datoms  id->same-entity-datoms}))
 

+ 47 - 7
src/test/frontend/worker/rtc/gen_client_op_test.cljs

@@ -167,10 +167,10 @@
                         :block/tags :block/title :db/cardinality}]
     #_{:clj-kondo/ignore [:unresolved-symbol :invalid-arity]}
     (is (->> (me/find (subject/generate-rtc-ops-from-property-entities [ent])
-                      ([:move _ {:block-uuid ?block-uuid}]
-                       [:update-page _ {:block-uuid ?block-uuid}]
-                       [:update _ {:block-uuid ?block-uuid :av-coll ([!av-coll-attrs . _ ...] ...)}])
-                      !av-coll-attrs)
+               ([:move _ {:block-uuid ?block-uuid}]
+                [:update-page _ {:block-uuid ?block-uuid}]
+                [:update _ {:block-uuid ?block-uuid :av-coll ([!av-coll-attrs . _ ...] ...)}])
+               !av-coll-attrs)
              set
              (set/difference av-coll-attrs)
              empty?))))
@@ -183,9 +183,49 @@
                         :block/tags :block/title}]
     #_{:clj-kondo/ignore [:unresolved-symbol :invalid-arity]}
     (is (->> (me/find (subject/generate-rtc-ops-from-class-entities [ent])
-                      ([:update-page _ {:block-uuid ?block-uuid}]
-                       [:update _ {:block-uuid ?block-uuid :av-coll ([!av-coll-attrs . _ ...] ...)}])
-                      !av-coll-attrs)
+               ([:update-page _ {:block-uuid ?block-uuid}]
+                [:update _ {:block-uuid ?block-uuid :av-coll ([!av-coll-attrs . _ ...] ...)}])
+               !av-coll-attrs)
              set
              (set/difference av-coll-attrs)
              empty?))))
+
+(deftest remove-conflict-same-block-datoms-test
+  (testing "remove conflict entity-datoms for same-block"
+    (let [block-uuid #uuid "693ec519-e73e-4f2c-b517-7e75ca2c64da"
+          datoms-182 [[182 :logseq.property/created-by-ref 161 536870976 false]
+                      [182 :block/created-at 1765721369994 536870976 false]
+                      [182 :block/parent 162 536870976 false]
+                      [182 :block/order "aF" 536870976 false]
+                      [182 :block/tx-id 536870972 536870976 false]
+                      [182 :block/page 162 536870976 false]
+                      [182 :block/uuid block-uuid 536870976 false]
+                      [182 :block/title "" 536870976 false]
+                      [182 :block/updated-at 1765721369994 536870976 false]]
+          datoms-185 [[185 :block/parent 162 536870976 true]
+                      [185 :logseq.property/created-by-ref 161 536870976 true]
+                      [185 :block/title "111" 536870976 true]
+                      [185 :logseq.property.embedding/hnsw-label-updated-at 0 536870976 true]
+                      [185 :block/order "aG" 536870976 true]
+                      [185 :block/page 162 536870976 true]
+                      [185 :block/created-at 1765721370449 536870976 true]
+                      [185 :block/updated-at 1765721370449 536870976 true]
+                      [185 :block/uuid block-uuid 536870976 true]
+                      [185 :block/tx-id 536870976 536870977 true]]
+          same-entity-datoms-coll [datoms-182 datoms-185]
+          result (subject/remove-conflict-same-block-datoms same-entity-datoms-coll)]
+      (is (= 1 (count result)))
+      (is (= 185 (nth (ffirst result) 0)))
+      (is (= datoms-185 (first result)))))
+
+  (testing "remove conflict entity-datoms should preserve order"
+    (let [block-uuid1 #uuid "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
+          block-uuid2 #uuid "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"
+          datoms-1    [[100 :block/uuid block-uuid1 1 true]]
+          datoms-2    [[101 :block/uuid block-uuid2 2 true]]
+          datoms-3    [[102 :block/uuid block-uuid2 2 true]] ;; Conflict with datoms-2, wins (higher ID)
+          same-entity-datoms-coll [datoms-1 datoms-2 datoms-3]
+          result      (subject/remove-conflict-same-block-datoms same-entity-datoms-coll)]
+      (is (= 2 (count result)))
+      (is (= datoms-1 (first result)))
+      (is (= datoms-3 (second result))))))