diff --git a/apps/client/src/widgets/note_detail.ts b/apps/client/src/widgets/note_detail.ts index 0c1255d39..5310b327a 100644 --- a/apps/client/src/widgets/note_detail.ts +++ b/apps/client/src/widgets/note_detail.ts @@ -28,7 +28,7 @@ import ContentWidgetTypeWidget from "./type_widgets/content_widget.js"; import AttachmentListTypeWidget from "./type_widgets/attachment_list.js"; import AttachmentDetailTypeWidget from "./type_widgets/attachment_detail.js"; import MindMapWidget from "./type_widgets/mind_map.js"; -import utils from "../services/utils.js"; +import utils, { isElectron } from "../services/utils.js"; import type { NoteType } from "../entities/fnote.js"; import type TypeWidget from "./type_widgets/type_widget.js"; import { MermaidTypeWidget } from "./type_widgets/mermaid.js"; @@ -303,18 +303,26 @@ export default class NoteDetailWidget extends NoteContextAwareWidget { message: t("note_detail.printing"), id: "printing" }); - const iframe = document.createElement('iframe'); - iframe.src = `?print#${this.notePath}`; - iframe.className = "print-iframe"; - document.body.appendChild(iframe); - iframe.onload = () => { - if (!iframe.contentWindow) return; - iframe.contentWindow.addEventListener("note-ready", () => { - toast.closePersistent("printing"); - iframe.contentWindow?.print(); - document.body.removeChild(iframe); + + if (isElectron()) { + const { ipcRenderer } = utils.dynamicRequire("electron"); + ipcRenderer.send("print-note", { + notePath: this.notePath }); - }; + } else { + const iframe = document.createElement('iframe'); + iframe.src = `?print#${this.notePath}`; + iframe.className = "print-iframe"; + document.body.appendChild(iframe); + iframe.onload = () => { + if (!iframe.contentWindow) return; + iframe.contentWindow.addEventListener("note-ready", () => { + toast.closePersistent("printing"); + iframe.contentWindow?.print(); + document.body.removeChild(iframe); + }); + }; + } } async exportAsPdfEvent() { diff --git a/apps/server/src/services/window.ts b/apps/server/src/services/window.ts index b26b000af..f149fd1e0 100644 --- a/apps/server/src/services/window.ts +++ b/apps/server/src/services/window.ts @@ -12,6 +12,8 @@ import type { App, BrowserWindowConstructorOptions, BrowserWindow, WebContents } 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; @@ -67,12 +69,38 @@ electron.ipcMain.on("create-extra-window", (event, arg) => { createExtraWindow(arg.extraWindowHash); }); +interface PrintOpts { + notePath: string; +} + interface ExportAsPdfOpts { title: string; landscape: boolean; pageSize: "A0" | "A1" | "A2" | "A3" | "A4" | "A5" | "A6" | "Legal" | "Letter" | "Tabloid" | "Ledger"; } +electron.ipcMain.on("print-note", async (e, { notePath }: PrintOpts) => { + const browserWindow = new electron.BrowserWindow({ + show: false, + webPreferences: { + nodeIntegration: true, + contextIsolation: false, + offscreen: true, + session: e.sender.session + }, + }); + await browserWindow.loadURL(`http://127.0.0.1:${port}/?print#${notePath}`); + await browserWindow.webContents.executeJavaScript(` + new Promise(resolve => { + if (window._noteReady) return resolve(); + window.addEventListener("note-ready", () => resolve()); + }); + `); + browserWindow.webContents.print({}, () => { + browserWindow.destroy(); + }); +}); + electron.ipcMain.on("export-as-pdf", async (e, opts: ExportAsPdfOpts) => { const browserWindow = electron.BrowserWindow.fromWebContents(e.sender); if (!browserWindow) {