소스 검색

undo/redo insert-nodes

rcmerci 4 년 전
부모
커밋
a795ff31ae

+ 0 - 1
src/main/frontend/modules/editor/undo_redo.cljs

@@ -148,5 +148,4 @@
                   :editor-cursor (:editor-cursor tx-meta)
                   :outliner-op (:outliner-op tx-meta)
                   :other-meta (:other-meta tx-meta)}]
-      (println "tx-meta: " tx-meta)
       (push-undo entity))))

+ 74 - 53
src/main/frontend/modules/outliner/core.cljs

@@ -224,6 +224,18 @@
       (tree/vec-tree->block-tree)
       (tree/block-tree-keep-props [:block/uuid :block/content])))
 
+(defn- node-tree->content-tree [tree]
+  (->
+   (loop [loc (zip/vector-zip tree)]
+     (if (zip/end? loc)
+       (zip/root loc)
+       (cond
+         (map? (zip/node loc))
+         (recur (zip/next (zip/replace loc (:data (zip/node loc)))))
+         :else
+         (recur (zip/next loc)))))
+   (tree/block-tree-keep-props [:block/uuid :block/content])))
+
 (defn save-node
   ([node]
    (save-node node nil))
@@ -369,12 +381,16 @@
                                          :or {skip-undo? false}}]
    {:pre [(> (count new-nodes-tree) 0)]}
    (let [page-name (get-page-name target-node)
-         target-id (tree/-get-id target-node)]
+         target-id (tree/-get-id target-node)
+         tree (node-tree->content-tree new-nodes-tree)]
      (ds/auto-transact!
-      [txs-state (ds/new-outliner-txs-state)] {:outliner-op :insert-nodes
-                                               :other-meta {:new-nodes-tree new-nodes-tree
-                                                            :target-id target-id
-                                                            :sibling? sibling?}}
+      [txs-state (ds/new-outliner-txs-state)]
+      {:outliner-op :insert-nodes
+       :skip-undo? skip-undo?
+       :other-meta {:page-name page-name
+                    :tree tree
+                    :target-id target-id
+                    :sibling? sibling?}}
       (let [loc (zip/vector-zip new-nodes-tree)]
         ;; TODO: validate new-nodes-tree structure
         (let [updated-nodes (walk-&-insert-nodes loc target-node sibling? txs-state)
@@ -496,54 +512,59 @@
     block-ids: block ids between the start node and end node, including all the
   children.
   "
-  [start-node end-node block-ids]
-  {:pre [(tree/satisfied-inode? start-node)
-         (tree/satisfied-inode? end-node)]}
-  (let [page-name (get-page-name start-node)
-        start-id (tree/-get-id start-node)
-        end-id (tree/-get-id end-node)]
-    (ds/auto-transact!
-     [txs-state (ds/new-outliner-txs-state)]
-     {:outliner-op :delete-nodes
-      :other-meta {:page-name page-name
-                   :start-id start-id
-                   :end-id end-id
-                   :block-ids block-ids}}
-     (let [end-node-parents (->>
-                             (db/get-block-parents
-                              (state/get-current-repo)
-                              (tree/-get-id end-node)
-                              1000)
-                             (map :block/uuid)
-                             (set))
-           self-block? (contains? end-node-parents (tree/-get-id start-node))]
-       (if (or (= start-node end-node)
-               self-block?)
-         (delete-node start-node true)
-         (let [sibling? (= (tree/-get-parent-id start-node)
-                           (tree/-get-parent-id end-node))
-               right-node (tree/-get-right end-node)]
-           (when (tree/satisfied-inode? right-node)
-             (let [left-node-id (if sibling?
-                                  (tree/-get-id (tree/-get-left start-node))
-                                  (let [end-node-left-nodes (get-left-nodes end-node (count block-ids))
-                                        parents (->>
-                                                 (db/get-block-parents
-                                                  (state/get-current-repo)
-                                                  (tree/-get-id start-node)
-                                                  1000)
-                                                 (map :block/uuid)
-                                                 (set))
-                                        result (first (set/intersection (set end-node-left-nodes) parents))]
-                                    (when-not result
-                                      (util/pprint {:parents parents
-                                                    :end-node-left-nodes end-node-left-nodes}))
-                                    result))]
-               (assert left-node-id "Can't find the left-node-id")
-               (let [new-right-node (tree/-set-left-id right-node left-node-id)]
-                 (tree/-save new-right-node txs-state))))
-           (let [txs (db-outliner/del-blocks block-ids)]
-             (ds/add-txs txs-state txs))))))))
+  ([start-node end-node block-ids]
+   (delete-nodes start-node end-node block-ids nil))
+  ([start-node end-node block-ids {:keys [skip-undo?]
+                                   :or {skip-undo? false}}]
+   {:pre [(tree/satisfied-inode? start-node)
+          (tree/satisfied-inode? end-node)]}
+   (let [page-name (get-page-name start-node)
+         start-id (tree/-get-id start-node)
+         end-id (tree/-get-id end-node)]
+     (ds/auto-transact!
+      [txs-state (ds/new-outliner-txs-state)]
+      {:outliner-op :delete-nodes
+       :skip-undo? skip-undo?
+       :other-meta {:page-name page-name
+                    :start-id start-id
+                    :end-id end-id
+                    :block-ids block-ids}}
+      (let [end-node-parents (->>
+                              (db/get-block-parents
+                               (state/get-current-repo)
+                               (tree/-get-id end-node)
+                               1000)
+                              (map :block/uuid)
+                              (set))
+            self-block? (contains? end-node-parents (tree/-get-id start-node))]
+        (if (or (= start-node end-node)
+                self-block?)
+          (delete-node start-node true)
+          (let [sibling? (= (tree/-get-parent-id start-node)
+                            (tree/-get-parent-id end-node))
+                right-node (tree/-get-right end-node)]
+            (println "DEL: 111 " end-node (db/get-page-blocks-no-cache page-name))
+            (when (tree/satisfied-inode? right-node)
+              (let [left-node-id (if sibling?
+                                   (tree/-get-id (tree/-get-left start-node))
+                                   (let [end-node-left-nodes (get-left-nodes end-node (count block-ids))
+                                         parents (->>
+                                                  (db/get-block-parents
+                                                   (state/get-current-repo)
+                                                   (tree/-get-id start-node)
+                                                   1000)
+                                                  (map :block/uuid)
+                                                  (set))
+                                         result (first (set/intersection (set end-node-left-nodes) parents))]
+                                     (when-not result
+                                       (util/pprint {:parents parents
+                                                     :end-node-left-nodes end-node-left-nodes}))
+                                     result))]
+                (assert left-node-id "Can't find the left-node-id")
+                (let [new-right-node (tree/-set-left-id right-node left-node-id)]
+                  (tree/-save new-right-node txs-state))))
+            (let [txs (db-outliner/del-blocks block-ids)]
+              (ds/add-txs txs-state txs)))))))))
 
 (defn first-child?
   [node]

+ 1 - 0
src/main/frontend/modules/outliner/datascript.cljc

@@ -7,6 +7,7 @@
                      [frontend.modules.editor.undo-redo :as undo-redo]
                      [frontend.state :as state]
                      [frontend.config :as config]
+                     ;; [frontend.util :as util]
                      [lambdaisland.glogi :as log])))
 
 

+ 74 - 24
src/main/frontend/modules/outliner/yjs.cljs

@@ -12,6 +12,7 @@
             [frontend.db.model :as db-model]
             [frontend.util.property :as property]
             [clojure.zip :as zip]
+            [clojure.walk :as walk]
             [datascript.core :as d]))
 (set! *warn-on-infer* false)
 
@@ -666,7 +667,7 @@ return [2 3]
          (when *debug*
            (validate-struct struct)
            (validate-no-left-conflict page-name))
-         (outliner-core/insert-nodes new-nodes-tree* target-node sibling?))))))
+         (outliner-core/insert-nodes new-nodes-tree* target-node sibling? {:skip-undo? skip-undo?}))))))
 
 (defn insert-node-yjs [struct new-node target-uuid sibling?]
   (insert-nodes-yjs struct [new-node] target-uuid sibling?))
@@ -758,27 +759,30 @@ return [2 3]
     (dissoc-contents ids (contentmap))))
 
 
-(defn delete-nodes-op [start-node end-node block-ids]
-  (let [start-block (:data start-node)
-        end-block (:data end-node)]
-    (when-some [page-name (or (:block/name start-block)
-                              (:block/name (db/entity (:db/id (:block/page start-block)))))]
-      (when-some [start-uuid (:block/uuid start-block)]
-        (when-some [end-uuid (:block/uuid end-block)]
-          (let [struct (structarray page-name)
-                start-pos (find-pos struct (str start-uuid))
-                end-pos (find-pos struct (str end-uuid))
-                [start-pos end-pos start-node end-node]
-                (if (< (compare start-pos end-pos) 0)
-                  [start-pos end-pos start-node end-node]
-                  [end-pos start-pos end-node start-node])]
-            (delete-nodes-yjs struct start-pos end-pos block-ids)
-            (distinct-struct struct (atom #{}))
-            (merge-doc @doc-remote @doc-local)
-            (when *debug*
-              (validate-struct struct)
-              (validate-no-left-conflict page-name))
-            (outliner-core/delete-nodes start-node end-node block-ids)))))))
+(defn delete-nodes-op
+  ([start-node end-node block-ids]
+   (delete-nodes-op start-node end-node block-ids {:skip-undo? true}))
+  ([start-node end-node block-ids {:keys [skip-undo?]}]
+   (let [start-block (:data start-node)
+         end-block (:data end-node)]
+     (when-some [page-name (or (:block/name start-block)
+                               (:block/name (db/entity (:db/id (:block/page start-block)))))]
+       (when-some [start-uuid (:block/uuid start-block)]
+         (when-some [end-uuid (:block/uuid end-block)]
+           (let [struct (structarray page-name)
+                 start-pos (find-pos struct (str start-uuid))
+                 end-pos (find-pos struct (str end-uuid))
+                 [start-pos end-pos start-node end-node]
+                 (if (< (compare start-pos end-pos) 0)
+                   [start-pos end-pos start-node end-node]
+                   [end-pos start-pos end-node start-node])]
+             (delete-nodes-yjs struct start-pos end-pos block-ids)
+             (distinct-struct struct (atom #{}))
+             (merge-doc @doc-remote @doc-local)
+             (when *debug*
+               (validate-struct struct)
+               (validate-no-left-conflict page-name))
+             (outliner-core/delete-nodes start-node end-node block-ids {:skip-undo? true}))))))))
 
 (defn- delete-node-struct-yjs [struct id children?]
   (let [pos (find-pos struct id)
@@ -1104,7 +1108,48 @@ return [2 3]
         children? (get-in txn-meta [:other-meta :children?])]
     (delete-node-op node children? {:skip-undo? true})))
 
+
+(defn undo-insert-nodes [page-name txn-meta]
+  {:pre [(= :insert-nodes (:outliner-op txn-meta))
+         (= page-name (get-in txn-meta [:other-meta :page-name]))]}
+  (let [tree (get-in txn-meta [:other-meta :tree])
+        block-ids (mapv (fn [block] [:block/uuid (:block/uuid block)])
+                        (flatten tree))]
+    (when-some [start-node (and (first tree)
+                                (outliner-core/block
+                                 (db/pull [:block/uuid (:block/uuid (first tree))])))]
+      (let [last-node (last tree)
+            end-node* (if (sequential? last-node)
+                        (last (butlast tree))
+                        last-node)]
+        (when-some [end-node (and end-node*
+                                  (outliner-core/block
+                                   (db/pull [:block/uuid (:block/uuid end-node*)])))]
+          (if (= start-node end-node)
+            (delete-node-op start-node true {:skip-undo? true})
+            (delete-nodes-op start-node end-node block-ids {:skip-undo? true})))))))
+
+(defn redo-insert-nodes [page-name txn-meta]
+  {:pre [(= :insert-nodes (:outliner-op txn-meta))
+         (= page-name (get-in txn-meta [:other-meta :page-name]))]}
+  (let [target-id (get-in txn-meta [:other-meta :target-id])
+        target-node (outliner-core/block (db/pull [:block/uuid target-id]))
+        tree (get-in txn-meta [:other-meta :tree])
+        content-tree (walk/postwalk (fn [e]
+                                      (if (map? e)
+                                        (:block/content e)
+                                        e)) tree)
+        page-block (db/pull (:db/id (db/get-page page-name)))
+        node-tree (content-tree->node-tree content-tree :markdown page-block)
+        sibling? (get-in txn-meta [:other-meta :sibling?])
+        struct (structarray page-name)]
+    (when (find-pos struct (str target-id))
+      (insert-nodes-op node-tree target-node sibling?))))
+
+
 (defn undo-op [page-name txn-meta]
+  (def bbb [page-name txn-meta])
+  (println "[UNDO]" page-name (:outliner-op txn-meta))
   (case (:outliner-op txn-meta)
     :insert-node
     (undo-insert-node page-name txn-meta)
@@ -1112,9 +1157,12 @@ return [2 3]
     (undo-delete-node page-name txn-meta)
     :save-node
     (undo-save-node page-name txn-meta)
-    (println "[UNDO]" page-name (:outliner-op txn-meta))))
+    :insert-nodes
+    (undo-insert-nodes page-name txn-meta)
+    (println "unsupport" (:outliner-op txn-meta))))
 
 (defn redo-op [page-name txn-meta]
+  (println "[REDO]" page-name (:outliner-op txn-meta))
   (case (:outliner-op txn-meta)
     :insert-node
     (redo-insert-node page-name txn-meta)
@@ -1122,7 +1170,9 @@ return [2 3]
     (redo-delete-node page-name txn-meta)
     :save-node
     (redo-save-node page-name txn-meta)
-    (println "[REDO]" page-name (:outliner-op txn-meta))))
+    :insert-nodes
+    (redo-insert-nodes page-name txn-meta)
+    (println "unsupport" (:outliner-op txn-meta))))
 
 (defn undo []
   (let [[e prev-e] (undo-redo/pop-undo)]