From 1a6e653600551a442c411a026d9b1b8a1ff67ee3 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 21 Nov 2025 19:57:13 +0200 Subject: [PATCH] feat(print): support progress report on electron --- apps/client/src/print.tsx | 8 +++++++- apps/client/src/widgets/NoteDetail.tsx | 14 ++++++++++---- apps/server/src/services/window.ts | 9 ++++++--- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/apps/client/src/print.tsx b/apps/client/src/print.tsx index 075b566e6..ffef86044 100644 --- a/apps/client/src/print.tsx +++ b/apps/client/src/print.tsx @@ -3,6 +3,7 @@ import { render } from "preact"; import { CustomNoteList, useNoteViewType } from "./widgets/collections/NoteList"; import { useCallback, useLayoutEffect, useRef } from "preact/hooks"; import content_renderer, { applyInlineMermaid } from "./services/content_renderer"; +import { dynamicRequire, isElectron } from "./services/utils"; interface RendererProps { note: FNote; @@ -25,7 +26,12 @@ async function main() { function App({ note, noteId }: { note: FNote | null | undefined, noteId: string }) { const sentReadyEvent = useRef(false); const onProgressChanged = useCallback((progress: number) => { - window.dispatchEvent(new CustomEvent("note-load-progress", { detail: { progress } })); + if (isElectron()) { + const { ipcRenderer } = dynamicRequire('electron'); + ipcRenderer.send("print-progress", progress); + } else { + window.dispatchEvent(new CustomEvent("note-load-progress", { detail: { progress } })); + } }, []); const onReady = useCallback(() => { if (sentReadyEvent.current) return; diff --git a/apps/client/src/widgets/NoteDetail.tsx b/apps/client/src/widgets/NoteDetail.tsx index 943322f9e..406354eee 100644 --- a/apps/client/src/widgets/NoteDetail.tsx +++ b/apps/client/src/widgets/NoteDetail.tsx @@ -113,11 +113,17 @@ export default function NoteDetail() { useEffect(() => { if (!isElectron()) return; const { ipcRenderer } = dynamicRequire("electron"); - const listener = () => { - toast.closePersistent("printing"); + const onPrintProgress = (_e: any, progress: number) => { + console.log("Got print progress:", progress); + showToast("printing", progress); + }; + const onPrintDone = () => toast.closePersistent("printing"); + ipcRenderer.on("print-progress", onPrintProgress); + ipcRenderer.on("print-done", onPrintDone); + return () => { + ipcRenderer.off("print-progress", onPrintProgress); + ipcRenderer.off("print-done", onPrintDone); }; - ipcRenderer.on("print-done", listener); - return () => ipcRenderer.off("print-done", listener); }, []); useTriliumEvent("executeInActiveNoteDetailWidget", ({ callback }) => { diff --git a/apps/server/src/services/window.ts b/apps/server/src/services/window.ts index c2fab2ac3..8f2d26f47 100644 --- a/apps/server/src/services/window.ts +++ b/apps/server/src/services/window.ts @@ -7,13 +7,11 @@ import log from "./log.js"; import sqlInit from "./sql_init.js"; import cls from "./cls.js"; import keyboardActionsService from "./keyboard_actions.js"; -import electron from "electron"; +import electron, { ipcMain } from "electron"; import type { App, BrowserWindowConstructorOptions, BrowserWindow, WebContents, IpcMainEvent } from "electron"; import { formatDownloadTitle, isDev, isMac, isWindows } from "./utils.js"; import { t } from "i18next"; import { RESOURCE_DIR } from "./resource_dir.js"; -import { PerformanceObserverEntryList } from "perf_hooks"; -import options from "./options.js"; // Prevent the window being garbage collected let mainWindow: BrowserWindow | null; @@ -155,6 +153,10 @@ async function getBrowserWindowForPrinting(e: IpcMainEvent, notePath: string) { session: e.sender.session }, }); + + const progressCallback = (_e, progress: number) => e.sender.send("print-progress", progress); + ipcMain.on("print-progress", progressCallback); + await browserWindow.loadURL(`http://127.0.0.1:${port}/?print#${notePath}`); await browserWindow.webContents.executeJavaScript(` new Promise(resolve => { @@ -162,6 +164,7 @@ async function getBrowserWindowForPrinting(e: IpcMainEvent, notePath: string) { window.addEventListener("note-ready", () => resolve()); }); `); + ipcMain.off("print-progress", progressCallback); return browserWindow; }