浏览代码

update page sync init process

rcmerci 4 年之前
父节点
当前提交
893f33064e

+ 14 - 0
src/main/frontend/handler/common.cljs

@@ -327,6 +327,9 @@
                      (drawer/remove-logbook)
                      (drawer/with-logbook block))
         content (with-timetracking block content)
+        content (if uuid ; persist uuid into content
+                  (property/insert-property format content "ID" (str uuid))
+                  content)
         first-block? (= left page)
         ast (mldoc/->edn (string/trim content) (mldoc/default-config format))
         first-elem-type (first (ffirst ast))
@@ -367,3 +370,14 @@
         (assoc :block/content content
                :block/properties new-properties)
         (merge (if level {:block/level level} {})))))
+
+(defn reorder-blocks
+  [blocks]
+  (if (<= (count blocks) 1)
+    blocks
+    (let [[f s & others] blocks]
+      (if (= (or (:block/left s)
+                 (:block/parent s))
+             {:db/id (:db/id f)})
+        blocks
+        (reverse blocks)))))

+ 3 - 17
src/main/frontend/handler/editor.cljs

@@ -343,7 +343,7 @@
       (when-not skip-save-current-block?
         (outliner-yjs/save-node-op current-node))
       (outliner-yjs/insert-node-op new-node current-node sibling? {:blocks-atom *blocks
-                                                                 :skip-transact? false})
+                                                                   :skip-transact? false})
       {:blocks @*blocks
        :sibling? sibling?})))
 
@@ -815,20 +815,6 @@
         end-block-parent (get-end-block-parent end-block blocks)]
     (outliner-core/block end-block-parent)))
 
-(defn- reorder-blocks
-  [blocks]
-  (if (<= (count blocks) 1)
-    blocks
-    (let [[f s & others] blocks]
-      (if (or
-           (= (:block/left s) {:db/id (:db/id f)})
-           (let [parents (db/get-block-parents (state/get-current-repo)
-                                               (:block/uuid f)
-                                               100)]
-             (some #(= (:block/left s) {:db/id (:db/id %)})
-                   parents)))
-        blocks
-        (reverse blocks)))))
 
 (defn delete-blocks!
   [repo dom-blocks]
@@ -837,7 +823,7 @@
       (let [uuid->dom-block (zipmap block-uuids dom-blocks)
             lookup-refs (map (fn [id] [:block/uuid id]) block-uuids)
             blocks (db/pull-many repo '[*] lookup-refs)
-            blocks (reorder-blocks blocks)
+            blocks (common-handler/reorder-blocks blocks)
             start-node (outliner-core/block (first blocks))
             end-node (get-top-level-end-node blocks)
             block (first blocks)
@@ -1720,7 +1706,7 @@
                                                     [:block/uuid (medley/uuid id)])) blocks)
                                  (remove nil?))
                 blocks (db/pull-many repo '[*] lookup-refs)
-                blocks (reorder-blocks blocks)
+                blocks (common-handler/reorder-blocks blocks)
                 end-node (get-top-level-end-node blocks)
                 end-node-parent (tree/-get-parent end-node)
                 top-level-nodes (->> (filter #(= (get-in end-node-parent [:data :db/id])

+ 1 - 0
src/main/frontend/modules/outliner/core.cljs

@@ -336,6 +336,7 @@
   "Insert nodes as children(or siblings) of target-node.
   new-nodes-tree is an vector of blocks, e.g [1 [2 3] 4 [5 [6 7]]]"
   [new-nodes-tree target-node sibling?]
+  {:pre [(> (count new-nodes-tree) 0)]}
   (ds/auto-transact!
    [txs-state (ds/new-outliner-txs-state)] {:outliner-op :insert-nodes}
    (let [loc (zip/vector-zip new-nodes-tree)]

+ 120 - 30
src/main/frontend/modules/outliner/yjs.cljs

@@ -8,7 +8,9 @@
             [frontend.handler.common :as common-handler]
             [frontend.state :as state]
             [frontend.db :as db]
-            [frontend.db.model :as db-model]))
+            [frontend.db.model :as db-model]
+            [clojure.zip :as zip]
+            [datascript.core :as d]))
 
 (set! *warn-on-infer* false)
 
@@ -119,7 +121,9 @@
 (defn- insert-node [left-id parent-id id contentmap]
   {:pre [(seq parent-id)]}
   (let [left-id (or left-id parent-id)
-        content (str "- " (.get contentmap id))
+        content (frontend.util.property/insert-property
+                 :markdown (str "- " (.get contentmap id))
+                 "ID" id)
         target-node (outliner-core/block (db-model/query-block-by-uuid left-id))
         format (:block/format target-node)
         new-node (outliner-core/block
@@ -133,7 +137,6 @@
   (when-let [block (db-model/query-block-by-uuid id)]
     (outliner-core/delete-node (outliner-core/block block) false)))
 
-
 (defn- observe-struct-fn [page-name]
   (fn [events]
     (mapv (fn [event]
@@ -158,14 +161,21 @@
     (mapv (fn [[k v]]
             (case (get "action" v)
               "update" (update-block-content k)
-              "delete" (delete-node k))) keys)))
+              "delete" (delete-node k)
+              (println "action" v))) keys)))
 
 (defn observe-page-doc [page-name doc]
+  (let [struct (.getArray doc (str page-name "-struct"))
+        contentmap (contentmap)]
+    (.unobserveDeep struct (observe-struct-fn-memo page-name))
+    (.unobserve contentmap observe-content-fn)
+    ;; (.observeDeep struct (observe-struct-fn-memo page-name))
+    (.observe contentmap observe-content-fn)))
+
+(defn unobserve-page-doc [page-name doc]
   (let [struct (.getArray doc (str page-name "-struct"))]
     (.unobserveDeep struct (observe-struct-fn-memo page-name))
-    (.unobserve struct observe-content-fn)
-    (.observeDeep struct (observe-struct-fn-memo page-name))
-    (.observe struct observe-content-fn)))
+    (.unobserve struct observe-content-fn)))
 
 (defn merge-doc [doc1 doc2]
   (let [s1 (y/encodeStateVector doc1)
@@ -183,16 +193,79 @@
   )
 
 
+(defn- remove-all-blocks-in-page [page-blocks page-name]
+  (let [order-blocks (common-handler/reorder-blocks page-blocks)
+        start-block (first order-blocks)
+        end-block (last order-blocks)
+        block-ids (mapv (fn [b] [:block/uuid (:block/uuid b)]) order-blocks)]
+    (when (and start-block end-block)
+      (outliner-core/delete-nodes (outliner-core/block start-block)
+                                  (outliner-core/block end-block)
+                                  block-ids))))
+
+(defn- insert-doc-contents [page-name]
+  (let [page-block (db/pull (:db/id (db/get-page page-name)))
+        format (or (:block/format page-block)
+                   (state/get-preferred-format))
+        smap (js->clj (.toJSON (contentmap)))
+        content-tree (clojure.walk/prewalk-replace smap (js->clj (.toJSON (structarray page-name))))
+        content-tree-z (zip/vector-zip content-tree)
+        node-tree (loop [loc content-tree-z]
+                    (if (zip/end? loc)
+                      (zip/root loc)
+                      (cond
+                        (vector? (zip/node loc))
+                        (recur (zip/next loc))
+
+                        (string? (zip/node loc))
+                        (let [block (first
+                                     (block/extract-blocks
+                                      (mldoc/->edn (zip/node loc) (mldoc/default-config format))
+                                      (zip/node loc) true format))
+                              block (merge
+                                     (dissoc block
+                                             :block/pre-block?
+                                             :db/id
+                                             :block/left
+                                             :block/parent
+                                             :block/file)
+                                     {:block/page (select-keys page-block [:db/id])
+                                      :block/format format
+                                      :block/path-refs (->> (cons (:db/id page-block)
+                                                                  (:block/path-refs block))
+                                                            (remove nil?))})]
+                          (if (:block/uuid block)
+                            (recur (zip/next
+                                    (zip/replace
+                                     loc
+                                     (outliner-core/block block))))
+                            (recur (zip/remove loc))))
+                        :else
+                        (recur (zip/next loc)))))]
+    (when-not (empty? node-tree)
+      (outliner-core/insert-nodes node-tree (outliner-core/block page-block) false)
+      (let [new-block-uuids (mapv (fn [n] (:block/uuid (:data n))) (flatten node-tree))
+            new-blocks (db/pull-many (state/get-current-repo) '[*] (map (fn [id] [:block/uuid id]) new-block-uuids))]
+        new-blocks))))
+
+(defn doc->page-blocks [page-blocks page-name]
+  (let [contentmap (contentmap)
+        struct (structarray page-name)]
+    (remove-all-blocks-in-page page-blocks page-name)
+    (when-let [new-blocks (insert-doc-contents page-name)]
+      (db/refresh! (state/get-current-repo) {:key :block/insert :data new-blocks}))))
+
 (defn start-sync-page [page-name]
-  (let [page-blocks (db/get-page-blocks page-name)]
+  (let [page-blocks (db/get-page-blocks-no-cache page-name)]
     (page-blocks->doc page-blocks page-name)
     (observe-page-doc page-name doc-local)
     (sync-doc doc-local doc-remote)
-    (merge-doc doc-remote doc-local)))
+    (distinct-struct (structarray page-name) (atom #{}))
+    (merge-doc doc-remote doc-local)
+    (doc->page-blocks page-blocks page-name)))
 
 (defn stop-sync-page [page-name]
-  ;; TODO
-  )
+  (unobserve-page-doc page-name doc-local))
 
 (defn- goto-innermost-struct-array [pos struct]
   (loop [i 0 s struct]
@@ -234,6 +307,10 @@
   INext
   (-next [_] (next pos-vec))
 
+  ISeq
+  (-first [_] (first pos-vec))
+  (-rest [_] (rest pos-vec))
+
   IComparable
   (-compare [this other]
     (let [pos1 (.-pos-vec this)
@@ -263,30 +340,36 @@
   (let [toplevel (js->clj (.toArray struct))
         index (.indexOf toplevel id)]
     (if (not= -1 index)
-      [index]
+      (->Pos [index])
       (loop [i 0]
         (if (>= i (count toplevel))
           nil
           (let [sublevel (get toplevel i)]
             (if (instance? y/Array sublevel)
-              (if-let [index (find-pos sublevel id)]
+              (if-let [index (.-pos-vec (find-pos sublevel id))]
                 (->Pos (vec (flatten [i index])))
                 (recur (+ i 1)))
               (recur (+ i 1)))))))))
 
 (defn- common-prefix [vec1 vec2]
-  (let [len1 (count vec1)
-        len2 (count vec2)]
-    (loop [i 0 r1 vec1 r2 vec2]
-      (cond
-        (or (>= i len1) (>= i len2))
-        [(subvec vec1 0 i) r1 r2]
-
-        (= (vec1 i) (vec2 i))
-        (recur (inc i) (vec (rest r1)) (vec (rest r2)))
-
-        :else
-        [(subvec vec1 0 i) r1 r2]))))
+  (let [vec1 (or (.-pos-vec vec1) vec1)
+        vec2 (or (.-pos-vec vec2) vec2)]
+    (try
+      (let [len1 (count vec1)
+            len2 (count vec2)]
+        (loop [i 0 r1 vec1 r2 vec2]
+          (cond
+            (or (>= i len1) (>= i len2))
+            [(subvec vec1 0 i) r1 r2]
+
+            (= (get vec1 i) (get vec2 i))
+            (recur (inc i) (vec (rest r1)) (vec (rest r2)))
+
+            :else
+            [(subvec vec1 0 i) r1 r2])))
+      (catch js/Error e
+        (println e vec1 vec2)
+        (js/console.trace)))))
 
 (defn distance [pos-vec1 pos-vec2]
     "(distance [1 2] [1 4]) => [[[1 2] 3]] => [[prefix-of-THIS-pos length]]
@@ -354,7 +437,8 @@
           :else
           (do
             (.insert struct* (last pos) (clj->js [s]))
-            (recur (inc i) (.inc-pos pos))))))))
+            (recur (inc i) (.inc-pos pos)))))))
+    )
 
 
 (defn insert-nodes-yjs [page-name new-nodes-tree target-uuid sibling?]
@@ -386,14 +470,19 @@
   ([new-node target-node sibling? {:keys [blocks-atom skip-transact?]
                                    :or {skip-transact? false}
                                    :as opts}]
-   (println "insert-node-op: " [new-node target-node sibling? opts])
    (let [target-block (:data target-node)]
      (when-let [page-name (or (:block/name target-block)
                               (:block/name (db/entity (:db/id (:block/page target-block)))))]
        (insert-node-yjs page-name new-node (str (:block/uuid target-block)) sibling?)
        (distinct-struct (structarray page-name) (atom #{}))
        (merge-doc doc-remote doc-local)
-       (outliner-core/insert-node new-node target-node sibling? opts)))))
+       (try (outliner-core/insert-node new-node target-node sibling? opts)
+            (catch js/Error e
+              (println e)
+              (println new-node target-node)
+              (js/console.trace)
+              )
+            )))))
 
 
 (defn- delete-range-nodes-prefix-part [prefix-vec start-pos-vec end-pos-vec struct]
@@ -438,8 +527,9 @@
 
 (defn delete-nodes-yjs [page-name start-uuid end-uuid]
   (let [struct (structarray page-name)
-        start-pos (find-pos struct start-uuid)
-        end-pos (find-pos struct end-uuid)]
+        start-pos (find-pos struct (str start-uuid))
+        end-pos (find-pos struct (str end-uuid))]
+    (println "delete-nodes-yjs" start-uuid end-uuid)
     (delete-range-nodes start-pos end-pos struct)))
 
 (defn delete-nodes-op [start-node end-node block-ids]