Browse Source

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
Tienson Qin 3 years ago
parent
commit
6647d805f1

+ 22 - 2
ios/App/App/FolderPicker.swift

@@ -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
+              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(

+ 2 - 1
src/main/frontend/components/file_sync.cljs

@@ -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)]

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

@@ -157,9 +157,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)]

+ 1 - 1
src/main/frontend/fs/bfs.cljs

@@ -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)

+ 22 - 16
src/main/frontend/fs/capacitor_fs.cljs

@@ -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]
@@ -266,6 +266,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]
@@ -342,21 +361,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]

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

@@ -232,7 +232,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]

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

@@ -83,8 +83,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" {}))]
@@ -121,8 +121,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]

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

@@ -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])

+ 18 - 0
src/main/frontend/handler/events.cljs

@@ -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!

+ 12 - 5
src/main/frontend/handler/page.cljs

@@ -691,11 +691,18 @@
 (defn ls-dir-files!
   ([ok-handler] (ls-dir-files! ok-handler nil))
   ([ok-handler opts]
-   (web-nfs/ls-dir-files-with-handler!
-     (fn [e]
-       (init-commands!)
-       (when ok-handler (ok-handler e)))
-     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)
+          (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]

+ 7 - 3
src/main/frontend/handler/web/nfs.cljs

@@ -122,18 +122,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)