Ver Fonte

feat: electron can read/write files now

Tienson Qin há 4 anos atrás
pai
commit
cf68a2ba80

+ 38 - 13
src/electron/electron/handler.cljs

@@ -1,46 +1,71 @@
 (ns electron.handler
-  (:require ["electron" :refer [ipcMain]]
+  (:require ["electron" :refer [ipcMain dialog]]
             [cljs-bean.core :as bean]
             ["fs" :as fs]
-            ["path" :as path]))
+            ["path" :as path]
+            [promesa.core :as p]
+            [goog.object :as gobj]))
 
-(defmulti handle (fn [args] (keyword (first args))))
+(defmulti handle (fn [_window args] (keyword (first args))))
 
-(defmethod handle :mkdir [[_ dir]]
+(defmethod handle :mkdir [_window [_ dir]]
   (fs/mkdirSync dir))
 
-(defmethod handle :readdir [[_ dir]]
+(defn- readdir
+  [dir]
   (->> (tree-seq
         (fn [f] (.isDirectory (fs/statSync f) ()))
         (fn [d] (map #(.join path d %) (fs/readdirSync d)))
         dir)
-       (doall)))
+       (doall)
+       (vec)))
 
-(defmethod handle :unlink [[_ path]]
+(defmethod handle :readdir [_window [_ dir]]
+  (readdir dir))
+
+(defmethod handle :unlink [_window [_ path]]
   (fs/unlinkSync path))
 
-(defmethod handle :readFile [[_ path]]
+(defn- read-file
+  [path]
   (.toString (fs/readFileSync path)))
+(defmethod handle :readFile [_window [_ path]]
+  (read-file path))
 
-(defmethod handle :writeFile [[_ path content]]
+(defmethod handle :writeFile [_window [_ path content]]
   (fs/writeFileSync path content))
 
-(defmethod handle :rename [[_ old-path new-path]]
+(defmethod handle :rename [_window [_ old-path new-path]]
   (fs/renameSync old-path new-path))
 
-(defmethod handle :stat [[_ path]]
+(defmethod handle :stat [_window [_ path]]
   (fs/statSync path))
 
+;; TODO: Is it going to be slow if it's a huge directory
+(defmethod handle :openDir [window _messages]
+  (let [result (.showOpenDialogSync dialog (bean/->js
+                                            {:properties ["openDirectory"]}))
+        path (first result)
+        result (->> (map
+                      (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))))
+
 (defmethod handle :default [args]
   (println "Error: no ipc handler for: " (bean/->js args)))
 
 (defn set-ipc-handler! [window]
   (.handle ipcMain "main"
            (fn [event args-js]
-             (println "received: " args-js)
              (try
                (let [message (bean/->clj args-js)]
-                 (bean/->js (handle message)))
+                 (bean/->js (handle window message)))
                (catch js/Error e
                  (println "IPC error: " e)
                  e)))))

+ 2 - 1
src/main/electron/ipc.cljs

@@ -5,4 +5,5 @@
 ;; TODO: handle errors
 (defn ipc
   [& args]
-  (js/window.apis.doAction (bean/->js args)))
+  (p/let [result (js/window.apis.doAction (bean/->js args))]
+    result))

+ 8 - 0
src/main/frontend/config.cljs

@@ -298,3 +298,11 @@
 (defn get-local-dir
   [s]
   (string/replace s local-db-prefix ""))
+
+(defn get-repo-dir
+  [repo-url]
+  (if (util/electron?)
+    (get-local-dir repo-url)
+    (str "/"
+        (->> (take-last 2 (string/split repo-url #"/"))
+             (string/join "_")))))

+ 21 - 9
src/main/frontend/fs.cljs

@@ -7,7 +7,8 @@
             [frontend.fs.protocol :as protocol]
             [frontend.fs.nfs :as nfs]
             [frontend.fs.bfs :as bfs]
-            [frontend.fs.node :as node]))
+            [frontend.fs.node :as node]
+            [cljs-bean.core :as bean]))
 
 (defonce nfs-record (nfs/->Nfs))
 (defonce bfs-record (bfs/->Bfs))
@@ -20,15 +21,17 @@
 
 (defn get-fs
   [dir]
-  (cond
-    (util/electron?)
-    node-record
+  (let [bfs-local? (or (string/starts-with? dir "/local")
+                       (string/starts-with? dir "local"))]
+    (cond
+      (and (util/electron?) (not bfs-local?))
+      node-record
 
-    (local-db? dir)
-    nfs-record
+      (local-db? dir)
+      nfs-record
 
-    :else
-    bfs-record))
+      :else
+      bfs-record)))
 
 (defn mkdir!
   [dir]
@@ -84,6 +87,15 @@
                       "")]
     (protocol/stat (get-fs dir) dir path)))
 
+(defn open-dir
+  [ok-handler]
+  (let [record (if (util/electron?) node-record nfs-record)]
+    (p/let [result (protocol/open-dir record ok-handler)]
+      (if (util/electron?)
+        (let [[dir & paths] (bean/->clj result)]
+          [(:path dir) paths])
+        result))))
+
 (defn mkdir-if-not-exists
   [dir]
   (when dir
@@ -101,7 +113,7 @@
                 path
                 (str "/" path))]
      (->
-      (p/let [_ (stat dir path)]
+      (p/let [stat (stat dir path)]
         true)
       (p/catch
        (fn [_error]

+ 9 - 4
src/main/frontend/fs/bfs.cljs

@@ -7,8 +7,10 @@
 (defrecord Bfs []
   protocol/Fs
   (mkdir! [this dir]
-    (when js/window.pfs
-      (js/window.pfs.mkdir dir)))
+    (when (and js/window.pfs (not (util/electron?)))
+      (->
+       (js/window.pfs.mkdir dir)
+       (p/catch (fn [error] (println "Mkdir error: " error))))))
   (readdir [this dir]
     (when js/window.pfs
       (js/window.pfs.readdir dir)))
@@ -24,8 +26,11 @@
     (let [option (clj->js {:encoding "utf8"})]
       (js/window.pfs.readFile (str dir "/" path) option)))
   (write-file! [this repo dir path content opts]
-    (js/window.pfs.writeFile (str dir "/" path) content))
+    (when-not (util/electron?)
+      (js/window.pfs.writeFile (str dir "/" path) content)))
   (rename! [this repo old-path new-path]
     (js/window.pfs.rename old-path new-path))
   (stat [this dir path]
-    (js/window.pfs.stat (str dir path))))
+    (js/window.pfs.stat (str dir path)))
+  (open-dir [this ok-handler]
+    nil))

+ 4 - 1
src/main/frontend/fs/nfs.cljs

@@ -193,4 +193,7 @@
           {:file/last-modified-at (get-attr "lastModified")
            :file/size (get-attr "size")
            :file/type (get-attr "type")}))
-      (p/rejected "File not exists"))))
+      (p/rejected "File not exists")))
+  (open-dir [this ok-handler]
+    (utils/openDirectory #js {:recursive true}
+                         ok-handler)))

+ 24 - 4
src/main/frontend/fs/node.cljs

@@ -3,7 +3,22 @@
             [frontend.util :as util]
             [clojure.string :as string]
             [promesa.core :as p]
-            [electron.ipc :as ipc]))
+            [electron.ipc :as ipc]
+            [cljs-bean.core :as bean]))
+
+(defn concat-path
+  [dir path]
+  (cond
+    (nil? path)
+    dir
+
+    (string/starts-with? path dir)
+    path
+
+    :else
+    (str (string/replace dir #"/$" "")
+         (when path
+           (str "/" (string/replace path #"^/" ""))))))
 
 (defrecord Node []
   protocol/Fs
@@ -16,10 +31,15 @@
   (rmdir! [this dir]
     nil)
   (read-file [this dir path]
-    (ipc/ipc "readFile" (str dir "/" path)))
+    (let [path (concat-path dir path)]
+      (ipc/ipc "readFile" path)))
   (write-file! [this repo dir path content _opts]
-    (ipc/ipc "writeFile" (str dir "/" path) content))
+    (let [path (concat-path dir path)]
+      (ipc/ipc "writeFile" path content)))
   (rename! [this repo old-path new-path]
     (ipc/ipc "rename" old-path new-path))
   (stat [this dir path]
-    (ipc/ipc "stat" (str dir path))))
+    (let [path (concat-path dir path)]
+      (ipc/ipc "stat" path)))
+  (open-dir [this ok-handler]
+    (ipc/ipc "openDir" {})))

+ 2 - 1
src/main/frontend/fs/protocol.cljs

@@ -8,4 +8,5 @@
   (read-file [this dir path])
   (write-file! [this repo dir path content opts])
   (rename! [this repo old-path new-path])
-  (stat [this dir path]))
+  (stat [this dir path])
+  (open-dir [this ok-handler]))

+ 19 - 18
src/main/frontend/git.cljs

@@ -2,6 +2,7 @@
   (:refer-clojure :exclude [clone merge])
   (:require [promesa.core :as p]
             [frontend.util :as util]
+            [frontend.config :as config]
             [clojure.string :as string]
             [clojure.set :as set]
             [frontend.state :as state]
@@ -30,7 +31,7 @@
 
 (defn clone
   [repo-url token]
-  (js/window.workerThread.clone (util/get-repo-dir repo-url)
+  (js/window.workerThread.clone (config/get-repo-dir repo-url)
                                 repo-url
                                 (get-cors-proxy repo-url)
                                 1
@@ -40,12 +41,12 @@
 
 (defn list-files
   [repo-url]
-  (js/window.workerThread.listFiles (util/get-repo-dir repo-url)
+  (js/window.workerThread.listFiles (config/get-repo-dir repo-url)
                                     (state/get-default-branch repo-url)))
 
 (defn fetch
   [repo-url token]
-  (js/window.workerThread.fetch (util/get-repo-dir repo-url)
+  (js/window.workerThread.fetch (config/get-repo-dir repo-url)
                                 repo-url
                                 (get-cors-proxy repo-url)
                                 100
@@ -55,23 +56,23 @@
 
 (defn merge
   [repo-url]
-  (js/window.workerThread.merge (util/get-repo-dir repo-url)
+  (js/window.workerThread.merge (config/get-repo-dir repo-url)
                                 (state/get-default-branch repo-url)))
 
 (defn checkout
   [repo-url]
-  (js/window.workerThread.checkout (util/get-repo-dir repo-url)
+  (js/window.workerThread.checkout (config/get-repo-dir repo-url)
                                    (state/get-default-branch repo-url)))
 
 (defn log
   [repo-url depth]
-  (js/window.workerThread.log (util/get-repo-dir repo-url)
+  (js/window.workerThread.log (config/get-repo-dir repo-url)
                               (state/get-default-branch repo-url)
                               depth))
 
 (defn pull
   [repo-url token]
-  (js/window.workerThread.pull (util/get-repo-dir repo-url)
+  (js/window.workerThread.pull (config/get-repo-dir repo-url)
                                (get-cors-proxy repo-url)
                                (state/get-default-branch repo-url)
                                (get-username)
@@ -80,12 +81,12 @@
 (defn add
   [repo-url file]
   (when js/window.git
-    (js/window.workerThread.add (util/get-repo-dir repo-url)
+    (js/window.workerThread.add (config/get-repo-dir repo-url)
                                 file)))
 
 (defn remove-file
   [repo-url file]
-  (js/window.workerThread.remove (util/get-repo-dir repo-url)
+  (js/window.workerThread.remove (config/get-repo-dir repo-url)
                                  file))
 
 (defn rename
@@ -100,7 +101,7 @@
    (commit repo-url message nil))
   ([repo-url message parent]
    (let [{:keys [name email]} (:me @state/state)]
-     (js/window.workerThread.commit (util/get-repo-dir repo-url)
+     (js/window.workerThread.commit (config/get-repo-dir repo-url)
                                     message
                                     name
                                     email
@@ -109,7 +110,7 @@
 (defn add-all
   "Equivalent to `git add --all`. Returns changed files."
   [repo-url]
-  (p/let [repo-dir (util/get-repo-dir repo-url)
+  (p/let [repo-dir (config/get-repo-dir repo-url)
 
           ; statusMatrix will return `[]` rather than raising an error if the repo directory does
           ; not exist. So checks whether repo-dir exists before proceeding.
@@ -141,14 +142,14 @@
 
 (defn read-commit
   [repo-url oid]
-  (js/window.workerThread.readCommit (util/get-repo-dir repo-url)
+  (js/window.workerThread.readCommit (config/get-repo-dir repo-url)
                                      oid))
 
 
 ;; FIXME: not working
 ;; (defn descendent?
 ;;   [repo-url oid ancestor]
-;;   (js/window.workerThread.isDescendent (util/get-repo-dir repo-url)
+;;   (js/window.workerThread.isDescendent (config/get-repo-dir repo-url)
 ;;                                        oid
 ;;                                        ancestor))
 
@@ -166,7 +167,7 @@
   ([repo-url token]
    (push repo-url token false))
   ([repo-url token force?]
-   (js/window.workerThread.push (util/get-repo-dir repo-url)
+   (js/window.workerThread.push (config/get-repo-dir repo-url)
                                 (get-cors-proxy repo-url)
                                 (state/get-default-branch repo-url)
                                 force?
@@ -188,7 +189,7 @@
 (defn get-diffs
   [repo-url hash-1 hash-2]
   (and js/window.git
-       (let [dir (util/get-repo-dir repo-url)]
+       (let [dir (config/get-repo-dir repo-url)]
          (p/let [diffs (js/window.workerThread.getFileStateChanges hash-1 hash-2 dir)
                  diffs (cljs-bean.core/->clj diffs)
                  diffs (remove #(= (:type %) "equal") diffs)
@@ -217,16 +218,16 @@
 
 (defn read-blob
   [repo-url oid path]
-  (js/window.workerThread.readBlob (util/get-repo-dir repo-url)
+  (js/window.workerThread.readBlob (config/get-repo-dir repo-url)
                                    oid
                                    path))
 ;; (resolve-ref (state/get-current-repo) "refs/remotes/origin/master")
 (defn resolve-ref
   [repo-url ref]
-  (js/window.workerThread.resolveRef (util/get-repo-dir repo-url) ref))
+  (js/window.workerThread.resolveRef (config/get-repo-dir repo-url) ref))
 
 (defn write-ref!
   [repo-url oid]
-  (js/window.workerThread.writeRef (util/get-repo-dir repo-url)
+  (js/window.workerThread.writeRef (config/get-repo-dir repo-url)
                                    (state/get-default-branch repo-url)
                                    oid))

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

@@ -35,7 +35,7 @@
           (gobj/get js/window "workerThread")
           (gobj/get js/window.workerThread "getChangedFiles"))
      (->
-      (p/let [files (js/window.workerThread.getChangedFiles (util/get-repo-dir repo))
+      (p/let [files (js/window.workerThread.getChangedFiles (config/get-repo-dir repo))
               files (bean/->clj files)]
         (->
          (p/let [remote-latest-commit (get-remote-ref repo)

+ 4 - 4
src/main/frontend/handler/draw.cljs

@@ -48,7 +48,7 @@
 (defn create-draws-directory!
   [repo]
   (when repo
-    (let [repo-dir (util/get-repo-dir repo)]
+    (let [repo-dir (config/get-repo-dir repo)]
       (util/p-handle
        (fs/mkdir! (str repo-dir (str "/" config/default-draw-directory)))
        (fn [_result] nil)
@@ -59,7 +59,7 @@
   (let [path (str config/default-draw-directory "/" file)
         repo (state/get-current-repo)]
     (when repo
-      (let [repo-dir (util/get-repo-dir repo)]
+      (let [repo-dir (config/get-repo-dir repo)]
         (->
          (p/do!
           (create-draws-directory! repo)
@@ -82,7 +82,7 @@
   [ok-handler]
   (when-let [repo (state/get-current-repo)]
     (p/let [_ (create-draws-directory! repo)]
-      (let [dir (str (util/get-repo-dir repo)
+      (let [dir (str (config/get-repo-dir repo)
                      "/"
                      config/default-draw-directory)]
         (util/p-handle
@@ -121,7 +121,7 @@
 (defn create-draw-with-default-content
   [current-file ok-handler]
   (when-let [repo (state/get-current-repo)]
-    (p/let [exists? (fs/file-exists? (util/get-repo-dir repo)
+    (p/let [exists? (fs/file-exists? (config/get-repo-dir repo)
                                      (str config/default-draw-directory current-file))]
       (when-not exists?
         (save-excalidraw! current-file default-content

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

@@ -502,7 +502,7 @@
                              (util/page-name-sanity))) "."
                        (if (= format "markdown") "md" format))
                  file-path (str "/" path)
-                 dir (util/get-repo-dir repo)]
+                 dir (config/get-repo-dir repo)]
              (p/let [exists? (fs/file-exists? dir file-path)]
                (if exists?
                  (notification/show!
@@ -781,7 +781,7 @@
                   "."
                   (if (= format "markdown") "md" format))
             file-path (str "/" path)
-            dir (util/get-repo-dir repo)]
+            dir (config/get-repo-dir repo)]
         (p/let [exists? (fs/file-exists? dir file-path)]
           (if exists?
             (do (notification/show!
@@ -1541,7 +1541,7 @@
 
 (defn ensure-assets-dir!
   [repo]
-  (let [repo-dir (util/get-repo-dir repo)
+  (let [repo-dir (config/get-repo-dir repo)
         assets-dir "assets"]
     (p/then
      (fs/mkdir-if-not-exists (str repo-dir "/" assets-dir))
@@ -1572,7 +1572,7 @@
 
 (defn make-asset-url
   [path]                                                    ;; path start with "/assets" or compatible for "../assets"
-  (let [repo-dir (util/get-repo-dir (state/get-current-repo))
+  (let [repo-dir (config/get-repo-dir (state/get-current-repo))
         path (string/replace path "../" "/")
         handle-path (str "handle" repo-dir path)
         cached-url (get @*assets-url-cache (keyword handle-path))]
@@ -1595,7 +1595,7 @@
     (save-block! repo block content)
     (when local?
       ;; FIXME: should be relative to current block page path
-      (fs/unlink! (str (util/get-repo-dir repo) (string/replace href #"^../" "/")) nil))))
+      (fs/unlink! (str (config/get-repo-dir repo) (string/replace href #"^../" "/")) nil))))
 
 (defn upload-image
   [id files format uploading? drop-or-paste?]

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

@@ -129,7 +129,7 @@
   [repo-url file content utf8-content]
   (if (string/blank? content)
     []
-    (let [journal? (util/starts-with? file "journals/")
+    (let [journal? (util/journal? file)
           format (format/get-format file)
           ast (mldoc/->edn content
                            (mldoc/default-config format))

+ 4 - 4
src/main/frontend/handler/file.cljs

@@ -30,7 +30,7 @@
 (defn load-file
   [repo-url path]
   (->
-   (p/let [content (fs/read-file (util/get-repo-dir repo-url) path)]
+   (p/let [content (fs/read-file (config/get-repo-dir repo-url) path)]
      content)
    (p/catch
     (fn [e]
@@ -162,7 +162,7 @@
         (reset-file! repo path content))
       (db/set-file-content! repo path content))
     (util/p-handle
-     (fs/write-file! repo (util/get-repo-dir repo) path content {:old-content original-content
+     (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)})
      (fn [_]
        (git-handler/git-add repo path update-status?)
@@ -222,7 +222,7 @@
   (let [write-file-f (fn [[path content]]
                        (let [original-content (get file->content path)]
                          (-> (p/let [_ (nfs/check-directory-permission! repo)]
-                               (fs/write-file! repo (util/get-repo-dir repo) path content
+                               (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)}))
                              (p/catch (fn [error]
@@ -265,7 +265,7 @@
     (->
      (p/let [_ (git/remove-file repo file)
              result (fs/unlink! (str
-                                 (util/get-repo-dir repo)
+                                 (config/get-repo-dir repo)
                                  "/"
                                  file)
                                 nil)]

+ 3 - 2
src/main/frontend/handler/git.cljs

@@ -30,7 +30,8 @@
   ([repo-url file]
    (git-add repo-url file true))
   ([repo-url file update-status?]
-   (when-not (config/local-db? repo-url)
+   (when (and (not (config/local-db? repo-url))
+              (not (util/electron?)))
      (-> (p/let [result (git/add repo-url file)]
            (when update-status?
              (common-handler/check-changed-files-status)))
@@ -57,6 +58,6 @@
   [repo-url {:keys [name email]}]
   (when (and name email)
     (git/set-username-email
-     (util/get-repo-dir repo-url)
+     (config/get-repo-dir repo-url)
      name
      email)))

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

@@ -34,7 +34,7 @@
                      (subs path 1)
                      path)]
           (util/p-handle
-           (fs/read-file (util/get-repo-dir (state/get-current-repo))
+           (fs/read-file (config/get-repo-dir (state/get-current-repo))
                          path)
            (fn [blob]
              (let [blob (js/Blob. (array blob) (clj->js {:type "image"}))

+ 4 - 4
src/main/frontend/handler/page.cljs

@@ -46,7 +46,7 @@
            :or {redirect? true}}]
    (let [title (and title (string/trim title))
          repo (state/get-current-repo)
-         dir (util/get-repo-dir repo)
+         dir (config/get-repo-dir repo)
          journal-page? (date/valid-journal-title? title)
          directory (get-directory journal-page?)]
      (when dir
@@ -273,7 +273,7 @@
               ;; remove file
               (->
                (p/let [_ (git/remove-file repo file-path)
-                       _ (fs/unlink! (str (util/get-repo-dir repo)
+                       _ (fs/unlink! (str (config/get-repo-dir repo)
                                           "/"
                                           file-path)
                                      nil)]
@@ -311,8 +311,8 @@
                             :file/path new-path}])))
     (->
      (p/let [_ (fs/rename! repo
-                           (str (util/get-repo-dir repo) "/" old-path)
-                           (str (util/get-repo-dir repo) "/" new-path))
+                           (str (config/get-repo-dir repo) "/" old-path)
+                           (str (config/get-repo-dir repo) "/" new-path))
              _ (when-not (config/local-db? repo)
                  (git/rename repo old-path new-path))]
        (common-handler/check-changed-files-status)

+ 9 - 9
src/main/frontend/handler/repo.cljs

@@ -52,7 +52,7 @@
 (defn create-config-file-if-not-exists
   [repo-url]
   (spec/validate :repos/url repo-url)
-  (let [repo-dir (util/get-repo-dir repo-url)
+  (let [repo-dir (config/get-repo-dir repo-url)
         app-dir config/app-name
         dir (str repo-dir "/" app-dir)]
     (p/let [_ (fs/mkdir-if-not-exists dir)]
@@ -70,7 +70,7 @@
 (defn create-contents-file
   [repo-url]
   (spec/validate :repos/url repo-url)
-  (let [repo-dir (util/get-repo-dir repo-url)
+  (let [repo-dir (config/get-repo-dir repo-url)
         format (state/get-preferred-format)
         path (str (state/get-pages-directory)
                   "/contents."
@@ -86,7 +86,7 @@
 (defn create-custom-theme
   [repo-url]
   (spec/validate :repos/url repo-url)
-  (let [repo-dir (util/get-repo-dir repo-url)
+  (let [repo-dir (config/get-repo-dir repo-url)
         path (str config/app-name "/" config/custom-css-file)
         file-path (str "/" path)
         default-content ""]
@@ -99,7 +99,7 @@
 (defn create-dummy-notes-page
   [repo-url content]
   (spec/validate :repos/url repo-url)
-  (let [repo-dir (util/get-repo-dir repo-url)
+  (let [repo-dir (config/get-repo-dir repo-url)
         path (str (config/get-pages-directory) "/how_to_make_dummy_notes.md")
         file-path (str "/" path)]
     (p/let [_ (fs/mkdir-if-not-exists (str repo-dir "/" (config/get-pages-directory)))
@@ -112,7 +112,7 @@
   ([repo-url content]
    (spec/validate :repos/url repo-url)
    (when (state/enable-journals? repo-url)
-     (let [repo-dir (util/get-repo-dir repo-url)
+     (let [repo-dir (config/get-repo-dir repo-url)
            format (state/get-preferred-format repo-url)
            title (date/today)
            file-name (date/journal-title->default title)
@@ -359,7 +359,7 @@
                 (nil? local-latest-commit)
                 (not descendent?)
                 force-pull?)
-        (p/let [files (js/window.workerThread.getChangedFiles (util/get-repo-dir repo-url))]
+        (p/let [files (js/window.workerThread.getChangedFiles (config/get-repo-dir repo-url))]
           (when (empty? files)
             (let [status (db/get-key-value repo-url :git/status)]
               (when (or
@@ -539,7 +539,7 @@
                       (db/remove-conn! url)
                       (db/remove-db! url)
                       (db/remove-files-db! url)
-                      (fs/rmdir! (util/get-repo-dir url))
+                      (fs/rmdir! (config/get-repo-dir url))
                       (state/delete-repo! repo))]
     (if (config/local-db? url)
       (p/let [_ (idb/clear-local-db! url)] ; clear file handles
@@ -621,7 +621,7 @@
       (doseq [{:keys [id url]} (:repos me)]
         (let [repo url]
           (p/let [config-exists? (fs/file-exists?
-                                  (util/get-repo-dir url)
+                                  (config/get-repo-dir url)
                                   ".git/config")]
             (if (and config-exists?
                      (db/cloned? repo))
@@ -645,7 +645,7 @@
     (db/clear-query-state!)
     (-> (p/do! (db/remove-db! url)
                (db/remove-files-db! url)
-               (fs/rmdir! (util/get-repo-dir url))
+               (fs/rmdir! (config/get-repo-dir url))
                (clone-and-load-db url))
         (p/catch (fn [error]
                    (prn "Delete repo failed, error: " error))))))

+ 71 - 59
src/main/frontend/handler/web/nfs.cljs

@@ -40,20 +40,28 @@
       (p/resolved files))))
 
 (defn- ->db-files
-  [dir-name result]
-  (let [result (flatten (bean/->clj result))]
-    (map (fn [file]
-           (let [handle (gobj/get file "handle")
-                 get-attr #(gobj/get file %)
-                 path (-> (get-attr "webkitRelativePath")
-                          (string/replace-first (str dir-name "/") ""))]
-             {:file/name             (get-attr "name")
-              :file/path             path
-              :file/last-modified-at (get-attr "lastModified")
-              :file/size             (get-attr "size")
-              :file/type             (get-attr "type")
-              :file/file             file
-              :file/handle           handle})) result)))
+  [electron? dir-name result]
+  (if electron?
+    (map (fn [{:keys [path stat content]}]
+           (let [{:keys [mtime size]} stat]
+             {:file/path             path
+              :file/last-modified-at mtime
+              :file/size             size
+              :file/content content}))
+      result)
+    (let [result (flatten (bean/->clj result))]
+      (map (fn [file]
+            (let [handle (gobj/get file "handle")
+                  get-attr #(gobj/get file %)
+                  path (-> (get-attr "webkitRelativePath")
+                           (string/replace-first (str dir-name "/") ""))]
+              {:file/name             (get-attr "name")
+               :file/path             path
+               :file/last-modified-at (get-attr "lastModified")
+               :file/size             (get-attr "size")
+               :file/type             (get-attr "type")
+               :file/file             file
+               :file/handle           handle})) result))))
 
 (defn- filter-markup-and-built-in-files
   [files]
@@ -92,40 +100,49 @@
 
 (defn ls-dir-files
   []
-  (let [path-handles (atom {})]
+  (let [path-handles (atom {})
+        electron? (util/electron?)
+        nfs? (not electron?)]
     ;; TODO: add ext filter to avoid loading .git or other ignored file handlers
     (->
-     (p/let [result (utils/openDirectory #js {:recursive true}
-                                         (fn [path handle]
-                                           (swap! path-handles assoc path handle)))
+     (p/let [result (fs/open-dir (fn [path handle]
+                                   (when nfs?
+                                     (swap! path-handles assoc path handle))))
              _ (state/set-loading-files! true)
-             root-handle (nth result 0)
-             dir-name (gobj/get root-handle "name")
+             root-handle (first result)
+             dir-name (if nfs?
+                        (gobj/get root-handle "name")
+                        root-handle)
              repo (str config/local-db-prefix dir-name)
              root-handle-path (str config/local-handle-prefix dir-name)
-             _ (idb/set-item! root-handle-path root-handle)
-             _ (nfs/add-nfs-file-handle! root-handle-path root-handle)
+             _ (when nfs?
+                 (idb/set-item! root-handle-path root-handle)
+                 (nfs/add-nfs-file-handle! root-handle-path root-handle))
              result (nth result 1)
-             files (-> (->db-files dir-name result)
+             files (-> (->db-files electron? dir-name result)
                        remove-ignore-files)
-             _ (let [file-paths (set (map :file/path files))]
-                 (swap! path-handles (fn [handles]
-                                       (->> handles
-                                            (filter (fn [[path _handle]]
-                                                      (or
-                                                       (contains? file-paths
-                                                                  (string/replace-first path (str dir-name "/") ""))
-                                                       (let [last-part (last (string/split path "/"))]
-                                                         (contains? #{config/app-name
-                                                                      config/default-draw-directory
-                                                                      config/default-journals-directory
-                                                                      config/default-pages-directory}
-                                                                    last-part)))))
-                                            (into {})))))
-             _ (set-files! @path-handles)
+             _ (when nfs?
+                 (let [file-paths (set (map :file/path files))]
+                  (swap! path-handles (fn [handles]
+                                        (->> handles
+                                             (filter (fn [[path _handle]]
+                                                       (or
+                                                        (contains? file-paths
+                                                                   (string/replace-first path (str dir-name "/") ""))
+                                                        (let [last-part (last (string/split path "/"))]
+                                                          (contains? #{config/app-name
+                                                                       config/default-draw-directory
+                                                                       config/default-journals-directory
+                                                                       config/default-pages-directory}
+                                                                     last-part)))))
+                                             (into {})))))
+
+                 (set-files! @path-handles))
              markup-files (filter-markup-and-built-in-files files)]
        (-> (p/all (map (fn [file]
-                         (p/let [content (.text (:file/file file))]
+                         (p/let [content (if nfs?
+                                           (.text (:file/file file))
+                                           (:file/content file))]
                            (assoc file :file/content content))) markup-files))
            (p/then (fn [result]
                      _ (state/set-loading-files! false)
@@ -142,13 +159,6 @@
                 (when (not= "AbortError" (gobj/get error "name"))
                   (log/error :nfs/open-dir-error error)))))))
 
-(defn open-file-picker
-  "Shows a file picker that lets a user select a single existing file, returning a handle for the selected file. "
-  ([]
-   (open-file-picker {}))
-  ([option]
-   (.showOpenFilePicker js/window (bean/->js option))))
-
 (defn get-local-repo
   []
   (when-let [repo (state/get-current-repo)]
@@ -157,16 +167,17 @@
 
 (defn ask-permission
   [repo]
-  (fn [close-fn]
-    [:div
-     [:p.text-gray-700
-      "Grant native filesystem permission for directory: "
-      [:b (config/get-local-dir repo)]]
-     (ui/button
-      "Grant"
-      :on-click (fn []
-                  (nfs/check-directory-permission! repo)
-                  (close-fn)))]))
+  (when-not (util/electron?)
+    (fn [close-fn]
+      [:div
+       [:p.text-gray-700
+        "Grant native filesystem permission for directory: "
+        [:b (config/get-local-dir repo)]]
+       (ui/button
+         "Grant"
+         :on-click (fn []
+                     (nfs/check-directory-permission! repo)
+                     (close-fn)))])))
 
 (defn ask-permission-if-local? []
   (when-let [repo (get-local-repo)]
@@ -201,7 +212,8 @@
      (let [old-files (db/get-files-full repo)
            dir-name (config/get-local-dir repo)
            handle-path (str config/local-handle-prefix dir-name)
-           path-handles (atom {})]
+           path-handles (atom {})
+           electron? (util/electron?)]
        (state/set-graph-syncing? true)
        (->
         (p/let [handle (idb/get-item handle-path)]
@@ -210,7 +222,7 @@
                     files-result (utils/getFiles handle true
                                                  (fn [path handle]
                                                    (swap! path-handles assoc path handle)))
-                    new-files (-> (->db-files dir-name files-result)
+                    new-files (-> (->db-files electron? dir-name files-result)
                                   remove-ignore-files)
                     _ (let [file-paths (set (map :file/path new-files))]
                         (swap! path-handles (fn [handles]
@@ -290,4 +302,4 @@
 
 (defn supported?
   []
-  (utils/nfsSupported))
+  (or (utils/nfsSupported) (util/electron?)))

+ 1 - 7
src/main/frontend/util.cljc

@@ -448,7 +448,7 @@
 
 (defn journal?
   [path]
-  (starts-with? path "journals/"))
+  (string/includes? path "journals/"))
 
 (defn drop-first-line
   [s]
@@ -782,12 +782,6 @@
   []
   #?(:cljs (tc/to-long (cljs-time.core/now))))
 
-(defn get-repo-dir
-  [repo-url]
-  (str "/"
-       (->> (take-last 2 (string/split repo-url #"/"))
-            (string/join "_"))))
-
 (defn d
   [k f]
   (let [result (atom nil)]