fix: prompt to create a Logseq sync graph or normal graph on iOS

Previously, users can create a graph everywhere including the iCloud
folder, which is both confusing and can cause unexpected data
conflicts.

Another enhancement:
After the user confirms the "Use Logseq Sync for this new graph?"
prompt, a remote graph will be created and start to sync automatically.

https://www.loom.com/share/69059969747c4b798a4c712c45e442d7
pull/7184/head
Tienson Qin 2022-11-02 13:18:11 +08:00
parent 2dfac3d774
commit 7ddfa66004
11 changed files with 92 additions and 36 deletions

View File

@ -18,13 +18,33 @@ public class FolderPicker: CAPPlugin, UIDocumentPickerDelegate {
self._call = call
DispatchQueue.main.async { [weak self] in
let documentPicker = UIDocumentPickerViewController(
documentTypes: [String(kUTTypeFolder)],
in: UIDocumentPickerMode.open
)
// Set the initial directory.
if let path = call.getString("path") {
// guard let url = URL(string: path) else {
// call.reject("can not parse url")
// return
// }
guard let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let url = documentDirectory.appendingPathComponent(path)
print("picked folder url = " + url.path)
documentPicker.directoryURL = url
}
documentPicker.allowsMultipleSelection = false
documentPicker.delegate = self
documentPicker.modalPresentationStyle = UIModalPresentationStyle.fullScreen
self?.bridge?.viewController?.present(

View File

@ -534,7 +534,8 @@
(file-sync-handler/init-remote-graph url graph)
(js/setTimeout (fn [] (repo-handler/refresh-repos!)) 200))
{:empty-dir?-or-pred
{:sync-from-remote? true
:empty-dir?-or-pred
(fn [ret]
(let [empty-dir? (nil? (second ret))]
(if-let [root (first ret)]

View File

@ -154,9 +154,9 @@
nfs-record))
(defn open-dir
[ok-handler]
[dir ok-handler]
(let [record (get-record)]
(p/let [result (protocol/open-dir record ok-handler)]
(p/let [result (protocol/open-dir record dir ok-handler)]
(if (or (util/electron?)
(mobile-util/native-platform?))
(let [[dir & paths] (bean/->clj result)]

View File

@ -30,7 +30,7 @@
(js/window.pfs.rename old-path new-path))
(stat [_this dir path]
(js/window.pfs.stat (str dir path)))
(open-dir [_this _ok-handler]
(open-dir [_this _dir _ok-handler]
nil)
(get-files [_this _path-or-handle _ok-handler]
nil)

View File

@ -1,6 +1,6 @@
(ns frontend.fs.capacitor-fs
"Implementation of fs protocol for mobile"
(:require ["@capacitor/filesystem" :refer [Encoding Filesystem]]
(:require ["@capacitor/filesystem" :refer [Encoding Filesystem Directory]]
[cljs-bean.core :as bean]
[clojure.string :as string]
[goog.string :as gstring]
@ -260,6 +260,25 @@
: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]
@ -336,21 +355,8 @@
(let [path (get-file-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]

View File

@ -224,7 +224,7 @@
:file/size (get-attr "size")
:file/type (get-attr "type")}))
(p/rejected "File not exists")))
(open-dir [_this ok-handler]
(open-dir [_this _dir ok-handler]
(utils/openDirectory #js {:recursive true}
ok-handler))
(get-files [_this path-or-handle ok-handler]

View File

@ -75,8 +75,8 @@
(error-handler error)
(log/error :write-file-failed error)))))))))
(defn- open-dir []
(p/let [dir-path (util/mocked-open-dir-path)
(defn- open-dir [dir]
(p/let [dir-path (or dir (util/mocked-open-dir-path))
result (if dir-path
(ipc/ipc "getFiles" dir-path)
(ipc/ipc "openDir" {}))]
@ -113,8 +113,8 @@
(stat [_this dir path]
(let [path (concat-path dir path)]
(ipc/ipc "stat" path)))
(open-dir [_this _ok-handler]
(open-dir))
(open-dir [_this dir _ok-handler]
(open-dir dir))
(get-files [_this path-or-handle _ok-handler]
(ipc/ipc "getFiles" path-or-handle))
(watch-dir! [_this dir options]

View File

@ -13,7 +13,7 @@
(rename! [this repo old-path new-path])
(copy! [this repo old-path new-path])
(stat [this dir path])
(open-dir [this ok-handler])
(open-dir [this dir ok-handler])
(get-files [this path-or-handle ok-handler])
(watch-dir! [this dir options])
(unwatch-dir! [this dir])

View File

@ -572,6 +572,24 @@
(state/close-modal!)
(nfs-handler/refresh! (state/get-current-repo) refresh-cb)))]]))
(defmethod handle :sync/create-remote-graph [[_ current-repo]]
(let [graph-name (js/decodeURI (util/node-path.basename current-repo))]
(async/go
(async/<! (sync/<sync-stop))
(state/set-state! [:ui/loading? :graph/create-remote?] true)
(when-let [GraphUUID (get (async/<! (file-sync-handler/create-graph graph-name)) 2)]
(async/<! (sync/sync-start))
(state/set-state! [:ui/loading? :graph/create-remote?] false)
;; update existing repo
(state/set-repos! (map (fn [r]
(if (= (:url r) current-repo)
(assoc r
:GraphUUID GraphUUID
:GraphName graph-name
:remote? true)
r))
(state/get-repos)))))))
(defmethod handle :graph/re-index [[_]]
;; Ensure the graph only has ONE window instance
(repo-handler/re-index!

View File

@ -691,11 +691,18 @@
(defn ls-dir-files!
([ok-handler] (ls-dir-files! ok-handler nil))
([ok-handler opts]
(let [ios-logseq-sync? (when (and (mobile-util/native-ios?)
(state/enable-sync?)
(not (:sync-from-remote? opts)))
(js/confirm "Use Logseq Sync for this new graph?"))]
(web-nfs/ls-dir-files-with-handler!
(fn [e]
(init-commands!)
(when ok-handler (ok-handler e)))
opts)))
(when ok-handler
(ok-handler e)
(when ios-logseq-sync?
(state/pub-event! [:sync/create-remote-graph (state/get-current-repo)]))))
(assoc opts :ios-logseq-sync? ios-logseq-sync?)))))
(defn get-all-pages
[repo]

View File

@ -121,18 +121,22 @@
(defn ^:large-vars/cleanup-todo ls-dir-files-with-handler!
"Read files from directory and setup repo (for the first time setup a repo)"
([ok-handler] (ls-dir-files-with-handler! ok-handler nil))
([ok-handler {:keys [empty-dir?-or-pred dir-result-fn]}]
([ok-handler {:keys [empty-dir?-or-pred dir-result-fn ios-logseq-sync?]}]
(let [path-handles (atom {})
electron? (util/electron?)
mobile-native? (mobile-util/native-platform?)
nfs? (and (not electron?)
(not mobile-native?))
*repo (atom nil)]
*repo (atom nil)
dir (when ios-logseq-sync?
;; open Logseq's Documents folder
"")]
;; TODO: add ext filter to avoid loading .git or other ignored file handlers
(->
(p/let [result (if (fn? dir-result-fn)
(dir-result-fn {:path-handles path-handles :nfs? nfs?})
(fs/open-dir (fn [path handle]
(fs/open-dir dir
(fn [path handle]
(when nfs?
(swap! path-handles assoc path handle)))))
_ (when-not (nil? empty-dir?-or-pred)