Browse Source

fix(fs): use normalized relative path for mobile platform

Fix #9378
Andelf 2 years ago
parent
commit
c917f2e087

+ 7 - 2
android/app/src/main/java/com/logseq/app/FsWatcher.java

@@ -10,6 +10,8 @@ import android.net.Uri;
 
 import java.io.*;
 
+import java.net.URI;
+import java.text.Normalizer;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Stack;
@@ -90,8 +92,11 @@ public class FsWatcher extends Plugin {
             shouldRead = true;
         }
 
-        obj.put("path", Uri.fromFile(f));
-        obj.put("dir", Uri.fromFile(new File(mPath)));
+        URI dir = (new File(mPath)).toURI();
+        URI fpath = f.toURI();
+
+        obj.put("path", Normalizer.normalize(dir.relativize(fpath).toString(), Normalizer.Form.NFC));
+        obj.put("dir", Uri.fromFile(new File(mPath))); // Uri is for Android. URI is for RFC compatible
         JSObject stat;
 
         switch (event) {

+ 33 - 3
ios/App/App/FsWatcher.swift

@@ -46,12 +46,16 @@ public class FsWatcher: CAPPlugin, PollingWatcherDelegate {
     }
 
     public func receivedNotification(_ url: URL, _ event: PollingWatcherEvent, _ metadata: SimpleFileMetadata?) {
+        guard let baseUrl = baseUrl else {
+            // unwatch, ignore incoming
+            return
+        }
         // NOTE: Event in js {dir path content stat{mtime}}
         switch event {
         case .Unlink:
             DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                 self.notifyListeners("watcher", data: ["event": "unlink",
-                                                       "dir": self.baseUrl?.description as Any,
+                                                       "dir": baseUrl.description as Any,
                                                        "path": url.description
                 ])
             }
@@ -61,8 +65,8 @@ public class FsWatcher: CAPPlugin, PollingWatcherDelegate {
                 content = try? String(contentsOf: url, encoding: .utf8)
             }
             self.notifyListeners("watcher", data: ["event": event.description,
-                                                   "dir": baseUrl?.description as Any,
-                                                   "path": url.description,
+                                                   "dir": baseUrl.description as Any,
+                                                   "path": url.relativePath(from: baseUrl)?.precomposedStringWithCanonicalMapping as Any,
                                                    "content": content as Any,
                                                    "stat": ["mtime": metadata?.contentModificationTimestamp ?? 0,
                                                             "ctime": metadata?.creationTimestamp ?? 0,
@@ -265,3 +269,29 @@ public class PollingWatcher {
         self.metaDb = newMetaDb
     }
 }
+
+
+extension URL {
+    func relativePath(from base: URL) -> String? {
+        // Ensure that both URLs represent files:
+        guard self.isFileURL && base.isFileURL else {
+            return nil
+        }
+
+        // Remove/replace "." and "..", make paths absolute:
+        let destComponents = self.standardizedFileURL.pathComponents
+        let baseComponents = base.standardizedFileURL.pathComponents
+
+        // Find number of common path components:
+        var i = 0
+        while i < destComponents.count && i < baseComponents.count
+                && destComponents[i] == baseComponents[i] {
+            i += 1
+        }
+
+        // Build relative path:
+        var relComponents = Array(repeating: "..", count: baseComponents.count - i)
+        relComponents.append(contentsOf: destComponents[i...])
+        return relComponents.joined(separator: "/")
+    }
+}

+ 2 - 9
src/main/frontend/handler/events.cljs

@@ -69,8 +69,7 @@
             [logseq.db.schema :as db-schema]
             [logseq.graph-parser.config :as gp-config]
             [promesa.core :as p]
-            [rum.core :as rum]
-            [logseq.common.path :as path]))
+            [rum.core :as rum]))
 
 ;; TODO: should we move all events here?
 
@@ -622,13 +621,7 @@
 
 (defmethod handle :mobile-file-watcher/changed [[_ ^js event]]
   (let [type (.-event event)
-        payload (js->clj event :keywordize-keys true)
-        dir (:dir payload)
-        payload (-> payload
-                    (update :path
-                           (fn [path]
-                             (when (string? path)
-                               (path/relative-path dir path)))))]
+        payload (js->clj event :keywordize-keys true)]
     (fs-watcher/handle-changed! type payload)
     (when (file-sync-handler/enable-sync?)
      (sync/file-watch-handler type payload))))