mirror of
https://github.com/zadam/trilium.git
synced 2026-02-15 10:14:23 +01:00
feat(desktop): display print errors
This commit is contained in:
parent
89d39f5f2b
commit
5eb32744c3
@ -18,6 +18,10 @@ export type PrintReport = {
|
||||
} | {
|
||||
type: "collection";
|
||||
ignoredNoteIds: string[];
|
||||
} | {
|
||||
type: "error";
|
||||
message: string;
|
||||
stack?: string;
|
||||
};
|
||||
|
||||
async function main() {
|
||||
|
||||
@ -1797,6 +1797,8 @@
|
||||
"printing": "Printing in progress...",
|
||||
"printing_pdf": "Exporting to PDF in progress...",
|
||||
"print_report_title": "Print report",
|
||||
"print_report_error_title": "Failed to print",
|
||||
"print_report_stack_trace": "Stack trace",
|
||||
"print_report_collection_content_one": "{{count}} note in the collection could not be printed because they are not supported or they are protected.",
|
||||
"print_report_collection_content_other": "{{count}} notes in the collection could not be printed because they are not supported or they are protected.",
|
||||
"print_report_collection_details_button": "See details",
|
||||
|
||||
@ -370,7 +370,33 @@ function showToast(type: "printing" | "exporting_pdf", progress: number = 0) {
|
||||
}
|
||||
|
||||
function handlePrintReport(printReport?: PrintReport) {
|
||||
if (printReport?.type === "collection" && printReport.ignoredNoteIds.length > 0) {
|
||||
if (!printReport) return;
|
||||
|
||||
if (printReport.type === "error") {
|
||||
toast.showPersistent({
|
||||
id: "print-error",
|
||||
icon: "bx bx-error-circle",
|
||||
title: t("note_detail.print_report_error_title"),
|
||||
message: printReport.message,
|
||||
buttons: printReport.stack ? [
|
||||
{
|
||||
text: t("note_detail.print_report_collection_details_button"),
|
||||
onClick(api) {
|
||||
api.dismissToast();
|
||||
dialog.info(<>
|
||||
<p>{printReport.message}</p>
|
||||
<details>
|
||||
<summary>{t("note_detail.print_report_stack_trace")}</summary>
|
||||
<pre style="font-size: 0.85em; overflow-x: auto;">{printReport.stack}</pre>
|
||||
</details>
|
||||
</>, {
|
||||
title: t("note_detail.print_report_error_title")
|
||||
});
|
||||
}
|
||||
}
|
||||
] : undefined
|
||||
});
|
||||
} else if (printReport.type === "collection" && printReport.ignoredNoteIds.length > 0) {
|
||||
toast.showPersistent({
|
||||
id: "print-report",
|
||||
icon: "bx bx-collection",
|
||||
|
||||
@ -81,66 +81,82 @@ interface ExportAsPdfOpts {
|
||||
}
|
||||
|
||||
electron.ipcMain.on("print-note", async (e, { notePath }: PrintOpts) => {
|
||||
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", printReport);
|
||||
browserWindow.destroy();
|
||||
});
|
||||
try {
|
||||
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", printReport);
|
||||
browserWindow.destroy();
|
||||
});
|
||||
} catch (err) {
|
||||
e.sender.send("print-done", {
|
||||
type: "error",
|
||||
message: err instanceof Error ? err.message : String(err),
|
||||
stack: err instanceof Error ? err.stack : undefined
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
electron.ipcMain.on("export-as-pdf", async (e, { title, notePath, landscape, pageSize }: ExportAsPdfOpts) => {
|
||||
const { browserWindow, printReport } = await getBrowserWindowForPrinting(e, notePath, "exporting_pdf");
|
||||
|
||||
async function print() {
|
||||
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: `<div></div>`,
|
||||
footerTemplate: `
|
||||
<div class="pageNumber" style="width: 100%; text-align: center; font-size: 10pt;">
|
||||
</div>
|
||||
`
|
||||
});
|
||||
} 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);
|
||||
}
|
||||
|
||||
try {
|
||||
await print();
|
||||
} finally {
|
||||
e.sender.send("print-done", printReport);
|
||||
browserWindow.destroy();
|
||||
const { browserWindow, printReport } = await getBrowserWindowForPrinting(e, notePath, "exporting_pdf");
|
||||
|
||||
async function print() {
|
||||
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: `<div></div>`,
|
||||
footerTemplate: `
|
||||
<div class="pageNumber" style="width: 100%; text-align: center; font-size: 10pt;">
|
||||
</div>
|
||||
`
|
||||
});
|
||||
} 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);
|
||||
}
|
||||
|
||||
try {
|
||||
await print();
|
||||
} finally {
|
||||
e.sender.send("print-done", printReport);
|
||||
browserWindow.destroy();
|
||||
}
|
||||
} catch (err) {
|
||||
e.sender.send("print-done", {
|
||||
type: "error",
|
||||
message: err instanceof Error ? err.message : String(err),
|
||||
stack: err instanceof Error ? err.stack : undefined
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@ -176,16 +192,29 @@ async function getBrowserWindowForPrinting(e: IpcMainEvent, notePath: string, ac
|
||||
throw err;
|
||||
}
|
||||
|
||||
// Set up error logging in the renderer process before content loads
|
||||
// Set up error tracking and logging in the renderer process
|
||||
await browserWindow.webContents.executeJavaScript(`
|
||||
(function() {
|
||||
window._printWindowErrors = [];
|
||||
window.addEventListener("error", (e) => {
|
||||
console.error("Uncaught error:", e.message, "at", e.filename + ":" + e.lineno + ":" + e.colno);
|
||||
const errorMsg = "Uncaught error: " + e.message + " at " + e.filename + ":" + e.lineno + ":" + e.colno;
|
||||
console.error(errorMsg);
|
||||
if (e.error?.stack) console.error(e.error.stack);
|
||||
window._printWindowErrors.push({
|
||||
type: 'error',
|
||||
message: errorMsg,
|
||||
stack: e.error?.stack
|
||||
});
|
||||
});
|
||||
window.addEventListener("unhandledrejection", (e) => {
|
||||
console.error("Unhandled rejection:", String(e.reason));
|
||||
const errorMsg = "Unhandled rejection: " + String(e.reason);
|
||||
console.error(errorMsg);
|
||||
if (e.reason?.stack) console.error(e.reason.stack);
|
||||
window._printWindowErrors.push({
|
||||
type: 'rejection',
|
||||
message: errorMsg,
|
||||
stack: e.reason?.stack
|
||||
});
|
||||
});
|
||||
})();
|
||||
`).catch(err => log.error(`Failed to set up error handlers in print window: ${err}`));
|
||||
@ -196,7 +225,17 @@ async function getBrowserWindowForPrinting(e: IpcMainEvent, notePath: string, ac
|
||||
new Promise((resolve, reject) => {
|
||||
if (window._noteReady) return resolve(window._noteReady);
|
||||
|
||||
// Check for errors periodically
|
||||
const errorChecker = setInterval(() => {
|
||||
if (window._printWindowErrors && window._printWindowErrors.length > 0) {
|
||||
clearInterval(errorChecker);
|
||||
const errors = window._printWindowErrors.map(e => e.message).join('; ');
|
||||
reject(new Error("Print window errors: " + errors));
|
||||
}
|
||||
}, 100);
|
||||
|
||||
window.addEventListener("note-ready", (data) => {
|
||||
clearInterval(errorChecker);
|
||||
resolve(data.detail);
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user