瀏覽代碼

Merge branch 'feat/db' into feat/capacitor-new

charlie 6 月之前
父節點
當前提交
5edbcfc6ae
共有 45 個文件被更改,包括 989 次插入836 次删除
  1. 4 4
      .cljfmt.edn
  2. 1 1
      android/app/build.gradle
  3. 3 0
      clj-e2e/.clj-kondo/config.edn
  4. 4 0
      clj-e2e/.cljfmt.edn
  5. 2 1
      clj-e2e/bb.edn
  6. 1 1
      clj-e2e/deps.edn
  7. 12 0
      clj-e2e/src/logseq/e2e/keyboard.clj
  8. 52 10
      clj-e2e/src/logseq/e2e/util.clj
  9. 7 6
      clj-e2e/test/logseq/e2e/editor_test.clj
  10. 30 3
      clj-e2e/test/logseq/e2e/fixtures.clj
  11. 6 5
      clj-e2e/test/logseq/e2e/outliner_test.clj
  12. 29 0
      clj-e2e/test/logseq/e2e/rtc_basic_test.clj
  13. 1 1
      deps/common/package.json
  14. 3 3
      deps/common/yarn.lock
  15. 1 1
      deps/db/package.json
  16. 2 3
      deps/db/src/logseq/db/common/sqlite.cljs
  17. 32 30
      deps/db/src/logseq/db/common/view.cljs
  18. 3 3
      deps/db/yarn.lock
  19. 1 1
      deps/graph-parser/package.json
  20. 3 3
      deps/graph-parser/yarn.lock
  21. 1 1
      deps/outliner/package.json
  22. 3 3
      deps/outliner/yarn.lock
  23. 1 1
      deps/publishing/package.json
  24. 3 3
      deps/publishing/yarn.lock
  25. 597 597
      ios/App/App.xcodeproj/project.pbxproj
  26. 1 1
      resources/package.json
  27. 1 1
      scripts/package.json
  28. 3 3
      scripts/yarn.lock
  29. 12 14
      src/main/frontend/components/block.cljs
  30. 1 1
      src/main/frontend/components/cmdk/list_item.cljs
  31. 13 14
      src/main/frontend/components/container.cljs
  32. 1 1
      src/main/frontend/components/editor.cljs
  33. 16 5
      src/main/frontend/components/header.cljs
  34. 33 20
      src/main/frontend/components/property/value.cljs
  35. 1 1
      src/main/frontend/components/rtc/indicator.cljs
  36. 12 6
      src/main/frontend/components/select.cljs
  37. 28 27
      src/main/frontend/components/settings.cljs
  38. 2 2
      src/main/frontend/components/views.cljs
  39. 19 12
      src/main/frontend/db/async.cljs
  40. 4 4
      src/main/frontend/handler/db_based/rtc_flows.cljs
  41. 2 1
      src/main/frontend/handler/editor.cljs
  42. 21 22
      src/main/frontend/modules/instrumentation/sentry.cljs
  43. 1 1
      src/main/frontend/version.cljs
  44. 13 16
      src/main/frontend/worker/db_worker.cljs
  45. 3 3
      src/main/frontend/worker/rtc/core.cljs

+ 4 - 4
.cljfmt.edn

@@ -1,4 +1,4 @@
- {:extra-indents {missionary.core/sp [[:block 0]]
-                  missionary.core/ap [[:block 0]]
-                  frontend.common.missionary/run-task [[:inner 0]]}
-  :sort-ns-references? true}
+{:extra-indents {missionary.core/sp [[:block 0]]
+                 missionary.core/ap [[:block 0]]
+                 frontend.common.missionary/run-task [[:inner 0]]}
+ :sort-ns-references? true}

+ 1 - 1
android/app/build.gradle

@@ -8,7 +8,7 @@ android {
         minSdkVersion rootProject.ext.minSdkVersion
         targetSdkVersion rootProject.ext.targetSdkVersion
         versionCode 84
-        versionName "0.10.10"
+        versionName "0.11.0"
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         aaptOptions {
              // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.

+ 3 - 0
clj-e2e/.clj-kondo/config.edn

@@ -0,0 +1,3 @@
+{:linters
+ {:unresolved-var {:exclude [wally.main/click
+                             wally.main/fill]}}}

+ 4 - 0
clj-e2e/.cljfmt.edn

@@ -0,0 +1,4 @@
+{:extra-indents {missionary.core/sp [[:block 0]]
+                 missionary.core/ap [[:block 0]]
+                 frontend.common.missionary/run-task [[:inner 0]]}
+ :sort-ns-references? true}

+ 2 - 1
clj-e2e/bb.edn

@@ -18,4 +18,5 @@
 
   -dev {:depends [serve prn test]}
 
-  dev {:task (run '-dev {:parallel true})}}}
+  dev {:doc "serve and test"
+       :task (run '-dev {:parallel true})}}}

+ 1 - 1
clj-e2e/deps.edn

@@ -4,7 +4,7 @@
         io.github.pfeodrippe/wally {:git/url "https://github.com/logseq/wally"
                                     :sha "6b0583701fc64ec5177eec6577e33bb8d9115d61"}
         ;; io.github.zmedelis/bosquet {:mvn/version "2025.03.28"}
-        }
+        org.clj-commons/claypoole          {:mvn/version "1.2.2"}}
  :aliases
  {:build {:deps {io.github.clojure/tools.build {:mvn/version "0.10.5"}}
           :ns-default build}

+ 12 - 0
clj-e2e/src/logseq/e2e/keyboard.clj

@@ -0,0 +1,12 @@
+(ns logseq.e2e.keyboard
+  (:require [wally.main :as w]))
+
+(def press w/keyboard-press)
+
+(def enter #(press "Enter"))
+(def esc #(press "Escape"))
+(def backspace #(press "Backspace"))
+(def tab #(press "Tab"))
+(def shift+tab #(press "Shift+Tab"))
+(def arrow-up #(press "ArrowUp"))
+(def arrow-down #(press "ArrowDown"))

+ 52 - 10
clj-e2e/src/logseq/e2e/util.clj

@@ -3,8 +3,10 @@
   (:require [clojure.string :as string]
             [clojure.test :refer [is]]
             [wally.main :as w]
-            [wally.selectors :as ws])
-  (:import (com.microsoft.playwright.assertions PlaywrightAssertions)))
+            [wally.selectors :as ws]
+            [logseq.e2e.keyboard :as k])
+  (:import [com.microsoft.playwright TimeoutError]
+           [com.microsoft.playwright.assertions PlaywrightAssertions]))
 
 (def assert-that PlaywrightAssertions/assertThat)
 
@@ -37,8 +39,6 @@
   (let [input-node (w/-query "*:focus")]
     (.type input-node text)))
 
-(def press w/keyboard-press)
-
 (defn search
   [text]
   (w/click :#search-button)
@@ -67,7 +67,7 @@
 
 (defn new-block
   [title]
-  (press "Enter")
+  (k/enter)
   (input title))
 
 (defn save-block
@@ -76,14 +76,14 @@
 
 (defn exit-edit
   []
-  (press "Escape"))
+  (k/esc))
 
 (defn delete-blocks
   "Delete the current block if in editing mode, otherwise, delete all the selected blocks."
   []
   (let [editor (get-editor)]
     (when editor (exit-edit))
-    (press "Backspace")))
+    (k/backspace)))
 
 (defn get-text
   [locator]
@@ -117,7 +117,7 @@
   [indent?]
   (let [editor (get-editor)
         [x1 _] (bounding-xy editor)
-        _ (press (if indent? "Tab" "Shift+Tab"))
+        _ (if indent? (k/tab) (k/shift+tab))
         [x2 _] (bounding-xy editor)]
     (if indent?
       (is (< x1 x2))
@@ -138,7 +138,7 @@
 (defn repeat-keyboard
   [n shortcut]
   (dotimes [_i n]
-    (press shortcut)))
+    (k/press shortcut)))
 
 (defn get-page-blocks-contents
   []
@@ -146,4 +146,46 @@
 
 (def mac? (= "Mac OS X" (System/getProperty "os.name")))
 
-(def mod-key (if mac? "Meta" "Control"))
+(defn login-test-account
+  [& {:keys [username password]
+      :or {username "e2etest"
+           password "Logseq-e2e"}}]
+  (w/eval-js "localStorage.setItem(\"login-enabled\",true);")
+  (w/click "button[title=\"More\"]")
+  (w/click "div:text(\"Login\")")
+  (input username)
+  (k/tab)
+  (input password)
+  (w/click "button[type=\"submit\"]:text(\"Sign in\")")
+  (w/wait-for-not-visible ".cp__user-login"))
+
+(defn new-graph
+  [graph-name enable-sync?]
+  (search "add a db graph")
+  (w/click (w/get-by-label "Add a DB graph"))
+  (w/wait-for "h2:text(\"Create a new graph\")")
+  (w/click "input[placeholder=\"your graph name\"]")
+  (input graph-name)
+  (when enable-sync?
+    (w/click "button#rtc-sync"))
+  (w/click "button:text(\"Submit\")")
+  (when enable-sync?
+    (w/wait-for "button.cloud.on.idle" {:timeout 20000})))
+
+(defn wait-for-remote-graph
+  [graph-name]
+  (search "all graphs")
+  (w/click (w/get-by-label "Go to all graphs"))
+  (let [max-try 5]
+    (loop [i 0]
+      (prn :wait-for-remote-graph-try i)
+      (w/click "span:text(\"Refresh\")")
+      (let [succ?
+            (try
+              (w/wait-for (str "span:has-text(\"" graph-name "\")"))
+              true
+              (catch TimeoutError e
+                (if (= max-try i)
+                  (throw e)
+                  false)))]
+        (when-not succ? (recur (inc i)))))))

+ 7 - 6
clj-e2e/test/logseq/e2e/editor_test.clj

@@ -3,7 +3,8 @@
    [clojure.string :as string]
    [clojure.test :refer [deftest testing is use-fixtures]]
    [logseq.e2e.fixtures :as fixtures]
-   [logseq.e2e.util :as util :refer [press]]
+   [logseq.e2e.keyboard :as k]
+   [logseq.e2e.util :as util]
    [wally.main :as w]))
 
 (use-fixtures :once fixtures/open-page)
@@ -15,7 +16,7 @@
     (util/type " /")
     (w/wait-for ".ui__popover-content")
     (is (some? (w/find-one-by-text "span" "Node reference")))
-    (press "Backspace")
+    (k/backspace)
     (w/wait-for-not-visible ".ui__popover-content"))
 
   (testing "Node reference"
@@ -23,9 +24,9 @@
       (util/new-block "/")
       (util/type "Node eferen")
       (w/wait-for ".ui__popover-content")
-      (press "Enter")
+      (k/enter)
       (util/type "Another page")
-      (press "Enter")
+      (k/enter)
       (is (= "[[Another page]]" (util/get-edit-content)))
       (util/exit-edit)
       (is (= "Another page" (util/get-text "a.page-ref"))))
@@ -33,10 +34,10 @@
       (util/new-block "/")
       (util/type "Node eferen")
       (w/wait-for ".ui__popover-content")
-      (press "Enter")
+      (k/enter)
       (util/type "b1")
       (util/wait-timeout 300)
-      (press "Enter")
+      (k/enter)
       (is (string/includes? (util/get-edit-content) "[["))
       (util/exit-edit)
       (is (= "b1" (util/get-text ".block-ref"))))))

+ 30 - 3
clj-e2e/test/logseq/e2e/fixtures.clj

@@ -4,8 +4,9 @@
 ;; TODO: save trace
 ;; TODO: parallel support
 (defn open-page
-  [f & {:keys [headless]
-        :or {headless true}}]
+  [f & {:keys [headless port]
+        :or {headless true
+             port 3002}}]
   (w/with-page-open
     (w/make-page {:headless headless
                   :persistent false
@@ -13,5 +14,31 @@
                   ;; Set `slow-mo` lower to find more flaky tests
                   ;; :slow-mo 30
                   })
-    (w/navigate "http://localhost:3002")
+    (w/navigate (str "http://localhost:" port))
     (f)))
+
+(def *page1 (atom nil))
+(def *page2 (atom nil))
+
+(defn open-2-pages
+  "Use `*page1` and `*page2` in `f`"
+  [f & {:keys [headless port]
+        :or {headless true
+             port 3002}}]
+  (let [p1 (w/make-page {:headless headless
+                         :persistent false
+                         :slow-mo 100})
+        p2 (w/make-page {:headless headless
+                         :persistent false
+                         :slow-mo 100})]
+    (run!
+     #(w/with-page %
+        (w/navigate (str "http://localhost:" port)))
+     [p1 p2])
+
+    (reset! *page1 p1)
+    (reset! *page2 p2)
+    (binding [w/*page* (delay (throw (ex-info "Don't use *page*, use *page1* and *page2* instead" {})))]
+      (f))
+    (w/with-page-open p1)
+    (w/with-page-open p2)))

+ 6 - 5
clj-e2e/test/logseq/e2e/outliner_test.clj

@@ -2,7 +2,8 @@
   (:require
    [clojure.test :refer [deftest testing is use-fixtures]]
    [logseq.e2e.fixtures :as fixtures]
-   [logseq.e2e.util :as util :refer [press]]
+   [logseq.e2e.keyboard :as k]
+   [logseq.e2e.util :as util]
    [wally.main :as w]))
 
 (use-fixtures :once fixtures/open-page)
@@ -25,7 +26,7 @@
   (testing "indent a block with its children"
     (util/new-block "b3")
     (util/indent)
-    (press "ArrowUp")
+    (k/arrow-up)
     (util/indent)
     (util/exit-edit)
     (let [[x1 x2 x3] (map (comp first util/bounding-xy #(w/find-one-by-text "span" %)) ["b1" "b2" "b3"])]
@@ -35,7 +36,7 @@
     (util/open-last-block)
     (util/new-blocks ["b4" "b5"])
     (util/indent)
-    (util/press "ArrowUp")
+    (k/arrow-up)
     (util/outdent)
     (util/exit-edit)
     (let [[x2 x3 x4 x5] (map (comp first util/bounding-xy #(w/find-one-by-text "span" %)) ["b2" "b3" "b4" "b5"])]
@@ -68,9 +69,9 @@
     (util/new-page "p5")
     (util/new-blocks ["b1" "b2" "b3" "b4"])
     (util/indent)
-    (press "ArrowUp")
+    (k/arrow-up)
     (util/indent)
-    (press "ArrowUp")
+    (k/arrow-up)
     (util/delete-blocks)
     (is (= "b1" (util/get-edit-content)))
     (is (= 1 (util/page-blocks-count)))))

+ 29 - 0
clj-e2e/test/logseq/e2e/rtc_basic_test.clj

@@ -0,0 +1,29 @@
+(ns logseq.e2e.rtc-basic-test
+  (:require
+   [clojure.test :refer [deftest testing is use-fixtures]]
+   [com.climate.claypoole :as cp]
+   [logseq.e2e.fixtures :as fixtures :refer [*page1 *page2]]
+   [logseq.e2e.util :as util]
+   [wally.main :as w]
+   [wally.repl :as repl]))
+
+(use-fixtures :once fixtures/open-2-pages)
+
+;; (use-fixtures :once #(fixtures/open-2-pages % :headless false :port 3001))
+
+(deftest rtc-basic-test
+  (let [graph-name (str "rtc-graph-" (.toEpochMilli (java.time.Instant/now)))]
+    (testing "open 2 app instances"
+      (cp/prun!
+       2
+       #(w/with-page %
+          (util/login-test-account))
+       [@*page1 @*page2])
+      (w/with-page @*page1
+        (util/new-graph graph-name true))
+      (w/with-page @*page2
+        (util/wait-for-remote-graph graph-name)))))
+
+(comment
+  (def xxx (future (clojure.test/run-tests)))
+  (future-cancel xxx))

+ 1 - 1
deps/common/package.json

@@ -3,7 +3,7 @@
   "version": "1.0.0",
   "private": true,
   "devDependencies": {
-    "@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v19"
+    "@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v20"
   },
   "scripts": {
     "test": "yarn nbb-logseq -cp test -m nextjournal.test-runner"

+ 3 - 3
deps/common/yarn.lock

@@ -2,9 +2,9 @@
 # yarn lockfile v1
 
 
-"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v19":
-  version "1.2.173-feat-db-v19"
-  resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/ca32553da41aff783d89264b2e1a753372721f2e"
+"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v20":
+  version "1.2.173-feat-db-v20"
+  resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/7fb63423ab566717cac79e5f76084d89b845fbd6"
   dependencies:
     import-meta-resolve "^2.1.0"
 

+ 1 - 1
deps/db/package.json

@@ -3,7 +3,7 @@
   "version": "1.0.0",
   "private": true,
   "devDependencies": {
-    "@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v19"
+    "@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v20"
   },
   "dependencies": {
     "better-sqlite3": "9.3.0"

+ 2 - 3
deps/db/src/logseq/db/common/sqlite.cljs

@@ -159,8 +159,7 @@
       (assoc :db/id (:db/id entity))))
 
 (defn ^:large-vars/cleanup-todo get-block-and-children
-  [db id {:keys [children? children-only? nested-children? including-property-vals? properties children-props]
-          :or {including-property-vals? true}}]
+  [db id {:keys [children? children-only? nested-children? properties children-props]}]
   (let [block (d/entity db (if (uuid? id)
                              [:block/uuid id]
                              id))
@@ -205,7 +204,7 @@
                          (entity->map block))
                 block' (cond->
                         (mark-block-fully-loaded block')
-                         including-property-vals?
+                         true
                          (update-vals (fn [v]
                                         (cond
                                           (de/entity? v)

+ 32 - 30
deps/db/src/logseq/db/common/view.cljs

@@ -94,34 +94,36 @@
   [db {:keys [id asc?] :as sorting} entities partition?]
   (let [property (or (d/entity db id) {:db/ident id})
         get-value-fn (memoize (get-value-for-sort property))
-        sorted-entities (cond
-                          (= id :block.temp/refs-count)
-                          (cond-> (sort-by :block.temp/refs-count entities)
-                            (not asc?)
-                            reverse)
-
-                          (not (ldb/db-based-graph? db)) ; file graph properties don't support index
-                          (sort (by-sorting
-                                 [{:get-value get-value-fn
-                                   :asc? asc?}]) entities)
-
-                          :else
-                          (let [ref-type? (= :db.type/ref (:db/valueType property))]
-                            (if ref-type?
-                              (sort-ref-entities-by-single-property entities sorting get-value-fn)
-                              (let [datoms (cond->
-                                            (->> (d/datoms db :avet id)
-                                                 (common-util/distinct-by :e)
-                                                 vec)
-                                             (not asc?)
-                                             rseq)
-                                    row-ids (set (map :db/id entities))
-                                    id->row (zipmap (map :db/id entities) entities)]
-                                (keep
-                                 (fn [d]
-                                   (when (row-ids (:e d))
-                                     (id->row (:e d))))
-                                 datoms)))))]
+        sorted-entities (->>
+                         (cond
+                           (= id :block.temp/refs-count)
+                           (cond-> (sort-by :block.temp/refs-count entities)
+                             (not asc?)
+                             reverse)
+
+                           (not (ldb/db-based-graph? db)) ; file graph properties don't support index
+                           (sort (by-sorting
+                                  [{:get-value get-value-fn
+                                    :asc? asc?}]) entities)
+
+                           :else
+                           (let [ref-type? (= :db.type/ref (:db/valueType property))]
+                             (if ref-type?
+                               (sort-ref-entities-by-single-property entities sorting get-value-fn)
+                               (let [datoms (cond->
+                                             (->> (d/datoms db :avet id)
+                                                  (common-util/distinct-by :e)
+                                                  vec)
+                                              (not asc?)
+                                              rseq)
+                                     row-ids (set (map :db/id entities))
+                                     id->row (zipmap (map :db/id entities) entities)]
+                                 (keep
+                                  (fn [d]
+                                    (when (row-ids (:e d))
+                                      (id->row (:e d))))
+                                  datoms)))))
+                         distinct)]
     (if partition?
       (partition-by get-value-fn sorted-entities)
       sorted-entities)))
@@ -339,7 +341,7 @@
            (let [e (d/entity db eid)]
              (when-not (or (some #(= id %) (map :db/id (:block/refs e)))
                            (:block/link e)
-                           (ldb/page? e))
+                           (ldb/built-in? e))
                e)))
          ids)))))
 
@@ -563,6 +565,6 @@
                   (map :db/id result))]
       (cond->
        {:count (count filtered-entities)
-        :data data'}
+        :data (distinct data')}
         (= feat-type :linked-references)
         (assoc :ref-pages-count (:ref-pages-count entities-result))))))

+ 3 - 3
deps/db/yarn.lock

@@ -2,9 +2,9 @@
 # yarn lockfile v1
 
 
-"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v19":
-  version "1.2.173-feat-db-v19"
-  resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/ca32553da41aff783d89264b2e1a753372721f2e"
+"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v20":
+  version "1.2.173-feat-db-v20"
+  resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/7fb63423ab566717cac79e5f76084d89b845fbd6"
   dependencies:
     import-meta-resolve "^2.1.0"
 

+ 1 - 1
deps/graph-parser/package.json

@@ -3,7 +3,7 @@
   "version": "1.0.0",
   "private": true,
   "devDependencies": {
-    "@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v19",
+    "@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v20",
     "better-sqlite3": "9.3.0"
   },
   "dependencies": {

+ 3 - 3
deps/graph-parser/yarn.lock

@@ -2,9 +2,9 @@
 # yarn lockfile v1
 
 
-"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v19":
-  version "1.2.173-feat-db-v19"
-  resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/ca32553da41aff783d89264b2e1a753372721f2e"
+"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v20":
+  version "1.2.173-feat-db-v20"
+  resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/7fb63423ab566717cac79e5f76084d89b845fbd6"
   dependencies:
     import-meta-resolve "^2.1.0"
 

+ 1 - 1
deps/outliner/package.json

@@ -3,7 +3,7 @@
   "version": "1.0.0",
   "private": true,
   "devDependencies": {
-    "@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v19"
+    "@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v20"
   },
   "dependencies": {
     "better-sqlite3": "9.3.0",

+ 3 - 3
deps/outliner/yarn.lock

@@ -2,9 +2,9 @@
 # yarn lockfile v1
 
 
-"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v19":
-  version "1.2.173-feat-db-v19"
-  resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/ca32553da41aff783d89264b2e1a753372721f2e"
+"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v20":
+  version "1.2.173-feat-db-v20"
+  resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/7fb63423ab566717cac79e5f76084d89b845fbd6"
   dependencies:
     import-meta-resolve "^2.1.0"
 

+ 1 - 1
deps/publishing/package.json

@@ -3,7 +3,7 @@
   "version": "1.0.0",
   "private": true,
   "devDependencies": {
-    "@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v19",
+    "@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v20",
     "mldoc": "^1.5.9"
   },
   "dependencies": {

+ 3 - 3
deps/publishing/yarn.lock

@@ -2,9 +2,9 @@
 # yarn lockfile v1
 
 
-"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v19":
-  version "1.2.173-feat-db-v19"
-  resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/ca32553da41aff783d89264b2e1a753372721f2e"
+"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v20":
+  version "1.2.173-feat-db-v20"
+  resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/7fb63423ab566717cac79e5f76084d89b845fbd6"
   dependencies:
     import-meta-resolve "^2.1.0"
 

+ 597 - 597
ios/App/App.xcodeproj/project.pbxproj

@@ -1,645 +1,645 @@
 // !$*UTF8*$!
 {
-	archiveVersion = 1;
-	classes = {
-	};
-	objectVersion = 48;
-	objects = {
+        archiveVersion = 1;
+        classes = {
+        };
+        objectVersion = 48;
+        objects = {
 
 /* Begin PBXBuildFile section */
-		2FAD9763203C412B000D30F8 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2FAD9762203C412B000D30F8 /* config.xml */; };
-		50379B232058CBB4000EE86E /* capacitor.config.json in Resources */ = {isa = PBXBuildFile; fileRef = 50379B222058CBB4000EE86E /* capacitor.config.json */; };
-		504EC3081FED79650016851F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC3071FED79650016851F /* AppDelegate.swift */; };
-		504EC30D1FED79650016851F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; };
-		504EC30F1FED79650016851F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30E1FED79650016851F /* Assets.xcassets */; };
-		504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; };
-		50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; };
-		5FF8632A283B5ADB0047731B /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FF86329283B5ADB0047731B /* Utils.swift */; };
-		5FF8632C283B5BFD0047731B /* Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FF8632B283B5BFD0047731B /* Utils.m */; };
-		5FFF7D6D27E343FA00B00DA8 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FFF7D6C27E343FA00B00DA8 /* ShareViewController.swift */; };
-		5FFF7D7027E343FA00B00DA8 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5FFF7D6E27E343FA00B00DA8 /* MainInterface.storyboard */; };
-		5FFF7D7427E343FA00B00DA8 /* ShareViewController.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 5FFF7D6A27E343FA00B00DA8 /* ShareViewController.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
-		7435D10C2704659F00AB88E0 /* FolderPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7435D10B2704659F00AB88E0 /* FolderPicker.swift */; };
-		7435D10F2704660B00AB88E0 /* FolderPicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 7435D10E2704660B00AB88E0 /* FolderPicker.m */; };
-		C3718FCEFAECFFB66E93FFC4 /* Pods_Logseq.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B2E26D73EA097D0B3B22942E /* Pods_Logseq.framework */; };
-		D32752BE275496C60039291C /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D32752BD275496C60039291C /* CloudKit.framework */; };
-		D3D62A0A275C92880003FBDC /* FileContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3D62A09275C92880003FBDC /* FileContainer.swift */; };
-		D3D62A0C275C928F0003FBDC /* FileContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = D3D62A0B275C928F0003FBDC /* FileContainer.m */; };
-		FE647FF427BDFEDE00F3206B /* FsWatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE647FF327BDFEDE00F3206B /* FsWatcher.swift */; };
-		FE647FF627BDFEF500F3206B /* FsWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = FE647FF527BDFEF500F3206B /* FsWatcher.m */; };
-		FE96D6102A1B811A001ECE32 /* SharedData.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE96D60F2A1B811A001ECE32 /* SharedData.swift */; };
+                2FAD9763203C412B000D30F8 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2FAD9762203C412B000D30F8 /* config.xml */; };
+                50379B232058CBB4000EE86E /* capacitor.config.json in Resources */ = {isa = PBXBuildFile; fileRef = 50379B222058CBB4000EE86E /* capacitor.config.json */; };
+                504EC3081FED79650016851F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC3071FED79650016851F /* AppDelegate.swift */; };
+                504EC30D1FED79650016851F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; };
+                504EC30F1FED79650016851F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30E1FED79650016851F /* Assets.xcassets */; };
+                504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; };
+                50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; };
+                5FF8632A283B5ADB0047731B /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FF86329283B5ADB0047731B /* Utils.swift */; };
+                5FF8632C283B5BFD0047731B /* Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FF8632B283B5BFD0047731B /* Utils.m */; };
+                5FFF7D6D27E343FA00B00DA8 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FFF7D6C27E343FA00B00DA8 /* ShareViewController.swift */; };
+                5FFF7D7027E343FA00B00DA8 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5FFF7D6E27E343FA00B00DA8 /* MainInterface.storyboard */; };
+                5FFF7D7427E343FA00B00DA8 /* ShareViewController.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 5FFF7D6A27E343FA00B00DA8 /* ShareViewController.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
+                7435D10C2704659F00AB88E0 /* FolderPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7435D10B2704659F00AB88E0 /* FolderPicker.swift */; };
+                7435D10F2704660B00AB88E0 /* FolderPicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 7435D10E2704660B00AB88E0 /* FolderPicker.m */; };
+                C3718FCEFAECFFB66E93FFC4 /* Pods_Logseq.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B2E26D73EA097D0B3B22942E /* Pods_Logseq.framework */; };
+                D32752BE275496C60039291C /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D32752BD275496C60039291C /* CloudKit.framework */; };
+                D3D62A0A275C92880003FBDC /* FileContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3D62A09275C92880003FBDC /* FileContainer.swift */; };
+                D3D62A0C275C928F0003FBDC /* FileContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = D3D62A0B275C928F0003FBDC /* FileContainer.m */; };
+                FE647FF427BDFEDE00F3206B /* FsWatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE647FF327BDFEDE00F3206B /* FsWatcher.swift */; };
+                FE647FF627BDFEF500F3206B /* FsWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = FE647FF527BDFEF500F3206B /* FsWatcher.m */; };
+                FE96D6102A1B811A001ECE32 /* SharedData.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE96D60F2A1B811A001ECE32 /* SharedData.swift */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
-		5FFF7D7227E343FA00B00DA8 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 504EC2FC1FED79650016851F /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 5FFF7D6927E343FA00B00DA8;
-			remoteInfo = ShareViewController;
-		};
+                5FFF7D7227E343FA00B00DA8 /* PBXContainerItemProxy */ = {
+                        isa = PBXContainerItemProxy;
+                        containerPortal = 504EC2FC1FED79650016851F /* Project object */;
+                        proxyType = 1;
+                        remoteGlobalIDString = 5FFF7D6927E343FA00B00DA8;
+                        remoteInfo = ShareViewController;
+                };
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXCopyFilesBuildPhase section */
-		5FFF7D7527E343FA00B00DA8 /* Embed App Extensions */ = {
-			isa = PBXCopyFilesBuildPhase;
-			buildActionMask = 2147483647;
-			dstPath = "";
-			dstSubfolderSpec = 13;
-			files = (
-				5FFF7D7427E343FA00B00DA8 /* ShareViewController.appex in Embed App Extensions */,
-			);
-			name = "Embed App Extensions";
-			runOnlyForDeploymentPostprocessing = 0;
-		};
+                5FFF7D7527E343FA00B00DA8 /* Embed App Extensions */ = {
+                        isa = PBXCopyFilesBuildPhase;
+                        buildActionMask = 2147483647;
+                        dstPath = "";
+                        dstSubfolderSpec = 13;
+                        files = (
+                                5FFF7D7427E343FA00B00DA8 /* ShareViewController.appex in Embed App Extensions */,
+                        );
+                        name = "Embed App Extensions";
+                        runOnlyForDeploymentPostprocessing = 0;
+                };
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
-		2FAD9762203C412B000D30F8 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = config.xml; sourceTree = "<group>"; };
-		50379B222058CBB4000EE86E /* capacitor.config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = capacitor.config.json; sourceTree = "<group>"; };
-		504EC3041FED79650016851F /* Logseq.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Logseq.app; sourceTree = BUILT_PRODUCTS_DIR; };
-		504EC3071FED79650016851F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
-		504EC30C1FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
-		504EC30E1FED79650016851F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
-		504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
-		504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
-		50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = "<group>"; };
-		5FF86329283B5ADB0047731B /* Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = "<group>"; };
-		5FF8632B283B5BFD0047731B /* Utils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Utils.m; sourceTree = "<group>"; };
-		5FFF7D6A27E343FA00B00DA8 /* ShareViewController.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = ShareViewController.appex; sourceTree = BUILT_PRODUCTS_DIR; };
-		5FFF7D6C27E343FA00B00DA8 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
-		5FFF7D6F27E343FA00B00DA8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
-		5FFF7D7127E343FA00B00DA8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
-		5FFF7D7927E4E70700B00DA8 /* ShareViewController.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShareViewController.entitlements; sourceTree = "<group>"; };
-		7435D10B2704659F00AB88E0 /* FolderPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FolderPicker.swift; sourceTree = "<group>"; };
-		7435D10D2704660A00AB88E0 /* App-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "App-Bridging-Header.h"; sourceTree = "<group>"; };
-		7435D10E2704660B00AB88E0 /* FolderPicker.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FolderPicker.m; sourceTree = "<group>"; };
-		8A489CEC51E94726DDD58810 /* Pods-Logseq.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Logseq.release.xcconfig"; path = "Target Support Files/Pods-Logseq/Pods-Logseq.release.xcconfig"; sourceTree = "<group>"; };
-		B2E26D73EA097D0B3B22942E /* Pods_Logseq.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Logseq.framework; sourceTree = BUILT_PRODUCTS_DIR; };
-		D32752BC275496A60039291C /* App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = App.entitlements; sourceTree = "<group>"; };
-		D32752BD275496C60039291C /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; };
-		D32752BF2754C5AB0039291C /* AppDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AppDebug.entitlements; sourceTree = "<group>"; };
-		D3D62A09275C92880003FBDC /* FileContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileContainer.swift; sourceTree = "<group>"; };
-		D3D62A0B275C928F0003FBDC /* FileContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FileContainer.m; sourceTree = "<group>"; };
-		DE5650F4AD4E2242AB9C012D /* Pods-Logseq.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Logseq.debug.xcconfig"; path = "Target Support Files/Pods-Logseq/Pods-Logseq.debug.xcconfig"; sourceTree = "<group>"; };
-		FE647FF327BDFEDE00F3206B /* FsWatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FsWatcher.swift; sourceTree = "<group>"; };
-		FE647FF527BDFEF500F3206B /* FsWatcher.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FsWatcher.m; sourceTree = "<group>"; };
-		FE96D60F2A1B811A001ECE32 /* SharedData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedData.swift; sourceTree = "<group>"; };
+                2FAD9762203C412B000D30F8 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = config.xml; sourceTree = "<group>"; };
+                50379B222058CBB4000EE86E /* capacitor.config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = capacitor.config.json; sourceTree = "<group>"; };
+                504EC3041FED79650016851F /* Logseq.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Logseq.app; sourceTree = BUILT_PRODUCTS_DIR; };
+                504EC3071FED79650016851F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
+                504EC30C1FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
+                504EC30E1FED79650016851F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+                504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
+                504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+                50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = "<group>"; };
+                5FF86329283B5ADB0047731B /* Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = "<group>"; };
+                5FF8632B283B5BFD0047731B /* Utils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Utils.m; sourceTree = "<group>"; };
+                5FFF7D6A27E343FA00B00DA8 /* ShareViewController.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = ShareViewController.appex; sourceTree = BUILT_PRODUCTS_DIR; };
+                5FFF7D6C27E343FA00B00DA8 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
+                5FFF7D6F27E343FA00B00DA8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
+                5FFF7D7127E343FA00B00DA8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+                5FFF7D7927E4E70700B00DA8 /* ShareViewController.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShareViewController.entitlements; sourceTree = "<group>"; };
+                7435D10B2704659F00AB88E0 /* FolderPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FolderPicker.swift; sourceTree = "<group>"; };
+                7435D10D2704660A00AB88E0 /* App-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "App-Bridging-Header.h"; sourceTree = "<group>"; };
+                7435D10E2704660B00AB88E0 /* FolderPicker.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FolderPicker.m; sourceTree = "<group>"; };
+                8A489CEC51E94726DDD58810 /* Pods-Logseq.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Logseq.release.xcconfig"; path = "Target Support Files/Pods-Logseq/Pods-Logseq.release.xcconfig"; sourceTree = "<group>"; };
+                B2E26D73EA097D0B3B22942E /* Pods_Logseq.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Logseq.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+                D32752BC275496A60039291C /* App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = App.entitlements; sourceTree = "<group>"; };
+                D32752BD275496C60039291C /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; };
+                D32752BF2754C5AB0039291C /* AppDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AppDebug.entitlements; sourceTree = "<group>"; };
+                D3D62A09275C92880003FBDC /* FileContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileContainer.swift; sourceTree = "<group>"; };
+                D3D62A0B275C928F0003FBDC /* FileContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FileContainer.m; sourceTree = "<group>"; };
+                DE5650F4AD4E2242AB9C012D /* Pods-Logseq.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Logseq.debug.xcconfig"; path = "Target Support Files/Pods-Logseq/Pods-Logseq.debug.xcconfig"; sourceTree = "<group>"; };
+                FE647FF327BDFEDE00F3206B /* FsWatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FsWatcher.swift; sourceTree = "<group>"; };
+                FE647FF527BDFEF500F3206B /* FsWatcher.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FsWatcher.m; sourceTree = "<group>"; };
+                FE96D60F2A1B811A001ECE32 /* SharedData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedData.swift; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
-		504EC3011FED79650016851F /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				D32752BE275496C60039291C /* CloudKit.framework in Frameworks */,
-				C3718FCEFAECFFB66E93FFC4 /* Pods_Logseq.framework in Frameworks */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		5FFF7D6727E343FA00B00DA8 /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
+                504EC3011FED79650016851F /* Frameworks */ = {
+                        isa = PBXFrameworksBuildPhase;
+                        buildActionMask = 2147483647;
+                        files = (
+                                D32752BE275496C60039291C /* CloudKit.framework in Frameworks */,
+                                C3718FCEFAECFFB66E93FFC4 /* Pods_Logseq.framework in Frameworks */,
+                        );
+                        runOnlyForDeploymentPostprocessing = 0;
+                };
+                5FFF7D6727E343FA00B00DA8 /* Frameworks */ = {
+                        isa = PBXFrameworksBuildPhase;
+                        buildActionMask = 2147483647;
+                        files = (
+                        );
+                        runOnlyForDeploymentPostprocessing = 0;
+                };
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
-		504EC2FB1FED79650016851F = {
-			isa = PBXGroup;
-			children = (
-				504EC3061FED79650016851F /* App */,
-				5FFF7D6B27E343FA00B00DA8 /* ShareViewController */,
-				504EC3051FED79650016851F /* Products */,
-				D337740F89DEEAD18C87762B /* Pods */,
-				9FC5AB18C7E7E43B09B33A61 /* Frameworks */,
-			);
-			sourceTree = "<group>";
-		};
-		504EC3051FED79650016851F /* Products */ = {
-			isa = PBXGroup;
-			children = (
-				504EC3041FED79650016851F /* Logseq.app */,
-				5FFF7D6A27E343FA00B00DA8 /* ShareViewController.appex */,
-			);
-			name = Products;
-			sourceTree = "<group>";
-		};
-		504EC3061FED79650016851F /* App */ = {
-			isa = PBXGroup;
-			children = (
-				5FF86329283B5ADB0047731B /* Utils.swift */,
-				5FF8632B283B5BFD0047731B /* Utils.m */,
-				D32752BF2754C5AB0039291C /* AppDebug.entitlements */,
-				D32752BC275496A60039291C /* App.entitlements */,
-				50379B222058CBB4000EE86E /* capacitor.config.json */,
-				504EC3071FED79650016851F /* AppDelegate.swift */,
-				504EC30B1FED79650016851F /* Main.storyboard */,
-				504EC30E1FED79650016851F /* Assets.xcassets */,
-				504EC3101FED79650016851F /* LaunchScreen.storyboard */,
-				504EC3131FED79650016851F /* Info.plist */,
-				2FAD9762203C412B000D30F8 /* config.xml */,
-				50B271D01FEDC1A000F3C39B /* public */,
-				7435D10B2704659F00AB88E0 /* FolderPicker.swift */,
-				FE647FF327BDFEDE00F3206B /* FsWatcher.swift */,
-				FE647FF527BDFEF500F3206B /* FsWatcher.m */,
-				7435D10E2704660B00AB88E0 /* FolderPicker.m */,
-				D3D62A09275C92880003FBDC /* FileContainer.swift */,
-				D3D62A0B275C928F0003FBDC /* FileContainer.m */,
-				7435D10D2704660A00AB88E0 /* App-Bridging-Header.h */,
-			);
-			path = App;
-			sourceTree = "<group>";
-		};
-		5FFF7D6B27E343FA00B00DA8 /* ShareViewController */ = {
-			isa = PBXGroup;
-			children = (
-				5FFF7D7927E4E70700B00DA8 /* ShareViewController.entitlements */,
-				5FFF7D6C27E343FA00B00DA8 /* ShareViewController.swift */,
-				FE96D60F2A1B811A001ECE32 /* SharedData.swift */,
-				5FFF7D6E27E343FA00B00DA8 /* MainInterface.storyboard */,
-				5FFF7D7127E343FA00B00DA8 /* Info.plist */,
-			);
-			path = ShareViewController;
-			sourceTree = "<group>";
-		};
-		9FC5AB18C7E7E43B09B33A61 /* Frameworks */ = {
-			isa = PBXGroup;
-			children = (
-				D32752BD275496C60039291C /* CloudKit.framework */,
-				B2E26D73EA097D0B3B22942E /* Pods_Logseq.framework */,
-			);
-			name = Frameworks;
-			sourceTree = "<group>";
-		};
-		D337740F89DEEAD18C87762B /* Pods */ = {
-			isa = PBXGroup;
-			children = (
-				DE5650F4AD4E2242AB9C012D /* Pods-Logseq.debug.xcconfig */,
-				8A489CEC51E94726DDD58810 /* Pods-Logseq.release.xcconfig */,
-			);
-			path = Pods;
-			sourceTree = "<group>";
-		};
+                504EC2FB1FED79650016851F = {
+                        isa = PBXGroup;
+                        children = (
+                                504EC3061FED79650016851F /* App */,
+                                5FFF7D6B27E343FA00B00DA8 /* ShareViewController */,
+                                504EC3051FED79650016851F /* Products */,
+                                D337740F89DEEAD18C87762B /* Pods */,
+                                9FC5AB18C7E7E43B09B33A61 /* Frameworks */,
+                        );
+                        sourceTree = "<group>";
+                };
+                504EC3051FED79650016851F /* Products */ = {
+                        isa = PBXGroup;
+                        children = (
+                                504EC3041FED79650016851F /* Logseq.app */,
+                                5FFF7D6A27E343FA00B00DA8 /* ShareViewController.appex */,
+                        );
+                        name = Products;
+                        sourceTree = "<group>";
+                };
+                504EC3061FED79650016851F /* App */ = {
+                        isa = PBXGroup;
+                        children = (
+                                5FF86329283B5ADB0047731B /* Utils.swift */,
+                                5FF8632B283B5BFD0047731B /* Utils.m */,
+                                D32752BF2754C5AB0039291C /* AppDebug.entitlements */,
+                                D32752BC275496A60039291C /* App.entitlements */,
+                                50379B222058CBB4000EE86E /* capacitor.config.json */,
+                                504EC3071FED79650016851F /* AppDelegate.swift */,
+                                504EC30B1FED79650016851F /* Main.storyboard */,
+                                504EC30E1FED79650016851F /* Assets.xcassets */,
+                                504EC3101FED79650016851F /* LaunchScreen.storyboard */,
+                                504EC3131FED79650016851F /* Info.plist */,
+                                2FAD9762203C412B000D30F8 /* config.xml */,
+                                50B271D01FEDC1A000F3C39B /* public */,
+                                7435D10B2704659F00AB88E0 /* FolderPicker.swift */,
+                                FE647FF327BDFEDE00F3206B /* FsWatcher.swift */,
+                                FE647FF527BDFEF500F3206B /* FsWatcher.m */,
+                                7435D10E2704660B00AB88E0 /* FolderPicker.m */,
+                                D3D62A09275C92880003FBDC /* FileContainer.swift */,
+                                D3D62A0B275C928F0003FBDC /* FileContainer.m */,
+                                7435D10D2704660A00AB88E0 /* App-Bridging-Header.h */,
+                        );
+                        path = App;
+                        sourceTree = "<group>";
+                };
+                5FFF7D6B27E343FA00B00DA8 /* ShareViewController */ = {
+                        isa = PBXGroup;
+                        children = (
+                                5FFF7D7927E4E70700B00DA8 /* ShareViewController.entitlements */,
+                                5FFF7D6C27E343FA00B00DA8 /* ShareViewController.swift */,
+                                FE96D60F2A1B811A001ECE32 /* SharedData.swift */,
+                                5FFF7D6E27E343FA00B00DA8 /* MainInterface.storyboard */,
+                                5FFF7D7127E343FA00B00DA8 /* Info.plist */,
+                        );
+                        path = ShareViewController;
+                        sourceTree = "<group>";
+                };
+                9FC5AB18C7E7E43B09B33A61 /* Frameworks */ = {
+                        isa = PBXGroup;
+                        children = (
+                                D32752BD275496C60039291C /* CloudKit.framework */,
+                                B2E26D73EA097D0B3B22942E /* Pods_Logseq.framework */,
+                        );
+                        name = Frameworks;
+                        sourceTree = "<group>";
+                };
+                D337740F89DEEAD18C87762B /* Pods */ = {
+                        isa = PBXGroup;
+                        children = (
+                                DE5650F4AD4E2242AB9C012D /* Pods-Logseq.debug.xcconfig */,
+                                8A489CEC51E94726DDD58810 /* Pods-Logseq.release.xcconfig */,
+                        );
+                        path = Pods;
+                        sourceTree = "<group>";
+                };
 /* End PBXGroup section */
 
 /* Begin PBXNativeTarget section */
-		504EC3031FED79650016851F /* Logseq */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "Logseq" */;
-			buildPhases = (
-				818545F0788D5DB466761623 /* [CP] Check Pods Manifest.lock */,
-				504EC3001FED79650016851F /* Sources */,
-				504EC3011FED79650016851F /* Frameworks */,
-				504EC3021FED79650016851F /* Resources */,
-				4BF32F1E9453A6AB603D7CD2 /* [CP] Embed Pods Frameworks */,
-				5FFF7D7527E343FA00B00DA8 /* Embed App Extensions */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-				5FFF7D7327E343FA00B00DA8 /* PBXTargetDependency */,
-			);
-			name = Logseq;
-			productName = App;
-			productReference = 504EC3041FED79650016851F /* Logseq.app */;
-			productType = "com.apple.product-type.application";
-		};
-		5FFF7D6927E343FA00B00DA8 /* ShareViewController */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 5FFF7D7827E343FA00B00DA8 /* Build configuration list for PBXNativeTarget "ShareViewController" */;
-			buildPhases = (
-				5FFF7D6627E343FA00B00DA8 /* Sources */,
-				5FFF7D6727E343FA00B00DA8 /* Frameworks */,
-				5FFF7D6827E343FA00B00DA8 /* Resources */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-			);
-			name = ShareViewController;
-			productName = ShareViewController;
-			productReference = 5FFF7D6A27E343FA00B00DA8 /* ShareViewController.appex */;
-			productType = "com.apple.product-type.app-extension";
-		};
+                504EC3031FED79650016851F /* Logseq */ = {
+                        isa = PBXNativeTarget;
+                        buildConfigurationList = 504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "Logseq" */;
+                        buildPhases = (
+                                818545F0788D5DB466761623 /* [CP] Check Pods Manifest.lock */,
+                                504EC3001FED79650016851F /* Sources */,
+                                504EC3011FED79650016851F /* Frameworks */,
+                                504EC3021FED79650016851F /* Resources */,
+                                4BF32F1E9453A6AB603D7CD2 /* [CP] Embed Pods Frameworks */,
+                                5FFF7D7527E343FA00B00DA8 /* Embed App Extensions */,
+                        );
+                        buildRules = (
+                        );
+                        dependencies = (
+                                5FFF7D7327E343FA00B00DA8 /* PBXTargetDependency */,
+                        );
+                        name = Logseq;
+                        productName = App;
+                        productReference = 504EC3041FED79650016851F /* Logseq.app */;
+                        productType = "com.apple.product-type.application";
+                };
+                5FFF7D6927E343FA00B00DA8 /* ShareViewController */ = {
+                        isa = PBXNativeTarget;
+                        buildConfigurationList = 5FFF7D7827E343FA00B00DA8 /* Build configuration list for PBXNativeTarget "ShareViewController" */;
+                        buildPhases = (
+                                5FFF7D6627E343FA00B00DA8 /* Sources */,
+                                5FFF7D6727E343FA00B00DA8 /* Frameworks */,
+                                5FFF7D6827E343FA00B00DA8 /* Resources */,
+                        );
+                        buildRules = (
+                        );
+                        dependencies = (
+                        );
+                        name = ShareViewController;
+                        productName = ShareViewController;
+                        productReference = 5FFF7D6A27E343FA00B00DA8 /* ShareViewController.appex */;
+                        productType = "com.apple.product-type.app-extension";
+                };
 /* End PBXNativeTarget section */
 
 /* Begin PBXProject section */
-		504EC2FC1FED79650016851F /* Project object */ = {
-			isa = PBXProject;
-			attributes = {
-				LastSwiftUpdateCheck = 1330;
-				LastUpgradeCheck = 1310;
-				TargetAttributes = {
-					504EC3031FED79650016851F = {
-						CreatedOnToolsVersion = 9.2;
-						LastSwiftMigration = 1250;
-						ProvisioningStyle = Automatic;
-					};
-					5FFF7D6927E343FA00B00DA8 = {
-						CreatedOnToolsVersion = 13.3;
-						ProvisioningStyle = Automatic;
-					};
-				};
-			};
-			buildConfigurationList = 504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */;
-			compatibilityVersion = "Xcode 8.0";
-			developmentRegion = en;
-			hasScannedForEncodings = 0;
-			knownRegions = (
-				en,
-				Base,
-			);
-			mainGroup = 504EC2FB1FED79650016851F;
-			productRefGroup = 504EC3051FED79650016851F /* Products */;
-			projectDirPath = "";
-			projectRoot = "";
-			targets = (
-				504EC3031FED79650016851F /* Logseq */,
-				5FFF7D6927E343FA00B00DA8 /* ShareViewController */,
-			);
-		};
+                504EC2FC1FED79650016851F /* Project object */ = {
+                        isa = PBXProject;
+                        attributes = {
+                                LastSwiftUpdateCheck = 1330;
+                                LastUpgradeCheck = 1310;
+                                TargetAttributes = {
+                                        504EC3031FED79650016851F = {
+                                                CreatedOnToolsVersion = 9.2;
+                                                LastSwiftMigration = 1250;
+                                                ProvisioningStyle = Automatic;
+                                        };
+                                        5FFF7D6927E343FA00B00DA8 = {
+                                                CreatedOnToolsVersion = 13.3;
+                                                ProvisioningStyle = Automatic;
+                                        };
+                                };
+                        };
+                        buildConfigurationList = 504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */;
+                        compatibilityVersion = "Xcode 8.0";
+                        developmentRegion = en;
+                        hasScannedForEncodings = 0;
+                        knownRegions = (
+                                en,
+                                Base,
+                        );
+                        mainGroup = 504EC2FB1FED79650016851F;
+                        productRefGroup = 504EC3051FED79650016851F /* Products */;
+                        projectDirPath = "";
+                        projectRoot = "";
+                        targets = (
+                                504EC3031FED79650016851F /* Logseq */,
+                                5FFF7D6927E343FA00B00DA8 /* ShareViewController */,
+                        );
+                };
 /* End PBXProject section */
 
 /* Begin PBXResourcesBuildPhase section */
-		504EC3021FED79650016851F /* Resources */ = {
-			isa = PBXResourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */,
-				50B271D11FEDC1A000F3C39B /* public in Resources */,
-				504EC30F1FED79650016851F /* Assets.xcassets in Resources */,
-				50379B232058CBB4000EE86E /* capacitor.config.json in Resources */,
-				504EC30D1FED79650016851F /* Main.storyboard in Resources */,
-				2FAD9763203C412B000D30F8 /* config.xml in Resources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		5FFF7D6827E343FA00B00DA8 /* Resources */ = {
-			isa = PBXResourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				5FFF7D7027E343FA00B00DA8 /* MainInterface.storyboard in Resources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
+                504EC3021FED79650016851F /* Resources */ = {
+                        isa = PBXResourcesBuildPhase;
+                        buildActionMask = 2147483647;
+                        files = (
+                                504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */,
+                                50B271D11FEDC1A000F3C39B /* public in Resources */,
+                                504EC30F1FED79650016851F /* Assets.xcassets in Resources */,
+                                50379B232058CBB4000EE86E /* capacitor.config.json in Resources */,
+                                504EC30D1FED79650016851F /* Main.storyboard in Resources */,
+                                2FAD9763203C412B000D30F8 /* config.xml in Resources */,
+                        );
+                        runOnlyForDeploymentPostprocessing = 0;
+                };
+                5FFF7D6827E343FA00B00DA8 /* Resources */ = {
+                        isa = PBXResourcesBuildPhase;
+                        buildActionMask = 2147483647;
+                        files = (
+                                5FFF7D7027E343FA00B00DA8 /* MainInterface.storyboard in Resources */,
+                        );
+                        runOnlyForDeploymentPostprocessing = 0;
+                };
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXShellScriptBuildPhase section */
-		4BF32F1E9453A6AB603D7CD2 /* [CP] Embed Pods Frameworks */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputPaths = (
-			);
-			name = "[CP] Embed Pods Frameworks";
-			outputPaths = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Logseq/Pods-Logseq-frameworks.sh\"\n";
-			showEnvVarsInLog = 0;
-		};
-		818545F0788D5DB466761623 /* [CP] Check Pods Manifest.lock */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputFileListPaths = (
-			);
-			inputPaths = (
-				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
-				"${PODS_ROOT}/Manifest.lock",
-			);
-			name = "[CP] Check Pods Manifest.lock";
-			outputFileListPaths = (
-			);
-			outputPaths = (
-				"$(DERIVED_FILE_DIR)/Pods-Logseq-checkManifestLockResult.txt",
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
-			showEnvVarsInLog = 0;
-		};
+                4BF32F1E9453A6AB603D7CD2 /* [CP] Embed Pods Frameworks */ = {
+                        isa = PBXShellScriptBuildPhase;
+                        buildActionMask = 2147483647;
+                        files = (
+                        );
+                        inputPaths = (
+                        );
+                        name = "[CP] Embed Pods Frameworks";
+                        outputPaths = (
+                        );
+                        runOnlyForDeploymentPostprocessing = 0;
+                        shellPath = /bin/sh;
+                        shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Logseq/Pods-Logseq-frameworks.sh\"\n";
+                        showEnvVarsInLog = 0;
+                };
+                818545F0788D5DB466761623 /* [CP] Check Pods Manifest.lock */ = {
+                        isa = PBXShellScriptBuildPhase;
+                        buildActionMask = 2147483647;
+                        files = (
+                        );
+                        inputFileListPaths = (
+                        );
+                        inputPaths = (
+                                "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+                                "${PODS_ROOT}/Manifest.lock",
+                        );
+                        name = "[CP] Check Pods Manifest.lock";
+                        outputFileListPaths = (
+                        );
+                        outputPaths = (
+                                "$(DERIVED_FILE_DIR)/Pods-Logseq-checkManifestLockResult.txt",
+                        );
+                        runOnlyForDeploymentPostprocessing = 0;
+                        shellPath = /bin/sh;
+                        shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+                        showEnvVarsInLog = 0;
+                };
 /* End PBXShellScriptBuildPhase section */
 
 /* Begin PBXSourcesBuildPhase section */
-		504EC3001FED79650016851F /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				504EC3081FED79650016851F /* AppDelegate.swift in Sources */,
-				5FF8632C283B5BFD0047731B /* Utils.m in Sources */,
-				FE647FF427BDFEDE00F3206B /* FsWatcher.swift in Sources */,
-				5FF8632A283B5ADB0047731B /* Utils.swift in Sources */,
-				D3D62A0A275C92880003FBDC /* FileContainer.swift in Sources */,
-				D3D62A0C275C928F0003FBDC /* FileContainer.m in Sources */,
-				7435D10F2704660B00AB88E0 /* FolderPicker.m in Sources */,
-				7435D10C2704659F00AB88E0 /* FolderPicker.swift in Sources */,
-				FE647FF627BDFEF500F3206B /* FsWatcher.m in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		5FFF7D6627E343FA00B00DA8 /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				FE96D6102A1B811A001ECE32 /* SharedData.swift in Sources */,
-				5FFF7D6D27E343FA00B00DA8 /* ShareViewController.swift in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
+                504EC3001FED79650016851F /* Sources */ = {
+                        isa = PBXSourcesBuildPhase;
+                        buildActionMask = 2147483647;
+                        files = (
+                                504EC3081FED79650016851F /* AppDelegate.swift in Sources */,
+                                5FF8632C283B5BFD0047731B /* Utils.m in Sources */,
+                                FE647FF427BDFEDE00F3206B /* FsWatcher.swift in Sources */,
+                                5FF8632A283B5ADB0047731B /* Utils.swift in Sources */,
+                                D3D62A0A275C92880003FBDC /* FileContainer.swift in Sources */,
+                                D3D62A0C275C928F0003FBDC /* FileContainer.m in Sources */,
+                                7435D10F2704660B00AB88E0 /* FolderPicker.m in Sources */,
+                                7435D10C2704659F00AB88E0 /* FolderPicker.swift in Sources */,
+                                FE647FF627BDFEF500F3206B /* FsWatcher.m in Sources */,
+                        );
+                        runOnlyForDeploymentPostprocessing = 0;
+                };
+                5FFF7D6627E343FA00B00DA8 /* Sources */ = {
+                        isa = PBXSourcesBuildPhase;
+                        buildActionMask = 2147483647;
+                        files = (
+                                FE96D6102A1B811A001ECE32 /* SharedData.swift in Sources */,
+                                5FFF7D6D27E343FA00B00DA8 /* ShareViewController.swift in Sources */,
+                        );
+                        runOnlyForDeploymentPostprocessing = 0;
+                };
 /* End PBXSourcesBuildPhase section */
 
 /* Begin PBXTargetDependency section */
-		5FFF7D7327E343FA00B00DA8 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 5FFF7D6927E343FA00B00DA8 /* ShareViewController */;
-			targetProxy = 5FFF7D7227E343FA00B00DA8 /* PBXContainerItemProxy */;
-		};
+                5FFF7D7327E343FA00B00DA8 /* PBXTargetDependency */ = {
+                        isa = PBXTargetDependency;
+                        target = 5FFF7D6927E343FA00B00DA8 /* ShareViewController */;
+                        targetProxy = 5FFF7D7227E343FA00B00DA8 /* PBXContainerItemProxy */;
+                };
 /* End PBXTargetDependency section */
 
 /* Begin PBXVariantGroup section */
-		504EC30B1FED79650016851F /* Main.storyboard */ = {
-			isa = PBXVariantGroup;
-			children = (
-				504EC30C1FED79650016851F /* Base */,
-			);
-			name = Main.storyboard;
-			sourceTree = "<group>";
-		};
-		504EC3101FED79650016851F /* LaunchScreen.storyboard */ = {
-			isa = PBXVariantGroup;
-			children = (
-				504EC3111FED79650016851F /* Base */,
-			);
-			name = LaunchScreen.storyboard;
-			sourceTree = "<group>";
-		};
-		5FFF7D6E27E343FA00B00DA8 /* MainInterface.storyboard */ = {
-			isa = PBXVariantGroup;
-			children = (
-				5FFF7D6F27E343FA00B00DA8 /* Base */,
-			);
-			name = MainInterface.storyboard;
-			sourceTree = "<group>";
-		};
+                504EC30B1FED79650016851F /* Main.storyboard */ = {
+                        isa = PBXVariantGroup;
+                        children = (
+                                504EC30C1FED79650016851F /* Base */,
+                        );
+                        name = Main.storyboard;
+                        sourceTree = "<group>";
+                };
+                504EC3101FED79650016851F /* LaunchScreen.storyboard */ = {
+                        isa = PBXVariantGroup;
+                        children = (
+                                504EC3111FED79650016851F /* Base */,
+                        );
+                        name = LaunchScreen.storyboard;
+                        sourceTree = "<group>";
+                };
+                5FFF7D6E27E343FA00B00DA8 /* MainInterface.storyboard */ = {
+                        isa = PBXVariantGroup;
+                        children = (
+                                5FFF7D6F27E343FA00B00DA8 /* Base */,
+                        );
+                        name = MainInterface.storyboard;
+                        sourceTree = "<group>";
+                };
 /* End PBXVariantGroup section */
 
 /* Begin XCBuildConfiguration section */
-		504EC3141FED79650016851F /* Debug */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_SEARCH_USER_PATHS = NO;
-				CLANG_ANALYZER_NONNULL = YES;
-				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
-				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
-				CLANG_CXX_LIBRARY = "libc++";
-				CLANG_ENABLE_MODULES = YES;
-				CLANG_ENABLE_OBJC_ARC = YES;
-				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
-				CLANG_WARN_BOOL_CONVERSION = YES;
-				CLANG_WARN_COMMA = YES;
-				CLANG_WARN_CONSTANT_CONVERSION = YES;
-				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
-				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
-				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
-				CLANG_WARN_EMPTY_BODY = YES;
-				CLANG_WARN_ENUM_CONVERSION = YES;
-				CLANG_WARN_INFINITE_RECURSION = YES;
-				CLANG_WARN_INT_CONVERSION = YES;
-				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
-				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
-				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
-				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
-				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
-				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
-				CLANG_WARN_STRICT_PROTOTYPES = YES;
-				CLANG_WARN_SUSPICIOUS_MOVE = YES;
-				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
-				CLANG_WARN_UNREACHABLE_CODE = YES;
-				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-				CODE_SIGN_IDENTITY = "iPhone Developer";
-				COPY_PHASE_STRIP = NO;
-				DEBUG_INFORMATION_FORMAT = dwarf;
-				ENABLE_STRICT_OBJC_MSGSEND = YES;
-				ENABLE_TESTABILITY = YES;
-				GCC_C_LANGUAGE_STANDARD = gnu11;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_NO_COMMON_BLOCKS = YES;
-				GCC_OPTIMIZATION_LEVEL = 0;
-				GCC_PREPROCESSOR_DEFINITIONS = (
-					"DEBUG=1",
-					"$(inherited)",
-				);
-				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
-				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
-				GCC_WARN_UNDECLARED_SELECTOR = YES;
-				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
-				GCC_WARN_UNUSED_FUNCTION = YES;
-				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
-				MTL_ENABLE_DEBUG_INFO = YES;
-				ONLY_ACTIVE_ARCH = YES;
-				SDKROOT = iphoneos;
-				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
-				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
-			};
-			name = Debug;
-		};
-		504EC3151FED79650016851F /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_SEARCH_USER_PATHS = NO;
-				CLANG_ANALYZER_NONNULL = YES;
-				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
-				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
-				CLANG_CXX_LIBRARY = "libc++";
-				CLANG_ENABLE_MODULES = YES;
-				CLANG_ENABLE_OBJC_ARC = YES;
-				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
-				CLANG_WARN_BOOL_CONVERSION = YES;
-				CLANG_WARN_COMMA = YES;
-				CLANG_WARN_CONSTANT_CONVERSION = YES;
-				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
-				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
-				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
-				CLANG_WARN_EMPTY_BODY = YES;
-				CLANG_WARN_ENUM_CONVERSION = YES;
-				CLANG_WARN_INFINITE_RECURSION = YES;
-				CLANG_WARN_INT_CONVERSION = YES;
-				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
-				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
-				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
-				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
-				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
-				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
-				CLANG_WARN_STRICT_PROTOTYPES = YES;
-				CLANG_WARN_SUSPICIOUS_MOVE = YES;
-				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
-				CLANG_WARN_UNREACHABLE_CODE = YES;
-				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-				CODE_SIGN_IDENTITY = "iPhone Developer";
-				COPY_PHASE_STRIP = NO;
-				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
-				ENABLE_NS_ASSERTIONS = NO;
-				ENABLE_STRICT_OBJC_MSGSEND = YES;
-				GCC_C_LANGUAGE_STANDARD = gnu11;
-				GCC_NO_COMMON_BLOCKS = YES;
-				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
-				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
-				GCC_WARN_UNDECLARED_SELECTOR = YES;
-				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
-				GCC_WARN_UNUSED_FUNCTION = YES;
-				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
-				MTL_ENABLE_DEBUG_INFO = NO;
-				SDKROOT = iphoneos;
-				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
-				VALIDATE_PRODUCT = YES;
-			};
-			name = Release;
-		};
-		504EC3171FED79650016851F /* Debug */ = {
-			isa = XCBuildConfiguration;
-			baseConfigurationReference = DE5650F4AD4E2242AB9C012D /* Pods-Logseq.debug.xcconfig */;
-			buildSettings = {
-				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
-				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-				CLANG_ENABLE_MODULES = YES;
-				CODE_SIGN_ENTITLEMENTS = App/AppDebug.entitlements;
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = K378MFWK59;
-				ENABLE_BITCODE = NO;
-				INFOPLIST_FILE = App/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
-				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
-				MARKETING_VERSION = 0.10.10;
-				OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
-				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq;
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
-				SWIFT_OBJC_BRIDGING_HEADER = "App/App-Bridging-Header.h";
-				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = "1,2";
-			};
-			name = Debug;
-		};
-		504EC3181FED79650016851F /* Release */ = {
-			isa = XCBuildConfiguration;
-			baseConfigurationReference = 8A489CEC51E94726DDD58810 /* Pods-Logseq.release.xcconfig */;
-			buildSettings = {
-				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
-				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-				CLANG_ENABLE_MODULES = YES;
-				CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = K378MFWK59;
-				ENABLE_BITCODE = NO;
-				INFOPLIST_FILE = App/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
-				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
-				MARKETING_VERSION = 0.10.10;
-				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq;
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
-				SWIFT_OBJC_BRIDGING_HEADER = "App/App-Bridging-Header.h";
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = "1,2";
-			};
-			name = Release;
-		};
-		5FFF7D7627E343FA00B00DA8 /* Debug */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
-				CLANG_ENABLE_OBJC_WEAK = YES;
-				CODE_SIGN_ENTITLEMENTS = ShareViewController/ShareViewController.entitlements;
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = K378MFWK59;
-				GENERATE_INFOPLIST_FILE = YES;
-				INFOPLIST_FILE = ShareViewController/Info.plist;
-				INFOPLIST_KEY_CFBundleDisplayName = ShareViewController;
-				INFOPLIST_KEY_NSHumanReadableCopyright = "";
-				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
-				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
-				MARKETING_VERSION = 0.10.10;
-				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
-				MTL_FAST_MATH = YES;
-				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController;
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SKIP_INSTALL = YES;
-				SWIFT_EMIT_LOC_STRINGS = YES;
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = "1,2";
-			};
-			name = Debug;
-		};
-		5FFF7D7727E343FA00B00DA8 /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
-				CLANG_ENABLE_OBJC_WEAK = YES;
-				CODE_SIGN_ENTITLEMENTS = ShareViewController/ShareViewController.entitlements;
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = K378MFWK59;
-				GENERATE_INFOPLIST_FILE = YES;
-				INFOPLIST_FILE = ShareViewController/Info.plist;
-				INFOPLIST_KEY_CFBundleDisplayName = ShareViewController;
-				INFOPLIST_KEY_NSHumanReadableCopyright = "";
-				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
-				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
-				MARKETING_VERSION = 0.10.10;
-				MTL_FAST_MATH = YES;
-				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController;
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SKIP_INSTALL = YES;
-				SWIFT_EMIT_LOC_STRINGS = YES;
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = "1,2";
-			};
-			name = Release;
-		};
+                504EC3141FED79650016851F /* Debug */ = {
+                        isa = XCBuildConfiguration;
+                        buildSettings = {
+                                ALWAYS_SEARCH_USER_PATHS = NO;
+                                CLANG_ANALYZER_NONNULL = YES;
+                                CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                                CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+                                CLANG_CXX_LIBRARY = "libc++";
+                                CLANG_ENABLE_MODULES = YES;
+                                CLANG_ENABLE_OBJC_ARC = YES;
+                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+                                CLANG_WARN_BOOL_CONVERSION = YES;
+                                CLANG_WARN_COMMA = YES;
+                                CLANG_WARN_CONSTANT_CONVERSION = YES;
+                                CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+                                CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                                CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+                                CLANG_WARN_EMPTY_BODY = YES;
+                                CLANG_WARN_ENUM_CONVERSION = YES;
+                                CLANG_WARN_INFINITE_RECURSION = YES;
+                                CLANG_WARN_INT_CONVERSION = YES;
+                                CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+                                CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+                                CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+                                CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                                CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+                                CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+                                CLANG_WARN_STRICT_PROTOTYPES = YES;
+                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
+                                CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+                                CLANG_WARN_UNREACHABLE_CODE = YES;
+                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                                CODE_SIGN_IDENTITY = "iPhone Developer";
+                                COPY_PHASE_STRIP = NO;
+                                DEBUG_INFORMATION_FORMAT = dwarf;
+                                ENABLE_STRICT_OBJC_MSGSEND = YES;
+                                ENABLE_TESTABILITY = YES;
+                                GCC_C_LANGUAGE_STANDARD = gnu11;
+                                GCC_DYNAMIC_NO_PIC = NO;
+                                GCC_NO_COMMON_BLOCKS = YES;
+                                GCC_OPTIMIZATION_LEVEL = 0;
+                                GCC_PREPROCESSOR_DEFINITIONS = (
+                                        "DEBUG=1",
+                                        "$(inherited)",
+                                );
+                                GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                                GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                                GCC_WARN_UNDECLARED_SELECTOR = YES;
+                                GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                                GCC_WARN_UNUSED_FUNCTION = YES;
+                                GCC_WARN_UNUSED_VARIABLE = YES;
+                                IPHONEOS_DEPLOYMENT_TARGET = 14.0;
+                                MTL_ENABLE_DEBUG_INFO = YES;
+                                ONLY_ACTIVE_ARCH = YES;
+                                SDKROOT = iphoneos;
+                                SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+                                SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+                        };
+                        name = Debug;
+                };
+                504EC3151FED79650016851F /* Release */ = {
+                        isa = XCBuildConfiguration;
+                        buildSettings = {
+                                ALWAYS_SEARCH_USER_PATHS = NO;
+                                CLANG_ANALYZER_NONNULL = YES;
+                                CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                                CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+                                CLANG_CXX_LIBRARY = "libc++";
+                                CLANG_ENABLE_MODULES = YES;
+                                CLANG_ENABLE_OBJC_ARC = YES;
+                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+                                CLANG_WARN_BOOL_CONVERSION = YES;
+                                CLANG_WARN_COMMA = YES;
+                                CLANG_WARN_CONSTANT_CONVERSION = YES;
+                                CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+                                CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                                CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+                                CLANG_WARN_EMPTY_BODY = YES;
+                                CLANG_WARN_ENUM_CONVERSION = YES;
+                                CLANG_WARN_INFINITE_RECURSION = YES;
+                                CLANG_WARN_INT_CONVERSION = YES;
+                                CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+                                CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+                                CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+                                CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                                CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+                                CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+                                CLANG_WARN_STRICT_PROTOTYPES = YES;
+                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
+                                CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+                                CLANG_WARN_UNREACHABLE_CODE = YES;
+                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                                CODE_SIGN_IDENTITY = "iPhone Developer";
+                                COPY_PHASE_STRIP = NO;
+                                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+                                ENABLE_NS_ASSERTIONS = NO;
+                                ENABLE_STRICT_OBJC_MSGSEND = YES;
+                                GCC_C_LANGUAGE_STANDARD = gnu11;
+                                GCC_NO_COMMON_BLOCKS = YES;
+                                GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                                GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                                GCC_WARN_UNDECLARED_SELECTOR = YES;
+                                GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                                GCC_WARN_UNUSED_FUNCTION = YES;
+                                GCC_WARN_UNUSED_VARIABLE = YES;
+                                IPHONEOS_DEPLOYMENT_TARGET = 14.0;
+                                MTL_ENABLE_DEBUG_INFO = NO;
+                                SDKROOT = iphoneos;
+                                SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+                                VALIDATE_PRODUCT = YES;
+                        };
+                        name = Release;
+                };
+                504EC3171FED79650016851F /* Debug */ = {
+                        isa = XCBuildConfiguration;
+                        baseConfigurationReference = DE5650F4AD4E2242AB9C012D /* Pods-Logseq.debug.xcconfig */;
+                        buildSettings = {
+                                ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+                                ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+                                CLANG_ENABLE_MODULES = YES;
+                                CODE_SIGN_ENTITLEMENTS = App/AppDebug.entitlements;
+                                CODE_SIGN_STYLE = Automatic;
+                                CURRENT_PROJECT_VERSION = 1;
+                                DEVELOPMENT_TEAM = K378MFWK59;
+                                ENABLE_BITCODE = NO;
+                                INFOPLIST_FILE = App/Info.plist;
+                                IPHONEOS_DEPLOYMENT_TARGET = 14.0;
+                                LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+                                MARKETING_VERSION = 0.11.0;
+                                OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
+                                PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq;
+                                PRODUCT_NAME = "$(TARGET_NAME)";
+                                SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+                                SWIFT_OBJC_BRIDGING_HEADER = "App/App-Bridging-Header.h";
+                                SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+                                SWIFT_VERSION = 5.0;
+                                TARGETED_DEVICE_FAMILY = "1,2";
+                        };
+                        name = Debug;
+                };
+                504EC3181FED79650016851F /* Release */ = {
+                        isa = XCBuildConfiguration;
+                        baseConfigurationReference = 8A489CEC51E94726DDD58810 /* Pods-Logseq.release.xcconfig */;
+                        buildSettings = {
+                                ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+                                ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+                                CLANG_ENABLE_MODULES = YES;
+                                CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
+                                CODE_SIGN_STYLE = Automatic;
+                                CURRENT_PROJECT_VERSION = 1;
+                                DEVELOPMENT_TEAM = K378MFWK59;
+                                ENABLE_BITCODE = NO;
+                                INFOPLIST_FILE = App/Info.plist;
+                                IPHONEOS_DEPLOYMENT_TARGET = 14.0;
+                                LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+                                MARKETING_VERSION = 0.11.0;
+                                PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq;
+                                PRODUCT_NAME = "$(TARGET_NAME)";
+                                SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
+                                SWIFT_OBJC_BRIDGING_HEADER = "App/App-Bridging-Header.h";
+                                SWIFT_VERSION = 5.0;
+                                TARGETED_DEVICE_FAMILY = "1,2";
+                        };
+                        name = Release;
+                };
+                5FFF7D7627E343FA00B00DA8 /* Debug */ = {
+                        isa = XCBuildConfiguration;
+                        buildSettings = {
+                                CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
+                                CLANG_ENABLE_OBJC_WEAK = YES;
+                                CODE_SIGN_ENTITLEMENTS = ShareViewController/ShareViewController.entitlements;
+                                CODE_SIGN_STYLE = Automatic;
+                                CURRENT_PROJECT_VERSION = 1;
+                                DEVELOPMENT_TEAM = K378MFWK59;
+                                GENERATE_INFOPLIST_FILE = YES;
+                                INFOPLIST_FILE = ShareViewController/Info.plist;
+                                INFOPLIST_KEY_CFBundleDisplayName = ShareViewController;
+                                INFOPLIST_KEY_NSHumanReadableCopyright = "";
+                                IPHONEOS_DEPLOYMENT_TARGET = 14.0;
+                                LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
+                                MARKETING_VERSION = 0.11.0;
+                                MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+                                MTL_FAST_MATH = YES;
+                                PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController;
+                                PRODUCT_NAME = "$(TARGET_NAME)";
+                                SKIP_INSTALL = YES;
+                                SWIFT_EMIT_LOC_STRINGS = YES;
+                                SWIFT_VERSION = 5.0;
+                                TARGETED_DEVICE_FAMILY = "1,2";
+                        };
+                        name = Debug;
+                };
+                5FFF7D7727E343FA00B00DA8 /* Release */ = {
+                        isa = XCBuildConfiguration;
+                        buildSettings = {
+                                CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
+                                CLANG_ENABLE_OBJC_WEAK = YES;
+                                CODE_SIGN_ENTITLEMENTS = ShareViewController/ShareViewController.entitlements;
+                                CODE_SIGN_STYLE = Automatic;
+                                CURRENT_PROJECT_VERSION = 1;
+                                DEVELOPMENT_TEAM = K378MFWK59;
+                                GENERATE_INFOPLIST_FILE = YES;
+                                INFOPLIST_FILE = ShareViewController/Info.plist;
+                                INFOPLIST_KEY_CFBundleDisplayName = ShareViewController;
+                                INFOPLIST_KEY_NSHumanReadableCopyright = "";
+                                IPHONEOS_DEPLOYMENT_TARGET = 14.0;
+                                LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
+                                MARKETING_VERSION = 0.11.0;
+                                MTL_FAST_MATH = YES;
+                                PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController;
+                                PRODUCT_NAME = "$(TARGET_NAME)";
+                                SKIP_INSTALL = YES;
+                                SWIFT_EMIT_LOC_STRINGS = YES;
+                                SWIFT_VERSION = 5.0;
+                                TARGETED_DEVICE_FAMILY = "1,2";
+                        };
+                        name = Release;
+                };
 /* End XCBuildConfiguration section */
 
 /* Begin XCConfigurationList section */
-		504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				504EC3141FED79650016851F /* Debug */,
-				504EC3151FED79650016851F /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
-		504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "Logseq" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				504EC3171FED79650016851F /* Debug */,
-				504EC3181FED79650016851F /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
-		5FFF7D7827E343FA00B00DA8 /* Build configuration list for PBXNativeTarget "ShareViewController" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				5FFF7D7627E343FA00B00DA8 /* Debug */,
-				5FFF7D7727E343FA00B00DA8 /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
+                504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */ = {
+                        isa = XCConfigurationList;
+                        buildConfigurations = (
+                                504EC3141FED79650016851F /* Debug */,
+                                504EC3151FED79650016851F /* Release */,
+                        );
+                        defaultConfigurationIsVisible = 0;
+                        defaultConfigurationName = Release;
+                };
+                504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "Logseq" */ = {
+                        isa = XCConfigurationList;
+                        buildConfigurations = (
+                                504EC3171FED79650016851F /* Debug */,
+                                504EC3181FED79650016851F /* Release */,
+                        );
+                        defaultConfigurationIsVisible = 0;
+                        defaultConfigurationName = Release;
+                };
+                5FFF7D7827E343FA00B00DA8 /* Build configuration list for PBXNativeTarget "ShareViewController" */ = {
+                        isa = XCConfigurationList;
+                        buildConfigurations = (
+                                5FFF7D7627E343FA00B00DA8 /* Debug */,
+                                5FFF7D7727E343FA00B00DA8 /* Release */,
+                        );
+                        defaultConfigurationIsVisible = 0;
+                        defaultConfigurationName = Release;
+                };
 /* End XCConfigurationList section */
-	};
-	rootObject = 504EC2FC1FED79650016851F /* Project object */;
+        };
+        rootObject = 504EC2FC1FED79650016851F /* Project object */;
 }

+ 1 - 1
resources/package.json

@@ -1,7 +1,7 @@
 {
   "name": "Logseq",
   "productName": "Logseq",
-  "version": "0.10.10",
+  "version": "0.11.0",
   "main": "electron.js",
   "author": "Logseq",
   "license": "AGPL-3.0",

+ 1 - 1
scripts/package.json

@@ -3,7 +3,7 @@
   "version": "1.0.0",
   "private": true,
   "devDependencies": {
-    "@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v19"
+    "@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v20"
   },
   "dependencies": {
     "better-sqlite3": "9.3.0",

+ 3 - 3
scripts/yarn.lock

@@ -2,9 +2,9 @@
 # yarn lockfile v1
 
 
-"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v19":
-  version "1.2.173-feat-db-v19"
-  resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/ca32553da41aff783d89264b2e1a753372721f2e"
+"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v20":
+  version "1.2.173-feat-db-v20"
+  resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/7fb63423ab566717cac79e5f76084d89b845fbd6"
   dependencies:
     import-meta-resolve "^2.1.0"
 

+ 12 - 14
src/main/frontend/components/block.cljs

@@ -507,14 +507,7 @@
             (file-based-asset-loader @src
                                      #(resizable-image config title @src metadata full_text true)))
 
-          (and db-based? (contains? (common-config/text-formats) ext) (:asset-block config))
-          (let [file-name (str (:block/title (:asset-block config)) "." (name ext))]
-            [:a.asset-ref.is-plaintext
-             {:href @src
-              :download file-name}
-             file-name])
-
-          (contains? (common-config/text-formats) ext)
+          (and (not db-based?) (contains? (common-config/text-formats) ext))
           [:a.asset-ref.is-plaintext {:href (rfe/href :file {:path path})
                                       :on-click (fn [_event]
                                                   (p/let [result (fs/read-file repo-dir path)]
@@ -534,9 +527,16 @@
              title
              [:span [:span.opacity-70 "[[📚"] title [:span.opacity-70 "]]"]])]
 
+          db-based?
+          (let [file-name (str (:block/title (:asset-block config)) "." (name ext))]
+            [:a.asset-ref.is-plaintext
+             {:href @src
+              :download file-name}
+             file-name])
+
           :else
-          [:a.asset-ref.is-doc {:href @src
-                                :on-click share-fn}
+          [:a.asset-ref {:href @src
+                         :on-click share-fn}
            title])))))
 
 ;; TODO: safe encoding asciis
@@ -926,8 +926,7 @@
                (reset! *result page)
                :else
                (p/let [result (db-async/<get-block (state/get-current-repo) page-id-or-name {:children? false
-                                                                                             :skip-refresh? true
-                                                                                             :including-property-vals? false})]
+                                                                                             :skip-refresh? true})]
                  (reset! *result result)))
 
              (assoc state :*entity *result)))}
@@ -1003,7 +1002,6 @@
                         (->elem :span (map-inline config title))
                         :else
                         path)]
-
     [:div.asset-ref-wrap
      {:data-ext ext-name}
 
@@ -3675,7 +3673,7 @@
 
      (when-not (or in-whiteboard? table? property?) (dnd-separator-wrapper block children block-id slide? false false))]))
 
-(rum/defc ^:large-vars/cleanup-todo block-container-inner
+(rum/defc block-container-inner
   [container-state repo config* block opts]
   (let [container-id (:container-id config*)
         block-id (:block/uuid block)

+ 1 - 1
src/main/frontend/components/cmdk/list_item.cljs

@@ -40,7 +40,7 @@
             highlighted-text (string/replace normal-text query-re "<:hlmarker>$1<:hlmarker>")
             segs (string/split highlighted-text #"<:hlmarker>")]
         (if (seq segs)
-          (into [:span]
+          (into [:span {:aria-label text-string}]
                 (map-indexed (fn [i seg]
                                (if (even? i)
                                  [:span seg]

+ 13 - 14
src/main/frontend/components/container.cljs

@@ -86,7 +86,6 @@
   [page icon recent?]
   (let [repo (state/get-current-repo)
         db-based? (config/db-based-graph? repo)
-        page (or (db/get-alias-source-page repo (:db/id page)) page)
         title (:block/title page)
         untitled? (db-model/untitled-page? title)
         name (:block/name page)
@@ -783,19 +782,19 @@
   []
   (when (state/sub [:document/mode?])
     (ui/tooltip
-      [:a.block.px-1.text-sm.font-medium.bg-base-2.rounded-md.mx-2
-       {:on-click state/toggle-document-mode!}
-       "D"]
-      [:div.p-2
-       [:p.mb-2 [:b "Document mode"]]
-       [:ul
-        [:li
-         [:div.inline-block.mr-1 (ui/render-keyboard-shortcut (shortcut-dh/gen-shortcut-seq :editor/new-line))]
-         [:p.inline-block "to create new block"]]
-        [:li
-         [:p.inline-block.mr-1 "Click `D` or type"]
-         [:div.inline-block.mr-1 (ui/render-keyboard-shortcut (shortcut-dh/gen-shortcut-seq :ui/toggle-document-mode))]
-         [:p.inline-block "to toggle document mode"]]]])))
+     [:a.block.px-1.text-sm.font-medium.bg-base-2.rounded-md.mx-2
+      {:on-click state/toggle-document-mode!}
+      "D"]
+     [:div.p-2
+      [:p.mb-2 [:b "Document mode"]]
+      [:ul
+       [:li
+        [:div.inline-block.mr-1 (ui/render-keyboard-shortcut (shortcut-dh/gen-shortcut-seq :editor/new-line))]
+        [:p.inline-block "to create new block"]]
+       [:li
+        [:p.inline-block.mr-1 "Click `D` or type"]
+        [:div.inline-block.mr-1 (ui/render-keyboard-shortcut (shortcut-dh/gen-shortcut-seq :ui/toggle-document-mode))]
+        [:p.inline-block "to toggle document mode"]]]])))
 
 (def help-menu-items
   [{:title "Handbook" :icon "book-2" :on-click #(handbooks/toggle-handbooks)}

+ 1 - 1
src/main/frontend/components/editor.cljs

@@ -354,7 +354,7 @@
         [matched-templates set-matched-templates!] (rum/use-state nil)]
     (hooks/use-effect! (fn []
                          (p/let [result (editor-handler/<get-matched-templates q)]
-                           (set-matched-templates! result)))
+                           (set-matched-templates! (sort-by :block/title result))))
                        [q])
     (ui/auto-complete
      matched-templates

+ 16 - 5
src/main/frontend/components/header.cljs

@@ -331,10 +331,9 @@
   (when (state/sub :ui/toggle-highlight-recent-blocks?)
     (recent-slider-inner)))
 
-(rum/defc ^:large-vars/cleanup-todo header < rum/reactive
+(rum/defc ^:large-vars/cleanup-todo header-aux < rum/reactive
   [{:keys [current-repo default-home new-block-mode]}]
-  (let [_ (state/sub [:user/info :UserGroups])
-        electron-mac? (and util/mac? (util/electron?))
+  (let [electron-mac? (and util/mac? (util/electron?))
         left-menu (left-menu-button {:on-click (fn []
                                                  (state/set-left-sidebar-open!
                                                   (not (:ui/left-sidebar-open? @state/state))))})
@@ -357,13 +356,13 @@
      [:div.l.flex.items-center.drag-region
       [left-menu
        (if (mobile-util/native-platform?)
-         ;; back button for mobile
+                 ;; back button for mobile
          (when-not (or (state/home?) custom-home-page? (state/whiteboard-dashboard?))
            (ui/with-shortcut :go/backward "bottom"
              [:button.it.navigation.nav-left.button.icon.opacity-70
               {:title (t :header/go-back) :on-click #(js/window.history.back)}
               (ui/icon "chevron-left" {:size 26})]))
-         ;; search button for non-mobile
+                 ;; search button for non-mobile
          (when current-repo
            (ui/with-shortcut :go/search "right"
              [:button.button.icon#search-button
@@ -421,3 +420,15 @@
       (sidebar/toggle)
 
       (updater-tips-new-version t)]]))
+
+(def ^:private header-related-flow
+  (m/latest
+   (fn [state rtc-running?]
+     {:user-groups (get-in state [:user/info :UserGroups])
+      :rtc-running? rtc-running?})
+   (m/watch state/state) rtc-flows/rtc-running-flow))
+
+(rum/defc header
+  [opts]
+  (let [_m (hooks/use-flow-state header-related-flow)]
+    (header-aux opts)))

+ 33 - 20
src/main/frontend/components/property/value.cljs

@@ -610,6 +610,11 @@
         clear-value-label [:div.flex.flex-row.items-center.gap-1.text-sm
                            (ui/icon "x" {:size 14})
                            [:div clear-value]]
+        items (if (:property/closed-values property)
+                items                   ; sorted by order
+                (sort-by (fn [item]
+                           (db-property/property-value-content item))
+                         items))
         items' (->>
                 (if (and (seq selected-choices)
                          (not multiple-choices?)
@@ -655,10 +660,9 @@
 
 (rum/defc ^:large-vars/cleanup-todo select-node < rum/static
   [property
-   {:keys [block multiple-choices? dropdown? input-opts on-input] :as opts}
+   {:keys [block multiple-choices? dropdown? input-opts on-input add-new-choice!] :as opts}
    result]
-  (let [[refresh-count set-refresh-count!] (rum/use-state 0)
-        repo (state/get-current-repo)
+  (let [repo (state/get-current-repo)
         classes (:logseq.property/classes property)
         tags? (= :block/tags (:db/ident property))
         alias? (= :block/alias (:db/ident property))
@@ -772,8 +776,9 @@
                                               (str "Set " (:block/title property)))
                  :show-new-when-not-exact-match? (if (or (and parent-property? (contains? (set children-pages) (:db/id block)))
                                                          ;; Don't allow creating private tags
-                                                         (seq (set/intersection (set (map :db/ident classes'))
-                                                                                ldb/private-tags)))
+                                                         (and (= :block/tags (:db/ident property))
+                                                              (seq (set/intersection (set (map :db/ident classes'))
+                                                                                     ldb/private-tags))))
                                                    false
                                                    true)
                  :extract-chosen-fn :value
@@ -781,18 +786,21 @@
                  :input-opts input-opts
                  :on-input (debounce on-input 50)
                  :on-chosen (fn [chosen selected?]
-                              (p/let [[id new?] (if (integer? chosen)
-                                                  [chosen false]
-                                                  (when-not (string/blank? (string/trim chosen))
-                                                    (p/let [result (<create-page-if-not-exists! block property classes' chosen)]
-                                                      [result true])))
+                              (p/let [id (if (integer? chosen)
+                                           chosen
+                                           (when-not (string/blank? (string/trim chosen))
+                                             (<create-page-if-not-exists! block property classes' chosen)))
                                       _ (when (and (integer? id) (not (entity-util/page? (db/entity id))))
                                           (db-async/<get-block repo id))]
-                                (p/do!
-                                 (if id
+                                (if id
+                                  (p/do!
                                    (add-or-remove-property-value block property id selected? {})
-                                   (log/error :msg "No :db/id found or created for chosen" :chosen chosen))
-                                 (when new? (set-refresh-count! (inc refresh-count))))))})
+                                   (when (fn? add-new-choice!)
+                                     (add-new-choice!
+                                      (let [e (db/entity id)]
+                                        {:value (select-keys e [:db/id :block/uuid])
+                                         :label (:block/title e)}))))
+                                  (log/error :msg "No :db/id found or created for chosen" :chosen chosen))))})
 
                 (and (seq classes') (not tags-or-alias?))
                 (assoc
@@ -834,11 +842,13 @@
                      :input-opts input-opts
                      :on-input (fn [v]
                                  (if (string/blank? v)
-                                   initial-choices
+                                   (set-result! initial-choices)
                                    ;; TODO rank initial choices higher
                                    (p/let [result (search/block-search (state/get-current-repo) v {:enable-snippet? false
                                                                                                    :built-in? false})]
-                                     (set-result! result)))))
+                                     (set-result! result))))
+                     :add-new-choice! (fn [new-choice]
+                                        (set-initial-choices! (conj (vec initial-choices) new-choice))))
         repo (state/get-current-repo)
         classes (:logseq.property/classes property)
         class? (= :class (:logseq.property/type property))
@@ -1081,7 +1091,7 @@
 
        (contains? #{:node :class :property :page} type)
        (when-let [reference (state/get-component :block/reference)]
-         (reference {:table-view? table-view?} (:block/uuid value)))
+         (when value (reference {:table-view? table-view?} (:block/uuid value))))
 
        (and (map? value) (some? (db-property/property-value-content value)))
        (let [content (str (db-property/property-value-content value))]
@@ -1338,11 +1348,14 @@
          self-value-or-embedded? (fn [v]
                                    (or (= (:db/id v) (:db/id block))
                                        ;; property value self embedded
-                                       (= (:db/id (:block/link v)) (:db/id block))))]
-     (if (and (or (and (entity-map? v) (self-value-or-embedded? v))
+                                       (and (:db/id block) (= (:db/id (:block/link v)) (:db/id block)))))]
+     (if (and (or (and (entity-map? v)
+                       (self-value-or-embedded? v))
                   (and (coll? v) (every? entity-map? v)
                        (some self-value-or-embedded? v))
-                  (and (= p-block (:db/id block)) (= p-property (:db/id property))))
+                  (and (:db/id block)
+                       (= p-block (:db/id block))
+                       (= p-property (:db/id property))))
               (not= :logseq.class/Tag (:db/ident block)))
        [:div.flex.flex-row.items-center.gap-1
         [:div.warning "Self reference"]

+ 1 - 1
src/main/frontend/components/rtc/indicator.cljs

@@ -51,7 +51,7 @@
                                          :local-tx (:local-tx state)
                                          :remote-tx (:remote-tx state)
                                          :rtc-state (if (:rtc-lock state) :open :close)))
-                                rtc-flows/rtc-state-stream-flow)))]
+                                rtc-flows/rtc-state-flow)))]
       (reset! *update-detail-info-canceler canceler))))
 (run-task--update-detail-info)
 

+ 12 - 6
src/main/frontend/components/select.cljs

@@ -52,6 +52,13 @@
        (reset! *input input)
        (when (fn? on-input) (on-input input)))
      [(hooks/use-debounced-value input 100)])
+
+    (hooks/use-effect!
+     (fn []
+       (when (= "" @*input)
+         (set-input! "")))
+     [(hooks/use-debounced-value @*input 100)])
+
     [:div.input-wrap
      {:style {:margin-bottom "-2px"}}
      [:input.cp__select-input.w-full
@@ -65,6 +72,7 @@
                                (set-input! v)))}
              input-opts)]]))
 
+;; TODO: rewrite using hooks
 (rum/defcs ^:large-vars/cleanup-todo select
   "Provides a select dropdown powered by a fuzzy search. Takes the following options:
    * :items - Vec of things to select from. Assumes a vec of maps with :value key by default. Required option
@@ -83,8 +91,8 @@
   (rum/local "" ::input)
   (rum/local nil ::toggle)
   {:init (fn [state]
-           (assoc state ::selected-choices
-                  (atom (set (:selected-choices (first (:rum/args state)))))))
+           (let [choices (:selected-choices (first (:rum/args state)))]
+             (assoc state ::selected-choices (atom (set choices)))))
    :will-remount (fn [_old-state new-state]
                    (let [choices (set (:selected-choices (first (:rum/args new-state))))]
                      (when (not= choices @(::selected-choices new-state))
@@ -113,9 +121,7 @@
         *selected-choices (::selected-choices state)
         selected-choices (rum/react *selected-choices)
         full-choices (cond->>
-                      (->> (concat (map (fn [v] {:value v}) selected-choices) items)
-                           (util/distinct-by-last-wins :value)
-                           (remove nil?))
+                      (remove nil? items)
                        (seq @input)
                        (remove :clear?))
         search-result' (->>
@@ -126,7 +132,7 @@
         exact-transform-fn (if new-case-sensitive? identity string/lower-case)
         exact-match? (contains? (set (map (comp exact-transform-fn str extract-fn) search-result'))
                                 (exact-transform-fn @input))
-        search-result' (if multiple-choices?
+        search-result' (if (and multiple-choices? (not (string/blank? @input)))
                          (sort-by (fn [item]
                                     (not (contains? selected-choices (:value item))))
                                   search-result')

+ 28 - 27
src/main/frontend/components/settings.cljs

@@ -398,11 +398,11 @@
                            :style {:background-color (if-not none? (str "var(--rx-" (name color) "-07)") "")
                                    :opacity (if (or none? active?) 1 0)}}])
 
-                         (case color
-                           :none [:p {:style {:max-width "300px"}}
-                                  "Cancel accent color. This is currently in beta stage and mainly used for compatibility with custom themes."]
-                           :logseq "Logseq classical color"
-                           (str (name color) " color")))])]]
+                        (case color
+                          :none [:p {:style {:max-width "300px"}}
+                                 "Cancel accent color. This is currently in beta stage and mainly used for compatibility with custom themes."]
+                          :logseq "Logseq classical color"
+                          (str (name color) " color")))])]]
 
     [:div
      (row-with-button-action
@@ -432,7 +432,7 @@
     (t :settings-page/custom-date-format)
     (when-not (config/db-based-graph? (state/get-current-repo))
       (ui/tooltip [:span.flex.px-2 (svg/info)]
-        [:span (t :settings-page/custom-date-format-warning)]))]
+                  [:span (t :settings-page/custom-date-format-warning)]))]
    [:div.mt-1.sm:mt-0.sm:col-span-2
     [:div.max-w-lg.rounded-md
      [:select.form-select.is-small
@@ -482,7 +482,7 @@
   (toggle "preferred_outdenting"
           [(t :settings-page/preferred-outdenting)
            (ui/tooltip [:span.flex.px-2 (svg/info)]
-             (outdenting-hint) {:content-props {:side "right"}})]
+                       (outdenting-hint) {:content-props {:side "right"}})]
           logical-outdenting?
           config-handler/toggle-logical-outdenting!))
 
@@ -496,7 +496,7 @@
   (toggle "preferred_pasting_file"
           [(t :settings-page/preferred-pasting-file)
            (ui/tooltip [:span.flex.px-2 (svg/info)]
-             [:span.block.w-64 (t :settings-page/preferred-pasting-file-hint)])]
+                       [:span.block.w-64 (t :settings-page/preferred-pasting-file-hint)])]
           preferred-pasting-file?
           config-handler/toggle-preferred-pasting-file!))
 
@@ -504,7 +504,7 @@
   (toggle "auto_expand_block_refs"
           [(t :settings-page/auto-expand-block-refs)
            (ui/tooltip [:span.flex.px-2 (svg/info)]
-             (auto-expand-hint))]
+                       (auto-expand-hint))]
           auto-expand-block-refs?
           config-handler/toggle-auto-expand-block-refs!))
 
@@ -600,11 +600,11 @@
                   (not instrument-disabled?)))
           [:span.text-sm.opacity-50 (t :settings-page/disable-sentry-desc)]))
 
-(defn clear-cache-row [t]
-  (row-with-button-action {:left-label   (t :settings-page/clear-cache)
-                           :button-label (t :settings-page/clear)
-                           :on-click     #(state/pub-event! [:graph/clear-cache!])
-                           :-for         "clear_cache"}))
+;; (defn clear-cache-row [t]
+;;   (row-with-button-action {:left-label   (t :settings-page/clear-cache)
+;;                            :button-label (t :settings-page/clear)
+;;                            :on-click     #(state/pub-event! [:graph/clear-cache!])
+;;                            :-for         "clear_cache"}))
 
 (defn version-row [t version]
   (row-with-button-action {:left-label (t :settings-page/current-version)
@@ -823,11 +823,12 @@
      (when-not (mobile-util/native-platform?) (developer-mode-row t developer-mode?))
      (when (util/electron?) (https-user-agent-row https-agent-opts))
      (when (util/electron?) (auto-chmod-row t))
-     (clear-cache-row t)
+     ;; (clear-cache-row t)
 
-     (ui/admonition
-      :warning
-      [:p (t :settings-page/clear-cache-warning)])]))
+     ;; (ui/admonition
+     ;;  :warning
+     ;;  [:p (t :settings-page/clear-cache-warning)])
+     ]))
 
 (rum/defc sync-enabled-switcher
   [enabled?]
@@ -855,22 +856,22 @@
    {:left-label (str (t :settings-page/sync-diff-merge) " (Experimental!)") ;; Not included in i18n to avoid outdating translations
     :action (sync-diff-merge-enabled-switcher enabled?)
     :desc (ui/tooltip [:span.inline-flex.px-1 (svg/info)]
-            [:div
-             [:div (t :settings-page/sync-diff-merge-desc)]
-             [:div (t :settings-page/sync-diff-merge-warn)]])}))
+                      [:div
+                       [:div (t :settings-page/sync-diff-merge-desc)]
+                       [:div (t :settings-page/sync-diff-merge-warn)]])}))
 
 (rum/defc rtc-enabled-switcher
   [enabled?]
   (ui/toggle enabled?
-    (fn []
-      (let [value (not enabled?)]
-        (state/set-rtc-enabled! value)))
-    true))
+             (fn []
+               (let [value (not enabled?)]
+                 (state/set-rtc-enabled! value)))
+             true))
 
 (defn rtc-switcher-row [enabled?]
   (row-with-button-action
-    {:left-label "RTC"
-     :action (rtc-enabled-switcher enabled?)}))
+   {:left-label "RTC"
+    :action (rtc-enabled-switcher enabled?)}))
 
 (rum/defc whiteboards-enabled-switcher
   [enabled?]

+ 2 - 2
src/main/frontend/components/views.cljs

@@ -1224,8 +1224,7 @@
         db-id (cond (map? item) (:db/id item)
                     (number? item) item
                     :else nil)
-        block (some-> db-id db/entity)
-        [item set-item!] (hooks/use-state (when (:block.temp/fully-loaded? block) block))
+        [item set-item!] (hooks/use-state nil)
         opts (if list-view?
                {:skip-refresh? true
                 :children? false}
@@ -1826,6 +1825,7 @@
         (hooks/use-debounced-value input 300)
         sorting-filters
         (:db/id (:logseq.property.view/group-by-property view-entity))
+        (:db/id (:logseq.property.view/type view-entity))
         ;; page filters
         (:logseq.property.linked-references/includes view-parent)
         (:logseq.property.linked-references/excludes view-parent)

+ 19 - 12
src/main/frontend/db/async.cljs

@@ -15,6 +15,7 @@
             [frontend.handler.file-based.property.util :as property-util]
             [frontend.state :as state]
             [frontend.util :as util]
+            [logseq.common.util :as common-util]
             [logseq.db :as ldb]
             [logseq.db.frontend.property :as db-property]
             [promesa.core :as p]))
@@ -126,19 +127,25 @@
       (p/promise e)
 
       :else
-      (p/let [result (state/<invoke-db-worker :thread-api/get-blocks graph
-                                              [{:id id :opts opts}])
-              {:keys [block children]} (first result)]
-        (when-not skip-transact?
-          (let [conn (db/get-db graph false)
-                block-and-children (if block (cons block children) children)
-                affected-keys [[:frontend.worker.react/block (:db/id block)]]
-                tx-data (remove (fn [b] (:block.temp/fully-loaded? (db/entity (:db/id b)))) block-and-children)]
-            (when (seq tx-data) (d/transact! conn tx-data))
-            (when-not skip-refresh?
-              (react/refresh-affected-queries! graph affected-keys))))
+      (->
+       (p/let [result (state/<invoke-db-worker :thread-api/get-blocks graph
+                                               [{:id id :opts opts}])
+               {:keys [block children]} (first result)]
+         (when-not skip-transact?
+           (let [conn (db/get-db graph false)
+                 block-and-children (if block (cons block children) children)
+                 affected-keys [[:frontend.worker.react/block (:db/id block)]]
+                 tx-data (->> (remove (fn [b] (:block.temp/fully-loaded? (db/entity (:db/id b)))) block-and-children)
+                              (common-util/fast-remove-nils)
+                              (remove empty?))]
+             (when (seq tx-data) (d/transact! conn tx-data))
+             (when-not skip-refresh?
+               (react/refresh-affected-queries! graph affected-keys))))
 
-        (if children-only? children block)))))
+         (if children-only? children block))
+       (p/catch (fn [error]
+                  (js/console.error error)
+                  (throw (ex-info "get-block error" {:block id-uuid-or-name}))))))))
 
 (defn <get-blocks
   [graph ids* & {:as opts}]

+ 4 - 4
src/main/frontend/handler/db_based/rtc_flows.cljs

@@ -28,8 +28,8 @@
 (def rtc-state-flow
   (m/watch (:rtc/state @state/state)))
 
-(def rtc-state-stream-flow
-  (m/stream rtc-state-flow))
+(def rtc-running-flow
+  (m/eduction (map :rtc-lock) rtc-state-flow))
 
 (def rtc-online-users-flow
   (c.m/throttle
@@ -40,7 +40,7 @@
                       (:rtc-lock m))
              (:online-users m))))
     (dedupe)
-    rtc-state-stream-flow)))
+    rtc-state-flow)))
 
 (def ^:private network-online-change-flow
   (m/stream
@@ -64,7 +64,7 @@ conditions:
   (->> (m/latest
         (fn [rtc-state _ login-user]
           (assoc rtc-state :login-user login-user))
-        (c.m/continue-flow rtc-state-stream-flow)
+        rtc-state-flow
         (c.m/continue-flow network-online-change-flow)
         flows/current-login-user-flow)
        (m/eduction

+ 2 - 1
src/main/frontend/handler/editor.cljs

@@ -3568,10 +3568,11 @@
   [block]
   (let [class-properties (:classes-properties (outliner-property/get-block-classes-properties (db/get-db) (:db/id block)))
         db (db/get-db)
+        attributes (set (remove #{:block/alias} db-property/db-attribute-properties))
         properties (->> (:block.temp/property-keys block)
                         (map (partial entity-plus/entity-memoized db))
                         (concat class-properties)
-                        (remove (fn [e] (db-property/db-attribute-properties (:db/ident e))))
+                        (remove (fn [e] (attributes (:db/ident e))))
                         (remove outliner-property/property-with-other-position?)
                         (remove (fn [e] (:logseq.property/hide? e)))
                         (remove nil?))]

+ 21 - 22
src/main/frontend/modules/instrumentation/sentry.cljs

@@ -1,10 +1,9 @@
 (ns frontend.modules.instrumentation.sentry
-  (:require [frontend.version :refer [version]]
-            [frontend.util :as util]
+  (:require ["@sentry/react" :as Sentry]
             [frontend.config :as config]
-            [medley.core :as medley]
-            ["@sentry/react" :as Sentry]
-            [frontend.mobile.util :as mobile-util]))
+            [frontend.mobile.util :as mobile-util]
+            [frontend.util :as util]
+            [frontend.version :refer [version]]))
 
 (goog-define SENTRY-DSN "")
 
@@ -35,25 +34,25 @@
                               (re-matches #"file://.*?/(app/index|static/index)\.html(.*)" (.. event -request -url))]
                      (set! (.. event -request -url) (str "http://localhost/index.html" query-and-fragment)))
 
-                   (let [*filtered (volatile! [])
-                         ^js values (.. event -exception -values)]
-                     (doseq [[idx value] (medley/indexed values)]
-                       (let [mf (some-> value (.. -mechanism -data -function))]
-                         (when (contains? #{"setInterval"} mf)
-                           (vswap! *filtered conj idx))
+                   ;; (let [*filtered (volatile! [])
+                   ;;       ^js values (.. event -exception -values)]
+                   ;;   (doseq [value (medley/indexed values)]
+                   ;;     ;; (let [mf (some-> value (.. -mechanism -data -function))]
+                   ;;     ;;   (when (contains? #{"setInterval"} mf)
+                   ;;     ;;     (vswap! *filtered conj idx)))
 
-                         (doseq [frame (.. value -stacktrace -frames)]
-                           (when (not-empty (.. frame -filename))
-                             (when-let [[_ filename]
-                                        (re-matches #"file://.*?/app/(js/.*\.js)" (.. frame -filename))]
-                               (set! (.. frame -filename) (str "/static/" filename))
-                               ;; NOTE: No idea of why there's a 2-line offset.
-                               (set! (.. frame -lineno) (- (.. frame -lineno) 2)))))))
+                   ;;     (doseq [frame (.. value -stacktrace -frames)]
+                   ;;       (when (not-empty (.. frame -filename))
+                   ;;         (when-let [[_ filename]
+                   ;;                    (re-matches #"file://.*?/app/(js/.*\.js)" (.. frame -filename))]
+                   ;;           (set! (.. frame -filename) (str "/static/" filename))
+                   ;;             ;; NOTE: No idea of why there's a 2-line offset.
+                   ;;           (set! (.. frame -lineno) (- (.. frame -lineno) 2))))))
 
-                     ;; remove filtered events
-                     (when-let [filtered (seq @*filtered)]
-                       (doseq [k filtered]
-                         (js-delete values k))))
+                   ;;   ;; remove filtered events
+                   ;;   (when-let [filtered (seq @*filtered)]
+                   ;;     (doseq [k filtered]
+                   ;;       (js-delete values k))))
                    (catch :default e
                      (js/console.error e)))
                  event)})

+ 1 - 1
src/main/frontend/version.cljs

@@ -1,3 +1,3 @@
 (ns ^:no-doc frontend.version)
 
-(defonce version "0.10.10")
+(defonce version "0.11.0")

+ 13 - 16
src/main/frontend/worker/db_worker.cljs

@@ -31,7 +31,6 @@
             [frontend.worker.util :as worker-util]
             [goog.object :as gobj]
             [lambdaisland.glogi.console :as glogi-console]
-            [logseq.common.config :as common-config]
             [logseq.common.util :as common-util]
             [logseq.db :as ldb]
             [logseq.db.common.order :as db-order]
@@ -174,7 +173,8 @@
       (worker-util/post-message :capture-error
                                 {:error "db-missing-addresses"
                                  :payload {:missing-addresses missing-addresses}})
-      (prn :error :missing-addresses missing-addresses))))
+      (prn :error :missing-addresses missing-addresses))
+    missing-addresses))
 
 (defn upsert-addr-content!
   "Upsert addr+data-seq. Update sqlite-cli/upsert-addr-content! when making changes"
@@ -356,17 +356,12 @@
                                                                         (when import-type {:import-type import-type}))]
             (d/transact! conn initial-data {:initial-db? true})))
 
-        (when-not db-based?
-          (try
-            (when-not (ldb/page-exists? @conn common-config/views-page-name #{:logseq.class/Page})
-              (ldb/transact! conn (sqlite-create-graph/build-initial-views)))
-            (catch :default _e)))
-
-        (find-missing-addresses db)
-        ;; (gc-kvs-table! db)
-
         (try
+          (when-let [missing-addresses (seq (find-missing-addresses db))]
+            (throw (ex-info "DB missing addresses" {:missing-addresses missing-addresses})))
+
           (db-migrate/migrate conn search-db)
+
           (catch :default _e
             (when db-based?
               (rebuild-db-from-datoms! conn db import-type)
@@ -885,11 +880,13 @@
                                 (= :thread-api/create-or-open-db method-k)
                                 ;; because shared-service operates at the graph level,
                                 ;; creating a new database or switching to another one requires re-initializing the service.
-                                (p/let [method-args (ldb/read-transit-str (last args))
-                                        service (<init-service! (first method-args))]
-                                  ;; wait for service ready
-                                  (get-in service [:status :ready])
-                                  (js-invoke (:proxy service) k args))
+                                (let [[graph opts] (ldb/read-transit-str (last args))]
+                                  (if (:import-type opts)
+                                    (start-db! graph opts)
+                                    (p/let [service (<init-service! graph)]
+                                      (get-in service [:status :ready])
+                                      ;; wait for service ready
+                                      (js-invoke (:proxy service) k args))))
 
                                 (or (contains? #{:thread-api/sync-app-state} method-k)
                                     (nil? service))

+ 3 - 3
src/main/frontend/worker/rtc/core.cljs

@@ -467,13 +467,13 @@
 (def ^:private create-get-state-flow*
   (let [rtc-loop-metadata-flow (m/watch *rtc-loop-metadata)]
     (m/ap
-      (let [{rtc-lock :*rtc-lock
+      (let [{*rtc-lock' :*rtc-lock
              :keys [repo graph-uuid local-graph-schema-version remote-graph-schema-version
                     user-uuid rtc-state-flow *rtc-auto-push? *rtc-remote-profile?
                     *online-users *last-stop-exception]}
             (m/?< rtc-loop-metadata-flow)]
         (try
-          (when (and repo rtc-state-flow *rtc-auto-push? rtc-lock)
+          (when (and repo rtc-state-flow *rtc-auto-push? *rtc-lock')
             (m/?<
              (m/latest
               (fn [rtc-state rtc-auto-push? rtc-remote-profile?
@@ -493,7 +493,7 @@
                  :last-stop-exception-ex-data (some-> *last-stop-exception deref ex-data)})
               rtc-state-flow
               (m/watch *rtc-auto-push?) (m/watch *rtc-remote-profile?)
-              (m/watch rtc-lock) (m/watch *online-users)
+              (m/watch *rtc-lock') (m/watch *online-users)
               (client-op/create-pending-block-ops-count-flow repo)
               (rtc-log-and-state/create-local-t-flow graph-uuid)
               (rtc-log-and-state/create-remote-t-flow graph-uuid))))