|
|
@@ -168,7 +168,7 @@
|
|
|
|
|
|
(defn- write-file-impl!
|
|
|
[_this repo _dir path content {:keys [ok-handler error-handler old-content skip-compare?]} stat]
|
|
|
- (if skip-compare?
|
|
|
+ (if (or (string/blank? repo) skip-compare?)
|
|
|
(p/catch
|
|
|
(p/let [result (<write-file-with-utf8 path content)]
|
|
|
(when ok-handler
|
|
|
@@ -212,31 +212,44 @@
|
|
|
(error-handler error)
|
|
|
(log/error :write-file-failed error)))))))))
|
|
|
|
|
|
-(defn get-file-path [dir path]
|
|
|
- (let [dir (some-> dir (string/replace #"/+$" ""))
|
|
|
- dir (if (and (not-empty dir) (string/starts-with? dir "/"))
|
|
|
- (do
|
|
|
- (js/console.trace "WARN: detect absolute path, use URL instead")
|
|
|
- (str "file://" (js/encodeURI dir)))
|
|
|
- dir)
|
|
|
- path (some-> path (string/replace #"^/+" ""))
|
|
|
- encode-url #(let [encoded-chars?
|
|
|
- (and (string? %) (boolean (re-find #"(?i)%[0-9a-f]{2}" %)))]
|
|
|
- (cond-> %
|
|
|
- (not encoded-chars?)
|
|
|
- (js/encodeURI path)))]
|
|
|
- (cond (string/blank? path)
|
|
|
- (encode-url dir)
|
|
|
+(defn remove-private-part
|
|
|
+ "iOS sometimes return the private part."
|
|
|
+ [path]
|
|
|
+ (string/replace path "///private/" "///"))
|
|
|
+
|
|
|
+(defn normalize-file-protocol-path [dir path]
|
|
|
+ (let [dir (some-> dir (string/replace #"/+$" ""))
|
|
|
+ dir (if (and (not-empty dir) (string/starts-with? dir "/"))
|
|
|
+ (do
|
|
|
+ (js/console.trace "WARN: detect absolute path, use URL instead")
|
|
|
+ (str "file://" (js/encodeURI dir)))
|
|
|
+ dir)
|
|
|
+ path (some-> path (string/replace #"^/+" ""))
|
|
|
+ safe-encode-url #(let [encoded-chars?
|
|
|
+ (and (string? %) (boolean (re-find #"(?i)%[0-9a-f]{2}" %)))]
|
|
|
+ (cond
|
|
|
+ (not encoded-chars?)
|
|
|
+ (js/encodeURI %)
|
|
|
+
|
|
|
+ :else
|
|
|
+ (js/encodeURI (js/decodeURI %))))
|
|
|
+ path' (cond
|
|
|
+ (and path (string/starts-with? path "file:/"))
|
|
|
+ (safe-encode-url path)
|
|
|
+
|
|
|
+ (string/blank? path)
|
|
|
+ (safe-encode-url dir)
|
|
|
|
|
|
- (string/blank? dir)
|
|
|
- (encode-url path)
|
|
|
+ (string/blank? dir)
|
|
|
+ (safe-encode-url path)
|
|
|
|
|
|
- (string/starts-with? path dir)
|
|
|
- (encode-url path)
|
|
|
+ (string/starts-with? path dir)
|
|
|
+ (safe-encode-url path)
|
|
|
|
|
|
- :else
|
|
|
- (let [path' (encode-url path)]
|
|
|
- (str dir "/" path')))))
|
|
|
+ :else
|
|
|
+ (let [path' (safe-encode-url path)]
|
|
|
+ (str dir "/" path')))]
|
|
|
+ (remove-private-part path')))
|
|
|
|
|
|
(defn- local-container-path?
|
|
|
"Check whether `path' is logseq's container `localDocumentsPath' on iOS"
|
|
|
@@ -260,15 +273,35 @@
|
|
|
:webkit-allow-full-screen "webkitallowfullscreen"
|
|
|
:height "100%"}]])
|
|
|
|
|
|
+(defn- open-dir
|
|
|
+ [dir]
|
|
|
+ (p/let [_ (when (mobile-util/native-android?) (android-check-permission))
|
|
|
+ {:keys [path localDocumentsPath]} (-> (.pickFolder mobile-util/folder-picker
|
|
|
+ (clj->js (when (and dir (mobile-util/native-ios?))
|
|
|
+ {:path dir})))
|
|
|
+ (p/then #(js->clj % :keywordize-keys true))
|
|
|
+ (p/catch (fn [e]
|
|
|
+ (js/alert (str e))
|
|
|
+ nil))) ;; NOTE: If pick folder fails, let it crash
|
|
|
+ _ (when (and (mobile-util/native-ios?)
|
|
|
+ (not (or (local-container-path? path localDocumentsPath)
|
|
|
+ (mobile-util/iCloud-container-path? path))))
|
|
|
+ (state/pub-event! [:modal/show-instruction]))
|
|
|
+ _ (js/console.log "Opening or Creating graph at directory: " path)
|
|
|
+ files (readdir path)
|
|
|
+ files (js->clj files :keywordize-keys true)]
|
|
|
+ (into [] (concat [{:path path}] files))))
|
|
|
+
|
|
|
(defrecord ^:large-vars/cleanup-todo Capacitorfs []
|
|
|
protocol/Fs
|
|
|
(mkdir! [_this dir]
|
|
|
- (-> (.mkdir Filesystem
|
|
|
- (clj->js
|
|
|
- {:path dir}))
|
|
|
- (p/catch (fn [error]
|
|
|
- (log/error :mkdir! {:path dir
|
|
|
- :error error})))))
|
|
|
+ (let [dir' (normalize-file-protocol-path "" dir)]
|
|
|
+ (-> (.mkdir Filesystem
|
|
|
+ (clj->js
|
|
|
+ {:path dir'}))
|
|
|
+ (p/catch (fn [error]
|
|
|
+ (log/error :mkdir! {:path dir'
|
|
|
+ :error error}))))))
|
|
|
(mkdir-recur! [_this dir]
|
|
|
(p/let
|
|
|
[_ (-> (.mkdir Filesystem
|
|
|
@@ -288,7 +321,7 @@
|
|
|
dir)]
|
|
|
(readdir dir)))
|
|
|
(unlink! [this repo path _opts]
|
|
|
- (p/let [path (get-file-path nil path)
|
|
|
+ (p/let [path (normalize-file-protocol-path nil path)
|
|
|
repo-url (config/get-local-dir repo)
|
|
|
recycle-dir (util/safe-path-join repo-url config/app-name ".recycle") ;; logseq/.recycle
|
|
|
;; convert url to pure path
|
|
|
@@ -302,20 +335,20 @@
|
|
|
;; Too dangerous!!! We'll never implement this.
|
|
|
nil)
|
|
|
(read-file [_this dir path _options]
|
|
|
- (let [path (get-file-path dir path)]
|
|
|
+ (let [path (normalize-file-protocol-path dir path)]
|
|
|
(->
|
|
|
(<read-file-with-utf8 path)
|
|
|
(p/catch (fn [error]
|
|
|
(log/error :read-file-failed error))))))
|
|
|
(write-file! [this repo dir path content opts]
|
|
|
- (let [path (get-file-path dir path)]
|
|
|
+ (let [path (normalize-file-protocol-path dir path)]
|
|
|
(p/let [stat (p/catch
|
|
|
(.stat Filesystem (clj->js {:path path}))
|
|
|
(fn [_e] :not-found))]
|
|
|
;; `path` is full-path
|
|
|
(write-file-impl! this repo dir path content opts stat))))
|
|
|
(rename! [_this _repo old-path new-path]
|
|
|
- (let [[old-path new-path] (map #(get-file-path "" %) [old-path new-path])]
|
|
|
+ (let [[old-path new-path] (map #(normalize-file-protocol-path "" %) [old-path new-path])]
|
|
|
(p/catch
|
|
|
(p/let [_ (.rename Filesystem
|
|
|
(clj->js
|
|
|
@@ -324,7 +357,7 @@
|
|
|
(fn [error]
|
|
|
(log/error :rename-file-failed error)))))
|
|
|
(copy! [_this _repo old-path new-path]
|
|
|
- (let [[old-path new-path] (map #(get-file-path "" %) [old-path new-path])]
|
|
|
+ (let [[old-path new-path] (map #(normalize-file-protocol-path "" %) [old-path new-path])]
|
|
|
(p/catch
|
|
|
(p/let [_ (.copy Filesystem
|
|
|
(clj->js
|
|
|
@@ -333,24 +366,11 @@
|
|
|
(fn [error]
|
|
|
(log/error :copy-file-failed error)))))
|
|
|
(stat [_this dir path]
|
|
|
- (let [path (get-file-path dir path)]
|
|
|
+ (let [path (normalize-file-protocol-path dir path)]
|
|
|
(p/chain (.stat Filesystem (clj->js {:path path}))
|
|
|
#(js->clj % :keywordize-keys true))))
|
|
|
- (open-dir [_this _ok-handler]
|
|
|
- (p/let [_ (when (mobile-util/native-android?) (android-check-permission))
|
|
|
- {:keys [path localDocumentsPath]} (-> (.pickFolder mobile-util/folder-picker)
|
|
|
- (p/then #(js->clj % :keywordize-keys true))
|
|
|
- (p/catch (fn [e]
|
|
|
- (js/alert (str e))
|
|
|
- nil))) ;; NOTE: If pick folder fails, let it crash
|
|
|
- _ (when (and (mobile-util/native-ios?)
|
|
|
- (not (or (local-container-path? path localDocumentsPath)
|
|
|
- (mobile-util/iCloud-container-path? path))))
|
|
|
- (state/pub-event! [:modal/show-instruction]))
|
|
|
- _ (js/console.log "Opening or Creating graph at directory: " path)
|
|
|
- files (readdir path)
|
|
|
- files (js->clj files :keywordize-keys true)]
|
|
|
- (into [] (concat [{:path path}] files))))
|
|
|
+ (open-dir [_this dir _ok-handler]
|
|
|
+ (open-dir dir))
|
|
|
(get-files [_this path-or-handle _ok-handler]
|
|
|
(readdir path-or-handle))
|
|
|
(watch-dir! [_this dir _options]
|