From 571cdfdeea0788415056b627dd632a2661a416e0 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Wed, 24 Dec 2025 19:16:31 +0200 Subject: [PATCH] feat(print): report for electron as well --- apps/client/src/print.tsx | 6 +-- apps/client/src/types.d.ts | 16 ++++---- apps/client/src/widgets/NoteDetail.tsx | 56 ++++++++++++++------------ apps/server/src/services/window.ts | 18 ++++----- 4 files changed, 51 insertions(+), 45 deletions(-) diff --git a/apps/client/src/print.tsx b/apps/client/src/print.tsx index 1df7f9c5f..1ee44ac9e 100644 --- a/apps/client/src/print.tsx +++ b/apps/client/src/print.tsx @@ -42,12 +42,12 @@ function App({ note, noteId }: { note: FNote | null | undefined, noteId: string window.dispatchEvent(new CustomEvent("note-load-progress", { detail: { progress } })); } }, []); - const onReady = useCallback((detail: PrintReport) => { + const onReady = useCallback((printReport: PrintReport) => { if (sentReadyEvent.current) return; window.dispatchEvent(new CustomEvent("note-ready", { - detail + detail: printReport })); - window._noteReady = true; + window._noteReady = printReport; sentReadyEvent.current = true; }, []); const props: RendererProps | undefined | null = note && { note, onReady, onProgressChanged }; diff --git a/apps/client/src/types.d.ts b/apps/client/src/types.d.ts index 7128ea5d8..c12ed615c 100644 --- a/apps/client/src/types.d.ts +++ b/apps/client/src/types.d.ts @@ -1,12 +1,12 @@ -import type FNote from "./entities/fnote"; -import type { Froca } from "./services/froca-interface"; -import { Suggestion } from "./services/note_autocomplete"; -import utils from "./services/utils"; import appContext, { AppContext } from "./components/app_context"; -import server from "./services/server"; -import library_loader, { Library } from "./services/library_loader"; +import type FNote from "./entities/fnote"; +import type { PrintReport } from "./print"; import type { lint } from "./services/eslint"; -import type { Mermaid, MermaidConfig } from "mermaid"; +import type { Froca } from "./services/froca-interface"; +import { Library } from "./services/library_loader"; +import { Suggestion } from "./services/note_autocomplete"; +import server from "./services/server"; +import utils from "./services/utils"; interface ElectronProcess { type: string; @@ -59,7 +59,7 @@ declare global { glob?: CustomGlobals; /** On the printing endpoint, set to true when the note has fully loaded and is ready to be printed/exported as PDF. */ - _noteReady?: boolean; + _noteReady?: PrintReport; EXCALIDRAW_ASSET_PATH?: string; } diff --git a/apps/client/src/widgets/NoteDetail.tsx b/apps/client/src/widgets/NoteDetail.tsx index e902a400e..c2f212044 100644 --- a/apps/client/src/widgets/NoteDetail.tsx +++ b/apps/client/src/widgets/NoteDetail.tsx @@ -131,7 +131,10 @@ export default function NoteDetail() { if (!isElectron()) return; const { ipcRenderer } = dynamicRequire("electron"); const onPrintProgress = (_e: any, { progress, action }: { progress: number, action: "printing" | "exporting_pdf" }) => showToast(action, progress); - const onPrintDone = () => toast.closePersistent("printing"); + const onPrintDone = (_e, printReport: PrintReport) => { + toast.closePersistent("printing"); + handlePrintReport(printReport); + }; ipcRenderer.on("print-progress", onPrintProgress); ipcRenderer.on("print-done", onPrintDone); return () => { @@ -186,30 +189,7 @@ export default function NoteDetail() { toast.closePersistent("printing"); if ("detail" in e) { - const printReport = e.detail as PrintReport; - if (printReport.type === "collection" && printReport.ignoredNoteIds.length > 0) { - toast.showPersistent({ - id: "print-report", - icon: "bx bx-collection", - title: t("note_detail.print_report_title"), - message: t("note_detail.print_report_collection_content", { count: printReport.ignoredNoteIds.length }), - buttons: [ - { - text: t("note_detail.print_report_collection_details_button"), - onClick(api) { - api.dismissToast(); - dialog.info(<> -

{t("note_detail.print_report_collection_details_ignored_notes")}

- - , { - title: t("note_detail.print_report_title"), - size: "md" - }); - } - } - ] - }); - } + handlePrintReport(e.detail as PrintReport); } iframe.contentWindow?.print(); @@ -377,3 +357,29 @@ function showToast(type: "printing" | "exporting_pdf", progress: number = 0) { progress }); } + +function handlePrintReport(printReport: PrintReport) { + if (printReport.type === "collection" && printReport.ignoredNoteIds.length > 0) { + toast.showPersistent({ + id: "print-report", + icon: "bx bx-collection", + title: t("note_detail.print_report_title"), + message: t("note_detail.print_report_collection_content", { count: printReport.ignoredNoteIds.length }), + buttons: [ + { + text: t("note_detail.print_report_collection_details_button"), + onClick(api) { + api.dismissToast(); + dialog.info(<> +

{t("note_detail.print_report_collection_details_ignored_notes")}

+ + , { + title: t("note_detail.print_report_title"), + size: "md" + }); + } + } + ] + }); + } +} diff --git a/apps/server/src/services/window.ts b/apps/server/src/services/window.ts index a959d7d99..572bee9cf 100644 --- a/apps/server/src/services/window.ts +++ b/apps/server/src/services/window.ts @@ -81,18 +81,18 @@ interface ExportAsPdfOpts { } electron.ipcMain.on("print-note", async (e, { notePath }: PrintOpts) => { - const browserWindow = await getBrowserWindowForPrinting(e, notePath, "printing"); + const { browserWindow, printReport } = await getBrowserWindowForPrinting(e, notePath, "printing"); browserWindow.webContents.print({}, (success, failureReason) => { if (!success && failureReason !== "Print job canceled") { electron.dialog.showErrorBox(t("pdf.unable-to-print"), failureReason); } - e.sender.send("print-done"); + e.sender.send("print-done", printReport); browserWindow.destroy(); }); }); electron.ipcMain.on("export-as-pdf", async (e, { title, notePath, landscape, pageSize }: ExportAsPdfOpts) => { - const browserWindow = await getBrowserWindowForPrinting(e, notePath, "exporting_pdf"); + const { browserWindow, printReport } = await getBrowserWindowForPrinting(e, notePath, "exporting_pdf"); async function print() { const filePath = electron.dialog.showSaveDialogSync(browserWindow, { @@ -139,7 +139,7 @@ electron.ipcMain.on("export-as-pdf", async (e, { title, notePath, landscape, pag try { await print(); } finally { - e.sender.send("print-done"); + e.sender.send("print-done", printReport); browserWindow.destroy(); } }); @@ -159,14 +159,14 @@ async function getBrowserWindowForPrinting(e: IpcMainEvent, notePath: string, ac ipcMain.on("print-progress", progressCallback); await browserWindow.loadURL(`http://127.0.0.1:${port}/?print#${notePath}`); - await browserWindow.webContents.executeJavaScript(` + const printReport = await browserWindow.webContents.executeJavaScript(` new Promise(resolve => { if (window._noteReady) return resolve(window._noteReady); - window.addEventListener("note-ready", (data) => resolve(data)); + window.addEventListener("note-ready", (data) => resolve(data.detail)); }); `); ipcMain.off("print-progress", progressCallback); - return browserWindow; + return { browserWindow, printReport }; } async function createMainWindow(app: App) { @@ -290,9 +290,9 @@ async function configureWebContents(webContents: WebContents, spellcheckEnabled: function getIcon() { if (process.env.NODE_ENV === "development") { return path.join(__dirname, "../../../desktop/electron-forge/app-icon/png/256x256-dev.png"); - } + } return path.join(RESOURCE_DIR, "../public/assets/icon.png"); - + } async function createSetupWindow() {