From 3cf7e709fc41a328af7b1d80836323ce8e55f857 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 19 Oct 2025 20:50:18 +0300 Subject: [PATCH] fix(desktop/print): proper reporting when it finishes --- .../src/translations/en/translation.json | 3 +- apps/client/src/widgets/note_detail.ts | 13 +++ apps/server/src/services/window.ts | 96 ++++++++++--------- 3 files changed, 65 insertions(+), 47 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index d09d2742f..c52acb3ff 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -1723,7 +1723,8 @@ }, "note_detail": { "could_not_find_typewidget": "Could not find typeWidget for type '{{type}}'", - "printing": "Printing in progress..." + "printing": "Printing in progress...", + "printing_pdf": "Exporting to PDF in progress..." }, "note_title": { "placeholder": "type note's title here..." diff --git a/apps/client/src/widgets/note_detail.ts b/apps/client/src/widgets/note_detail.ts index 7d2791e32..a701d442b 100644 --- a/apps/client/src/widgets/note_detail.ts +++ b/apps/client/src/widgets/note_detail.ts @@ -141,6 +141,13 @@ export default class NoteDetailWidget extends NoteContextAwareWidget { doRender() { this.$widget = $(TPL); this.contentSized(); + + if (utils.isElectron()) { + const { ipcRenderer } = utils.dynamicRequire("electron"); + ipcRenderer.on("print-done", () => { + toast.closePersistent("printing"); + }); + } } async refresh() { @@ -330,6 +337,12 @@ export default class NoteDetailWidget extends NoteContextAwareWidget { return; } + toast.showPersistent({ + icon: "bx bx-loader-circle bx-spin", + message: t("note_detail.printing_pdf"), + id: "printing" + }); + const { ipcRenderer } = utils.dynamicRequire("electron"); ipcRenderer.send("export-as-pdf", { title: this.note.title, diff --git a/apps/server/src/services/window.ts b/apps/server/src/services/window.ts index 83d1ca185..69d273158 100644 --- a/apps/server/src/services/window.ts +++ b/apps/server/src/services/window.ts @@ -89,9 +89,59 @@ electron.ipcMain.on("print-note", async (e, { notePath }: PrintOpts) => { } else { electron.dialog.showErrorBox(t("pdf.unable-to-print"), failureReason); } + e.sender.send("print-done"); }); }); +electron.ipcMain.on("export-as-pdf", async (e, { title, notePath, landscape, pageSize }: ExportAsPdfOpts) => { + async function print() { + const browserWindow = await getBrowserWindowForPrinting(e, notePath); + + const filePath = electron.dialog.showSaveDialogSync(browserWindow, { + defaultPath: formatDownloadTitle(title, "file", "application/pdf"), + filters: [ + { + name: t("pdf.export_filter"), + extensions: ["pdf"] + } + ] + }); + if (!filePath) return; + + let buffer: Buffer; + try { + buffer = await browserWindow.webContents.printToPDF({ + landscape, + pageSize, + generateDocumentOutline: true, + generateTaggedPDF: true, + printBackground: true, + displayHeaderFooter: true, + headerTemplate: `
`, + footerTemplate: ` +
+
+ ` + }); + } catch (e) { + electron.dialog.showErrorBox(t("pdf.unable-to-export-title"), t("pdf.unable-to-export-message")); + return; + } + + try { + await fs.writeFile(filePath, buffer); + } catch (e) { + electron.dialog.showErrorBox(t("pdf.unable-to-export-title"), t("pdf.unable-to-save-message")); + return; + } + + electron.shell.openPath(filePath); + } + + await print(); + e.sender.send("print-done"); +}); + async function getBrowserWindowForPrinting(e: IpcMainEvent, notePath: string) { const browserWindow = new electron.BrowserWindow({ show: false, @@ -112,52 +162,6 @@ async function getBrowserWindowForPrinting(e: IpcMainEvent, notePath: string) { return browserWindow; } -electron.ipcMain.on("export-as-pdf", async (e, { title, notePath, landscape, pageSize }: ExportAsPdfOpts) => { - const browserWindow = await getBrowserWindowForPrinting(e, notePath); - - const filePath = electron.dialog.showSaveDialogSync(browserWindow, { - defaultPath: formatDownloadTitle(title, "file", "application/pdf"), - filters: [ - { - name: t("pdf.export_filter"), - extensions: ["pdf"] - } - ] - }); - if (!filePath) { - return; - } - - let buffer: Buffer; - try { - buffer = await browserWindow.webContents.printToPDF({ - landscape, - pageSize, - generateDocumentOutline: true, - generateTaggedPDF: true, - printBackground: true, - displayHeaderFooter: true, - headerTemplate: `
`, - footerTemplate: ` -
-
- ` - }); - } catch (e) { - electron.dialog.showErrorBox(t("pdf.unable-to-export-title"), t("pdf.unable-to-export-message")); - return; - } - - try { - await fs.writeFile(filePath, buffer); - } catch (e) { - electron.dialog.showErrorBox(t("pdf.unable-to-export-title"), t("pdf.unable-to-save-message")); - return; - } - - electron.shell.openPath(filePath); -}); - async function createMainWindow(app: App) { if ("setUserTasks" in app) { app.setUserTasks([