From 7f6fa2dbd902905ebed7bfc2845883bcb36ef92a Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Thu, 17 Apr 2025 18:20:28 +0800 Subject: [PATCH 01/11] refactor: separate ui/file graph events from handler.events --- src/main/frontend/handler.cljs | 1 + src/main/frontend/handler/events.cljs | 601 +----------------- src/main/frontend/handler/events/ui.cljs | 354 +++++++++++ .../frontend/handler/file_based/events.cljs | 333 +++++++++- 4 files changed, 662 insertions(+), 627 deletions(-) create mode 100644 src/main/frontend/handler/events/ui.cljs diff --git a/src/main/frontend/handler.cljs b/src/main/frontend/handler.cljs index 3fb2b748f3..347387c5ee 100644 --- a/src/main/frontend/handler.cljs +++ b/src/main/frontend/handler.cljs @@ -17,6 +17,7 @@ [frontend.error :as error] [frontend.handler.command-palette :as command-palette] [frontend.handler.events :as events] + [frontend.handler.events.ui] [frontend.handler.file-based.events] [frontend.handler.file-based.file :as file-handler] [frontend.handler.global-config :as global-config-handler] diff --git a/src/main/frontend/handler/events.cljs b/src/main/frontend/handler/events.cljs index f8ab9bb804..786f016f3f 100644 --- a/src/main/frontend/handler/events.cljs +++ b/src/main/frontend/handler/events.cljs @@ -10,24 +10,7 @@ [clojure.core.async.interop :refer [p->c]] [clojure.string :as string] [frontend.commands :as commands] - [frontend.components.block :as block] - [frontend.components.cmdk.core :as cmdk] - [frontend.components.diff :as diff] - [frontend.components.encryption :as encryption] - [frontend.components.file-based.git :as git-component] - [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] - [frontend.components.repo :as repo] - [frontend.components.select :as select] - [frontend.components.selection :as selection] - [frontend.components.settings :as settings] - [frontend.components.shell :as shell] - [frontend.components.user.login :as login] - [frontend.components.whiteboard :as whiteboard] [frontend.config :as config] - [frontend.context.i18n :refer [t]] [frontend.date :as date] [frontend.db :as db] [frontend.db.async :as db-async] @@ -36,10 +19,7 @@ [frontend.db.persist :as db-persist] [frontend.db.transact :as db-transact] [frontend.extensions.fsrs :as fsrs] - [frontend.extensions.srs :as srs] [frontend.fs :as fs] - [frontend.fs.capacitor-fs :as capacitor-fs] - [frontend.fs.nfs :as nfs] [frontend.fs.sync :as sync] [frontend.fs.watcher-handler :as fs-watcher] [frontend.handler.assets :as assets-handler] @@ -50,8 +30,6 @@ [frontend.handler.db-based.rtc-flows :as rtc-flows] [frontend.handler.editor :as editor-handler] [frontend.handler.export :as export] - [frontend.handler.file-based.file :as file-handler] - [frontend.handler.file-based.nfs :as nfs-handler] [frontend.handler.file-sync :as file-sync-handler] [frontend.handler.graph :as graph-handler] [frontend.handler.notification :as notification] @@ -63,12 +41,9 @@ [frontend.handler.search :as search-handler] [frontend.handler.shell :as shell-handler] [frontend.handler.ui :as ui-handler] - [frontend.handler.user :as user-handler] [frontend.mobile.core :as mobile] - [frontend.mobile.graph-picker :as graph-picker] [frontend.mobile.util :as mobile-util] [frontend.modules.instrumentation.posthog :as posthog] - [frontend.modules.instrumentation.sentry :as sentry-event] [frontend.modules.outliner.pipeline :as pipeline] [frontend.modules.outliner.ui :as ui-outliner-tx] [frontend.modules.shortcut.core :as st] @@ -76,16 +51,11 @@ [frontend.quick-capture :as quick-capture] [frontend.search :as search] [frontend.state :as state] - [frontend.ui :as ui] [frontend.util :as util] [frontend.util.persist-var :as persist-var] [goog.dom :as gdom] [lambdaisland.glogi :as log] - [logseq.common.config :as common-config] - [logseq.common.util :as common-util] - [logseq.shui.ui :as shui] - [promesa.core :as p] - [rum.core :as rum])) + [promesa.core :as p])) ;; TODO: should we move all events here? @@ -96,54 +66,10 @@ (async/ (sync/c (persist-var/load-vars))) (async/c (rtc-handler/ - (p/let [exists? (fs/dir-exists? graph-path)] - (let [overwrite? (if exists? - (js/confirm (str "There's already a directory with the name \"" graph-name "\", do you want to overwrite it? Make sure to backup it first if you're not sure about it.")) - true)] - (if overwrite? - (p/let [_ (fs/mkdir-if-not-exists graph-path)] - (nfs-handler/ls-dir-files-with-path! - graph-path - {:ok-handler (fn [] - (file-sync-handler/init-remote-graph graph-path graph) - (js/setTimeout (fn [] (repo-handler/refresh-repos!)) 200))})) - (let [graph-name (-> (js/prompt "Please specify a new directory name to download the graph:") - str - string/trim)] - (when-not (string/blank? graph-name) - (state/pub-event! [:graph/pull-down-remote-graph graph graph-name])))))) - (p/catch (fn [^js e] - (notification/show! (str e) :error) - (js/console.error e))))))))) - (when (:GraphName graph) - (shui/dialog-open! - (file-sync/pick-dest-to-sync-panel graph))))) - -(defmethod handle :graph/pick-page-histories [[_ graph-uuid page-name]] - (shui/dialog-open! - (file-sync/pick-page-histories-panel graph-uuid page-name) - {:id :page-histories :label "modal-page-histories"})) - (defmethod handle :graph/open-new-window [[_ev target-repo]] (p/let [current-repo (state/get-current-repo)] (ui-handler/open-new-window-or-tab! current-repo target-repo))) @@ -261,67 +148,6 @@ (defmethod handle :graph/migrated [[_ _repo]] (js/alert "Graph migrated.")) -(defn get-local-repo - [] - (when-let [repo (state/get-current-repo)] - (when (config/local-file-based-graph? repo) - repo))) - -(defn ask-permission - [repo] - (when - (and (not (util/electron?)) - (not (mobile-util/native-platform?))) - (fn [{:keys [close]}] - [:div - ;; TODO: fn translation with args - [:p - "Grant native filesystem permission for directory: " - [:b (config/get-local-dir repo)]] - (ui/button - (t :settings-permission/start-granting) - :class "ui__modal-enter" - :on-click (fn [] - (nfs/check-directory-permission! repo) - (close)))]))) - -(defmethod handle :modal/nfs-ask-permission [] - (when-let [repo (get-local-repo)] - (some-> (ask-permission repo) - (shui/dialog-open! {:align :top})))) - -(defmethod handle :modal/show-cards [[_ cards-id]] - (let [db-based? (config/db-based-graph? (state/get-current-repo))] - (shui/dialog-open! - (if db-based? (fn [] (fsrs/cards-view cards-id)) srs/global-cards) - {:id :srs - :label "flashcards__cp"}))) - -(defmethod handle :modal/show-instruction [_] - (shui/dialog-open! - capacitor-fs/instruction - {:id :instruction - :label "instruction__cp"})) - -(defmethod handle :modal/show-themes-modal [[_ classic?]] - (if classic? - (plugin/open-select-theme!) - (route-handler/go-to-search! :themes))) - -(defmethod handle :ui/toggle-appearance [_] - (let [popup-id "appearance_settings"] - (if (gdom/getElement popup-id) - (shui/popup-hide! popup-id) - (shui/popup-show! - (js/document.querySelector ".toolbar-dots-btn") - (fn [] - (settings/appearance)) - {:id popup-id - :align :end})))) - -(defmethod handle :modal/set-git-username-and-email [[_ _content]] - (shui/dialog-open! git-component/set-git-username-and-email)) - (defmethod handle :page/create [[_ page-name opts]] (if (= page-name (date/today)) (page-handler/create-today-journal!) @@ -333,26 +159,10 @@ (defmethod handle :page/renamed [[_ repo data]] (page-common-handler/after-page-renamed! repo data)) -(defmethod handle :page/show-delete-dialog [[_ selected-rows ok-handler]] - (shui/dialog-open! - (component-page/batch-delete-dialog - selected-rows false - ok-handler))) - (defmethod handle :page/create-today-journal [[_ _repo]] (p/let [_ (page-handler/create-today-journal!)] (ui-handler/re-render-root!))) -(defmethod handle :file/not-matched-from-disk [[_ path disk-content db-content]] - (when-let [repo (state/get-current-repo)] - (shui/dialog-open! - #(diff/local-file repo path disk-content db-content) - {:label "diff__cp"}))) - -(defmethod handle :modal/display-file-version-selector [[_ versions path get-content]] - (shui/dialog-open! - #(git-component/file-version-selector versions path get-content))) - (defmethod handle :graph/sync-context [] (let [context {:dev? config/dev? :node-test? util/node-test? @@ -391,48 +201,6 @@ (export/auto-db-backup! repo {:backup-now? true}) (fs-watcher/load-graph-files! repo))))) -(defmethod handle :notification/show [[_ {:keys [content status clear?]}]] - (notification/show! content status clear?)) - -(defmethod handle :command/run [_] - (when (util/electron?) - (shui/dialog-open! shell/shell))) - -(defmethod handle :go/search [_] - (shui/dialog-open! - cmdk/cmdk-modal - {:id :ls-dialog-cmdk - :align :top - :content-props {:class "ls-dialog-cmdk"} - :close-btn? false})) - -(defmethod handle :go/plugins [_] - (plugin/open-plugins-modal!)) - -(defmethod handle :go/plugins-waiting-lists [_] - (plugin/open-waiting-updates-modal!)) - -(defmethod handle :go/plugins-from-file [[_ plugins]] - (plugin/open-plugins-from-file-modal! plugins)) - -(defmethod handle :go/install-plugin-from-github [[_]] - (shui/dialog-open! - (plugin/install-from-github-release-container))) - -(defmethod handle :go/plugins-settings [[_ pid nav? title]] - (when pid - (state/set-state! :plugin/focused-settings pid) - (state/set-state! :plugin/navs-settings? (not (false? nav?))) - (plugin/open-focused-settings-modal! title))) - -(defmethod handle :go/proxy-settings [[_ agent-opts]] - (shui/dialog-open! - (plugin/user-proxy-settings-container agent-opts) - {:id :https-proxy-panel :center? true :class "lg:max-w-2xl"})) - -(defmethod handle :redirect-to-home [_] - (page-handler/create-today-journal!)) - (defmethod handle :instrument [[_ {:keys [type payload] :as opts}]] (when-not (empty? (dissoc opts :type :payload)) (js/console.error "instrument data-map should only contains [:type :payload]")) @@ -557,57 +325,12 @@ (file-sync-restart!)))) (state/pub-event! [:graph/ready (state/get-current-repo)]))))) -(defmethod handle :plugin/consume-updates [[_ id prev-pending? updated?]] - (let [downloading? (:plugin/updates-downloading? @state/state) - auto-checking? (plugin-handler/get-auto-checking?)] - (when-let [coming (and (not downloading?) - (get-in @state/state [:plugin/updates-coming id]))] - (let [error-code (:error-code coming) - error-code (if (= error-code (str :no-new-version)) nil error-code) - title (:title coming)] - (when (and prev-pending? (not auto-checking?)) - (if-not error-code - (plugin/set-updates-sub-content! (str title "...") 0) - (notification/show! - (str "[Checked]<" title "> " error-code) :error))))) - - (if (and updated? downloading?) - ;; try to start consume downloading item - (if-let [next-coming (state/get-next-selected-coming-update)] - (plugin-handler/check-or-update-marketplace-plugin! - (assoc next-coming :only-check false :error-code nil) - (fn [^js e] (js/console.error "[Download Err]" next-coming e))) - (plugin-handler/close-updates-downloading)) - - ;; try to start consume pending item - (if-let [next-pending (second (first (:plugin/updates-pending @state/state)))] - (do - (println "Updates: take next pending - " (:id next-pending)) - (js/setTimeout - #(plugin-handler/check-or-update-marketplace-plugin! - (assoc next-pending :only-check true :auto-check auto-checking? :error-code nil) - (fn [^js e] - (notification/show! (.toString e) :error) - (js/console.error "[Check Err]" next-pending e))) 500)) - - ;; try to open waiting updates list - (do (when (and prev-pending? (not auto-checking?) - (seq (state/all-available-coming-updates))) - (plugin/open-waiting-updates-modal!)) - (plugin-handler/set-auto-checking! false)))))) - (defmethod handle :plugin/hook-db-tx [[_ {:keys [blocks tx-data] :as payload}]] (when-let [payload (and (seq blocks) (merge payload {:tx-data (map #(into [] %) tx-data)}))] (plugin-handler/hook-plugin-db :changed payload) (plugin-handler/hook-plugin-block-changes payload))) -(defmethod handle :plugin/loader-perf-tip [[_ {:keys [^js o _s _e]}]] - (when-let [opts (.-options o)] - (notification/show! - (plugin/perf-tip-content (.-id o) (.-name opts) (.-url opts)) - :warning false (.-id o)))) - (defmethod handle :mobile-file-watcher/changed [[_ ^js event]] (let [type (.-event event) payload (js->clj event :keywordize-keys true)] @@ -621,51 +344,6 @@ (defmethod handle :shortcut/refresh [[_]] (st/refresh!)) -(defn- refresh-cb [] - (page-handler/create-today-journal!) - (file-sync-restart!)) - -(defmethod handle :graph/ask-for-re-fresh [_] - (shui/dialog-open! - [:div {:style {:max-width 700}} - [:p (t :sync-from-local-changes-detected)] - [:div.flex.justify-end - (ui/button - (t :yes) - :autoFocus "on" - :class "ui__modal-enter" - :on-click (fn [] - (shui/dialog-close!) - (nfs-handler/refresh! (state/get-current-repo) refresh-cb)))]])) - -(defmethod handle :sync/create-remote-graph [[_ current-repo]] - (let [graph-name (js/decodeURI (util/node-path.basename current-repo))] - (async/go - (async/ opts - editing-block - (assoc :original-block editing-block - :edit-original-block - (fn [{:keys [editing-default-property?]}] - (when editing-block - (let [content (:block/title (db/entity (:db/id editing-block))) - esc? (= "Escape" (state/get-ui-last-key-code)) - [content' pos] (cond - esc? - [nil pos] - (and (>= (count content) pos) - (>= pos 2) - (= (util/nth-safe content (dec pos)) - (util/nth-safe content (- pos 2)) - ";")) - [(str (common-util/safe-subs content 0 (- pos 2)) - (common-util/safe-subs content pos)) - (- pos 2)] - :else - [nil pos])] - (when content' - (if editing-default-property? - (editor-handler/save-block! (state/get-current-repo) (:block/uuid editing-block) content') - (editor-handler/edit-block! editing-block (or pos :max) - (cond-> {} - content' - (assoc :custom-content content'))))))))))] - (when (seq blocks) - (let [target' (or target - (some-> (state/get-edit-input-id) - (gdom/getElement)) - (first (state/get-selection-blocks)))] - (if target' - (shui/popup-show! target' - #(property-dialog/dialog blocks opts') - {:align "start" - :auto-focus? true}) - (shui/dialog-open! #(property-dialog/dialog blocks opts') - {:id :property-dialog - :align "start"})))))) - -(defmethod handle :editor/new-property [[_ {:keys [block target] :as opts}]] - (when-not config/publishing? - (p/do! - (editor-handler/save-current-block!) - (editor-new-property block target opts)))) - (defmethod handle :editor/upsert-type-block [[_ {:keys [block type lang update-current-block?]}]] (p/do! (when-not update-current-block? @@ -1026,25 +466,6 @@ (db/entity [:block/uuid (:block/uuid block)])))] (js/setTimeout #(editor-handler/edit-block! block :max) 100))))) -(rum/defc multi-tabs-dialog - [] - (let [word (if (util/electron?) "window" "tab")] - [:div.flex.p-4.flex-col.gap-4.h-64 - [:span.warning.text-lg - (util/format "Logseq doesn't support multiple %ss access to the same graph yet, please close this %s or switch to another graph." - word word)] - [:div.text-lg - [:p "Switch to another repo: "] - [:div.border.rounded.bg-gray-01.overflow-hidden.w-60 - (repo/repos-dropdown {:on-click (fn [e] - (util/stop e) - (state/set-state! :error/multiple-tabs-access-opfs? false) - (shui/dialog-close!))})]]])) - -(defmethod handle :show/multiple-tabs-error-dialog [_] - (state/set-state! :error/multiple-tabs-access-opfs? true) - (shui/dialog-open! multi-tabs-dialog)) - (defmethod handle :rtc/sync-state [[_ state]] (state/update-state! :rtc/state (fn [old] (merge old state)))) @@ -1075,24 +496,6 @@ (defmethod handle :editor/run-query-command [_] (editor-handler/run-query-command!)) -(defmethod handle :editor/show-action-bar [] - (let [selection (state/get-selection-blocks) - first-visible-block (some #(when (util/el-visible-in-viewport? % true) %) selection)] - (when first-visible-block - (shui/popup-hide! :selection-action-bar) - (shui/popup-show! - first-visible-block - (fn [] - (selection/action-bar)) - {:id :selection-action-bar - :content-props {:side "top" - :class "!py-0 !px-0 !border-none"} - :auto-side? false - :align :start})))) - -(defmethod handle :editor/hide-action-bar [] - (shui/popup-hide! :selection-action-bar)) - (defmethod handle :editor/load-blocks [[_ ids]] (when (seq ids) ;; not using ` (ask-permission repo) + (shui/dialog-open! {:align :top})))) + +(defmethod events/handle :modal/show-cards [[_ cards-id]] + (let [db-based? (config/db-based-graph? (state/get-current-repo))] + (shui/dialog-open! + (if db-based? (fn [] (fsrs/cards-view cards-id)) srs/global-cards) + {:id :srs + :label "flashcards__cp"}))) + +(defmethod events/handle :modal/show-instruction [_] + (shui/dialog-open! + capacitor-fs/instruction + {:id :instruction + :label "instruction__cp"})) + +(defmethod events/handle :modal/show-themes-modal [[_ classic?]] + (if classic? + (plugin/open-select-theme!) + (route-handler/go-to-search! :themes))) + +(defmethod events/handle :ui/toggle-appearance [_] + (let [popup-id "appearance_settings"] + (if (gdom/getElement popup-id) + (shui/popup-hide! popup-id) + (shui/popup-show! + (js/document.querySelector ".toolbar-dots-btn") + (fn [] + (settings/appearance)) + {:id popup-id + :align :end})))) + +(defmethod events/handle :plugin/consume-updates [[_ id prev-pending? updated?]] + (let [downloading? (:plugin/updates-downloading? @state/state) + auto-checking? (plugin-handler/get-auto-checking?)] + (when-let [coming (and (not downloading?) + (get-in @state/state [:plugin/updates-coming id]))] + (let [error-code (:error-code coming) + error-code (if (= error-code (str :no-new-version)) nil error-code) + title (:title coming)] + (when (and prev-pending? (not auto-checking?)) + (if-not error-code + (plugin/set-updates-sub-content! (str title "...") 0) + (notification/show! + (str "[Checked]<" title "> " error-code) :error))))) + + (if (and updated? downloading?) + ;; try to start consume downloading item + (if-let [next-coming (state/get-next-selected-coming-update)] + (plugin-handler/check-or-update-marketplace-plugin! + (assoc next-coming :only-check false :error-code nil) + (fn [^js e] (js/console.error "[Download Err]" next-coming e))) + (plugin-handler/close-updates-downloading)) + + ;; try to start consume pending item + (if-let [next-pending (second (first (:plugin/updates-pending @state/state)))] + (do + (println "Updates: take next pending - " (:id next-pending)) + (js/setTimeout + #(plugin-handler/check-or-update-marketplace-plugin! + (assoc next-pending :only-check true :auto-check auto-checking? :error-code nil) + (fn [^js e] + (notification/show! (.toString e) :error) + (js/console.error "[Check Err]" next-pending e))) 500)) + + ;; try to open waiting updates list + (do (when (and prev-pending? (not auto-checking?) + (seq (state/all-available-coming-updates))) + (plugin/open-waiting-updates-modal!)) + (plugin-handler/set-auto-checking! false)))))) + +(defmethod events/handle :plugin/loader-perf-tip [[_ {:keys [^js o _s _e]}]] + (when-let [opts (.-options o)] + (notification/show! + (plugin/perf-tip-content (.-id o) (.-name opts) (.-url opts)) + :warning false (.-id o)))) + +(defn- refresh-cb [] + (page-handler/create-today-journal!) + (events/file-sync-restart!)) + +(defmethod events/handle :graph/ask-for-re-fresh [_] + (shui/dialog-open! + [:div {:style {:max-width 700}} + [:p (t :sync-from-local-changes-detected)] + [:div.flex.justify-end + (ui/button + (t :yes) + :autoFocus "on" + :class "ui__modal-enter" + :on-click (fn [] + (shui/dialog-close!) + (nfs-handler/refresh! (state/get-current-repo) refresh-cb)))]])) + +(defn- editor-new-property [block target {:keys [selected-blocks] :as opts}] + (let [editing-block (state/get-edit-block) + pos (state/get-edit-pos) + edit-block-or-selected (cond + editing-block + [editing-block] + (seq selected-blocks) + selected-blocks + :else + (seq (keep #(db/entity [:block/uuid %]) (state/get-selection-block-ids)))) + current-block (when-let [s (state/get-current-page)] + (when (util/uuid-string? s) + (db/entity [:block/uuid (uuid s)]))) + blocks (or (when block [block]) + edit-block-or-selected + (when current-block [current-block])) + opts' (cond-> opts + editing-block + (assoc :original-block editing-block + :edit-original-block + (fn [{:keys [editing-default-property?]}] + (when editing-block + (let [content (:block/title (db/entity (:db/id editing-block))) + esc? (= "Escape" (state/get-ui-last-key-code)) + [content' pos] (cond + esc? + [nil pos] + (and (>= (count content) pos) + (>= pos 2) + (= (util/nth-safe content (dec pos)) + (util/nth-safe content (- pos 2)) + ";")) + [(str (common-util/safe-subs content 0 (- pos 2)) + (common-util/safe-subs content pos)) + (- pos 2)] + :else + [nil pos])] + (when content' + (if editing-default-property? + (editor-handler/save-block! (state/get-current-repo) (:block/uuid editing-block) content') + (editor-handler/edit-block! editing-block (or pos :max) + (cond-> {} + content' + (assoc :custom-content content'))))))))))] + (when (seq blocks) + (let [target' (or target + (some-> (state/get-edit-input-id) + (gdom/getElement)) + (first (state/get-selection-blocks)))] + (if target' + (shui/popup-show! target' + #(property-dialog/dialog blocks opts') + {:align "start" + :auto-focus? true}) + (shui/dialog-open! #(property-dialog/dialog blocks opts') + {:id :property-dialog + :align "start"})))))) + +(defmethod events/handle :editor/new-property [[_ {:keys [block target] :as opts}]] + (when-not config/publishing? + (p/do! + (editor-handler/save-current-block!) + (editor-new-property block target opts)))) + +(defmethod events/handle :graph/new-db-graph [[_ _opts]] + (shui/dialog-open! + repo/new-db-graph + {:id :new-db-graph + :title [:h2 "Create a new graph"] + :style {:max-width "500px"}})) + +(defmethod events/handle :dialog-select/graph-open [] + (select/dialog-select! :graph-open)) + +(defmethod events/handle :dialog-select/graph-remove [] + (select/dialog-select! :graph-remove)) + +(defmethod events/handle :dialog-select/db-graph-replace [] + (select/dialog-select! :db-graph-replace)) + +(rum/defc multi-tabs-dialog + [] + (let [word (if (util/electron?) "window" "tab")] + [:div.flex.p-4.flex-col.gap-4.h-64 + [:span.warning.text-lg + (util/format "Logseq doesn't support multiple %ss access to the same graph yet, please close this %s or switch to another graph." + word word)] + [:div.text-lg + [:p "Switch to another repo: "] + [:div.border.rounded.bg-gray-01.overflow-hidden.w-60 + (repo/repos-dropdown {:on-click (fn [e] + (util/stop e) + (state/set-state! :error/multiple-tabs-access-opfs? false) + (shui/dialog-close!))})]]])) + +(defmethod events/handle :show/multiple-tabs-error-dialog [_] + (state/set-state! :error/multiple-tabs-access-opfs? true) + (shui/dialog-open! multi-tabs-dialog)) + +(defmethod events/handle :editor/show-action-bar [] + (let [selection (state/get-selection-blocks) + first-visible-block (some #(when (util/el-visible-in-viewport? % true) %) selection)] + (when first-visible-block + (shui/popup-hide! :selection-action-bar) + (shui/popup-show! + first-visible-block + (fn [] + (selection/action-bar)) + {:id :selection-action-bar + :content-props {:side "top" + :class "!py-0 !px-0 !border-none"} + :auto-side? false + :align :start})))) + +(defmethod events/handle :editor/hide-action-bar [] + (shui/popup-hide! :selection-action-bar)) + +(defmethod events/handle :user/logout [[_]] + (file-sync-handler/reset-session-graphs) + (sync/remove-all-pwd!) + (file-sync-handler/reset-user-state!) + (login/sign-out!)) + +(defmethod events/handle :user/login [[_ host-ui?]] + (if (or host-ui? (not util/electron?)) + (js/window.open config/LOGIN-URL) + (if (mobile-util/native-platform?) + (route-handler/redirect! {:to :user-login}) + (login/open-login-modal!)))) + +(defmethod events/handle :whiteboard/onboarding [[_ opts]] + (shui/dialog-open! + (fn [{:keys [close]}] (whiteboard/onboarding-welcome close)) + (merge {:close-btn? false + :center? true + :close-backdrop? false} opts))) diff --git a/src/main/frontend/handler/file_based/events.cljs b/src/main/frontend/handler/file_based/events.cljs index cb87891a39..f6330d5946 100644 --- a/src/main/frontend/handler/file_based/events.cljs +++ b/src/main/frontend/handler/file_based/events.cljs @@ -1,21 +1,42 @@ (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] + [frontend.components.encryption :as encryption] + [frontend.components.file-based.git :as git-component] + [frontend.components.file-sync :as file-sync] + [frontend.config :as config] [frontend.context.i18n :refer [t]] [frontend.db :as db] - [frontend.handler.events :as events] - [frontend.handler.page :as page-handler] - [frontend.handler.repo :as repo-handler] - [frontend.handler.file-based.nfs :as nfs-handler] - [frontend.handler.common :as common-handler] - [frontend.handler.property :as property-handler] + [frontend.db.conn :as conn] + [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] + [frontend.handler.file-sync :as file-sync-handler] + [frontend.handler.notification :as notification] + [frontend.handler.page :as page-handler] + [frontend.handler.property :as property-handler] + [frontend.handler.repo :as repo-handler] + [frontend.handler.route :as route-handler] + [frontend.handler.ui :as ui-handler] + [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] [frontend.util :as util] - [frontend.config :as config] + [logseq.common.config :as common-config] [logseq.shui.ui :as shui] + [promesa.core :as p] [rum.core :as rum])) (defmethod events/handle :graph/ask-for-re-index [[_ *multiple-windows? ui]] @@ -23,32 +44,32 @@ ;; ui - custom message to show on asking for re-index (if (and (util/atom? *multiple-windows?) @*multiple-windows?) (shui/dialog-open! - [:div - (when (not (nil? ui)) ui) - [:p (t :re-index-multiple-windows-warning)]]) + [:div + (when (not (nil? ui)) ui) + [:p (t :re-index-multiple-windows-warning)]]) (shui/dialog-open! - [:div {:style {:max-width 700}} - (when (not (nil? ui)) ui) - [:p (t :re-index-discard-unsaved-changes-warning)] - [:div.flex.justify-end.pt-2 - (ui/button - (t :yes) - :autoFocus "on" - :class "ui__modal-enter" - :on-click (fn [] - (shui/dialog-close!) - (state/pub-event! [:graph/re-index])))]]))) + [:div {:style {:max-width 700}} + (when (not (nil? ui)) ui) + [:p (t :re-index-discard-unsaved-changes-warning)] + [:div.flex.justify-end.pt-2 + (ui/button + (t :yes) + :autoFocus "on" + :class "ui__modal-enter" + :on-click (fn [] + (shui/dialog-close!) + (state/pub-event! [:graph/re-index])))]]))) (defmethod events/handle :graph/re-index [[_]] ;; Ensure the graph only has ONE window instance (when (config/local-file-based-graph? (state/get-current-repo)) (async/go - (async/c (rtc-handler/ + (p/let [exists? (fs/dir-exists? graph-path)] + (let [overwrite? (if exists? + (js/confirm (str "There's already a directory with the name \"" graph-name "\", do you want to overwrite it? Make sure to backup it first if you're not sure about it.")) + true)] + (if overwrite? + (p/let [_ (fs/mkdir-if-not-exists graph-path)] + (nfs-handler/ls-dir-files-with-path! + graph-path + {:ok-handler (fn [] + (file-sync-handler/init-remote-graph graph-path graph) + (js/setTimeout (fn [] (repo-handler/refresh-repos!)) 200))})) + (let [graph-name (-> (js/prompt "Please specify a new directory name to download the graph:") + str + string/trim)] + (when-not (string/blank? graph-name) + (state/pub-event! [:graph/pull-down-remote-graph graph graph-name])))))) + (p/catch (fn [^js e] + (notification/show! (str e) :error) + (js/console.error e))))))))) + (when (:GraphName graph) + (shui/dialog-open! + (file-sync/pick-dest-to-sync-panel graph))))) + +(defmethod events/handle :graph/pick-page-histories [[_ graph-uuid page-name]] + (shui/dialog-open! + (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)) + +(defmethod events/handle :file-sync/storage-exceed-limit [[_]] + (notification/show! "file sync storage exceed limit" :warning false) + (events/file-sync-stop!)) + +(defmethod events/handle :file-sync/graph-count-exceed-limit [[_]] + (notification/show! "file sync graph count exceed limit" :warning false) + (events/file-sync-stop!)) + +(defmethod events/handle :graph/dir-gone [[_ dir]] + (state/pub-event! [:notification/show + {:content (str "The directory " dir " has been renamed or deleted, the editor will be disabled for this graph, you can unlink the graph.") + :status :error + :clear? false}]) + (state/update-state! :file/unlinked-dirs (fn [dirs] (conj dirs dir)))) + +(defmethod events/handle :graph/dir-back [[_ repo dir]] + (when (contains? (:file/unlinked-dirs @state/state) dir) + (notification/clear-all!) + (state/pub-event! [:notification/show + {:content (str "The directory " dir " has been back, you can edit your graph now.") + :status :success + :clear? true}]) + (state/update-state! :file/unlinked-dirs (fn [dirs] (disj dirs dir))) + (when (= dir (config/get-repo-dir repo)) + (fs/watch-dir! dir)))) + +(defmethod events/handle :ui/notify-skipped-downloading-files [[_ paths]] + (notification/show! + [:div + [:div.mb-4 + [:div.font-semibold.mb-4.text-xl "It seems that some of your filenames are in the outdated format."] + [:p + "The files below that have reserved characters can't be saved on this device."] + [:div.overflow-y-auto.max-h-96 + [:ol.my-2 + (for [path paths] + [:li path])]] + + [:div + [:p + "Check " [:a {:href "https://docs.logseq.com/#/page/logseq%20file%20and%20folder%20naming%20rules" + :target "_blank"} + "Logseq file and folder naming rules"] + " for more details."]]]] + :warning + false)) + +(defmethod events/handle :graph/setup-a-repo [[_ opts]] + (let [opts' (merge {:picked-root-fn #(state/close-modal!) + :native-icloud? (not (string/blank? (state/get-icloud-container-root-url))) + :logged? (user-handler/logged-in?)} opts)] + (if (mobile-util/native-ios?) + (shui/dialog-open! + #(graph-picker/graph-picker-cp opts') + {:label "graph-setup"}) + (page-handler/ls-dir-files! st/refresh! opts')))) + +(defmethod events/handle :file/alter [[_ repo path content]] + (p/let [_ (file-handler/alter-file repo path content {:from-disk? true})] + (ui-handler/re-render-root!))) + +(rum/defcs file-id-conflict-item < + (rum/local false ::resolved?) + [state repo file data] + (let [resolved? (::resolved? state) + id (last (:assertion data))] + [:li {:key file} + [:div + [:a {:on-click #(js/window.apis.openPath file)} file] + (if @resolved? + [:div.flex.flex-row.items-center + (ui/icon "circle-check" {:style {:font-size 20}}) + [:div.ml-1 "Resolved"]] + [:div + [:p + (str "It seems that another whiteboard file already has the ID \"" id + "\". You can fix it by changing the ID in this file with another UUID.")] + [:p + "Or, let me" + (ui/button "Fix" + :on-click (fn [] + (let [dir (config/get-repo-dir repo)] + (p/let [content (fs/read-file dir file)] + (let [new-content (string/replace content (str id) (str (random-uuid)))] + (p/let [_ (fs/write-file! repo + dir + file + new-content + {})] + (reset! resolved? true)))))) + :class "inline mx-1") + "it."]])]])) + +(defmethod events/handle :file/parse-and-load-error [[_ repo parse-errors]] + (state/pub-event! [:notification/show + {:content + [:div + [:h2.title "Oops. These files failed to import to your graph:"] + [:ol.my-2 + (for [[file error] parse-errors] + (let [data (ex-data error)] + (cond + (and (common-config/whiteboard? file) + (= :transact/upsert (:error data)) + (uuid? (last (:assertion data)))) + (rum/with-key (file-id-conflict-item repo file data) file) + + :else + (do + (state/pub-event! [:capture-error {:error error + :payload {:type :file/parse-and-load-error}}]) + [:li.my-1 {:key file} + [:a {:on-click #(js/window.apis.openPath file)} file] + [:p (.-message error)]]))))] + [:p "Don't forget to re-index your graph when all the conflicts are resolved."]] + :status :error}])) + +(defmethod events/handle :file-sync-graph/restore-file [[_ graph page-entity content]] + (when (db/get-db graph) + (let [file (:block/file page-entity)] + (when-let [path (:file/path file)] + (when (and (not= content (:file/content file)) + (:file/content file)) + (sync/add-new-version-file graph path (:file/content file))) + (p/let [_ (file-handler/alter-file graph + path + content + {:re-render-root? true + :skip-compare? true})] + (state/close-modal!) + (route-handler/redirect! {:to :page + :path-params {:name (:block/name page-entity)}})))))) + +(defmethod events/handle :sync/create-remote-graph [[_ current-repo]] + (let [graph-name (js/decodeURI (util/node-path.basename current-repo))] + (async/go + (async/ Date: Thu, 17 Apr 2025 18:28:49 +0800 Subject: [PATCH 02/11] fix: lint --- src/main/frontend/handler/file_based/events.cljs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/frontend/handler/file_based/events.cljs b/src/main/frontend/handler/file_based/events.cljs index f6330d5946..eb6134ef4f 100644 --- a/src/main/frontend/handler/file_based/events.cljs +++ b/src/main/frontend/handler/file_based/events.cljs @@ -11,7 +11,6 @@ [frontend.config :as config] [frontend.context.i18n :refer [t]] [frontend.db :as db] - [frontend.db.conn :as conn] [frontend.fs :as fs] [frontend.fs.sync :as sync] [frontend.handler.common :as common-handler] From 21c58e89120e84f15511d932c3b8f85704a4205c Mon Sep 17 00:00:00 2001 From: Charlie Date: Thu, 17 Apr 2025 18:32:06 +0800 Subject: [PATCH 03/11] refactor(ui): remove react tippy (#11822) * refactor: remove all react tippy stuff --- deps/shui/src/logseq/shui/ui.cljs | 1 + src/main/frontend/components/container.cljs | 27 +++--- src/main/frontend/components/editor.cljs | 8 +- .../frontend/components/file_based/block.cljs | 37 ++++---- .../frontend/components/file_based/query.cljs | 27 +++--- src/main/frontend/components/page.cljs | 93 +++++++++++-------- src/main/frontend/components/plugins.cljs | 20 ++-- src/main/frontend/components/property.cljs | 7 +- .../frontend/components/property/config.cljs | 12 +-- src/main/frontend/components/settings.cljs | 67 ++++++------- src/main/frontend/extensions/srs.cljs | 68 +++++++------- src/main/frontend/tippy-tooltip.css | 79 ---------------- src/main/frontend/ui.cljs | 66 +++---------- 13 files changed, 181 insertions(+), 331 deletions(-) delete mode 100644 src/main/frontend/tippy-tooltip.css diff --git a/deps/shui/src/logseq/shui/ui.cljs b/deps/shui/src/logseq/shui/ui.cljs index 0acfa454ea..def5f40bbb 100644 --- a/deps/shui/src/logseq/shui/ui.cljs +++ b/deps/shui/src/logseq/shui/ui.cljs @@ -53,6 +53,7 @@ (def tooltip-portal (util/lsui-wrap "TooltipPortal")) (def tooltip-content (util/lsui-wrap "TooltipContent")) (def tooltip-provider (util/lsui-wrap "TooltipProvider")) +(def tooltip-arrow (util/lsui-wrap "TooltipArrow")) (def card (util/lsui-wrap "Card")) (def card-header (util/lsui-wrap "CardHeader")) diff --git a/src/main/frontend/components/container.cljs b/src/main/frontend/components/container.cljs index c884234aa4..21a5b955bc 100644 --- a/src/main/frontend/components/container.cljs +++ b/src/main/frontend/components/container.cljs @@ -782,19 +782,20 @@ (rum/defc new-block-mode < rum/reactive [] (when (state/sub [:document/mode?]) - (ui/tippy {:html [: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"]))) + (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"]]]]))) (def help-menu-items [{:title "Handbook" :icon "book-2" :on-click #(handbooks/toggle-handbooks)} diff --git a/src/main/frontend/components/editor.cljs b/src/main/frontend/components/editor.cljs index 0fd6f1ca2e..98a04d3794 100644 --- a/src/main/frontend/components/editor.cljs +++ b/src/main/frontend/components/editor.cljs @@ -81,13 +81,7 @@ [:div.has-help {:title plugin-id} command-name - (when doc (ui/tippy - {:html doc - :interactive true - :fixed-position? true - :position "right"} - - [:small (svg/help-circle)]))] + (when doc (ui/tooltip [:small (svg/help-circle)] doc))] (string? doc) [:div {:title doc} diff --git a/src/main/frontend/components/file_based/block.cljs b/src/main/frontend/components/file_based/block.cljs index 47f435d2f3..cb54f1c39d 100644 --- a/src/main/frontend/components/file_based/block.cljs +++ b/src/main/frontend/components/file_based/block.cljs @@ -81,10 +81,9 @@ (defn priority-cp [{:block/keys [pre-block? priority] :as block}] (when (and (not pre-block?) priority) - (ui/tippy - {:interactive true - :html (set-priority block priority)} - (priority-text priority)))) + (ui/tooltip + (priority-text priority) + (set-priority block priority)))) (defn clock-summary-cp [block body] @@ -96,22 +95,20 @@ (not= summary "0m") (not (string/blank? summary))) [:div {:style {:max-width 100}} - (ui/tippy {:html (fn [] - (when-let [logbook (drawer/get-logbook body)] - (let [clocks (->> (last logbook) - (filter #(string/starts-with? % "CLOCK:")) - (remove string/blank?))] - [:div.p-4 - [:div.font-bold.mb-2 "LOGBOOK:"] - [:ul - (for [clock (take 10 (reverse clocks))] - [:li clock])]]))) - :interactive true - :in-editor? true - :delay [1000, 100]} - [:div.text-sm.time-spent.ml-1 {:style {:padding-top 3}} - [:a.fade-link - summary]])])))) + (ui/tooltip + [:div.text-sm.time-spent.ml-1 {:style {:padding-top 3}} + [:a.fade-link + summary]] + + (when-let [logbook (drawer/get-logbook body)] + (let [clocks (->> (last logbook) + (filter #(string/starts-with? % "CLOCK:")) + (remove string/blank?))] + [:div.p-4 + [:div.font-bold.mb-2 "LOGBOOK:"] + [:ul + (for [clock (take 10 (reverse clocks))] + [:li clock])]])))])))) (rum/defc timestamp-editor [ast *show-datapicker?] diff --git a/src/main/frontend/components/file_based/query.cljs b/src/main/frontend/components/file_based/query.cljs index ff04e3dcef..57337980b3 100644 --- a/src/main/frontend/components/file_based/query.cljs +++ b/src/main/frontend/components/file_based/query.cljs @@ -10,22 +10,17 @@ (rum/defc query-refresh-button [query-time {:keys [on-pointer-down full-text-search?]}] - (ui/tippy - {:html [:div - [:p - (if full-text-search? - [:span "Full-text search results will not be refreshed automatically."] - [:span (str "This query takes " (int query-time) "ms to finish, it's a bit slow so that auto refresh is disabled.")])] - [:p - "Click the refresh button instead if you want to see the latest result."]] - :interactive true - :popperOptions {:modifiers {:preventOverflow - {:enabled true - :boundariesElement "viewport"}}} - :arrow true} - [:a.fade-link.flex - {:on-pointer-down on-pointer-down} - (ui/icon "refresh" {:style {:font-size 20}})])) + (ui/tooltip + [:a.fade-link.flex + {:on-pointer-down on-pointer-down} + (ui/icon "refresh" {:style {:font-size 20}})] + [:div + [:p + (if full-text-search? + [:span "Full-text search results will not be refreshed automatically."] + [:span (str "This query takes " (int query-time) "ms to finish, it's a bit slow so that auto refresh is disabled.")])] + [:p + "Click the refresh button instead if you want to see the latest result."]])) ;; Custom query header only used by file graphs (rum/defc custom-query-header diff --git a/src/main/frontend/components/page.cljs b/src/main/frontend/components/page.cljs index 7cc014175e..d5feabca84 100644 --- a/src/main/frontend/components/page.cljs +++ b/src/main/frontend/components/page.cljs @@ -908,30 +908,35 @@ (reset! *excluded-pages? value) (set-setting! :excluded-pages? value))) true)]] + (when (config/db-based-graph? (state/get-current-repo)) [:div.flex.flex-col.mb-2 [:p "Created before"] (when created-at-filter [:div (.toDateString (js/Date. (+ created-at-filter (get-in graph [:all-pages :created-at-min]))))]) - (ui/tippy {:html [:div.pr-3 (str (js/Date. (+ created-at-filter (get-in graph [:all-pages :created-at-min]))))]} - ;; Slider keeps track off the range from min created-at to max created-at - ;; because there were bugs with setting min and max directly - (ui/slider created-at-filter - {:min 0 - :max (- (get-in graph [:all-pages :created-at-max]) - (get-in graph [:all-pages :created-at-min])) - :on-change #(do - (reset! *created-at-filter (int %)) - (set-setting! :created-at-filter (int %)))}))]) + + (ui/tooltip + ;; Slider keeps track off the range from min created-at to max created-at + ;; because there were bugs with setting min and max directly + (ui/slider created-at-filter + {:min 0 + :max (- (get-in graph [:all-pages :created-at-max]) + (get-in graph [:all-pages :created-at-min])) + :on-change #(do + (reset! *created-at-filter (int %)) + (set-setting! :created-at-filter (int %)))}) + [:div.px-1 (str (js/Date. (+ created-at-filter (get-in graph [:all-pages :created-at-min]))))])]) + (when (seq focus-nodes) [:div.flex.flex-col.mb-2 [:p {:title "N hops from selected nodes"} "N hops from selected nodes"] - (ui/tippy {:html [:div.pr-3 n-hops]} - (ui/slider (or n-hops 10) - {:min 1 - :max 10 - :on-change #(reset! *n-hops (int %))}))]) + (ui/tooltip + (ui/slider (or n-hops 10) + {:min 1 + :max 10 + :on-change #(reset! *n-hops (int %))}) + [:div n-hops])]) [:a.opacity-70.opacity-100 {:on-click (fn [] (swap! *graph-reset? not) @@ -977,39 +982,45 @@ [:div.flex.flex-col.mb-2 [:p {:title "Link Distance"} "Link Distance"] - (ui/tippy {:html [:div.pr-3 link-dist]} - (ui/slider (/ link-dist 10) - {:min 1 ;; 10 - :max 18 ;; 180 - :on-change #(let [value (int %)] - (reset! *link-dist (* value 10)) - (set-forcesetting! :link-dist (* value 10)))}))] + (ui/tooltip + (ui/slider (/ link-dist 10) + {:min 1 ;; 10 + :max 18 ;; 180 + :on-change #(let [value (int %)] + (reset! *link-dist (* value 10)) + (set-forcesetting! :link-dist (* value 10)))}) + [:div link-dist])] + [:div.flex.flex-col.mb-2 [:p {:title "Charge Strength"} "Charge Strength"] - (ui/tippy {:html [:div.pr-3 charge-strength]} - (ui/slider (/ charge-strength 100) - {:min -10 ;;-1000 - :max 10 ;;1000 - :on-change #(let [value (int %)] - (reset! *charge-strength (* value 100)) - (set-forcesetting! :charge-strength (* value 100)))}))] + (ui/tooltip + (ui/slider (/ charge-strength 100) + {:min -10 ;;-1000 + :max 10 ;;1000 + :on-change #(let [value (int %)] + (reset! *charge-strength (* value 100)) + (set-forcesetting! :charge-strength (* value 100)))}) + [:div charge-strength])] + [:div.flex.flex-col.mb-2 [:p {:title "Charge Range"} "Charge Range"] - (ui/tippy {:html [:div.pr-3 charge-range]} - (ui/slider (/ charge-range 100) - {:min 5 ;;500 - :max 40 ;;4000 - :on-change #(let [value (int %)] - (reset! *charge-range (* value 100)) - (set-forcesetting! :charge-range (* value 100)))}))] + (ui/tooltip + (ui/slider (/ charge-range 100) + {:min 5 ;;500 + :max 40 ;;4000 + :on-change #(let [value (int %)] + (reset! *charge-range (* value 100)) + (set-forcesetting! :charge-range (* value 100)))}) + [:div charge-range])] - [:a.opacity-70.opacity-100 {:on-click (fn [] - (swap! *graph-forcereset? not) - (reset! *link-dist 70) - (reset! *charge-strength -600) - (reset! *charge-range 600))} + [:a + {:on-click (fn [] + (swap! *graph-forcereset? not) + (reset! *link-dist 70) + (reset! *charge-strength -600) + (reset! *charge-range 600))} "Reset Forces"]]])) {}) (graph-filter-section diff --git a/src/main/frontend/components/plugins.cljs b/src/main/frontend/components/plugins.cljs index ac67dd6b2d..80e1add4f3 100644 --- a/src/main/frontend/components/plugins.cljs +++ b/src/main/frontend/components/plugins.cljs @@ -585,14 +585,14 @@ (when (and develop-mode? (util/electron?) (not market?)) [:div - (ui/tippy {:html [:div (t :plugin/unpacked-tips)] - :arrow true} - (ui/button - (t :plugin/load-unpacked) - {:icon "upload" - :intent "link" - :class "load-unpacked" - :on-click plugin-handler/load-unpacked-plugin})) + (ui/tooltip + (ui/button + (t :plugin/load-unpacked) + {:icon "upload" + :intent "link" + :class "load-unpacked" + :on-click plugin-handler/load-unpacked-plugin}) + [:div (t :plugin/unpacked-tips)]) (when (util/electron?) (unpacked-plugin-loader selected-unpacked-pkg))])] @@ -1075,9 +1075,7 @@ [:div.px-4 (when-not (string/blank? notes) - (ui/tippy - {:html [:p notes]} - [:span.opacity-30.hover:opacity-80 (ui/icon "info-circle")]))]])] + (ui/tooltip [:span.opacity-30.hover:opacity-80 (ui/icon "info-circle")] [:p notes]))]])] ;; all done [:div.py-4 [:strong.text-4xl (str "\uD83C\uDF89 " (t :plugin/all-updated))]]) diff --git a/src/main/frontend/components/property.cljs b/src/main/frontend/components/property.cljs index d6795e3364..ec3078505c 100644 --- a/src/main/frontend/components/property.cljs +++ b/src/main/frontend/components/property.cljs @@ -145,11 +145,8 @@ (when (= "Enter" (.-key e)) (util/stop-propagation e)))} label))))) (when show-type-change-hints? - (ui/tippy {:html "Changing the property type clears some property configurations." - :class "tippy-hover ml-2" - :interactive true - :disabled false} - (svg/info)))])) + (ui/tooltip (svg/info) + [:span "Changing the property type clears some property configurations."]))])) (rum/defc property-select [exclude-properties select-opts] diff --git a/src/main/frontend/components/property/config.cljs b/src/main/frontend/components/property/config.cljs index 939317a404..a542623bb3 100644 --- a/src/main/frontend/components/property/config.cljs +++ b/src/main/frontend/components/property/config.cljs @@ -601,19 +601,17 @@ (dropdown-editor-menuitem {:icon :letter-t :title "Property type" :desc (if disabled?' - (ui/tippy {:html [:div.w-96 - "The type of this property is locked once you start using it. This is to make sure all your existing information stays correct if the property type is changed later. To unlock, all uses of a property must be deleted."] - :class "tippy-hover ml-2" - :interactive true - :disabled false} - (str property-type-label')) + (ui/tooltip + [:span (str property-type-label')] + [:div.w-96 + "The type of this property is locked once you start using it. This is to make sure all your existing information stays correct if the property type is changed later. To unlock, all uses of a property must be deleted."]) (str property-type-label')) :disabled? disabled?' :submenu-content (fn [ops] (property-type-sub-pane property ops))})) (when (and (= property-type :node) - (not (contains? #{:logseq.property/parent} (:db/ident property)))) + (not (contains? #{:logseq.property/parent} (:db/ident property)))) (dropdown-editor-menuitem {:icon :hash :disabled? disabled? :title "Specify node tags" diff --git a/src/main/frontend/components/settings.cljs b/src/main/frontend/components/settings.cljs index ec633b381f..12b2bf6962 100644 --- a/src/main/frontend/components/settings.cljs +++ b/src/main/frontend/components/settings.cljs @@ -381,13 +381,7 @@ :let [active? (= color color-accent) none? (= color :none)]] [:div.flex.items-center - (ui/tippy - {:html (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")) - :delay [1000, 100]} + (ui/tooltip (shui/button {:class "w-5 h-5 px-1 rounded-full flex justify-center items-center transition ease-in duration-100 hover:cursor-pointer hover:opacity-100" :auto-focus (and _in-modal? active?) @@ -402,7 +396,13 @@ {:class (if none? "h-0.5 w-full bg-red-700" "w-2 h-2 rounded-full transition ease-in duration-100") :style {:background-color (if-not none? (str "var(--rx-" (name color) "-07)") "") - :opacity (if (or none? active?) 1 0)}}]))])]] + :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")))])]] [:div (row-with-button-action @@ -431,11 +431,8 @@ {:for "custom_date_format"} (t :settings-page/custom-date-format) (when-not (config/db-based-graph? (state/get-current-repo)) - (ui/tippy {:html (t :settings-page/custom-date-format-warning) - :class "tippy-hover ml-2" - :interactive true - :disabled false} - (svg/info)))] + (ui/tooltip [:span.flex.px-2 (svg/info)] + [: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 @@ -484,11 +481,8 @@ (defn outdenting-row [t logical-outdenting?] (toggle "preferred_outdenting" [(t :settings-page/preferred-outdenting) - (ui/tippy {:html (outdenting-hint) - :class "tippy-hover ml-2" - :interactive true - :disabled false} - (svg/info))] + (ui/tooltip [:span.flex.px-2 (svg/info)] + (outdenting-hint) {:content-props {:side "right"}})] logical-outdenting? config-handler/toggle-logical-outdenting!)) @@ -501,22 +495,16 @@ (defn preferred-pasting-file [t preferred-pasting-file?] (toggle "preferred_pasting_file" [(t :settings-page/preferred-pasting-file) - (ui/tippy {:html (t :settings-page/preferred-pasting-file-hint) - :class "tippy-hover ml-2" - :interactive true - :disabled false} - (svg/info))] + (ui/tooltip [:span.flex.px-2 (svg/info)] + [:span.block.w-64 (t :settings-page/preferred-pasting-file-hint)])] preferred-pasting-file? config-handler/toggle-preferred-pasting-file!)) (defn auto-expand-row [t auto-expand-block-refs?] (toggle "auto_expand_block_refs" [(t :settings-page/auto-expand-block-refs) - (ui/tippy {:html (auto-expand-hint) - :class "tippy-hover ml-2" - :interactive true - :disabled false} - (svg/info))] + (ui/tooltip [:span.flex.px-2 (svg/info)] + (auto-expand-hint))] auto-expand-block-refs? config-handler/toggle-auto-expand-block-refs!)) @@ -866,26 +854,23 @@ (row-with-button-action {: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/tippy {:html [:div - [:div (t :settings-page/sync-diff-merge-desc)] - [:div (t :settings-page/sync-diff-merge-warn)]] - :class "tippy-hover ml-2" - :interactive true - :disabled false} - (svg/info))})) + :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)]])})) (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?] diff --git a/src/main/frontend/extensions/srs.cljs b/src/main/frontend/extensions/srs.cljs index bfb387c66d..7c2a236937 100644 --- a/src/main/frontend/extensions/srs.cljs +++ b/src/main/frontend/extensions/srs.cljs @@ -488,16 +488,17 @@ :on-click #(score-and-next-card 5 card card-index finished? phase review-records cb)})]) (when preview? - (ui/tippy {:html [:div.text-sm - (t :flashcards/modal-btn-reset-tip)] - :class "tippy-hover" - :interactive true} - (ui/button [:span (t :flashcards/modal-btn-reset)] - :id "card-reset" - :class (util/hiccup->class "opacity-60.hover:opacity-100.card-reset") - :on-click (fn [e] - (util/stop e) - (operation-reset! card)))))] + (ui/tooltip + (ui/button [:span (t :flashcards/modal-btn-reset)] + :id "card-reset" + :class (util/hiccup->class "opacity-60.hover:opacity-100.card-reset") + :on-click (fn [e] + (util/stop e) + (operation-reset! card))) + + [:div.text-sm + (t :flashcards/modal-btn-reset-tip)] + {:trigger-props {:as-child false}}))] [:div.my-3 (ui/button "Review cards" :small? true)])])))) (rum/defc view-modal < @@ -629,27 +630,20 @@ ;; FIXME: CSS issue (if @*preview-mode? - (ui/tippy {:html [:div.text-sm (t :flashcards/modal-current-total)] - :interactive true} - [:div.opacity-60.text-sm.mr-2 - @*card-index - [:span "/"] - total]) - (ui/tippy {:html [:div.text-sm (t :flashcards/modal-overdue-total)] - ;; :class "tippy-hover" - :interactive true} - [:div.opacity-60.text-sm.mr-2 - (max 0 (- filtered-total @*card-index)) - [:span "/"] - total])) - - (ui/tippy - {:html [:div.text-sm (t :flashcards/modal-toggle-preview-mode)] - :delay [1000, 100] - :class "tippy-hover" - :interactive true - :disabled false} + (ui/tooltip + [:div.opacity-60.text-sm.mr-2 + @*card-index + [:span "/"] + total] + [:div.text-sm (t :flashcards/modal-current-total)]) + (ui/tooltip + [:div.opacity-60.text-sm.mr-2 + (max 0 (- filtered-total @*card-index)) + [:span "/"] + total] + [:div.text-sm (t :flashcards/modal-overdue-total)])) + (ui/tooltip (ui/button (merge {:icon "letter-a" @@ -661,13 +655,11 @@ :button-props {:id "preview-all-cards"} :small? true} (when @*preview-mode? - {:icon-props {:style {:color "var(--ls-button-background)"}}})))) + {:icon-props {:style {:color "var(--ls-button-background)"}}}))) + [:div.text-sm (t :flashcards/modal-toggle-preview-mode)] + {:trigger-props {:as-child false}}) - (ui/tippy - {:html [:div.text-sm (t :flashcards/modal-toggle-random-mode)] - :delay [1000, 100] - :class "tippy-hover" - :interactive true} + (ui/tooltip (ui/button (merge {:icon "arrows-shuffle" @@ -677,7 +669,9 @@ (swap! *random-mode? not)) :small? true} (when @*random-mode? - {:icon-props {:style {:color "var(--ls-button-background)"}}}))))]] + {:icon-props {:style {:color "var(--ls-button-background)"}}}))) + [:div.text-sm (t :flashcards/modal-toggle-random-mode)] + {:trigger-props {:as-child false}})]] [:div.px-1 (when (and (not modal?) (not @*preview-mode?)) {:on-click (fn [] diff --git a/src/main/frontend/tippy-tooltip.css b/src/main/frontend/tippy-tooltip.css deleted file mode 100644 index 2308f13277..0000000000 --- a/src/main/frontend/tippy-tooltip.css +++ /dev/null @@ -1,79 +0,0 @@ -.tippy-popper { - max-width: 800px; -} - -.tippy-popper[x-placement^=top] [x-arrow], -.tippy-popper[x-placement^=top] [x-arrow].arrow-small, -.tippy-popper[x-placement^=top] [x-arrow].arrow-big { - border-top-color: var(--ls-tertiary-background-color); -} - -.tippy-popper[x-placement^=top] .tippy-tooltip.transparent-theme [x-circle], -.tippy-popper[x-placement^=bottom] .tippy-tooltip.transparent-theme [x-circle], -.tippy-popper[x-placement^=left] .tippy-tooltip.transparent-theme [x-circle], -.tippy-popper[x-placement^=right] .tippy-tooltip.transparent-theme [x-circle], -.tippy-popper .tippy-tooltip.transparent-theme { - background-color: var(--ls-secondary-background-color); -} - -.tippy-popper[x-placement^=top] .tippy-tooltip.transparent-theme [x-arrow], -.tippy-popper[x-placement^=top] .tippy-tooltip.transparent-theme [x-arrow].arrow-small, -.tippy-popper[x-placement^=top] .tippy-tooltip.transparent-theme [x-arrow].arrow-big { - border-top-color: var(--ls-secondary-background-color); -} - -.tippy-popper[x-placement^=bottom] [x-arrow], -.tippy-popper[x-placement^=bottom] [x-arrow].arrow-small, -.tippy-popper[x-placement^=bottom] [x-arrow].arrow-big { - border-bottom-color: var(--ls-tertiary-background-color); -} - -.tippy-popper[x-placement^=bottom] .tippy-tooltip.transparent-theme [x-arrow], -.tippy-popper[x-placement^=bottom] .tippy-tooltip.transparent-theme [x-arrow].arrow-small, -.tippy-popper[x-placement^=bottom] .tippy-tooltip.transparent-theme [x-arrow].arrow-big { - border-bottom-color: var(--ls-secondary-background-color); -} - -.tippy-popper[x-placement^=left] [x-arrow], -.tippy-popper[x-placement^=left] [x-arrow].arrow-small, -.tippy-popper[x-placement^=left] [x-arrow].arrow-big { - border-left-color: var(--ls-tertiary-background-color); -} - -.tippy-popper[x-placement^=left] .tippy-tooltip.transparent-theme [x-arrow], -.tippy-popper[x-placement^=left] .tippy-tooltip.transparent-theme [x-arrow].arrow-small, -.tippy-popper[x-placement^=left] .tippy-tooltip.transparent-theme [x-arrow].arrow-big { - border-left-color: var(--ls-secondary-background-color); -} - -.tippy-popper[x-placement^=right] [x-arrow], -.tippy-popper[x-placement^=right] [x-arrow].arrow-small, -.tippy-popper[x-placement^=right] [x-arrow].arrow-big { - border-right-color: var(--ls-tertiary-background-color); -} - -.tippy-popper[x-placement^=right] .tippy-tooltip.transparent-theme [x-arrow], -.tippy-popper[x-placement^=right] .tippy-tooltip.transparent-theme [x-arrow].arrow-small, -.tippy-popper[x-placement^=right] .tippy-tooltip.transparent-theme [x-arrow].arrow-big { - border-right-color: var(--ls-tertiary-background-color); -} - -.tippy-tooltip { - @apply shadow border border-gray-07 dark:border-gray-05 px-2 py-1; - - will-change: auto; - color: var(--ls-primary-text-color, hsl(var(--foreground))); - background-color: var(--lx-gray-03, var(--ls-tertiary-background-color, var(--rx-gray-03))); -} - -.tippy-tooltip [x-circle] { - will-change: auto; -} - -.tippy-popper .tippy-tooltip.customized-theme * { - text-align: left; -} - -.tippy-popper .tippy-tooltip.monospace-theme { - font-family: 'Fira Code', Monaco, Menlo, Consolas, 'COURIER NEW', monospace; -} diff --git a/src/main/frontend/ui.cljs b/src/main/frontend/ui.cljs index f8c1852cdb..67932cfb9f 100644 --- a/src/main/frontend/ui.cljs +++ b/src/main/frontend/ui.cljs @@ -5,7 +5,6 @@ ["emoji-mart" :as emoji-mart] ["react-intersection-observer" :as react-intersection-observer] ["react-textarea-autosize" :as TextareaAutosize] - ["react-tippy" :as react-tippy] ["react-transition-group" :refer [CSSTransition TransitionGroup]] ["react-virtuoso" :refer [Virtuoso VirtuosoGrid]] [cljs-bean.core :as bean] @@ -40,6 +39,7 @@ [rum.core :as rum])) (declare icon) +(declare tooltip) (defonce transition-group (r/adapt-class TransitionGroup)) (defonce css-transition (r/adapt-class CSSTransition)) @@ -47,7 +47,6 @@ (defonce virtualized-list (r/adapt-class Virtuoso)) (defonce virtualized-grid (r/adapt-class VirtuosoGrid)) -(def Tippy (r/adapt-class (gobj/get react-tippy "Tooltip"))) (def ReactTweetEmbed (r/adapt-class react-tweet-embed)) (def useInView (gobj/get react-intersection-observer "useInView")) (defonce _emoji-init-data ((gobj/get emoji-mart "init") #js {:data emoji-data})) @@ -791,45 +790,6 @@ :checked selected}] label])])) -(rum/defcs tippy < rum/static - (rum/local false ::mounted?) - [state {:keys [fixed-position? open? html] :as opts} child] - (let [*mounted? (::mounted? state) - manual (not= open? nil) - open? (if manual open? @*mounted?) - disabled? (not (state/enable-tooltip?))] - (Tippy (-> - (merge {:arrow true - :sticky true - :delay 600 - :theme "customized" - :disabled disabled? - :unmountHTMLWhenHide true - :open (if disabled? false open?) - :trigger (if manual "manual" "mouseenter focus") - ;; See https://github.com/tvkhoa/react-tippy/issues/13 - :popperOptions {:modifiers {:flip {:enabled (not fixed-position?)} - :hide {:enabled false} - :preventOverflow {:enabled false}}} - :onShow #(when-not (or (state/editing?) - @(:ui/scrolling? @state/state)) - (reset! *mounted? true)) - :onHide #(reset! *mounted? false)} - opts) - (assoc :html (or - (when open? - (try - (when html - (if (fn? html) - (html) - [:div.px-2.py-1 - html])) - (catch :default e - (log/error :exception e) - [:div]))) - [:div {:key "tippy"} ""]))) - (rum/fragment {:key "tippy-children"} child)))) - (rum/defcs slider < rum/reactive {:init (fn [state] (assoc state ::value (atom (first (:rum/args state)))))} @@ -911,18 +871,13 @@ (rum/defc with-shortcut < rum/reactive < {:key-fn (fn [key pos] (str "shortcut-" key pos))} - [shortcut-key position content] + [shortcut-key _position content] (let [shortcut-tooltip? (state/sub :ui/shortcut-tooltip?) enabled-tooltip? (state/enable-tooltip?)] (if (and enabled-tooltip? shortcut-tooltip?) - (tippy - {:html [:div.text-sm.font-medium (keyboard-shortcut-from-config shortcut-key)] - :interactive true - :position position - :theme "monospace" - :delay [1000, 100] - :arrow true} - content) + (tooltip content + [:div.text-sm.font-medium (keyboard-shortcut-from-config shortcut-key)] + {:trigger-props {:as-child true}}) content))) (rum/defc progress-bar @@ -1020,11 +975,14 @@ :small? true)]])) (rum/defc tooltip - [trigger tooltip-content & {:keys [trigger-props]}] + [trigger tooltip-content & {:keys [portal? root-props trigger-props content-props]}] (shui/tooltip-provider - (shui/tooltip - (shui/tooltip-trigger trigger-props trigger) - (shui/tooltip-content tooltip-content)))) + (shui/tooltip root-props + (shui/tooltip-trigger (merge {:as-child true} trigger-props) trigger) + (if (not (false? portal?)) + (shui/tooltip-portal + (shui/tooltip-content content-props tooltip-content)) + (shui/tooltip-content content-props tooltip-content))))) (rum/defc DelDateButton [on-delete] From 0baaadadeb8f31423db64681f36178afcc49ab11 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Thu, 17 Apr 2025 18:34:26 +0800 Subject: [PATCH 04/11] chore: remove react-tippy css --- package.json | 5 ++--- tailwind.all.css | 1 - yarn.lock | 12 ------------ 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index ee828984d0..26be8c51d7 100644 --- a/package.json +++ b/package.json @@ -17,10 +17,9 @@ "del": "^6.0.0", "glob": "9.0.0", "gulp": "^4.0.2", - "gulp-replace": "^1.1.4", "gulp-postcss": "^10.0.0", + "gulp-replace": "^1.1.4", "ip": "1.1.9", - "semver": "7.5.2", "karma": "^6.4.4", "karma-chrome-launcher": "^3.2.0", "karma-cljs-test": "^0.1.0", @@ -33,6 +32,7 @@ "postcss-import-ext-glob": "2.0.1", "postcss-nested": "6.0.0", "purgecss": "4.0.2", + "semver": "7.5.2", "shadow-cljs": "2.26.0", "stylelint": "^13.8.0", "stylelint-config-standard": "^20.0.0", @@ -161,7 +161,6 @@ "react-intersection-observer": "^9.3.5", "react-resize-context": "3.0.0", "react-textarea-autosize": "8.3.3", - "react-tippy": "1.4.0", "react-transition-group": "4.3.0", "react-virtuoso": "4.12.5", "remove-accents": "0.4.2", diff --git a/tailwind.all.css b/tailwind.all.css index 692b862e4c..4bdde8d089 100644 --- a/tailwind.all.css +++ b/tailwind.all.css @@ -17,7 +17,6 @@ @import "codemirror/lib/codemirror.css"; @import "codemirror/theme/solarized.css"; @import "codemirror/addon/hint/show-hint.css"; -@import "react-tippy/dist/tippy.css"; @import "pdfjs-dist/web/pdf_viewer.css"; @import "resources/css/tabler-extension.css"; @import "resources/css/codemirror.lsradix.css"; diff --git a/yarn.lock b/yarn.lock index ac6b528b0b..36af11f49a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6584,11 +6584,6 @@ plugin-error@^2.0.1: dependencies: ansi-colors "^1.0.1" -popper.js@^1.11.1: - version "1.16.1" - resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" - integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== - posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -7249,13 +7244,6 @@ react-textarea-autosize@8.3.3: use-composed-ref "^1.0.0" use-latest "^1.0.0" -react-tippy@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/react-tippy/-/react-tippy-1.4.0.tgz#e8a8b4085ec985e5c94fe128918b733b588a1465" - integrity sha512-r/hM5XK9Ztr2ZY7IWKuRmISTlUPS/R6ddz6PO2EuxCgW+4JBcGZRPU06XcVPRDCOIiio8ryBQFrXMhFMhsuaHA== - dependencies: - popper.js "^1.11.1" - react-transition-group@4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.3.0.tgz#fea832e386cf8796c58b61874a3319704f5ce683" From cb66a5ad7fe9402fb13803b8240aa869d32c1f2e Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Thu, 17 Apr 2025 20:26:40 +0800 Subject: [PATCH 05/11] fix: check and fix db schema --- deps/db/src/logseq/db/common/sqlite.cljs | 4 +--- deps/db/src/logseq/db/file_based/schema.cljs | 3 ++- src/main/frontend/worker/db/fix.cljs | 23 ++++++++++++++++++++ src/main/frontend/worker/db_worker.cljs | 2 ++ 4 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 src/main/frontend/worker/db/fix.cljs diff --git a/deps/db/src/logseq/db/common/sqlite.cljs b/deps/db/src/logseq/db/common/sqlite.cljs index 3c01af14da..34fc2afade 100644 --- a/deps/db/src/logseq/db/common/sqlite.cljs +++ b/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 diff --git a/deps/db/src/logseq/db/file_based/schema.cljs b/deps/db/src/logseq/db/file_based/schema.cljs index b111d2565e..00e3beb83e 100644 --- a/deps/db/src/logseq/db/file_based/schema.cljs +++ b/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 {} diff --git a/src/main/frontend/worker/db/fix.cljs b/src/main/frontend/worker/db/fix.cljs new file mode 100644 index 0000000000..b598ba7235 --- /dev/null +++ b/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)))) diff --git a/src/main/frontend/worker/db_worker.cljs b/src/main/frontend/worker/db_worker.cljs index 2051e6259f..1ed18b6361 100644 --- a/src/main/frontend/worker/db_worker.cljs +++ b/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)] From 813d18402f5121199238d84305f5904b0f2bd292 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Thu, 17 Apr 2025 20:38:29 +0800 Subject: [PATCH 06/11] fix: lint --- src/main/frontend/handler/events/ui.cljs | 41 ++++++++++++++++++- .../frontend/handler/file_based/events.cljs | 34 --------------- 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/main/frontend/handler/events/ui.cljs b/src/main/frontend/handler/events/ui.cljs index 9089eb4c63..ab5f1055f6 100644 --- a/src/main/frontend/handler/events/ui.cljs +++ b/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,35 @@ (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/c (rtc-handler/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/c (rtc-handler/ Date: Thu, 17 Apr 2025 20:48:39 +0800 Subject: [PATCH 07/11] fix: lint --- src/main/frontend/handler/events/ui.cljs | 9 +++++++++ src/main/frontend/handler/file_based/events.cljs | 9 --------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/frontend/handler/events/ui.cljs b/src/main/frontend/handler/events/ui.cljs index ab5f1055f6..4e322209af 100644 --- a/src/main/frontend/handler/events/ui.cljs +++ b/src/main/frontend/handler/events/ui.cljs @@ -391,3 +391,12 @@ (util/uuid-string? (second (:sync-meta %)))) repos) (sync/ Date: Thu, 17 Apr 2025 21:08:03 +0800 Subject: [PATCH 08/11] fix: can't set status in page reference --- src/main/frontend/components/block.cljs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/frontend/components/block.cljs b/src/main/frontend/components/block.cljs index ce750bf85f..d90e63c15d 100644 --- a/src/main/frontend/components/block.cljs +++ b/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? From 424dfce32ce88df0afdc49ad9808d2c4f3bf4018 Mon Sep 17 00:00:00 2001 From: Gabriel Horner Date: Thu, 17 Apr 2025 09:39:20 -0400 Subject: [PATCH 09/11] fix: backspace on block with property deletes prev children Fixes https://github.com/logseq/db-test/issues/249 --- src/main/frontend/handler/editor.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index 6a39c91edb..6d629b9383 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/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)) From 5bd127b10161bbb9af77080db2cfca50f5475ba9 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Thu, 17 Apr 2025 21:41:28 +0800 Subject: [PATCH 10/11] fix: fuzzy search on commands returns wrong result --- src/main/frontend/commands.cljs | 27 +++++++++++------------- src/main/frontend/components/editor.cljs | 2 +- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/main/frontend/commands.cljs b/src/main/frontend/commands.cljs index ee19b85269..eda82796bb 100644 --- a/src/main/frontend/commands.cljs +++ b/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,7 +294,7 @@ [] (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 *matched-commands (atom nil)) (defonce *initial-commands (atom nil)) diff --git a/src/main/frontend/components/editor.cljs b/src/main/frontend/components/editor.cljs index 98a04d3794..bc9eaac8df 100644 --- a/src/main/frontend/components/editor.cljs +++ b/src/main/frontend/components/editor.cljs @@ -45,7 +45,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 From 1d4c6a100f249b99ba9132533a12c4eb97b11d7e Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Thu, 17 Apr 2025 21:53:25 +0800 Subject: [PATCH 11/11] enhance: hide group when user already input some command text --- src/main/frontend/components/editor.cljs | 94 ++++++++++++------------ 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/src/main/frontend/components/editor.cljs b/src/main/frontend/components/editor.cljs index bc9eaac8df..9ce0cd5e26 100644 --- a/src/main/frontend/components/editor.cljs +++ b/src/main/frontend/components/editor.cljs @@ -56,57 +56,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 (filter-commands page? @*matched) + filtered? (not= matched @commands/*initial-commands)] (ui/auto-complete matched - {:get-group-name - (fn [item] - (when (= (count item) 5) (last item))) + (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))] - :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] - (string? doc) - [:div {:title doc} - command-name] + :else + [:div 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"}))) + :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]