Browse Source

electron: file watcher

Tienson Qin 5 năm trước cách đây
mục cha
commit
b3224d0869

+ 8 - 9
src/electron/electron/handler.cljs

@@ -46,13 +46,13 @@
 (defn- get-files
   [path]
   (let [result (->> (map
-                      (fn [path]
-                        (let [stat (fs/statSync path)]
-                          (when-not (.isDirectory stat)
-                            {:path path
-                             :content (read-file path)
-                             :stat stat})))
-                      (readdir path))
+                     (fn [path]
+                       (let [stat (fs/statSync path)]
+                         (when-not (.isDirectory stat)
+                           {:path path
+                            :content (read-file path)
+                            :stat stat})))
+                     (readdir path))
                     (remove nil?))]
     (vec (cons {:path path} result))))
 
@@ -72,8 +72,6 @@
 
 (defonce file-watcher-chan "file-watcher")
 (defn send-file-watcher! [win type payload]
-  (prn "file watch: " {:type type
-                       :payload payload})
   (.. win -webContents
       (send file-watcher-chan
             (bean/->js {:type type :payload payload}))))
@@ -83,6 +81,7 @@
   (let [watcher (.watch watcher dir
                         (clj->js
                          {:ignored #"^\."
+                          :ignoreInitial true
                           :persistent true
                           :awaitWriteFinish true}))]
     (.on watcher "add"

+ 2 - 2
src/main/frontend/components/repo.cljs

@@ -65,7 +65,7 @@
                              :on-click (fn []
                                          (if local?
                                            (nfs-handler/rebuild-index! url
-                                                                 repo-handler/create-today-journal!)
+                                                                       repo-handler/create-today-journal!)
                                            (repo-handler/rebuild-index! url))
                                          (js/setTimeout
                                           (fn []
@@ -97,7 +97,7 @@
              [:a
               {:on-click #(nfs-handler/refresh! repo
                                                 repo-handler/create-today-journal!)
-               :title (str "Sync files with the local directory: " (config/get-local-dir repo) ".\nVersion: "
+               :title (str "Import files from the local directory: " (config/get-local-dir repo) ".\nVersion: "
                            version/version)}
               svg/refresh]])
           (let [changed-files (state/sub [:repo/changed-files repo])

+ 9 - 3
src/main/frontend/config.cljs

@@ -305,8 +305,14 @@
 
 (defn get-repo-dir
   [repo-url]
-  (if (util/electron?)
+  (if (and (util/electron?) (local-db? repo-url))
     (get-local-dir repo-url)
     (str "/"
-        (->> (take-last 2 (string/split repo-url #"/"))
-             (string/join "_")))))
+         (->> (take-last 2 (string/split repo-url #"/"))
+              (string/join "_")))))
+
+(defn get-repo-path
+  [repo-url path]
+  (if (and (util/electron?) (local-db? repo-url))
+    path
+    (str (get-repo-dir repo-url) "/" path)))

+ 28 - 18
src/main/frontend/fs/watcher_handler.cljs

@@ -3,31 +3,41 @@
             [lambdaisland.glogi :as log]
             [frontend.handler.file :as file-handler]
             [frontend.handler.page :as page-handler]
+            [frontend.handler.notification :as notification]
             [frontend.config :as config]
-            [cljs-bean.core :as bean]))
+            [cljs-bean.core :as bean]
+            [frontend.db :as db]))
 
 (defn handle-changed!
   [type {:keys [dir path content stat] :as payload}]
   (when dir
-    (let [repo (config/get-local-repo dir)]
-      (prn "handle file notifier: "
-           {:repo repo
-            :type type
-            :payload payload})
-     ;; (cond
-     ;;   (contains? #{"add" "change"} type)
-     ;;   ;; TODO: check content and mtime
-     ;;   (file-handler/alter-file repo path content {})
+    (let [repo (config/get-local-repo dir)
+          {:keys [mtime]} stat]
+      (cond
+        (= "add" type)
+        (when (not= content (db/get-file path))
+          (file-handler/alter-file repo path content {:re-render-root? true}))
 
-     ;;   (= "unlink" type)
-     ;;   ;; TODO: Remove page and blocks too
-     ;;   ;; what if it's a mistaken, should we put it to .trash to have a way to restore it back?
-     ;;   (file-handler/remove-file! repo path)
+        (and (= "change" type)
+             (not= content (db/get-file path))
+             (when-let [last-modified-at (db/get-file-last-modified-at repo path)]
+               (> mtime last-modified-at)))
+        (file-handler/alter-file repo path content {:re-render-root? true})
 
-     ;;   :else
-     ;;   (log/error :fs/watcher-no-handler {:type type
-     ;;                                      :payload payload}))
-     )))
+        (= "unlink" type)
+        (when-let [page-name (db/get-file-page path)]
+          (page-handler/delete!
+           page-name
+           (fn []
+             (notification/show! (str "Page " page-name " was deleted on disk.")
+                                 :success))))
+
+        (contains? #{"add" "change" "unlink"} type)
+        nil
+
+        :else
+        (log/error :fs/watcher-no-handler {:type type
+                                           :payload payload})))))
 
 (defn run-dirs-watcher!
   []

+ 1 - 1
src/main/frontend/handler/editor.cljs

@@ -1595,7 +1595,7 @@
     (save-block! repo block content)
     (when local?
       ;; FIXME: should be relative to current block page path
-      (fs/unlink! (str (config/get-repo-dir repo) (string/replace href #"^../" "/")) nil))))
+      (fs/unlink! (config/get-repo-path repo (string/replace href #"^../" "/")) nil))))
 
 (defn upload-image
   [id files format uploading? drop-or-paste?]

+ 6 - 8
src/main/frontend/handler/file.cljs

@@ -27,6 +27,8 @@
             [frontend.utf8 :as utf8]
             ["ignore" :as Ignore]))
 
+;; TODO: extract all git ops using a channel
+
 (defn load-file
   [repo-url path]
   (->
@@ -163,7 +165,7 @@
       (db/set-file-content! repo path content))
     (util/p-handle
      (fs/write-file! repo (config/get-repo-dir repo) path content {:old-content original-content
-                                                                 :last-modified-at (db/get-file-last-modified-at repo path)})
+                                                                   :last-modified-at (db/get-file-last-modified-at repo path)})
      (fn [_]
        (git-handler/git-add repo path update-status?)
        (when (= path (str config/app-name "/" config/config-file))
@@ -264,11 +266,7 @@
   (when-not (string/blank? file)
     (->
      (p/let [_ (git/remove-file repo file)
-             result (fs/unlink! (str
-                                 (config/get-repo-dir repo)
-                                 "/"
-                                 file)
-                                nil)]
+             result (fs/unlink! (config/get-repo-path repo file) nil)]
        (when-let [file (db/entity repo [:file/path file])]
          (common-handler/check-changed-files-status)
          (let [file-id (:db/id file)
@@ -313,7 +311,7 @@
     (let [repos (->> (state/get-repos)
                      (filter (fn [repo]
                                (config/local-db? (:url repo)))))
-         directories (map (fn [repo] (config/get-repo-dir (:url repo))) repos)]
+          directories (map (fn [repo] (config/get-repo-dir (:url repo))) repos)]
       (doseq [dir directories]
-        (prn "watch for dir changes: " dir)
+        (prn "Watch for dir changes: " dir)
         (fs/watch-dir! dir)))))

+ 10 - 7
src/main/frontend/handler/page.cljs

@@ -65,14 +65,20 @@
                 [:p.content
                  (util/format "File %s already exists!" file-path)]
                 :error)
-               ;; create the file
+               ;; Create the file
                (let [content (util/default-content-with-title format title)]
-                 (p/let [_ (fs/create-if-not-exists repo dir file-path content)
+                 ;; Write to the db first, then write to the filesystem,
+                 ;; otherwise, the main electron ipc will notify that there's
+                 ;; a new file created.
+                 ;; Question: what if the fs write failed?
+                 (p/let [_ (file-handler/reset-file! repo path content)
+                         _ (fs/create-if-not-exists repo dir file-path content)
                          _ (git-handler/git-add repo path)]
-                   (file-handler/reset-file! repo path content)
                    (when redirect?
                      (route-handler/redirect! {:to :page
                                                :path-params {:name page}})
+
+                     ;; Edit the first block
                      (let [blocks (db/get-page-blocks page)
                            last-block (last blocks)]
                        (when last-block
@@ -273,10 +279,7 @@
               ;; remove file
               (->
                (p/let [_ (git/remove-file repo file-path)
-                       _ (fs/unlink! (str (config/get-repo-dir repo)
-                                          "/"
-                                          file-path)
-                                     nil)]
+                       _ (fs/unlink! (config/get-repo-path repo file-path) nil)]
                  (common-handler/check-changed-files-status)
                  (repo-handler/push-if-auto-enabled! repo))
                (p/catch (fn [err]