mirror of https://github.com/logseq/logseq
fix(mobile): diff when write conflicts occur
parent
b628044569
commit
0eed799ccf
|
@ -1,13 +1,16 @@
|
||||||
(ns frontend.fs.capacitor-fs
|
(ns frontend.fs.capacitor-fs
|
||||||
(:require [frontend.fs.protocol :as protocol]
|
(:require ["@capacitor/filesystem" :refer [Encoding Filesystem]]
|
||||||
[lambdaisland.glogi :as log]
|
|
||||||
[frontend.util :as futil]
|
|
||||||
[frontend.config :as config]
|
|
||||||
[cljs-bean.core :as bean]
|
[cljs-bean.core :as bean]
|
||||||
["@capacitor/filesystem" :refer [Filesystem Encoding]]
|
|
||||||
[promesa.core :as p]
|
|
||||||
[clojure.string :as string]
|
[clojure.string :as string]
|
||||||
[frontend.mobile.util :as mobile-util]))
|
[frontend.config :as config]
|
||||||
|
[frontend.fs.protocol :as protocol]
|
||||||
|
[frontend.mobile.util :as mobile-util]
|
||||||
|
[frontend.util :as util]
|
||||||
|
[lambdaisland.glogi :as log]
|
||||||
|
[promesa.core :as p]
|
||||||
|
[frontend.encrypt :as encrypt]
|
||||||
|
[frontend.state :as state]
|
||||||
|
[frontend.db :as db]))
|
||||||
|
|
||||||
(when (mobile-util/native-ios?)
|
(when (mobile-util/native-ios?)
|
||||||
(defn iOS-ensure-documents!
|
(defn iOS-ensure-documents!
|
||||||
|
@ -28,7 +31,7 @@
|
||||||
(when (string? uri)
|
(when (string? uri)
|
||||||
(-> uri
|
(-> uri
|
||||||
(string/replace "file://" "")
|
(string/replace "file://" "")
|
||||||
(futil/url-decode))))
|
(util/url-decode))))
|
||||||
|
|
||||||
(defn readdir
|
(defn readdir
|
||||||
"readdir recursively"
|
"readdir recursively"
|
||||||
|
@ -51,10 +54,10 @@
|
||||||
(= file "bak")))))
|
(= file "bak")))))
|
||||||
files (->> files
|
files (->> files
|
||||||
(map (fn [file]
|
(map (fn [file]
|
||||||
(futil/node-path.join
|
(util/node-path.join
|
||||||
d
|
d
|
||||||
(if (mobile-util/native-ios?)
|
(if (mobile-util/native-ios?)
|
||||||
(futil/url-encode file)
|
(util/url-encode file)
|
||||||
file)))))
|
file)))))
|
||||||
files-with-stats (p/all
|
files-with-stats (p/all
|
||||||
(mapv
|
(mapv
|
||||||
|
@ -93,6 +96,70 @@
|
||||||
result (js->clj result :keywordize-keys true)]
|
result (js->clj result :keywordize-keys true)]
|
||||||
(map (fn [result] (update result :uri clean-uri)) result)))
|
(map (fn [result] (update result :uri clean-uri)) result)))
|
||||||
|
|
||||||
|
(defn- contents-matched?
|
||||||
|
[disk-content db-content]
|
||||||
|
(when (and (string? disk-content) (string? db-content))
|
||||||
|
(if (encrypt/encrypted-db? (state/get-current-repo))
|
||||||
|
(p/let [decrypted-content (encrypt/decrypt disk-content)]
|
||||||
|
(= (string/trim decrypted-content) (string/trim db-content)))
|
||||||
|
(p/resolved (= (string/trim disk-content) (string/trim db-content))))))
|
||||||
|
|
||||||
|
(defn- write-file-impl!
|
||||||
|
[_this repo dir path content {:keys [ok-handler error-handler old-content skip-compare?]} stat]
|
||||||
|
(println (string/join "\n" [repo dir path content stat]))
|
||||||
|
(if skip-compare?
|
||||||
|
(p/catch
|
||||||
|
(p/let [result (.writeFile Filesystem (clj->js {:path path
|
||||||
|
:data content
|
||||||
|
:encoding (.-UTF8 Encoding)
|
||||||
|
:recursive true}))]
|
||||||
|
(when ok-handler
|
||||||
|
(ok-handler repo path result)))
|
||||||
|
(fn [error]
|
||||||
|
(if error-handler
|
||||||
|
(error-handler error)
|
||||||
|
(log/error :write-file-failed error))))
|
||||||
|
|
||||||
|
(p/let [disk-content (-> (p/chain (.readFile Filesystem (clj->js {:path path
|
||||||
|
:encoding (.-UTF8 Encoding)}))
|
||||||
|
#(js->clj % :keywordize-keys true)
|
||||||
|
:data)
|
||||||
|
(p/catch (fn [error]
|
||||||
|
(js/console.error error)
|
||||||
|
nil)))
|
||||||
|
disk-content (or disk-content "")
|
||||||
|
ext (string/lower-case (util/get-file-ext path))
|
||||||
|
db-content (or old-content (db/get-file repo path) "")
|
||||||
|
contents-matched? (contents-matched? disk-content db-content)
|
||||||
|
pending-writes (state/get-write-chan-length)]
|
||||||
|
(cond
|
||||||
|
(and
|
||||||
|
(not= stat :not-found) ; file on the disk was deleted
|
||||||
|
(not contents-matched?)
|
||||||
|
(not (contains? #{"excalidraw" "edn" "css"} ext))
|
||||||
|
(not (string/includes? path "/.recycle/"))
|
||||||
|
(zero? pending-writes))
|
||||||
|
(p/let [disk-content (encrypt/decrypt disk-content)]
|
||||||
|
(state/pub-event! [:file/not-matched-from-disk path disk-content content]))
|
||||||
|
|
||||||
|
:else
|
||||||
|
(->
|
||||||
|
(p/let [result (.writeFile Filesystem (clj->js {:path path
|
||||||
|
:data content
|
||||||
|
:encoding (.-UTF8 Encoding)
|
||||||
|
:recursive true}))]
|
||||||
|
(p/let [content (if (encrypt/encrypted-db? (state/get-current-repo))
|
||||||
|
(encrypt/decrypt content)
|
||||||
|
content)]
|
||||||
|
(db/set-file-content! repo path content))
|
||||||
|
(when ok-handler
|
||||||
|
(ok-handler repo path result))
|
||||||
|
result)
|
||||||
|
(p/catch (fn [error]
|
||||||
|
(if error-handler
|
||||||
|
(error-handler error)
|
||||||
|
(log/error :write-file-failed error)))))))))
|
||||||
|
|
||||||
(defrecord Capacitorfs []
|
(defrecord Capacitorfs []
|
||||||
protocol/Fs
|
protocol/Fs
|
||||||
(mkdir! [_this dir]
|
(mkdir! [_this dir]
|
||||||
|
@ -145,16 +212,16 @@
|
||||||
(-> (str dir "/" path)
|
(-> (str dir "/" path)
|
||||||
(string/replace "//" "/")))]
|
(string/replace "//" "/")))]
|
||||||
(p/catch
|
(p/catch
|
||||||
(p/let [result (.deleteFile Filesystem
|
(p/let [result (.deleteFile Filesystem
|
||||||
(clj->js
|
(clj->js
|
||||||
{:path path}))]
|
{:path path}))]
|
||||||
(when ok-handler
|
(when ok-handler
|
||||||
(ok-handler repo path result)))
|
(ok-handler repo path result)))
|
||||||
(fn [error]
|
(fn [error]
|
||||||
(if error-handler
|
(if error-handler
|
||||||
(error-handler error)
|
(error-handler error)
|
||||||
(log/error :delete-file-failed error))))))
|
(log/error :delete-file-failed error))))))
|
||||||
(write-file! [_this repo dir path content {:keys [ok-handler error-handler]}]
|
(write-file! [this repo dir path content opts]
|
||||||
(let [path (cond
|
(let [path (cond
|
||||||
(= (mobile-util/platform) "ios")
|
(= (mobile-util/platform) "ios")
|
||||||
(js/encodeURI (js/decodeURI path))
|
(js/encodeURI (js/decodeURI path))
|
||||||
|
@ -165,19 +232,10 @@
|
||||||
:else
|
:else
|
||||||
(-> (str dir "/" path)
|
(-> (str dir "/" path)
|
||||||
(string/replace "//" "/")))]
|
(string/replace "//" "/")))]
|
||||||
(p/catch
|
(p/let [stat (p/catch
|
||||||
(p/let [result (.writeFile Filesystem
|
(.stat Filesystem (clj->js {:path path}))
|
||||||
(clj->js
|
(fn [_e] :not-found))]
|
||||||
{:path path
|
(write-file-impl! this repo dir path content opts stat))))
|
||||||
:data content
|
|
||||||
:encoding (.-UTF8 Encoding)
|
|
||||||
:recursive true}))]
|
|
||||||
(when ok-handler
|
|
||||||
(ok-handler repo path result)))
|
|
||||||
(fn [error]
|
|
||||||
(if error-handler
|
|
||||||
(error-handler error)
|
|
||||||
(log/error :write-file-failed error))))))
|
|
||||||
(rename! [_this _repo _old-path _new-path]
|
(rename! [_this _repo _old-path _new-path]
|
||||||
nil)
|
nil)
|
||||||
(stat [_this dir path]
|
(stat [_this dir path]
|
||||||
|
|
Loading…
Reference in New Issue