Przeglądaj źródła

fix save issues after iOS app re-installation (#5697)

* fix save issues after iOS app re-installation
* fix: ios installation id updates when switching graphs
* fix duplicated file-paths in db

Co-authored-by: Tienson Qin <[email protected]>
llcc 3 lat temu
rodzic
commit
7c8ae98911

+ 6 - 0
src/main/frontend/db.cljs

@@ -144,6 +144,12 @@
   (when-let [conn (get-db repo false)]
     (repo-listen-to-tx! repo conn)))
 
+(defn relisten-and-persist!
+  [repo]
+  (when-let [conn (get-db repo false)]
+    (d/unlisten! conn :persistence)
+    (listen-and-persist! repo)))
+
 (defn start-db-conn!
   ([repo]
    (start-db-conn! repo {}))

+ 15 - 0
src/main/frontend/db/model.cljs

@@ -170,6 +170,21 @@
          ;; (sort-by last)
          (reverse))))
 
+(defn get-files-v2
+  [repo]
+  (when-let [db (conn/get-db repo)]
+    (->> (d/q
+          '[:find ?file ?path
+            ;; ?modified-at
+            :where
+            [?file :file/path ?path]
+            ;; [?file :file/last-modified-at ?modified-at]
+            ]
+          db)
+         (seq)
+         ;; (sort-by last)
+         (reverse))))
+
 (defn get-files-blocks
   [repo-url paths]
   (let [paths (set paths)

+ 6 - 11
src/main/frontend/fs/capacitor_fs.cljs

@@ -2,15 +2,15 @@
   (:require ["@capacitor/filesystem" :refer [Encoding Filesystem]]
             [cljs-bean.core :as bean]
             [clojure.string :as string]
+            [frontend.db :as db]
+            [frontend.encrypt :as encrypt]
             [frontend.fs.protocol :as protocol]
             [frontend.mobile.util :as mobile-util]
+            [frontend.state :as state]
             [frontend.util :as util]
             [lambdaisland.glogi :as log]
             [promesa.core :as p]
-            [rum.core :as rum]
-            [frontend.state :as state]
-            [frontend.db :as db]
-            [frontend.encrypt :as encrypt]))
+            [rum.core :as rum]))
 
 (when (mobile-util/native-ios?)
   (defn iOS-ensure-documents!
@@ -184,11 +184,6 @@
   [path localDocumentsPath]
   (string/includes? path localDocumentsPath))
 
-(defn- iCloud-container-path?
-  "Check whether `path' is logseq's iCloud container path on iOS"
-  [path]
-  (string/includes? path "iCloud~com~logseq~logseq"))
-
 (rum/defc instruction
   []
   [:div.instruction
@@ -283,10 +278,10 @@
             _ (when (mobile-util/native-ios?)
                 (cond
                   (not (or (local-container-path? path localDocumentsPath)
-                           (iCloud-container-path? path)))
+                           (mobile-util/iCloud-container-path? path)))
                   (state/pub-event! [:modal/show-instruction])
 
-                  (iCloud-container-path? path)
+                  (mobile-util/iCloud-container-path? path)
                   (mobile-util/sync-icloud-repo path)
 
                   :else nil))

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

@@ -19,7 +19,6 @@
             [frontend.handler.ui :as ui-handler]
             [frontend.handler.user :as user-handler]
             [frontend.extensions.srs :as srs]
-            [frontend.mobile.core :as mobile]
             [frontend.mobile.util :as mobile-util]
             [frontend.idb :as idb]
             [frontend.modules.instrumentation.core :as instrument]
@@ -111,7 +110,8 @@
 
          (watch-for-date!)
          (file-handler/watch-for-current-graph-dir!)
-         (state/pub-event! [:graph/ready (state/get-current-repo)])))
+         (state/pub-event! [:graph/ready (state/get-current-repo)])
+         (state/pub-event! [:graph/restored (state/get-current-repo)])))
       (p/catch (fn [error]
                  (log/error :exception error)))))
 
@@ -184,8 +184,6 @@
     (instrument/init)
     (set-network-watcher!)
 
-    (mobile/init!)
-
     (util/indexeddb-check?
      (fn [_error]
        (notification/show! "Sorry, it seems that your browser doesn't support IndexedDB, we recommend to use latest Chrome(Chromium) or Firefox(Non-private mode)." :error false)

+ 94 - 15
src/main/frontend/handler/events.cljs

@@ -1,8 +1,10 @@
 (ns frontend.handler.events
   (:refer-clojure :exclude [run!])
-  (:require [clojure.core.async :as async]
+  (:require ["@capacitor/filesystem" :refer [Directory Filesystem]]
+            [clojure.core.async :as async]
             [clojure.set :as set]
             [clojure.string :as string]
+            [datascript.core :as d]
             [frontend.commands :as commands]
             [frontend.components.diff :as diff]
             [frontend.components.encryption :as encryption]
@@ -13,7 +15,9 @@
             [frontend.config :as config]
             [frontend.context.i18n :refer [t]]
             [frontend.db :as db]
-            [logseq.db.schema :as db-schema]
+            [frontend.db.conn :as conn]
+            [frontend.db.model :as db-model]
+            [frontend.db.persist :as db-persist]
             [frontend.encrypt :as encrypt]
             [frontend.extensions.srs :as srs]
             [frontend.fs :as fs]
@@ -32,15 +36,18 @@
             [frontend.handler.search :as search-handler]
             [frontend.handler.ui :as ui-handler]
             [frontend.handler.web.nfs :as nfs-handler]
+            [frontend.mobile.core :as mobile]
             [frontend.mobile.util :as mobile-util]
             [frontend.modules.instrumentation.posthog :as posthog]
             [frontend.modules.outliner.file :as outliner-file]
             [frontend.modules.shortcut.core :as st]
+            [frontend.search :as search-db]
             [frontend.state :as state]
             [frontend.ui :as ui]
             [frontend.util :as util]
             [frontend.util.persist-var :as persist-var]
             [goog.dom :as gdom]
+            [logseq.db.schema :as db-schema]
             [promesa.core :as p]
             [rum.core :as rum]))
 
@@ -63,19 +70,25 @@
          (sync/sync-start)
 ))
 
-(defn- graph-switch [graph]
-  (state/set-current-repo! graph)
-  ;; load config
-  (common-handler/reset-config! graph nil)
-  (st/refresh!)
-  (when-not (= :draw (state/get-current-route))
-    (route-handler/redirect-to-home!))
-  (when-let [dir-name (config/get-repo-dir graph)]
-    (fs/watch-dir! dir-name))
-  (srs/update-cards-due-count!)
-  (state/pub-event! [:graph/ready graph])
-
-  (file-sync-stop-when-switch-graph))
+(defn- graph-switch
+  ([graph]
+   (graph-switch graph false))
+  ([graph skip-ios-check?]
+   (if (and (mobile-util/native-ios?) (not skip-ios-check?))
+     (state/pub-event! [:validate-appId graph-switch graph])
+     (do
+       (state/set-current-repo! graph)
+       ;; load config
+       (common-handler/reset-config! graph nil)
+       (st/refresh!)
+       (when-not (= :draw (state/get-current-route))
+         (route-handler/redirect-to-home!))
+       (when-let [dir-name (config/get-repo-dir graph)]
+         (fs/watch-dir! dir-name))
+       (srs/update-cards-due-count!)
+       (state/pub-event! [:graph/ready graph])
+
+       (file-sync-stop-when-switch-graph)))))
 
 (def persist-db-noti-m
   {:before     #(notification/show!
@@ -330,6 +343,60 @@
       (when-let [right-sidebar-node (gdom/getElementByClass "sidebar-item-list")]
         (set! (.. right-sidebar-node -style -paddingBottom) "150px")))))
 
+(defn update-file-path [deprecated-repo current-repo deprecated-app-id current-app-id]
+  (let [files (db-model/get-files-v2 deprecated-repo)
+        conn (conn/get-db deprecated-repo false)
+        tx (mapv (fn [[id path]]
+                   (let [new-path (string/replace path deprecated-app-id current-app-id)]
+                     {:db/id id
+                      :file/path new-path}))
+                 files)]
+    (d/transact! conn tx)
+    (reset! conn/conns
+            (update-keys @conn/conns
+                         (fn [key] (if (string/includes? key deprecated-repo)
+                                     (string/replace key deprecated-repo current-repo)
+                                     key))))))
+
+(defn get-ios-app-id
+  [repo-url]
+  (when repo-url
+    (let [app-id (-> (first (string/split repo-url "/Documents"))
+                     (string/split "/")
+                     last)]
+      app-id)))
+
+(defmethod handle :validate-appId [[_ graph-switch-f graph]]
+  (when-let [deprecated-repo (or graph (state/get-current-repo))]
+    ;; Installation is will not be changed for iCloud
+    (if (mobile-util/iCloud-container-path? deprecated-repo)
+      (when graph-switch-f (graph-switch-f graph true))
+      (p/let [deprecated-app-id (get-ios-app-id deprecated-repo)
+              current-document-url (.getUri Filesystem #js {:path ""
+                                                            :directory (.-Documents Directory)})
+              current-app-id (-> (js->clj current-document-url :keywordize-keys true)
+                                 get-ios-app-id)]
+        (if (= deprecated-app-id current-app-id)
+          (when graph-switch-f (graph-switch-f graph true))
+          (do
+            (.unwatch mobile-util/fs-watcher)
+            (let [current-repo (string/replace deprecated-repo deprecated-app-id current-app-id)
+                  current-repo-dir (config/get-repo-dir current-repo)]
+              (try
+                (update-file-path deprecated-repo current-repo deprecated-app-id current-app-id)
+                (db-persist/delete-graph! deprecated-repo)
+                (search-db/remove-db! deprecated-repo)
+                (state/delete-repo! {:url deprecated-repo})
+                (state/add-repo! {:url current-repo :nfs? true})
+                (catch :default e
+                  (js/console.error e)))
+              (state/set-current-repo! current-repo)
+              (db/relisten-and-persist! current-repo)
+              (db/persist-if-idle! current-repo)
+              (file-handler/restore-config! current-repo false)
+              (.watch mobile-util/fs-watcher #js {:path current-repo-dir})
+              (when graph-switch-f (graph-switch-f current-repo true)))))))))
+
 (defmethod handle :plugin/consume-updates [[_ id pending? updated?]]
   (let [downloading? (:plugin/updates-downloading? @state/state)]
 
@@ -433,6 +500,8 @@
            template
            {:target page}))))))
 
+(defmethod handle :graph/restored [[_ _graph]]
+  (mobile/init!))
 (defmethod handle :graph/dir-gone [[_ dir]]
   (state/pub-event! [:notification/show
                      {:content (str "The directory " dir " has been renamed or deleted, the editor will be disabled for this graph, you can unlink the graph.")
@@ -466,3 +535,13 @@
                                               :error error}])))))
       (recur))
     chan))
+
+(comment
+  (let [{:keys [deprecated-app-id current-app-id]} {:deprecated-app-id "AFDADF9A-7466-4ED8-B74F-AAAA0D4565B9", :current-app-id "7563518E-0EFD-4AD2-8577-10CFFD6E4596"}]
+    (def deprecated-app-id deprecated-app-id)
+    (def current-app-id current-app-id))
+  (def deprecated-repo (state/get-current-repo))
+  (def new-repo (string/replace deprecated-repo deprecated-app-id current-app-id))
+
+  (update-file-path deprecated-repo new-repo deprecated-app-id current-app-id)
+  )

+ 3 - 1
src/main/frontend/handler/repo.cljs

@@ -336,7 +336,9 @@
                         (db-persist/delete-graph! url)
                         (search/remove-db! url)
                         (state/delete-repo! repo)
-                        (when graph-exists? (ipc/ipc "graphUnlinked" repo))))]
+                        (when graph-exists? (ipc/ipc "graphUnlinked" repo))
+                        (when (= (state/get-current-repo) url)
+                          (state/set-current-repo! (:url (first (state/get-repos)))))))]
     (when (or (config/local-db? url) (= url "local"))
       (p/let [_ (idb/clear-local-db! url)] ; clear file handles
         (delete-db-f)))))

+ 5 - 3
src/main/frontend/mobile/core.cljs

@@ -2,7 +2,7 @@
   (:require ["@capacitor/app" :refer [^js App]]
             ["@capacitor/keyboard" :refer [^js Keyboard]]
             [clojure.string :as string]
-            [frontend.fs.capacitor-fs :as fs]
+            [frontend.fs.capacitor-fs :as mobile-fs]
             [frontend.handler.editor :as editor-handler]
             [frontend.mobile.deeplink :as deeplink]
             [frontend.mobile.intent :as intent]
@@ -20,8 +20,10 @@
 (defn- ios-init
   "Initialize iOS-specified event listeners"
   []
-  (let [path (fs/iOS-ensure-documents!)]
+  (let [path (mobile-fs/iOS-ensure-documents!)]
     (println "iOS container path: " path))
+
+  (state/pub-event! [:validate-appId])
   
   (.addEventListener js/window
                      "load"
@@ -29,7 +31,7 @@
                        (when @*url
                          (js/setTimeout #(deeplink/deeplink @*url)
                                         1000))))
-
+  
   (mobile-util/check-ios-zoomed-display)
   
   (.removeAllListeners mobile-util/file-sync)

+ 7 - 1
src/main/frontend/mobile/util.cljs

@@ -92,4 +92,10 @@
                               #(js->clj % :keywordize-keys true))]
     (when (:isZoomed is-zoomed?)
       (let [^js cl (.-classList js/document.documentElement)]
-        (.add cl "is-zoomed-native-ios")))))
+        (.add cl "is-zoomed-native-ios")))))
+
+(defn iCloud-container-path?
+  "Check whether `path' is logseq's iCloud container path on iOS"
+  [path]
+  (string/includes? path "iCloud~com~logseq~logseq"))
+

+ 1 - 3
src/main/frontend/state.cljs

@@ -530,9 +530,7 @@
            (->> (remove #(= (:url repo)
                             (:url %))
                         repos)
-                (util/distinct-by :url))))
-  (when (= (get-current-repo) (:url repo))
-    (set-current-repo! (:url (first (get-repos))))))
+                (util/distinct-by :url)))))
 
 (defn set-timestamp-block!
   [value]