Browse Source

enhance(undo): use a promise-chan to make the undo behavior stable

Tienson Qin 4 years ago
parent
commit
3c327eb4ba

+ 8 - 5
src/main/frontend/handler/editor.cljs

@@ -430,7 +430,7 @@
    (save-block-if-changed! block value nil))
   ([{:block/keys [uuid content meta file page dummy? format repo pre-block? content ref-pages ref-blocks] :as block}
     value
-    {:keys [indent-left? custom-properties remove-properties rebuild-content?]
+    {:keys [indent-left? custom-properties remove-properties rebuild-content? chan chan-callback]
      :or {rebuild-content? true
           custom-properties nil
           remove-properties nil}
@@ -598,7 +598,9 @@
                {:key :block/change
                 :data (map (fn [block] (assoc block :block/page page)) blocks)}
                (let [new-content (new-file-content-indent-outdent block file-content value block-children-content new-end-pos indent-left?)]
-                 [[file-path new-content]])))
+                 [[file-path new-content]])
+               (when chan {:chan chan
+                           :chan-callback chan-callback})))
 
              (when (or (seq retract-refs) pre-block?)
                (ui-handler/re-render-root!))
@@ -1423,8 +1425,9 @@
 
 (defn save-current-block-when-idle!
   ([]
-   (save-current-block-when-idle! true))
-  ([check-idle?]
+   (save-current-block-when-idle! {}))
+  ([{:keys [check-idle? chan chan-callback]
+     :or {check-idle? true}}]
    (when-let [repo (state/get-current-repo)]
      (when (and (if check-idle? (state/input-idle? repo) true)
                 (not (state/get-editor-show-page-search?))
@@ -1446,7 +1449,7 @@
                        (not= (string/trim db-content-without-heading)
                              (string/trim value))))
              (let [cur-pos (util/get-input-pos elem)]
-               (save-block-aux! db-block value (:block/format db-block) {}))))
+               (save-block-aux! db-block value (:block/format db-block) {:chan chan}))))
          (catch js/Error error
            (log/error :save-block-failed error)))
        (state/set-editor-op! nil)))))

+ 6 - 5
src/main/frontend/handler/extract.cljs

@@ -22,6 +22,7 @@
          (map string/lower-case)
          (distinct))))
 
+;; TODO: performance improvement
 (defn- extract-pages-and-blocks
   [repo-url format ast properties file content utf8-content journal? pages-fn]
   (try
@@ -55,8 +56,8 @@
                   (fn [page]
                     (let [page-file? (= page (string/lower-case file))
                           aliases (and (:alias properties)
-                                           (seq (remove #(= page %)
-                                                        (:alias properties))))
+                                       (seq (remove #(= page %)
+                                                    (:alias properties))))
                           journal-date-long (if journal?
                                               (date/journal-title->long (string/capitalize page)))
                           page-list (when-let [list-content (:list properties)]
@@ -93,14 +94,14 @@
                                       {:page/name page-name
                                        :page/alias aliases}
                                       {:page/name page-name})))
-                                 aliases))
+                                aliases))
 
                         (:tags properties)
                         (assoc :page/tags (let [tags (:tags properties)]
                                             (swap! ref-tags set/union (set tags))
                                             (map (fn [tag] {:page/name (string/lower-case tag)
-                                                           :page/original-name tag})
-                                              tags))))))
+                                                            :page/original-name tag})
+                                                 tags))))))
                   (->> (map first pages)
                        (remove nil?))))
           pages (concat

+ 30 - 22
src/main/frontend/handler/file.cljs

@@ -125,23 +125,25 @@
 
 (defn reset-file!
   [repo-url file content]
-  (let [new? (nil? (db/entity [:file/path file]))]
-    (db/set-file-content! repo-url file content)
-    (let [format (format/get-format file)
-          utf8-content (utf8/encode content)
-          file-content [{:file/path file}]
-          tx (if (contains? config/mldoc-support-formats format)
-               (let [delete-blocks (db/delete-file-blocks! repo-url file)
-                     [pages block-ids blocks] (extract-handler/extract-blocks-pages repo-url file content utf8-content)]
-                 (concat file-content delete-blocks pages block-ids blocks))
-               file-content)
-          tx (concat tx [(let [t (tc/to-long (t/now))]
-                           (cond->
-                            {:file/path file
-                             :file/last-modified-at t}
-                             new?
-                             (assoc :file/created-at t)))])]
-      (db/transact! repo-url tx))))
+  (profile "reset"
+           (let [new? (nil? (db/entity [:file/path file]))]
+             (db/set-file-content! repo-url file content)
+             (let [format (format/get-format file)
+                   utf8-content (utf8/encode content)
+                   file-content [{:file/path file}]
+                   tx (if (contains? config/mldoc-support-formats format)
+                        (let [delete-blocks (db/delete-file-blocks! repo-url file)
+                              [pages block-ids blocks] (profile "extract"
+                                                                (extract-handler/extract-blocks-pages repo-url file content utf8-content))]
+                          (concat file-content delete-blocks pages block-ids blocks))
+                        file-content)
+                   tx (concat tx [(let [t (tc/to-long (t/now))]
+                                    (cond->
+                                     {:file/path file
+                                      :file/last-modified-at t}
+                                      new?
+                                      (assoc :file/created-at t)))])]
+               (profile "transact" (db/transact! repo-url tx))))))
 
 ;; TODO: better name to separate from reset-file!
 (defn alter-file
@@ -188,7 +190,7 @@
                                    :path-params {:path path}}))))))
 
 (defn alter-files
-  [repo files {:keys [add-history? update-status? git-add-cb reset? update-db?]
+  [repo files {:keys [add-history? update-status? git-add-cb reset? update-db? chan chan-callback]
                :or {add-history? true
                     update-status? true
                     reset? false
@@ -206,10 +208,13 @@
           (db/set-file-content! repo path content))))
 
     (when-let [chan (state/get-file-write-chan)]
-      (async/put! chan [repo files opts file->content]))))
+      (let [chan-callback (:chan-callback opts)]
+        (async/put! chan [repo files opts file->content])
+        (when chan-callback
+          (chan-callback))))))
 
 (defn alter-files-handler!
-  [repo files {:keys [add-history? update-status? git-add-cb reset?]
+  [repo files {:keys [add-history? update-status? git-add-cb reset? chan]
                :or {add-history? true
                     update-status? true
                     reset? false}} file->content]
@@ -245,10 +250,13 @@
                         (history/add-history! repo files-tx))))]
     (-> (p/all (map write-file-f files))
         (p/then (fn []
-                  (git-add-f)))
+                  (git-add-f)
+                  (when chan
+                    (async/put! chan true))))
         (p/catch (fn [error]
                    (println "Alter files failed:")
-                   (js/console.error error))))))
+                   (js/console.error error)
+                   (async/put! chan false))))))
 
 (defn remove-file!
   [repo file]

+ 14 - 4
src/main/frontend/handler/history.cljs

@@ -2,7 +2,9 @@
   (:require [frontend.state :as state]
             [frontend.history :as history]
             [frontend.handler.file :as file]
-            [frontend.handler.editor :as editor]))
+            [frontend.handler.editor :as editor]
+            [promesa.core :as p]
+            [clojure.core.async :as async]))
 
 (defn- default-undo
   []
@@ -17,9 +19,17 @@
   (let [route (get-in (:route-match @state/state) [:data :name])]
     (if (and (contains? #{:home :page :file} route)
              (state/get-current-repo))
-      (let [repo (state/get-current-repo)]
-        (editor/save-current-block-when-idle! false)
-        (js/setTimeout #(history/undo! repo file/alter-file) 200))
+      (let [repo (state/get-current-repo)
+            chan (async/promise-chan)
+            save-commited? (atom nil)]
+        (editor/save-current-block-when-idle! {:check-idle? false
+                                               :chan chan
+                                               :chan-callback #(reset! save-commited? true)})
+        (if @save-commited?
+          (async/go
+            (let [_ (async/<! chan)]
+              (history/undo! repo file/alter-file)))
+          (history/undo! repo file/alter-file)))
       (default-undo))))
 
 (defn redo!

+ 2 - 1
src/main/frontend/handler/page.cljs

@@ -43,7 +43,8 @@
    (create! title {}))
   ([title {:keys [redirect?]
            :or {redirect? true}}]
-   (let [repo (state/get-current-repo)
+   (let [title (and title (string/trim title))
+         repo (state/get-current-repo)
          dir (util/get-repo-dir repo)
          journal-page? (date/valid-journal-title? title)
          directory (get-directory journal-page?)]

+ 17 - 15
src/main/frontend/handler/repo.cljs

@@ -303,21 +303,23 @@
                  (remove nil?))))))))
 
 (defn transact-react-and-alter-file!
-  [repo tx transact-option files]
-  (spec/validate :repos/url repo)
-  (let [files (remove nil? files)
-        pages (->> (map db/get-file-page (map first files))
-                   (remove nil?))]
-    (db/transact-react!
-     repo
-     tx
-     transact-option)
-    (when (seq pages)
-      (let [children-tx (mapcat #(rebuild-page-blocks-children repo %) pages)]
-        (when (seq children-tx)
-          (db/transact! repo children-tx))))
-    (when (seq files)
-      (file-handler/alter-files repo files {}))))
+  ([repo tx transact-option files]
+   (transact-react-and-alter-file! repo tx transact-option files {}))
+  ([repo tx transact-option files opts]
+   (spec/validate :repos/url repo)
+   (let [files (remove nil? files)
+         pages (->> (map db/get-file-page (map first files))
+                    (remove nil?))]
+     (db/transact-react!
+      repo
+      tx
+      transact-option)
+     (when (seq pages)
+       (let [children-tx (mapcat #(rebuild-page-blocks-children repo %) pages)]
+         (when (seq children-tx)
+           (db/transact! repo children-tx))))
+     (when (seq files)
+       (file-handler/alter-files repo files opts)))))
 
 (declare push)