Merge branch 'master' into enhance/ios-native-navigation

This commit is contained in:
Tienson Qin
2025-11-26 16:18:54 +08:00
10 changed files with 121 additions and 61 deletions

View File

@@ -7,7 +7,7 @@
(defn append
[{{:keys [api-server-token args]} :opts}]
(let [text (string/join " " args)]
(-> (p/let [resp (cli-util/api-fetch api-server-token "logseq.app.append_block_in_page" [text nil nil])]
(-> (p/let [resp (cli-util/api-fetch api-server-token "logseq.app.append_block_in_page" [text])]
(if (= 200 (.-status resp))
(println "Success!")
(cli-util/api-handle-error-response resp)))

View File

@@ -161,8 +161,12 @@
;; (cljs.pprint/pprint _txs)
(if error
(reset! *result {:error error})
(ldb/transact! conn (vec (concat init-tx block-props-tx misc-tx))
(merge {::sqlite-export/imported-data? true} tx-meta)))))
(try
(ldb/transact! conn (vec (concat init-tx block-props-tx misc-tx))
(merge {::sqlite-export/imported-data? true} tx-meta))
(catch :default e
(js/console.error "Unexpected Import EDN error:" e)
(reset! *result {:error (str "Unexpected Import EDN error: " (pr-str (ex-message e)))}))))))
(defn ^:large-vars/cleanup-todo apply-ops!
[repo conn ops date-formatter opts]

View File

@@ -657,7 +657,7 @@ export interface IEditorProxy extends Record<string, any> {
*
* @param srcPage - the page name or uuid
*/
getPageBlocksTree: (srcPage: PageIdentity) => Promise<Array<BlockEntity>>
getPageBlocksTree: (srcPage: PageIdentity) => Promise<Array<BlockEntity> | null>
/**
* get all page/block linked references

View File

@@ -406,7 +406,7 @@
(let [current-repo (state/sub :git/current-repo)
theme (state/sub :ui/theme)
accent-color (some-> (state/sub :ui/radix-color) (name))
editor-font (some-> (state/sub :ui/editor-font) (name))
editor-font (state/sub :ui/editor-font)
system-theme? (state/sub :ui/system-theme?)
light? (= "light" (state/sub :ui/theme))
sidebar-open? (state/sub :ui/sidebar-open?)

View File

@@ -14,16 +14,16 @@
(rum/defcs panel-of-tokens
< rum/reactive
(rum/local nil ::tokens)
{:will-mount
(fn [s]
(let [*tokens (s ::tokens)]
(reset! *tokens (get-in @state/state [:electron/server :tokens])) s))}
(rum/local nil ::tokens)
{:will-mount
(fn [s]
(let [*tokens (s ::tokens)]
(reset! *tokens (get-in @state/state [:electron/server :tokens])) s))}
[_state close-panel]
(let [server-state (state/sub :electron/server)
*tokens (::tokens _state)
changed? (not= @*tokens (:tokens server-state))]
*tokens (::tokens _state)
changed? (not= @*tokens (:tokens server-state))]
[:div.cp__server-tokens-panel.pt-6
[:h2.text-3xl.-translate-y-4 "Authorization tokens"]
;; items
@@ -32,17 +32,25 @@
[:div.item.py-2.flex.space-x-2.items-center
{:key idx}
[:input.form-input.basis-36
{:auto-focus true
{:auto-focus true
:placeholder "name"
:value name
:on-change #(let [value (.-value (.-target %))]
(update-value! idx :name value))}]
:value name
:on-change #(let [value (.-value (.-target %))]
(update-value! idx :name value))}]
[:input.form-input
{:placeholder "value"
:value value
:on-change #(let [value (.-value (.-target %))]
(update-value! idx :value value))}]
:value value
:on-change #(let [value (.-value (.-target %))]
(update-value! idx :value value))}]
[:button.px-2.opacity-50.hover:opacity-90.active:opacity-100
{:on-click #(let [new-token (util/unique-id)
^js input-el (some-> (.-target %) (.closest ".item") (.querySelector "input.form-input:nth-child(2)"))]
(update-value! idx :value new-token)
(when input-el
(js/setTimeout (fn [] (.select input-el)) 64)))
:title "Regenerate token value"}
[:span.flex.items-center (ui/icon "refresh")]]
[:button.px-2.opacity-50.hover:opacity-90.active:opacity-100
{:on-click #(reset! *tokens (into [] (medley/remove-nth idx @*tokens)))}
[:span.flex.items-center (ui/icon "trash-x")]]]))
@@ -134,10 +142,10 @@
#(js/clearTimeout t))))
[])
(let [{:keys [status error]} server-state
status (keyword (util/safe-lower-case status))
(let [{:keys [status error mcp-enabled?]} server-state
status (keyword (util/safe-lower-case status))
running? (= :running status)
href (and running? (str "http://" (:host server-state) ":" (:port server-state)))]
href (and running? (str "http://" (:host server-state) ":" (:port server-state)))]
(hooks/use-effect!
#(when error
@@ -180,7 +188,16 @@
[:span.ml-1.text-sm.opacity-70
(if-not running?
(string/upper-case (or (:status server-state) "stopped"))
[:a.hover:underline {:href href} href])]]
[:span.flex.flex-col.gap-1.text-xs.font-mono
[:a.hover:underline.flex.items-center {:href href}
href (shui/tabler-icon "external-link" {:size 12 :class "inline-block ml-1 pt-[1px]"})]
(when mcp-enabled?
[:a.hover:underline.flex.items-center
{:on-click (fn []
(util/copy-to-clipboard! (str href "/mcp"))
(notification/show! "MCP URL copied to clipboard!" :success))}
(str href "/mcp")
(shui/tabler-icon "copy" {:size 12 :class "inline-block ml-1 mt-[1px]"})])])]]
(for [{:keys [hr? title options icon]} items]
(cond
hr?

View File

@@ -241,25 +241,31 @@
[:div {:style {:text-align "right"}}
(ui/render-keyboard-shortcut (shortcut-helper/gen-shortcut-seq :ui/toggle-wide-mode))])])
(defn editor-font-family-row [t font]
(defn editor-font-family-row [t {:keys [type global]}]
[:div.it.sm:grid.sm:grid-cols-3.sm:gap-4
[:label.block.text-sm.font-medium.leading-5.opacity-70
{:for "font_family"}
(t :settings-page/editor-font)]
[:div.col-span-2.flex.gap-2
(for [t [:default :serif :mono]
:let [t (name t)
tt (string/capitalize t)
active? (= font t)]]
(shui/button
{:variant :secondary
:class (when active? " border-primary border-[2px]")
:style {:width "4.4rem"}
:on-click #(state/set-editor-font! t)}
[:span.flex.flex-col
{:class (str "ls-font-" t)}
[:strong "Ag"]
[:small tt]]))]])
[:div.flex.flex-col.col-span-2
[:div.flex.gap-2
(for [t [:default :serif :mono]
:let [t (name t)
tt (string/capitalize t)
active? (= (or type "default") t)]]
(shui/button
{:variant :secondary
:class (when active? " border-primary border-[2px]")
:style {:width "4.4rem"}
:on-click #(state/set-editor-font! {:type t})}
[:span.flex.flex-col
{:class (str "ls-font-" t)}
[:strong "Ag"]
[:small tt]]))]
[:div.pt-3
[:label.w-full.flex.items-center.cursor-pointer
(shui/checkbox {:checked (boolean global)
:on-checked-change #(state/set-editor-font! {:global %})})
[:span.pl-1.text-sm.opacity-70 "Set as global font family"]]]]])
(rum/defcs switch-spell-check-row < rum/reactive
[state t]
@@ -1356,7 +1362,7 @@
(when (and new-val (not (storage/get ::storage-spec/http-server-enabled)))
(storage/set ::storage-spec/http-server-enabled true))
(-> (ipc/ipc :server/set-config {:mcp-enabled? new-val})
;; Dont start server if it's not running
;; Don't start server if it's not running
(p/then #(when (= "running" (state/sub [:electron/server :status]))
(p/let [_ (p/delay 1000)]
(ipc/ipc :server/do :restart))))

View File

@@ -63,9 +63,12 @@
[accent-color])
(hooks/use-effect!
#(some-> js/document.documentElement
(.setAttribute "data-font" (or editor-font "default")))
[editor-font])
(fn []
(when-let [{:keys [type global]} editor-font]
(doto js/document.documentElement
(.setAttribute "data-font" (or type "default"))
(.setAttribute "data-font-global" (boolean global)))))
[editor-font])
(hooks/use-effect!
#(let [doc js/document.documentElement]

View File

@@ -16,7 +16,7 @@
}
}
.visible-scrollbar , html.custom-scrollbar {
.visible-scrollbar, html.custom-scrollbar {
::-webkit-scrollbar-thumb {
background-color: var(--lx-gray-05, var(--ls-scrollbar-foreground-color, var(--rx-gray-05)));
}
@@ -89,7 +89,8 @@ html[data-theme='light'] .theme-container {
}
}
html[data-theme='dark'] .theme-container {}
html[data-theme='dark'] .theme-container {
}
html.locked-scroll {
overflow: hidden !important;
@@ -195,6 +196,14 @@ html[data-font='serif'] .ls-block, .ls-font-serif {
font-family: Lyon-Text, Georgia, ui-serif, serif;
}
html[data-font='serif'][data-font-global='true'] {
--ls-font-family: Lyon-Text, Georgia, ui-serif, serif;
}
html[data-font='mono'] .ls-block, .ls-font-mono {
font-family: iawriter-mono, Nitti, Menlo, Courier, monospace;
}
html[data-font='mono'][data-font-global='true'] {
--ls-font-family: iawriter-mono, Nitti, Menlo, Courier, monospace;
}

View File

@@ -2287,10 +2287,11 @@ Similar to re-frame subscriptions"
(swap! state assoc :ui/radix-color color)
(storage/set :ui/radix-color color))
(defn set-editor-font! [font]
(let [font (if (keyword? font) (name font) (str font))]
(swap! state assoc :ui/editor-font font)
(storage/set :ui/editor-font font)))
(defn set-editor-font! [config]
(let [config' (:ui/editor-font @state)
config (if (map? config') (merge config' config) {})]
(swap! state assoc :ui/editor-font config)
(storage/set :ui/editor-font config)))
(defn handbook-open?
[]

View File

@@ -174,24 +174,44 @@
(defn- send&recv*
"Return a task: send message wait to recv its response and return it.
Throw if timeout"
[mws message & {:keys [timeout-ms] :or {timeout-ms 10000}}]
[mws message & {:keys [timeout-ms s3-get-timeout-ms]
:or {timeout-ms 10000 s3-get-timeout-ms 10000}}]
{:pre [(pos-int? timeout-ms)
(some? (:req-id message))]}
(m/sp
(m/? (send mws message))
(let [req-id (:req-id message)
result (m/?
(m/timeout
(m/reduce
(fn [_ v]
(when (= req-id (:req-id v))
(reduced v)))
(recv-flow mws))
timeout-ms))]
(when-not result
(throw (ex-info (str "recv timeout (" timeout-ms "ms)") {:missionary/retry true
:type :rtc.exception/ws-timeout
:message message})))
ws-message-result
(m/?
(m/timeout
(m/reduce
(fn [_ v]
(when (= req-id (:req-id v))
(reduced v)))
(recv-flow* mws))
timeout-ms
(ex-info (str "recv ws message timeout (" timeout-ms "ms)") {})))
result (if-let [s3-presign-url (:s3-presign-url ws-message-result)]
(let [{:keys [status body] :as r}
(m/? (m/timeout
(http/get s3-presign-url {:with-credentials? false})
s3-get-timeout-ms
(ex-info (str "recv s3 message timeout (" s3-get-timeout-ms "ms)") {})))]
(cond
(instance? ExceptionInfo r) r
(http/unexceptional-status? status)
(rtc-schema/data-from-ws-coercer (js->clj (js/JSON.parse body) :keywordize-keys true))
:else
{:req-id (:req-id ws-message-result)
:ex-message "get s3 object failed"
:ex-data {:type :rtc.exception/get-s3-object-failed :status status :body body}}))
ws-message-result)]
(when (instance? ExceptionInfo result)
(throw (ex-info (ex-message result) {:missionary/retry true
:type :rtc.exception/ws-timeout
:message message})))
result)))
(defn send&recv