Browse Source

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

charlie 6 months ago
parent
commit
573f2ce145

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

@@ -330,9 +330,7 @@
                       views
                       all-files
                       pages-datoms))]
-    (prn :debug "db-graph?" db-graph?)
-    (prn :debug "block/journal-day schema" (str (:block/journal-day (:schema db))))
-    {:schema (assoc schema :block/journal-day {:db/index true})
+    {:schema schema
      :initial-data data}))
 
 (defn restore-initial-data

+ 2 - 1
deps/db/src/logseq/db/file_based/schema.cljs

@@ -45,7 +45,8 @@
 
    ;; for pages
    :block/alias {:db/valueType :db.type/ref
-                 :db/cardinality :db.cardinality/many}
+                 :db/cardinality :db.cardinality/many
+                 :db/index true}
 
    ;; todo keywords, e.g. "TODO", "DOING", "DONE"
    :block/marker {}

+ 20 - 16
src/main/frontend/commands.cljs

@@ -241,19 +241,16 @@
                 (if db-based?
                   (db-based-statuses)
                   (file-based-statuses))
-                (mapv (fn [m]
-                        (let [command (if db-based?
-                                        [:div.flex.flex-row.items-center.gap-2 m [:div.text-xs.opacity-50 "Status"]]
-                                        m)
-                              icon (if db-based?
-                                     (case m
+                (mapv (fn [command]
+                        (let [icon (if db-based?
+                                     (case command
                                        "Canceled" "Cancelled"
                                        "Doing" "InProgress50"
-                                       m)
+                                       command)
                                      "square-asterisk")]
-                          [command (->marker m) (str "Set status to " m) icon]))))]
+                          [command (->marker command) (str "Set status to " command) icon]))))]
     (when (seq result)
-      (map (fn [v] (conj v "TASK")) result))))
+      (map (fn [v] (conj v "TASK STATUS")) result))))
 
 (defn file-based-priorities
   []
@@ -273,17 +270,17 @@
                   (db-based-priorities)
                   (file-based-priorities))
                 (mapv (fn [item]
-                        (let [command (if db-based?
-                                        [:div.flex.flex-row.items-center.gap-2 item [:div.text-xs.opacity-50 "Priority"]]
-                                        item)]
-                          [command (->priority item) (str "Set priority to " item)
+                        (let [command item]
+                          [command
+                           (->priority item)
+                           (str "Set priority to " item)
                            (if db-based?
                              (str "priorityLvl" item)
                              (str "circle-letter-" (util/safe-lower-case item)))])))
                 (with-no-priority)
                 (vec))]
     (when (seq result)
-      (map (fn [v] (conj v "PRIORITY")) result))))
+      (map (fn [v] (into v ["PRIORITY"])) result))))
 
 ;; Credits to roamresearch.com
 
@@ -297,8 +294,9 @@
   []
   (mapv (fn [level]
           (let [heading (str "Heading " level)]
-            [heading (->heading level) heading (str "h-" level)])) (range 1 7)))
+            [heading (->heading level) heading (str "h-" level) "Heading"])) (range 1 7)))
 
+(defonce *latest-matched-command (atom ""))
 (defonce *matched-commands (atom nil))
 (defonce *initial-commands (atom nil))
 
@@ -474,12 +472,18 @@
 (defn init-commands!
   [get-page-ref-text]
   (let [commands (commands-map get-page-ref-text)]
+    (reset! *latest-matched-command "")
     (reset! *initial-commands commands)
     (reset! *matched-commands commands)))
 
+(defn set-matched-commands!
+  [command matched-commands]
+  (reset! *latest-matched-command command)
+  (reset! *matched-commands matched-commands))
+
 (defn reinit-matched-commands!
   []
-  (reset! *matched-commands @*initial-commands))
+  (set-matched-commands! "" @*initial-commands))
 
 (defn restore-state
   []

+ 3 - 2
src/main/frontend/components/block.cljs

@@ -1068,7 +1068,7 @@
         (contains? config/video-formats asset-type))))
 
 (declare block-positioned-properties)
-(rum/defc page-reference < rum/reactive
+(rum/defc page-reference < rum/reactive db-mixins/query
   "Component for page reference"
   [html-export? uuid-or-title* {:keys [nested-link? show-brackets? id] :as config} label]
   (when uuid-or-title*
@@ -1077,7 +1077,8 @@
                           uuid-or-title*)
           show-brackets? (if (some? show-brackets?) show-brackets? (state/show-brackets?))
           contents-page? (= "contents" (string/lower-case (str id)))
-          block (db/get-page uuid-or-title)
+          block* (db/get-page uuid-or-title)
+          block (or (some-> (:db/id block*) db/sub-block) block*)
           config' (assoc config
                          :label (mldoc/plain->text label)
                          :contents-page? contents-page?

+ 54 - 50
src/main/frontend/components/editor.cljs

@@ -38,6 +38,8 @@
             [react-draggable]
             [rum.core :as rum]))
 
+(defonce no-matched-commands [["No matched commands" [[:editor/move-cursor-to-end]]]])
+
 (defn filter-commands
   [page? commands]
   (if page?
@@ -45,7 +47,7 @@
               (or
                (= "Add new property" (first item))
                (when (= (count item) 5)
-                 (contains? #{"TASK" "PRIORITY"} (last item))))) commands)
+                 (contains? #{"TASK STATUS" "PRIORITY"} (last item))))) commands)
     commands))
 
 (rum/defcs commands < rum/reactive
@@ -56,57 +58,59 @@
         _ (when (state/get-editor-action)
             (reset! *matched matched'))
         page? (db/page? (db/entity (:db/id (state/get-edit-block))))
-        matched (filter-commands page? @*matched)]
+        matched (or (filter-commands page? @*matched) no-matched-commands)
+        filtered? (not= matched @commands/*initial-commands)]
     (ui/auto-complete
      matched
-     {:get-group-name
-      (fn [item]
-        (when (= (count item) 5) (last item)))
-
-      :item-render
-      (fn [item]
-        (let [command-name (first item)
-              command-doc (get item 2)
-              plugin-id (get-in item [1 1 1 :pid])
-              doc (when (state/show-command-doc?) command-doc)
-              options (some-> item (get 3))
-              icon-name (some-> (if (map? options) (:icon options) options) (name))
-              command-name (if icon-name
-                             [:span.flex.items-center.gap-1
-                              (shui/tabler-icon icon-name)
-                              [:strong.font-normal command-name]]
-                             command-name)]
-          (cond
-            (or plugin-id (vector? doc))
-            [:div.has-help
-             {:title plugin-id}
-             command-name
-             (when doc (ui/tooltip [:small (svg/help-circle)] doc))]
-
-            (string? doc)
-            [:div {:title doc}
-             command-name]
-
-            :else
-            [:div command-name])))
-
-      :on-chosen
-      (fn [chosen-item]
-        (let [command (first chosen-item)]
-          (reset! commands/*current-command command)
-          (let [command-steps (get (into {} matched) command)
-                restore-slash? (or
-                                (contains? #{"Today" "Yesterday" "Tomorrow" "Current time"} command)
-                                (and
-                                 (not (fn? command-steps))
-                                 (not (contains? (set (map first command-steps)) :editor/input))
-                                 (not (contains? #{"Date picker" "Template" "Deadline" "Scheduled" "Upload an image"} command))))]
-            (editor-handler/insert-command! id command-steps
-                                            format
-                                            {:restore? restore-slash?
-                                             :command command}))))
-      :class
-      "cp__commands-slash"})))
+     (cond->
+      {:item-render
+       (fn [item]
+         (let [command-name (first item)
+               command-doc (get item 2)
+               plugin-id (get-in item [1 1 1 :pid])
+               doc (when (state/show-command-doc?) command-doc)
+               options (some-> item (get 3))
+               icon-name (some-> (if (map? options) (:icon options) options) (name))
+               command-name (if icon-name
+                              [:span.flex.items-center.gap-1
+                               (shui/tabler-icon icon-name)
+                               [:strong.font-normal command-name]]
+                              command-name)]
+           (cond
+             (or plugin-id (vector? doc))
+             [:div.has-help
+              {:title plugin-id}
+              command-name
+              (when doc (ui/tooltip [:small (svg/help-circle)] doc))]
+
+             (string? doc)
+             [:div {:title doc}
+              command-name]
+
+             :else
+             [:div command-name])))
+
+       :on-chosen
+       (fn [chosen-item]
+         (let [command (first chosen-item)]
+           (reset! commands/*current-command command)
+           (let [command-steps (get (into {} matched) command)
+                 restore-slash? (or
+                                 (contains? #{"Today" "Yesterday" "Tomorrow" "Current time"} command)
+                                 (and
+                                  (not (fn? command-steps))
+                                  (not (contains? (set (map first command-steps)) :editor/input))
+                                  (not (contains? #{"Date picker" "Template" "Deadline" "Scheduled" "Upload an image"} command))))]
+             (editor-handler/insert-command! id command-steps
+                                             format
+                                             {:restore? restore-slash?
+                                              :command command}))))
+       :class
+       "cp__commands-slash"}
+       (not filtered?)
+       (assoc :get-group-name
+              (fn [item]
+                (when (= (count item) 5) (last item))))))))
 
 (defn- page-on-chosen-handler
   [embed? input id q pos format]

+ 18 - 13
src/main/frontend/handler/editor.cljs

@@ -818,7 +818,7 @@
                     concat-prev-block?
                     (let [children (:block/_parent (db/entity (:db/id block)))
                           db-based? (config/db-based-graph? repo)
-                          prev-block-is-not-parent? (not= (:block/uuid (:block/parent block)) (:block/uuid prev-block))
+                          prev-block-is-not-parent? (empty? (:block/_parent prev-block))
                           delete-prev-block? (and db-based?
                                                   prev-block-is-not-parent?
                                                   (empty? (:block/tags block))
@@ -1773,23 +1773,25 @@
   [property q]
   (search/property-value-search property q))
 
-(defn get-matched-commands
+(defn get-last-command
   [input]
   (try
     (let [edit-content (or (gobj/get input "value") "")
           pos (cursor/pos input)
           last-slash-caret-pos (:pos (:pos (state/get-editor-action-data)))
           last-command (and last-slash-caret-pos (subs edit-content last-slash-caret-pos pos))]
-      (when (> pos 0)
-        (or
-         (and (= commands/command-trigger (util/nth-safe edit-content (dec pos)))
-              @commands/*initial-commands)
-         (and last-command
-              (commands/get-matched-commands last-command)))))
+      (when (> pos 0) last-command))
     (catch :default e
       (js/console.error e)
       nil)))
 
+(defn get-matched-commands
+  [command]
+  (condp = command
+    nil nil
+    "" @commands/*initial-commands
+    (commands/get-matched-commands command)))
+
 (defn auto-complete?
   []
   (or @*asset-uploading?
@@ -1929,9 +1931,9 @@
 (defn resize-image!
   [config block-id metadata full_text size]
   (let [asset (:asset-block config)]
-    (if (and asset (config/db-based-graph?))
+    (if (config/db-based-graph?)
       (property-handler/set-block-property! (state/get-current-repo)
-                                            (:db/id asset)
+                                            (if asset (:db/id asset) block-id)
                                             :logseq.property.asset/resize-metadata
                                             size)
       (let [new-meta (merge metadata size)
@@ -3206,10 +3208,13 @@
           (and (= :commands (state/get-editor-action)) (not= k commands/command-trigger))
           (if (= commands/command-trigger (second (re-find #"(\S+)\s+$" value)))
             (state/clear-editor-action!)
-            (let [matched-commands (get-matched-commands input)]
+            (let [command (get-last-command input)
+                  matched-commands (get-matched-commands command)]
               (if (seq matched-commands)
-                (reset! commands/*matched-commands matched-commands)
-                (state/clear-editor-action!))))
+                (commands/set-matched-commands! command matched-commands)
+                (if (> (- (count command) (count @commands/*latest-matched-command)) 2)
+                  (state/clear-editor-action!)
+                  (reset! commands/*matched-commands nil)))))
 
           :else
           (default-case-for-keyup-handler input current-pos k code is-processed?))

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

@@ -1,7 +1,10 @@
 (ns frontend.handler.events.ui
   "UI events"
-  (:require [frontend.components.block :as block]
+  (:require [clojure.core.async :as async]
+            [clojure.core.async.interop :refer [p->c]]
+            [frontend.components.block :as block]
             [frontend.components.cmdk.core :as cmdk]
+            [frontend.components.file-sync :as file-sync]
             [frontend.components.page :as component-page]
             [frontend.components.plugins :as plugin]
             [frontend.components.property.dialog :as property-dialog]
@@ -20,6 +23,7 @@
             [frontend.fs.capacitor-fs :as capacitor-fs]
             [frontend.fs.nfs :as nfs]
             [frontend.fs.sync :as sync]
+            [frontend.handler.db-based.rtc :as rtc-handler]
             [frontend.handler.editor :as editor-handler]
             [frontend.handler.events :as events]
             [frontend.handler.file-based.nfs :as nfs-handler]
@@ -27,8 +31,11 @@
             [frontend.handler.notification :as notification]
             [frontend.handler.page :as page-handler]
             [frontend.handler.plugin :as plugin-handler]
+            [frontend.handler.repo :as repo-handler]
             [frontend.handler.route :as route-handler]
+            [frontend.handler.user :as user-handler]
             [frontend.mobile.util :as mobile-util]
+            [frontend.modules.instrumentation.sentry :as sentry-event]
             [frontend.state :as state]
             [frontend.ui :as ui]
             [frontend.util :as util]
@@ -352,3 +359,44 @@
    (merge {:close-btn?      false
            :center?         true
            :close-backdrop? false} opts)))
+
+(defn- enable-beta-features!
+  []
+  (when-not (false? (state/enable-sync?)) ; user turns it off
+    (file-sync-handler/set-sync-enabled! true)))
+
+;; TODO: separate rtc and file-based implementation
+(defmethod events/handle :user/fetch-info-and-graphs [[_]]
+  (state/set-state! [:ui/loading? :login] false)
+  (async/go
+    (let [result (async/<! (sync/<user-info sync/remoteapi))]
+      (cond
+        (instance? ExceptionInfo result)
+        nil
+        (map? result)
+        (do
+          (state/set-user-info! result)
+          (when-let [uid (user-handler/user-uuid)]
+            (sentry-event/set-user! uid))
+          (let [status (if (user-handler/alpha-or-beta-user?) :welcome :unavailable)]
+            (when (and (= status :welcome) (user-handler/logged-in?))
+              (enable-beta-features!)
+              (async/<! (p->c (rtc-handler/<get-remote-graphs)))
+              (async/<! (file-sync-handler/load-session-graphs))
+              (p/let [repos (repo-handler/refresh-repos!)]
+                (when-let [repo (state/get-current-repo)]
+                  (when (some #(and (= (:url %) repo)
+                                    (vector? (:sync-meta %))
+                                    (util/uuid-string? (first (:sync-meta %)))
+                                    (util/uuid-string? (second (:sync-meta %)))) repos)
+                    (sync/<sync-start)))))
+            (file-sync/maybe-onboarding-show status)))))))
+
+(defmethod events/handle :file-sync/onboarding-tip [[_ type opts]]
+  (let [type (keyword type)]
+    (when-not (config/db-based-graph? (state/get-current-repo))
+      (shui/dialog-open!
+       (file-sync/make-onboarding-panel type)
+       (merge {:close-btn? false
+               :center? true
+               :close-backdrop? (not= type :welcome)} opts)))))

+ 0 - 43
src/main/frontend/handler/file_based/events.cljs

@@ -1,7 +1,6 @@
 (ns frontend.handler.file-based.events
   "Events that are only for file graphs"
   (:require [clojure.core.async :as async]
-            [clojure.core.async.interop :refer [p->c]]
             [clojure.set :as set]
             [clojure.string :as string]
             [frontend.components.diff :as diff]
@@ -14,7 +13,6 @@
             [frontend.fs :as fs]
             [frontend.fs.sync :as sync]
             [frontend.handler.common :as common-handler]
-            [frontend.handler.db-based.rtc :as rtc-handler]
             [frontend.handler.events :as events]
             [frontend.handler.file-based.file :as file-handler]
             [frontend.handler.file-based.nfs :as nfs-handler]
@@ -28,7 +26,6 @@
             [frontend.handler.user :as user-handler]
             [frontend.mobile.graph-picker :as graph-picker]
             [frontend.mobile.util :as mobile-util]
-            [frontend.modules.instrumentation.sentry :as sentry-event]
             [frontend.modules.shortcut.core :as st]
             [frontend.state :as state]
             [frontend.ui :as ui]
@@ -164,37 +161,6 @@
                   opts))
    {:center? true :close-btn? false :close-backdrop? false}))
 
-(defn- enable-beta-features!
-  []
-  (when-not (false? (state/enable-sync?)) ; user turns it off
-    (file-sync-handler/set-sync-enabled! true)))
-
-(defmethod events/handle :user/fetch-info-and-graphs [[_]]
-  (state/set-state! [:ui/loading? :login] false)
-  (async/go
-    (let [result (async/<! (sync/<user-info sync/remoteapi))]
-      (cond
-        (instance? ExceptionInfo result)
-        nil
-        (map? result)
-        (do
-          (state/set-user-info! result)
-          (when-let [uid (user-handler/user-uuid)]
-            (sentry-event/set-user! uid))
-          (let [status (if (user-handler/alpha-or-beta-user?) :welcome :unavailable)]
-            (when (and (= status :welcome) (user-handler/logged-in?))
-              (enable-beta-features!)
-              (async/<! (p->c (rtc-handler/<get-remote-graphs)))
-              (async/<! (file-sync-handler/load-session-graphs))
-              (p/let [repos (repo-handler/refresh-repos!)]
-                (when-let [repo (state/get-current-repo)]
-                  (when (some #(and (= (:url %) repo)
-                                    (vector? (:sync-meta %))
-                                    (util/uuid-string? (first (:sync-meta %)))
-                                    (util/uuid-string? (second (:sync-meta %)))) repos)
-                    (sync/<sync-start)))))
-            (file-sync/maybe-onboarding-show status)))))))
-
 (defmethod events/handle :graph/pull-down-remote-graph [[_ graph dir-name]]
   (if (mobile-util/native-ios?)
     (when-let [graph-name (or dir-name (:GraphName graph))]
@@ -234,15 +200,6 @@
    (file-sync/pick-page-histories-panel graph-uuid page-name)
    {:id :page-histories :label "modal-page-histories"}))
 
-(defmethod events/handle :file-sync/onboarding-tip [[_ type opts]]
-  (let [type (keyword type)]
-    (when-not (config/db-based-graph? (state/get-current-repo))
-      (shui/dialog-open!
-       (file-sync/make-onboarding-panel type)
-       (merge {:close-btn? false
-               :center? true
-               :close-backdrop? (not= type :welcome)} opts)))))
-
 (defmethod events/handle :file-sync/maybe-onboarding-show [[_ type]]
   (file-sync/maybe-onboarding-show type))
 

+ 23 - 0
src/main/frontend/worker/db/fix.cljs

@@ -0,0 +1,23 @@
+(ns frontend.worker.db.fix
+  "fix db"
+  (:require [datascript.core :as d]
+            [logseq.db.sqlite.util :as sqlite-util]))
+
+(defn check-and-fix-schema!
+  [repo conn]
+  (let [schema (sqlite-util/get-schema repo)
+        db-schema (:schema @conn)
+        diffs (->> (keep (fn [[k v]]
+                           (let [schema-v (-> (get db-schema k)
+                                              (dissoc :db/ident))
+                                 schema-v' (cond-> schema-v
+                                             (= (:db/cardinality schema-v) :db.cardinality/one)
+                                             (dissoc :db/cardinality)
+                                             (and (:db/index schema-v)
+                                                  (nil? (:db/index v)))
+                                             (dissoc :db/index))]
+                             (when-not (or (= v schema-v') (= k :db/ident))
+                               (assoc v :db/ident k))))
+                         schema))]
+    (when (seq diffs)
+      (d/transact! conn diffs))))

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

@@ -13,6 +13,7 @@
             [frontend.common.graph-view :as graph-view]
             [frontend.common.thread-api :as thread-api :refer [def-thread-api]]
             [frontend.worker.db-listener :as db-listener]
+            [frontend.worker.db.fix :as db-fix]
             [frontend.worker.db.migrate :as db-migrate]
             [frontend.worker.db.validate :as worker-db-validate]
             [frontend.worker.export :as worker-export]
@@ -333,6 +334,7 @@
       (search/create-tables-and-triggers! search-db)
       (let [schema (sqlite-util/get-schema repo)
             conn (sqlite-common-db/get-storage-conn storage schema)
+            _ (db-fix/check-and-fix-schema! repo conn)
             _ (when datoms
                 (let [data (map (fn [datom]
                                   [:db/add (:e datom) (:a datom) (:v datom)]) datoms)]

+ 21 - 6
src/test/frontend/handler/editor_test.cljs

@@ -82,8 +82,10 @@
   (state/set-editor-action! action)
   ;; Default cursor pos to end of line
   (let [pos (or cursor-pos (count value))
-        input #js {:value value}]
-    (with-redefs [editor/get-matched-commands (constantly commands)
+        input #js {:value value}
+        command (subs value 1)]
+    (with-redefs [editor/get-last-command (constantly command)
+                  editor/get-matched-commands (constantly commands)
                   ;; Ignore as none of its behaviors are tested
                   editor/default-case-for-keyup-handler (constantly nil)
                   cursor/pos (constantly pos)]
@@ -93,17 +95,30 @@
 
 (deftest keyup-handler-test
   (testing "Command autocompletion"
-    (keyup-handler {:value "/b"
+    ;; default last matching command is ""
+    (keyup-handler {:value "/z"
                     :action :commands
-                    :commands [:fake-command]})
+                    :commands []})
     (is (= :commands (state/get-editor-action))
-        "Completion stays open if there is a matching command")
+        "Completion stays open if no matches but differs from last success by <= 2 chars")
 
     (keyup-handler {:value "/zz"
                     :action :commands
                     :commands []})
+    (is (= :commands (state/get-editor-action))
+        "Completion stays open if no matches but differs from last success by <= 2 chars")
+
+    (keyup-handler {:value "/zzz"
+                    :action :commands
+                    :commands []})
     (is (= nil (state/get-editor-action))
-        "Completion closed if there no matching commands")
+        "Completion closed if no matches and > 2 chars form last success")
+
+    (keyup-handler {:value "/b"
+                    :action :commands
+                    :commands [:fake-command]})
+    (is (= :commands (state/get-editor-action))
+        "Completion stays open if there is a matching command")
 
     (keyup-handler {:value "/ " :action :commands})
     (is (= nil (state/get-editor-action))