فهرست منبع

feat: limit the scope of undo/redo to page only

Tienson Qin 2 سال پیش
والد
کامیت
68691467de

+ 72 - 3
src/main/frontend/modules/editor/undo_redo.cljs

@@ -4,7 +4,8 @@
             [frontend.db.conn :as conn]
             [frontend.modules.datascript-report.core :as db-report]
             [frontend.state :as state]
-            [clojure.set :as set]))
+            [clojure.set :as set]
+            [medley.core :as medley]))
 
 ;;;; APIs
 
@@ -30,6 +31,21 @@
   []
   (-> (get-state) :redo-stack))
 
+(defn- get-page-from-block
+  [stack]
+  (let [last-blocks (:blocks (last stack))]
+    (or (:db/id (some #(when (:block/name %) %) last-blocks))
+        (:db/id (some :block/page last-blocks)))))
+
+(defn- get-history-page
+  [action]
+  (or
+   (:history/page @state/state)
+   (when-let [id (if (= :undo action)
+                   (get-page-from-block @(get-undo-stack))
+                   (get-page-from-block @(get-redo-stack)))]
+     (swap! state/state assoc :history/page id))))
+
 (defn push-undo
   [txs]
   (let [undo-stack (get-undo-stack)]
@@ -74,6 +90,33 @@
      (swap! redo-stack pop)
      removed-e)))
 
+(defn page-pop-redo
+  [page-id]
+  (prn "[debug] redo: " (:block/original-name (db/pull page-id)))
+  (when-let [redo-stack (get-redo-stack)]
+    (when-let [stack @redo-stack]
+      (when (seq stack)
+        (let [reversed-stack (medley/indexed (reverse stack))
+              idx (some (fn [[idx item]]
+                          (some #(when (or (= (:db/id %) page-id)
+                                           (= (:db/id (:block/page %)) page-id)) idx) (:blocks item))) reversed-stack)]
+          (when idx
+            (let [idx' (- (count stack) idx 1)
+                  before (subvec stack 0 idx')
+                  after (subvec stack (inc idx'))
+                  others (vec (concat before after))]
+              (reset! redo-stack others)
+              (prn "[debug] redo remove: " (nth stack idx'))
+              (nth stack idx'))))))))
+
+(defn- smart-pop-redo
+  []
+  (if (:history/page-only-mode? @state/state)
+    (if-let [page-id (get-history-page :redo)]
+      (page-pop-redo page-id)
+      (pop-redo))
+    (pop-redo)))
+
 (defn reset-redo
   []
   (let [redo-stack (get-redo-stack)]
@@ -98,9 +141,35 @@
   (let [conn (conn/get-db false)]
     (d/transact! conn txs tx-meta)))
 
+(defn page-pop-undo
+  [page-id]
+  (let [undo-stack (get-undo-stack)]
+    (when-let [stack @undo-stack]
+      (when (seq stack)
+        (let [reversed-stack (medley/indexed (reverse stack))
+              idx (some (fn [[idx item]]
+                          (some #(when (or (= (:db/id %) page-id)
+                                           (= (:db/id (:block/page %)) page-id)) idx) (:blocks item))) reversed-stack)]
+          (when idx
+            (let [idx' (- (count stack) idx 1)
+                  before (subvec stack 0 idx')
+                  after (subvec stack (inc idx'))
+                  others (vec (concat before after))]
+              (reset! undo-stack others)
+              (prn "[debug] undo remove: " (nth stack idx'))
+              [(nth stack idx') others])))))))
+
+(defn- smart-pop-undo
+  []
+  (if (:history/page-only-mode? @state/state)
+    (if-let [page-id (get-history-page :undo)]
+      (page-pop-undo page-id)
+      (pop-undo))
+    (pop-undo)))
+
 (defn undo
   []
-  (let [[e prev-e] (pop-undo)]
+  (let [[e prev-e] (smart-pop-undo)]
     (when e
       (let [{:keys [txs tx-meta]} e
             new-txs (get-txs false txs)
@@ -139,7 +208,7 @@
 
 (defn redo
   []
-  (when-let [{:keys [txs tx-meta] :as e} (pop-redo)]
+  (when-let [{:keys [txs tx-meta] :as e} (smart-pop-redo)]
     (let [new-txs (get-txs true txs)]
       (push-undo e)
       (transact! new-txs (merge {:redo? true}

+ 5 - 0
src/main/frontend/modules/shortcut/config.cljs

@@ -257,6 +257,9 @@
    :editor/zoom-out                {:binding (if mac? "mod+," "alt+left")
                                     :fn      editor-handler/zoom-out!}
 
+   :editor/toggle-undo-redo-mode   {:binding "t u"
+                                    :fn      state/toggle-undo-redo-mode!}
+
    :ui/toggle-brackets             {:binding "mod+c mod+b"
                                     :fn      config-handler/toggle-ui-show-brackets!}
 
@@ -586,6 +589,7 @@
                           :editor/select-all-blocks
                           :editor/zoom-in
                           :editor/zoom-out
+                          :editor/toggle-undo-redo-mode
                           :editor/undo
                           :editor/redo
                           :ui/toggle-brackets
@@ -743,6 +747,7 @@
    :shortcut.category/toggle
    [:ui/toggle-help
     :editor/toggle-open-blocks
+    :editor/toggle-undo-redo-mode
     :ui/toggle-wide-mode
     :ui/toggle-cards
     :ui/toggle-document-mode

+ 1 - 0
src/main/frontend/modules/shortcut/dicts.cljc

@@ -78,6 +78,7 @@
    :editor/select-parent           "Select parent block"
    :editor/zoom-in                 "Zoom in editing block / Forwards otherwise"
    :editor/zoom-out                "Zoom out editing block / Backwards otherwise"
+   :editor/toggle-undo-redo-mode   "Toggle undo redo mode (global or page only)"
    :ui/toggle-brackets             "Toggle whether to display brackets"
    :go/search-in-page              "Search blocks in the current page"
    :go/electron-find-in-page       "Find text in page"

+ 13 - 1
src/main/frontend/state.cljs

@@ -275,7 +275,9 @@
      :whiteboard/onboarding-whiteboard?     (or (storage/get :ls-onboarding-whiteboard?) false)
      :whiteboard/onboarding-tour?           (or (storage/get :whiteboard-onboarding-tour?) false)
      :whiteboard/last-persisted-at          {}
-     :whiteboard/pending-tx-data            {}})))
+     :whiteboard/pending-tx-data            {}
+     :history/page-only-mode?               false
+     :history/page                          nil})))
 
 ;; Block ast state
 ;; ===============
@@ -2093,3 +2095,13 @@ Similar to re-frame subscriptions"
 (defn clear-user-info!
   []
   (storage/remove :user-groups))
+
+(defn toggle-undo-redo-mode!
+  []
+  (if (:history/page-only-mode? @state)
+    (swap! state assoc
+           :history/page-only-mode? false
+           :history/page nil)
+    (swap! state assoc
+           :history/page-only-mode? true
+           :history/page nil)))