From 6c05b9d66efd893d13ae2eb6a4f98525d7f51ed6 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Thu, 16 Apr 2026 16:32:50 +0800 Subject: [PATCH 1/5] chore: bump cider-nrepl --- deps.edn | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deps.edn b/deps.edn index 3bb1087a23..4b29a1cc31 100644 --- a/deps.edn +++ b/deps.edn @@ -56,7 +56,7 @@ :aliases {:cljs {:extra-paths ["src/dev-cljs/" "src/test/" "src/electron/"] :extra-deps {org.clojure/tools.namespace {:mvn/version "1.5.0"} - cider/cider-nrepl {:mvn/version "0.58.0"} + cider/cider-nrepl {:mvn/version "0.59.0"} org.clojars.knubie/cljs-run-test {:mvn/version "1.0.1"} tortue/spy {:mvn/version "2.15.0"} binaryage/devtools {:mvn/version "1.0.7"}} @@ -66,7 +66,7 @@ pjstadig/humane-test-output {:mvn/version "0.11.0"} org.clojars.knubie/cljs-run-test {:mvn/version "1.0.1"} tortue/spy {:mvn/version "2.15.0"} - cider/cider-nrepl {:mvn/version "0.58.0"}} + cider/cider-nrepl {:mvn/version "0.59.0"}} :main-opts ["-m" "shadow.cljs.devtools.cli"]} :bench {:extra-paths ["src/bench/"] From 8606a8b5f0c2f5200621cf51785136250f9dd53b Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Fri, 17 Apr 2026 01:30:48 +0800 Subject: [PATCH 2/5] fix: it's unsafe to invoke d/store in nested batch tx Switched to use our own `conn-from-db` that doesn't call `d/store`. --- deps/db/src/logseq/db.cljs | 19 +++++++- deps/outliner/src/logseq/outliner/op.cljs | 56 ++--------------------- 2 files changed, 23 insertions(+), 52 deletions(-) diff --git a/deps/db/src/logseq/db.cljs b/deps/db/src/logseq/db.cljs index b09b01e968..425854a6ed 100644 --- a/deps/db/src/logseq/db.cljs +++ b/deps/db/src/logseq/db.cljs @@ -212,6 +212,23 @@ (transact-fn repo-or-conn tx-data tx-meta) (transact-sync repo-or-conn tx-data tx-meta)))))) +(defn- make-conn [opts] + ;; `datascript.conn/->Conn` is not exposed in nbb runtime. + ;; Start from a fresh conn and merge the desired internal state. + (let [conn (d/create-conn)] + (swap! (:atom conn) merge opts) + conn)) + +(defn- conn-from-db + "Forked conn-from-db to not invoke `d/store`, it's unsafe to store during nested batch tx." + [db] + (if-some [_storage (storage/storage db)] + (make-conn + {:db db + :tx-tail [] + :db-last-stored db}) + (make-conn {:db db}))) + (defn batch-transact-with-temp-conn! "Run batched tx work against a temporary conn, then apply all collected tx-data to `conn` with a single final `transact!`. @@ -229,7 +246,7 @@ - `listen-db` (if provided) receives each intermediate tx-report from temp conn. - Do not rely on returned tx-report shape for undo/redo behavior." [conn tx-meta batch-tx-fn & {:keys [listen-db]}] - (let [temp-conn (d/conn-from-db @conn) + (let [temp-conn (conn-from-db @conn) *batch-tx-data (volatile! []) *complete? (volatile! false)] ;; can read from disk, write is disallowed diff --git a/deps/outliner/src/logseq/outliner/op.cljs b/deps/outliner/src/logseq/outliner/op.cljs index 00549d2019..49eac988f5 100644 --- a/deps/outliner/src/logseq/outliner/op.cljs +++ b/deps/outliner/src/logseq/outliner/op.cljs @@ -371,41 +371,6 @@ (reset! *result (apply toggle-reaction! conn args)) nil)) -(defn- apply-single-op! - [conn ops *result opts' clean-tx-meta] - (let [db @conn - op (first ops) - result (case (ffirst ops) - :save-block - (apply outliner-core/save-block db (second op)) - :insert-blocks - (let [[blocks target-block-id insert-opts] (second op)] - (outliner-core/insert-blocks db blocks - (d/entity db [:block/uuid target-block-id]) - insert-opts)) - :delete-blocks - (let [[block-ids opts] (second op) - blocks (keep #(d/entity db [:block/uuid %]) block-ids)] - (outliner-core/delete-blocks db blocks (merge opts opts')))) - additional-tx (:additional-tx opts') - full-tx (concat (:tx-data result) additional-tx)] - (ldb/transact! conn full-tx clean-tx-meta) - (reset! *result result))) - -(defn- apply-save-followed-by-insert! - [conn ops *result opts' clean-tx-meta] - (let [save-block-tx (:tx-data (apply outliner-core/save-block @conn (second (first ops)))) - [blocks target-block-id insert-opts] (second (second ops)) - insert-blocks-result (outliner-core/insert-blocks @conn blocks - (d/entity @conn [:block/uuid target-block-id]) - insert-opts) - additional-tx (:additional-tx opts') - full-tx (concat save-block-tx - (:tx-data insert-blocks-result) - additional-tx)] - (ldb/transact! conn full-tx clean-tx-meta) - (reset! *result insert-blocks-result))) - (defn apply-ops! [conn ops opts] (assert (ops-validator ops) ops) @@ -420,22 +385,11 @@ (and single-op-outliner-op (nil? (:outliner-op opts))) (assoc :outliner-op single-op-outliner-op)) - *result (atom nil) - clean-tx-meta (dissoc opts' :additional-tx :transact-opts :current-block)] - (cond - (and single-op-outliner-op - (contains? #{:save-block :insert-blocks :delete-blocks} (ffirst ops))) - (apply-single-op! conn ops *result opts' clean-tx-meta) + *result (atom nil)] - (and (= 2 (count ops)) - (= :save-block (ffirst ops)) - (= :insert-blocks (first (second ops)))) - (apply-save-followed-by-insert! conn ops *result opts' clean-tx-meta) - - :else - (outliner-tx/transact! - opts' - (doseq [op-entry ops] - (apply-op! conn opts' *result op-entry)))) + (outliner-tx/transact! + opts' + (doseq [op-entry ops] + (apply-op! conn opts' *result op-entry))) @*result)) From ea3a732095dc5b56287dfaf28dba76c77ab42626 Mon Sep 17 00:00:00 2001 From: Gabriel Horner Date: Thu, 16 Apr 2026 13:26:48 -0400 Subject: [PATCH 3/5] fix: Can't copy image in desktop Addresses one of the issues in https://github.com/logseq/db-test/issues/792 --- src/main/frontend/components/block.cljs | 30 +++++++++++++++++++++---- src/main/frontend/util.cljc | 12 ++++++---- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/main/frontend/components/block.cljs b/src/main/frontend/components/block.cljs index 4994b1c084..b7ee391642 100644 --- a/src/main/frontend/components/block.cljs +++ b/src/main/frontend/components/block.cljs @@ -259,10 +259,32 @@ [:<> (let [handle-copy! (fn [_e] - (-> (util/copy-image-to-clipboard image-src) - (p/then #(notification/show! "Copied!" :success)) - (p/catch (fn [error] - (js/console.error error))))) + ;; Electron renderer cannot fetch file:// URLs; read the + ;; file via IPC and copy the blob directly. + (if (util/electron?) + (let [ext (some-> (util/get-file-ext image-src) string/lower-case) + ;; Should support all exts in common-config/img-formats + ext->mime {"png" "image/png" + "jpg" "image/jpeg" + "jpeg" "image/jpeg" + "gif" "image/gif" + "webp" "image/webp" + "bmp" "image/bmp" + "svg" "image/svg+xml" + "ico" "image/x-icon"} + mime (get ext->mime ext)] + (if-not mime + (notification/show! (str "Copy image is not supported for ." ext " files") :warning) + (-> (p/let [binary (fs/read-file-raw nil image-src {}) + blob (js/Blob. (array binary) (clj->js {:type mime}))] + (util/copy-image-blob-to-clipboard blob)) + (p/then #(notification/show! "Copied!" :success)) + (p/catch (fn [error] + (js/console.error error)))))) + (-> (util/copy-image-to-clipboard src') + (p/then #(notification/show! "Copied!" :success)) + (p/catch (fn [error] + (js/console.error error)))))) handle-delete! (fn [_e] (when-let [block-id (get-blockid)] diff --git a/src/main/frontend/util.cljc b/src/main/frontend/util.cljc index b1b43fcf3f..87d45cddb6 100644 --- a/src/main/frontend/util.cljc +++ b/src/main/frontend/util.cljc @@ -1314,16 +1314,20 @@ (.catch (fn [err] (js/console.error "Web clipboard failed" err))))))))) +#?(:cljs + (defn copy-image-blob-to-clipboard + [blob] + (if (= (.-type blob) "image/png") + (write-blob-to-clipboard blob) + (image-blob->png blob write-blob-to-clipboard)))) + #?(:cljs (defn copy-image-to-clipboard [src] (-> (js/fetch src) (.then (fn [data] (-> (.blob data) - (.then (fn [blob] - (if (= (.-type blob) "image/png") - (write-blob-to-clipboard blob) - (image-blob->png blob write-blob-to-clipboard)))) + (.then copy-image-blob-to-clipboard) (.catch js/console.error))))))) (defn memoize-last From 9804728afa9f442f7638b32ade48c34564873b3e Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Fri, 17 Apr 2026 01:47:21 +0800 Subject: [PATCH 4/5] fix: failed to convert page to tag fixes https://github.com/logseq/db-test/issues/805 --- src/main/frontend/handler/db_based/page.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/frontend/handler/db_based/page.cljs b/src/main/frontend/handler/db_based/page.cljs index 435dc90ba6..198154b47e 100644 --- a/src/main/frontend/handler/db_based/page.cljs +++ b/src/main/frontend/handler/db_based/page.cljs @@ -54,7 +54,7 @@ :else ;; FIXME: should move to worker (let [txs [(db-class/build-new-class (db/get-db) - {:block/uuid [:block/uuid (:block/uuid page-entity)] + {:block/uuid (:block/uuid page-entity) :block/title (:block/title page-entity) :block/created-at (:block/created-at page-entity)}) [:db/retract (:db/id page-entity) :block/tags :logseq.class/Page]]] From eb1d921d5da9ccb43224782c659f7b30a0c72b81 Mon Sep 17 00:00:00 2001 From: Gabriel Horner Date: Thu, 16 Apr 2026 15:53:47 -0400 Subject: [PATCH 5/5] enhance: add block context menu option to open an asset file Addresses 2nd issue in https://github.com/logseq/db-test/issues/792 of not being able to download an asset that doesn't have a special block view --- src/main/frontend/components/content.cljs | 13 +++++++++++++ src/resources/dicts/en.edn | 1 + 2 files changed, 14 insertions(+) diff --git a/src/main/frontend/components/content.cljs b/src/main/frontend/components/content.cljs index d921b5797e..ad84249870 100644 --- a/src/main/frontend/components/content.cljs +++ b/src/main/frontend/components/content.cljs @@ -2,11 +2,13 @@ (:require [cljs-time.coerce :as tc] [cljs.pprint :as pp] [clojure.string :as string] + [electron.ipc :as ipc] [frontend.commands :as commands] [frontend.components.editor :as editor] [frontend.components.export :as export] [frontend.components.icon :as icon-component] [frontend.components.page-menu :as page-menu] + [frontend.config :as config] [frontend.context.i18n :refer [t]] [frontend.db :as db] [frontend.extensions.fsrs :as fsrs] @@ -23,6 +25,7 @@ [frontend.util.url :as url-util] [goog.dom :as gdom] [goog.object :as gobj] + [logseq.common.path :as path] [logseq.common.util :as common-util] [logseq.db :as ldb] [logseq.shui.ui :as shui] @@ -240,6 +243,16 @@ (editor-handler/copy-block-ref! block-id tap-f)))} (t :content/copy-block-url))) + (when (and (util/electron?) (ldb/asset? block)) + (shui/dropdown-menu-item + {:key "Show asset in folder" + :on-click (fn [_e] + (let [assets-dir (config/get-current-repo-assets-root) + ext (name (:logseq.property.asset/type block)) + file-path (path/path-join assets-dir (str (:block/uuid block) "." ext))] + (ipc/ipc "openFileInFolder" file-path)))} + (t :asset/show-file-in-folder))) + (shui/dropdown-menu-item {:key "Copy as" :on-click (fn [_] diff --git a/src/resources/dicts/en.edn b/src/resources/dicts/en.edn index 0b55c36f8d..71b70df466 100644 --- a/src/resources/dicts/en.edn +++ b/src/resources/dicts/en.edn @@ -128,6 +128,7 @@ :linked-references/filter-excludes "Excludes: " :editor/block-search "Search for a block" :text/image "Image" + :asset/show-file-in-folder "Show file in folder" :asset/show-in-folder "Show image in folder" :asset/open-in-browser "Open image in browser" :asset/delete "Delete image"