浏览代码

Merge branch 'master' into feat/new-auth-ui

charlie 1 周之前
父节点
当前提交
0e82b602ab

+ 1 - 1
.github/workflows/build-ios-release.yml

@@ -25,7 +25,7 @@ jobs:
           ref: ${{ github.event.inputs.git-ref }}
       - uses: maxim-lobanov/setup-xcode@v1
         with:
-          xcode-version: '26.0.0'
+          xcode-version: '26.0.1'
       - name: Show runtimes
         run: |
           xcrun simctl list > /dev/null

+ 1 - 1
deps.edn

@@ -41,7 +41,7 @@
   logseq/shui                           {:local/root "deps/shui"}
   metosin/malli                         {:mvn/version "0.16.1"}
   com.cognitect/transit-cljs            {:mvn/version "0.8.280"}
-  missionary/missionary                 {:mvn/version "b.44"}
+  missionary/missionary                 {:mvn/version "b.46"}
   meander/epsilon                       {:mvn/version "0.0.650"}
 
   io.github.open-spaced-repetition/cljc-fsrs {:git/sha "eeef3520df664e51c3d0ba2031ec2ba071635442"

+ 45 - 2
deps/db/src/logseq/db/frontend/property.cljs

@@ -6,6 +6,7 @@
             [flatland.ordered.map :refer [ordered-map]]
             [logseq.common.defkeywords :refer [defkeywords]]
             [logseq.common.uuid :as common-uuid]
+            [logseq.db.common.order :as db-order]
             [logseq.db.frontend.db-ident :as db-ident]
             [logseq.db.frontend.property.type :as db-property-type]))
 
@@ -715,10 +716,52 @@
   ([property-name user-namespace]
    (db-ident/create-db-ident-from-name user-namespace property-name)))
 
+(defn normalize-sorted-entities-block-order
+  "Return tx-data.
+  Generate appropriate :block/order values for sorted-blocks with :block/order value = nil or duplicated"
+  [sorted-entities]
+  (let [parts (partition-by :block/order sorted-entities)
+        [_ tx-data]
+        (reduce (fn [[start-order tx-data] ents]
+                  (let [n (count ents)]
+                    (if (> n 1)
+                      (let [orders (db-order/gen-n-keys n start-order (:block/order (first ents)))
+                            tx-data* (apply conj tx-data (map
+                                                          (fn [order ent]
+                                                            {:db/id (:db/id ent)
+                                                             :block/order order})
+                                                          orders ents))]
+                        [(last orders) tx-data*])
+                      [(:block/order (first ents)) tx-data])))
+                [nil []] parts)]
+    tx-data))
+
+(defn sort-properties
+  "Sort by :block/order and :block/uuid.
+  - nil is greater than non-nil
+  - When block/order is equal, sort by block/uuid"
+  [prop-entities]
+  (sort
+   (fn [a b]
+     (let [order-a (:block/order a)
+           order-b (:block/order b)]
+       (cond
+         (and (nil? order-a) (nil? order-b))
+         (compare (:block/uuid a) (:block/uuid b))
+
+         (nil? order-a) 1
+         (nil? order-b) -1
+
+         (= order-a order-b)
+         (compare (:block/uuid a) (:block/uuid b))
+
+         :else
+         (compare order-a order-b))))
+   prop-entities))
+
 (defn get-class-ordered-properties
   [class-entity]
-  (->> (:logseq.property.class/properties class-entity)
-       (sort-by :block/order)))
+  (sort-properties (:logseq.property.class/properties class-entity)))
 
 (defn property-created-block?
   "`block` has been created in a property and it's not a closed value."

+ 45 - 0
deps/db/test/logseq/db/frontend/property_test.cljs

@@ -0,0 +1,45 @@
+(ns logseq.db.frontend.property-test
+  (:require [cljs.test :refer [deftest is testing]]
+            [logseq.db.frontend.property :as db-property]))
+
+(deftest sort-properties
+  (let [p1 {:db/id 1, :block/order "a", :block/uuid "uuid-a"}
+        p2 {:db/id 2, :block/order "b", :block/uuid "uuid-b"}
+        p3 {:db/id 3, :block/order nil, :block/uuid "uuid-d"}
+        p4 {:db/id 4, :block/order "b", :block/uuid "uuid-c"}
+        p5 {:db/id 5, :block/order nil, :block/uuid "uuid-e"}]
+    (is (= [p1 p2 p4 p3 p5]
+           (db-property/sort-properties [p3 p1 p5 p2 p4])))))
+
+(deftest normalize-block-order-tx-data-test
+  (testing "Generate appropriate :block/order values for sorted-blocks with :block/order value = nil or duplicated"
+    (let [p1 {:db/id 1, :block/order "a0"}
+          p2 {:db/id 2, :block/order "bbb"}
+          p3 {:db/id 3, :block/order "bbb"}
+          p4 {:db/id 4, :block/order nil}
+          p5 {:db/id 5, :block/order nil}
+          sorted-entities [p1 p2 p3 p4 p5]
+          tx-data (db-property/normalize-sorted-entities-block-order sorted-entities)
+          ;; apply tx-data to entities
+          tx-map (into {} (map (juxt :db/id identity) tx-data))
+          updated-entities (map (fn [ent]
+                                  (if-let [tx (get tx-map (:db/id ent))]
+                                    (merge ent tx)
+                                    ent))
+                                sorted-entities)
+          ;; sort again and test
+          final-sorted (db-property/sort-properties updated-entities)]
+      (is (= 5 (count final-sorted)))
+      ;; Check that all orders are now strings
+      (is (every? string? (map :block/order final-sorted)))
+      ;; Check that all orders are unique
+      (is (= 5 (count (set (map :block/order final-sorted)))))
+      ;; Check that the final list is sorted correctly by the new orders
+      (is (= final-sorted (sort-by :block/order final-sorted)))))
+
+  (testing "No changes needed for already valid orders"
+    (let [p1 {:db/id 1, :block/order "b00"}
+          p2 {:db/id 2, :block/order "b01"}
+          sorted-entities [p1 p2]
+          tx-data (db-property/normalize-sorted-entities-block-order sorted-entities)]
+      (is (empty? tx-data)))))

+ 87 - 10
scripts/install-linux.sh

@@ -38,6 +38,11 @@ This script installs Logseq on Linux systems.
 
 USAGE:
     $0 [VERSION] [OPTIONS]
+    $0 uninstall
+
+COMMANDS:
+    install (default)   Install Logseq
+    uninstall           Removes Logseq installation (keeps user data)
 
 ARGUMENTS:
     VERSION    Version to install (e.g., "0.10.14"). Default: latest
@@ -59,6 +64,70 @@ For more information, visit: https://github.com/logseq/logseq
 HELP
 }
 
+uninstall() {
+    log_info "Searching for Logseq installations..."
+    
+    local user_removed=false
+    local system_removed=false
+    
+    # User installation paths
+    local -a user_paths=(
+        "$HOME/.local/share/logseq"
+        "$HOME/.local/bin/logseq"
+        "$HOME/.local/share/applications/logseq.desktop"
+        "$HOME/.local/share/icons/hicolor/512x512/apps/logseq.png"
+    )
+    
+    # System installation paths
+    local -a system_paths=(
+        "/opt/logseq"
+        "/usr/local/bin/logseq"
+        "/usr/share/applications/logseq.desktop"
+        "/usr/share/icons/hicolor/512x512/apps/logseq.png"
+    )
+    
+    # Remove user installation
+    log_info "Checking user installation..."
+    for path in "${user_paths[@]}"; do
+        if [[ -e "$path" ]] || [[ -L "$path" ]]; then
+            log_info "Removing: $path"
+            rm -rf "$path"
+            user_removed=true
+        fi
+    done
+    
+    # Remove system installation
+    log_info "Checking system-wide installation..."
+    for path in "${system_paths[@]}"; do
+        if [[ -e "$path" ]] || [[ -L "$path" ]]; then
+            if [[ "$EUID" -ne 0 ]]; then
+                log_warn "System-wide installation found at $path, but root privileges required"
+                log_warn "Run with sudo to uninstall system-wide installation"
+            else
+                log_info "Removing: $path"
+                rm -rf "$path"
+                system_removed=true
+            fi
+        fi
+    done
+    
+    # Update desktop databases
+    if [[ "$user_removed" == true ]] && [[ -d "$HOME/.local/share/applications" ]]; then
+        update-desktop-database "$HOME/.local/share/applications" 2>/dev/null || true
+    fi
+    
+    if [[ "$system_removed" == true ]]; then
+        update-desktop-database /usr/share/applications 2>/dev/null || true
+    fi
+    
+    # Final status message
+    if [[ "$user_removed" == true ]] || [[ "$system_removed" == true ]]; then
+        log_info "Logseq has been uninstalled successfully!"
+    else
+        log_warn "No Logseq installation found in default locations"
+    fi
+}
+
 # Parse command line arguments
 VERSION="$DEFAULT_VERSION"
 USER_INSTALL=false
@@ -87,6 +156,10 @@ while [[ $# -gt 0 ]]; do
             VERBOSE=true
             shift
             ;;
+        uninstall)
+            uninstall
+            exit 0
+            ;;
         -*)
             log_error "Unknown option: $1"
             show_help
@@ -183,7 +256,7 @@ else
 fi
 
 # Fix sandbox permissions
-if [[ -f "$INSTALL_DIR/chrome-sandbox" ]]; then
+if [[ "$USER_INSTALL" == false && -f "$INSTALL_DIR/chrome-sandbox" ]]; then
     log_info "Setting sandbox permissions..."
     chown root:root "$INSTALL_DIR/chrome-sandbox"
     chmod 4755 "$INSTALL_DIR/chrome-sandbox"
@@ -192,12 +265,19 @@ fi
 # Desktop integration
 if [[ "$SKIP_DESKTOP" == false ]]; then
     log_info "Creating desktop integration..."
-    
+
     DESKTOP_FILE="/usr/share/applications/logseq.desktop"
     if [[ "$USER_INSTALL" == true ]]; then
         mkdir -p ~/.local/share/applications/
         DESKTOP_FILE="$HOME/.local/share/applications/logseq.desktop"
     fi
+
+    # Copy icon to standard location
+    ICON_DIR="/usr/share/icons/hicolor/512x512/apps/"
+    if [[ "$USER_INSTALL" == true ]]; then
+        ICON_DIR="$HOME/.local/share/icons/hicolor/512x512/apps/"
+        mkdir -p "$ICON_DIR"
+    fi
     
     # Create desktop file
     cat > "$DESKTOP_FILE" << DESKTOP_EOF
@@ -205,8 +285,8 @@ if [[ "$SKIP_DESKTOP" == false ]]; then
 Version=1.0
 Name=Logseq
 Comment=Logseq - A privacy-first, open-source platform for knowledge management and collaboration
-Exec=$INSTALL_DIR/Logseq %U
-Icon=$INSTALL_DIR/resources/app.asar.unpacked/dist/icon.png
+Exec=$INSTALL_DIR/Logseq $([ "$USER_INSTALL" = true ] && echo "--no-sandbox") %U
+Icon=$ICON_DIR/logseq.png
 Terminal=false
 Type=Application
 Categories=Office;Productivity;Utility;TextEditor;
@@ -217,13 +297,7 @@ DESKTOP_EOF
     # Make desktop file executable
     chmod +x "$DESKTOP_FILE"
     
-    # Copy icon to standard location
     if [[ -f "$INSTALL_DIR/resources/app.asar.unpacked/dist/icon.png" ]]; then
-        ICON_DIR="/usr/share/icons/hicolor/512x512/apps/"
-        if [[ "$USER_INSTALL" == true ]]; then
-            ICON_DIR="$HOME/.local/share/icons/hicolor/512x512/apps/"
-            mkdir -p "$ICON_DIR"
-        fi
         
         cp "$INSTALL_DIR/resources/app.asar.unpacked/dist/icon.png" "$ICON_DIR/logseq.png"
         
@@ -232,6 +306,9 @@ DESKTOP_EOF
             sed -i 's|Icon=$INSTALL_DIR/resources/app.asar.unpacked/dist/icon.png|Icon=logseq|' "$DESKTOP_FILE"
         fi
     fi
+    if [[ "$USER_INSTALL" == true && -f "$INSTALL_DIR/resources/app/icon.png" ]]; then
+        cp "$INSTALL_DIR/resources/app/icon.png" "$ICON_DIR/logseq.png"
+    fi
     
     # Update desktop database
     if [[ "$USER_INSTALL" == false ]]; then

+ 5 - 5
src/main/frontend/components/block.cljs

@@ -2303,7 +2303,7 @@
   [:div.relative
    [:div.dnd-separator.absolute
     {:style {:left (cond-> (if (= move-to :nested) 48 20)
-                     (util/capacitor-new?)
+                     (util/capacitor?)
                      (- 20))
              :top 0
              :width "100%"
@@ -3002,7 +3002,7 @@
                                             journal-title?
                                             (do
                                               (.preventDefault e)
-                                              (when-not (util/capacitor-new?)
+                                              (when-not (util/capacitor?)
                                                 (route-handler/redirect-to-page! (:block/uuid block))))
 
                                             (ldb/journal? block)
@@ -3349,7 +3349,7 @@
                           (and top? (<= (js/Math.abs (- cursor-top element-top)) 16))
                           :top
 
-                          (> x-offset (if (util/capacitor-new?) 100 50))
+                          (> x-offset (if (util/capacitor?) 100 50))
                           :nested
 
                           :else
@@ -3392,7 +3392,7 @@
         ;; dnd block moving in current Logseq instance
         (do
           (dnd/move-blocks event blocks target-block original-block @*move-to')
-          (when (util/capacitor-new?)
+          (when (util/capacitor?)
             (state/set-state! :mobile/show-action-bar? false)
             (state/clear-selection!)))
         ;; handle DataTransfer
@@ -3675,7 +3675,7 @@
        :on-touch-cancel (fn [e]
                           (block-handler/on-touch-cancel e))}
 
-       (and (util/capacitor-new?) (not (ldb/page? block)))
+       (and (util/capacitor?) (not (ldb/page? block)))
        (assoc
         :draggable true
         :on-drag-start

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

@@ -698,7 +698,7 @@
             (when (not tag-dialog?)
               [:div.ls-page-blocks
                {:style {:margin-left (if (or whiteboard? (util/mobile?)) 0 -20)}
-                :class (when-not (or sidebar? (util/capacitor-new?))
+                :class (when-not (or sidebar? (util/capacitor?))
                          "mt-4")}
                (page-blocks-cp page (merge option {:sidebar? sidebar?
                                                    :container-id (:container-id state)

+ 20 - 16
src/main/frontend/components/property.cljs

@@ -506,7 +506,7 @@
                 (pv/property-value block property opts))]]])]))))
 
 (rum/defc ordered-properties
-  [block properties* opts]
+  [block properties* sorted-property-entities opts]
   (let [[properties set-properties!] (hooks/use-state properties*)
         [properties-order set-properties-order!] (hooks/use-state (mapv first properties))
         m (zipmap (map first properties*) (map second properties*))
@@ -530,15 +530,21 @@
                {:sort-by-inner-element? true
                 :on-drag-end (fn [properties-order {:keys [active-id over-id direction]}]
                                (set-properties-order! properties-order)
-                               (let [move-down? (= direction :down)
-                                     over (db/entity (keyword over-id))
-                                     active (db/entity (keyword active-id))
-                                     over-order (:block/order over)
-                                     new-order (if move-down?
-                                                 (let [next-order (db-order/get-next-order (db/get-db) nil (:db/id over))]
-                                                   (db-order/gen-key over-order next-order))
-                                                 (let [prev-order (db-order/get-prev-order (db/get-db) nil (:db/id over))]
-                                                   (db-order/gen-key prev-order over-order)))]
+                               (p/let [;; Before reordering properties,
+                                       ;; check if the :block/order of these properties is reasonable.
+                                       normalize-tx-data (db-property/normalize-sorted-entities-block-order
+                                                          sorted-property-entities)
+                                       _ (when (seq normalize-tx-data)
+                                           (db/transact! (state/get-current-repo) normalize-tx-data))
+                                       move-down? (= direction :down)
+                                       over (db/entity (keyword over-id))
+                                       active (db/entity (keyword active-id))
+                                       over-order (:block/order over)
+                                       new-order (if move-down?
+                                                   (let [next-order (db-order/get-next-order (db/get-db) nil (:db/id over))]
+                                                     (db-order/gen-key over-order next-order))
+                                                   (let [prev-order (db-order/get-prev-order (db/get-db) nil (:db/id over))]
+                                                     (db-order/gen-key prev-order over-order)))]
                                  (db/transact! (state/get-current-repo)
                                                [{:db/id (:db/id active)
                                                  :block/order new-order}
@@ -549,12 +555,10 @@
 (rum/defc properties-section < rum/static
   [block properties opts]
   (when (seq properties)
-      ;; Sort properties by :block/order
-    (let [properties' (sort-by (fn [[k _v]]
-                                 (if (= k :logseq.property.class/properties)
-                                   "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
-                                   (:block/order (db/entity k)))) properties)]
-      (ordered-properties block properties' opts))))
+    (let [sorted-prop-entities (db-property/sort-properties (map (comp db/entity first) properties))
+          prop-kv-map (reduce (fn [m [p v]] (assoc m p v)) {} properties)
+          properties' (keep (fn [ent] (find prop-kv-map (:db/ident ent))) sorted-prop-entities)]
+      (ordered-properties block properties' sorted-prop-entities opts))))
 
 (rum/defc hidden-properties-cp
   [block hidden-properties {:keys [root-block? sidebar-properties?] :as opts}]

+ 4 - 4
src/main/frontend/components/repo.cljs

@@ -84,7 +84,7 @@
                                      (state/pub-event! [:rtc/download-remote-graph GraphName GraphUUID GraphSchemaVersion])
 
                                      :else
-                                     (when-not (util/capacitor-new?)
+                                     (when-not (util/capacitor?)
                                        (state/pub-event! [:graph/pull-down-remote-graph repo]))))))]
       (when-let [time (some-> (or last-seen-at created-at) (safe-locale-date))]
         [:small.text-muted-foreground (str "Last opened at: " time)])]
@@ -207,7 +207,7 @@
                           (config/db-based-graph? (:url item)))))
         {remote-graphs true local-graphs false} (group-by (comp boolean :remote?) repos)]
     [:div#graphs
-     (when-not (util/capacitor-new?)
+     (when-not (util/capacitor?)
        [:h1.title (t :graph/all-graphs)])
 
      [:div.pl-1.content.mt-3
@@ -217,7 +217,7 @@
        (when (seq local-graphs)
          (repos-inner local-graphs))
 
-       (when-not (util/capacitor-new?)
+       (when-not (util/capacitor?)
          [:div.flex.flex-row.my-4
           (if util/web-platform?
             [:div.mr-8
@@ -245,7 +245,7 @@
             :background "gray"
             :disabled remotes-loading?
             :on-click (fn []
-                        (when-not (util/capacitor-new?)
+                        (when-not (util/capacitor?)
                           (file-sync/load-session-graphs))
                         (rtc-handler/<get-remote-graphs)))]]
          (repos-inner remote-graphs)])]]))

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

@@ -932,7 +932,7 @@
           block-parent (get uuid->dom-block (:block/uuid block))
           sibling-block (when block-parent (util/get-prev-block-non-collapsed-non-embed block-parent))
           blocks' (block-handler/get-top-level-blocks blocks)
-          mobile? (util/capacitor-new?)]
+          mobile? (util/capacitor?)]
       (p/do!
        (when (and sibling-block (not mobile?))
          (let [{:keys [edit-block-f]} (move-to-prev-block repo sibling-block
@@ -1056,7 +1056,7 @@
                                       (assoc :db/id (:db/id b)))))))]
         (common-handler/copy-to-clipboard-without-id-property! repo (get block :block/format :markdown) content (when html? html) copied-blocks))
       (state/set-block-op-type! :copy)
-      (when-not (util/capacitor-new?)
+      (when-not (util/capacitor?)
         (notification/show! "Copied!" :success)))))
 
 (defn copy-block-refs

+ 1 - 1
src/main/frontend/handler/events/ui.cljs

@@ -90,7 +90,7 @@
 
 (defmethod events/handle :redirect-to-home [_]
   (page-handler/create-today-journal!)
-  (when (util/capacitor-new?)
+  (when (util/capacitor?)
     (mobile-state/redirect-to-tab! "home")))
 
 (defmethod events/handle :page/show-delete-dialog [[_ selected-rows ok-handler]]

+ 1 - 1
src/main/frontend/handler/worker.cljs

@@ -56,7 +56,7 @@
 
 (defmethod handle :record-worker-client-id [_ _worker data]
   (when-let [client-id (:client-id data)]
-    (reset! state/*db-worker-client-id client-id)))
+    (state/set-db-worker-client-id! client-id)))
 
 (defmethod handle :capture-error [_ _worker data]
   (state/pub-event! [:capture-error data]))

+ 1 - 1
src/main/frontend/mobile/haptics.cljs

@@ -7,7 +7,7 @@
   ([]
    (haptics :light))
   ([impact-style]
-   (when (util/capacitor-new?)
+   (when (util/capacitor?)
      (let [style (cond
                    (= impact-style :light)
                    {:style (.-Light ImpactStyle)}

+ 49 - 37
src/main/frontend/persist_db/browser.cljs

@@ -101,46 +101,58 @@
     (set! (.-pfs js/window) pfs)
     (set! (.-workerThread js/window) worker-thread)))
 
+(defn- reload-app-if-old-db-worker-exists
+  []
+  (when (util/capacitor?)
+    (when-let [client-id @state/*db-worker-client-id]
+      (js/navigator.locks.request client-id #js {:mode "exclusive"
+                                                 :ifAvailable true}
+                                  (fn [lock]
+                                    (when-not lock
+                                      (js/window.location.reload)))))))
+
 (defn start-db-worker!
   []
   (when-not util/node-test?
-    (let [worker-url (if config/publishing? "static/js/db-worker.js" "js/db-worker.js")
-          worker (js/Worker. (str worker-url "?electron=" (util/electron?) "&publishing=" config/publishing?))
-          _ (set-worker-fs worker)
-          wrapped-worker* (Comlink/wrap worker)
-          wrapped-worker (fn [qkw direct-pass? & args]
-                           (p/let [result (.remoteInvoke ^js wrapped-worker*
-                                                         (str (namespace qkw) "/" (name qkw))
-                                                         direct-pass?
-                                                         (cond
-                                                           (= qkw :thread-api/set-infer-worker-proxy)
-                                                           (first args)
-                                                           direct-pass?
-                                                           (into-array args)
-                                                           :else
-                                                           (ldb/write-transit-str args)))]
-                             (if direct-pass?
-                               result
-                               (ldb/read-transit-str result))))
-          t1 (util/time-ms)]
-      (Comlink/expose #js{"remoteInvoke" thread-api/remote-function} worker)
-      (worker-handler/handle-message! worker wrapped-worker)
-      (reset! state/*db-worker wrapped-worker)
-      (-> (p/let [_ (state/<invoke-db-worker :thread-api/init config/RTC-WS-URL)
-                  _ (sync-app-state!)
-                  _ (log/debug "init worker spent" (str (- (util/time-ms) t1) "ms"))
-                  _ (sync-ui-state!)
-                  _ (ask-persist-permission!)
-                  _ (state/pub-event! [:graph/sync-context])]
-            (ldb/register-transact-fn!
-             (fn worker-transact!
-               [repo tx-data tx-meta]
-               (db-transact/transact transact!
-                                     (if (string? repo) repo (state/get-current-repo))
-                                     tx-data
-                                     (assoc tx-meta :client-id (:client-id @state/state))))))
-          (p/catch (fn [error]
-                     (log/error :init-sqlite-wasm-error ["Can't init SQLite wasm" error])))))))
+    (p/do!
+     (reload-app-if-old-db-worker-exists)
+     (let [worker-url (if config/publishing? "static/js/db-worker.js" "js/db-worker.js")
+           worker (js/Worker. (str worker-url "?electron=" (util/electron?) "&publishing=" config/publishing?))
+           _ (set-worker-fs worker)
+           wrapped-worker* (Comlink/wrap worker)
+           wrapped-worker (fn [qkw direct-pass? & args]
+                            (p/let [result (.remoteInvoke ^js wrapped-worker*
+                                                          (str (namespace qkw) "/" (name qkw))
+                                                          direct-pass?
+                                                          (cond
+                                                            (= qkw :thread-api/set-infer-worker-proxy)
+                                                            (first args)
+                                                            direct-pass?
+                                                            (into-array args)
+                                                            :else
+                                                            (ldb/write-transit-str args)))]
+                              (if direct-pass?
+                                result
+                                (ldb/read-transit-str result))))
+           t1 (util/time-ms)]
+       (Comlink/expose #js{"remoteInvoke" thread-api/remote-function} worker)
+       (worker-handler/handle-message! worker wrapped-worker)
+       (reset! state/*db-worker wrapped-worker)
+       (-> (p/let [_ (state/<invoke-db-worker :thread-api/init config/RTC-WS-URL)
+                   _ (sync-app-state!)
+                   _ (log/debug "init worker spent" (str (- (util/time-ms) t1) "ms"))
+                   _ (sync-ui-state!)
+                   _ (ask-persist-permission!)
+                   _ (state/pub-event! [:graph/sync-context])]
+             (ldb/register-transact-fn!
+              (fn worker-transact!
+                [repo tx-data tx-meta]
+                (db-transact/transact transact!
+                                      (if (string? repo) repo (state/get-current-repo))
+                                      tx-data
+                                      (assoc tx-meta :client-id (:client-id @state/state))))))
+           (p/catch (fn [error]
+                      (log/error :init-sqlite-wasm-error ["Can't init SQLite wasm" error]))))))))
 
 (defn <check-webgpu-available?
   []

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

@@ -32,7 +32,7 @@
 (defonce *profile-state (volatile! {}))
 
 (defonce *db-worker (atom nil))
-(defonce *db-worker-client-id (atom nil))
+(defonce *db-worker-client-id (atom (storage/get :db-worker-client-id)))
 (defonce *editor-info (atom nil))
 (defonce app-ready-promise (p/deferred))
 
@@ -2360,3 +2360,9 @@ Similar to re-frame subscriptions"
   [days]
   (reset! (:ui/highlight-recent-days @state) days)
   (storage/set :ui/highlight-recent-days days))
+
+(defn set-db-worker-client-id!
+  [new-id]
+  (when new-id
+    (reset! *db-worker-client-id new-id)
+    (storage/set :db-worker-client-id new-id)))

+ 4 - 4
src/main/frontend/util.cljc

@@ -77,7 +77,7 @@
        (when-not node-test?
          (safe-re-find #"Mobi" js/navigator.userAgent)))
      (def mobile? (memoize mobile*?))
-     (def capacitor-new? (memoize #(and js/window (gobj/get js/window "isCapacitorNew"))))))
+     (def capacitor? (memoize #(and js/window (gobj/get js/window "isCapacitorNew"))))))
 
 #?(:cljs
    (extend-protocol IPrintWithWriter
@@ -103,11 +103,11 @@
 
 #?(:cljs (defn app-scroll-container-node
            ([]
-            (if (capacitor-new?)
+            (if (capacitor?)
               (mobile-page-scroll)
               (gdom/getElement "main-content-container")))
            ([el]
-            (if (capacitor-new?)
+            (if (capacitor?)
               (mobile-page-scroll el)
               (if (some-> el (.closest "#main-content-container"))
                 (app-scroll-container-node)
@@ -1491,7 +1491,7 @@ Arg *stop: atom, reset to true to stop the loop"
      ([schedule?]
       (when (mobile?)
         (let [f #(when-let [node (or (get-keep-keyboard-input-el "in-modal")
-                                  (get-keep-keyboard-input-el))]
+                                     (get-keep-keyboard-input-el))]
                    (.focus node))]
           (if schedule? (schedule f) (f)))))))
 

+ 2 - 2
src/main/frontend/worker/db_worker.cljs

@@ -83,8 +83,8 @@
   (when-not @*sqlite
     (p/let [href (.. js/location -href)
             publishing? (string/includes? href "publishing=true")
-            sqlite (sqlite3InitModule (clj->js {:print js/console.log
-                                                :printErr js/console.error}))]
+            sqlite (sqlite3InitModule (clj->js {:print #(log/info :init-sqlite-module! %)
+                                                :printErr #(log/error :init-sqlite-module! %)}))]
       (reset! *publishing? publishing?)
       (reset! *sqlite sqlite)
       nil)))

+ 7 - 0
src/main/frontend/worker/rtc/ws.cljs

@@ -202,3 +202,10 @@
     (let [req-id (str (random-uuid))
           message (assoc message :req-id req-id)]
       (m/? (send&recv* mws message :timeout-ms timeout-ms)))))
+
+(comment
+  (defn- inject-fake-message-to-recv
+    "Debug fn.
+  use `queryObjects(WebSocket)` to fetch all websocket objs under db-worker.js context"
+    [ws fake-message-to-recv]
+    (.dispatchEvent ws (js/MessageEvent. "message" #js {:data fake-message-to-recv}))))

+ 2 - 1
src/main/mobile/core.cljs

@@ -56,7 +56,8 @@
                        (mobile-state/close-left-sidebar!))
                      (when (state/get-edit-block)
                        (state/clear-edit!))
-
+                     (when (mobile-state/quick-add-open?)
+                       (mobile-state/close-popup!))
                      (mobile-state/open-block-modal! entity)))))))
 
          :graphs