mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-11-09 19:01:45 +08:00
Merge branch 'develop' of https://github.com/TriliumNext/Notes into develop
This commit is contained in:
commit
2659bd33e8
@ -83,7 +83,7 @@ export type CommandMappings = {
|
|||||||
};
|
};
|
||||||
showExportDialog: CommandData & {
|
showExportDialog: CommandData & {
|
||||||
notePath: string;
|
notePath: string;
|
||||||
defaultType: "single";
|
defaultType: "single" | "subtree";
|
||||||
};
|
};
|
||||||
showDeleteNotesDialog: CommandData & {
|
showDeleteNotesDialog: CommandData & {
|
||||||
branchIdsToDelete: string[];
|
branchIdsToDelete: string[];
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
import treeService from "../../services/tree.js";
|
import treeService from "../../services/tree.js";
|
||||||
import utils from "../../services/utils.js";
|
import utils from "../../services/utils.js";
|
||||||
import ws from "../../services/ws.js";
|
import ws from "../../services/ws.js";
|
||||||
import toastService from "../../services/toast.js";
|
import toastService, { type ToastOptions } from "../../services/toast.js";
|
||||||
import froca from "../../services/froca.js";
|
import froca from "../../services/froca.js";
|
||||||
import openService from "../../services/open.js";
|
import openService from "../../services/open.js";
|
||||||
import BasicWidget from "../basic_widget.js";
|
import BasicWidget from "../basic_widget.js";
|
||||||
import { t } from "../../services/i18n.js";
|
import { t } from "../../services/i18n.js";
|
||||||
|
import type { EventData } from "../../components/app_context.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="export-dialog modal fade mx-auto" tabindex="-1" role="dialog">
|
<div class="export-dialog modal fade mx-auto" tabindex="-1" role="dialog">
|
||||||
@ -105,6 +106,13 @@ const TPL = `
|
|||||||
${t("export.format_markdown")}
|
${t("export.format_markdown")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<label class="form-check-label tn-radio">
|
||||||
|
<input class="form-check-input" type="radio" name="export-single-format" value="pdf">
|
||||||
|
${t("export.format_pdf")}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
@ -116,6 +124,19 @@ const TPL = `
|
|||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
export default class ExportDialog extends BasicWidget {
|
export default class ExportDialog extends BasicWidget {
|
||||||
|
|
||||||
|
private taskId: string;
|
||||||
|
private branchId: string | null;
|
||||||
|
private modal?: bootstrap.Modal;
|
||||||
|
private $form!: JQuery<HTMLElement>;
|
||||||
|
private $noteTitle!: JQuery<HTMLElement>;
|
||||||
|
private $subtreeFormats!: JQuery<HTMLElement>;
|
||||||
|
private $singleFormats!: JQuery<HTMLElement>;
|
||||||
|
private $subtreeType!: JQuery<HTMLElement>;
|
||||||
|
private $singleType!: JQuery<HTMLElement>;
|
||||||
|
private $exportButton!: JQuery<HTMLElement>;
|
||||||
|
private $opmlVersions!: JQuery<HTMLElement>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@ -125,6 +146,8 @@ export default class ExportDialog extends BasicWidget {
|
|||||||
|
|
||||||
doRender() {
|
doRender() {
|
||||||
this.$widget = $(TPL);
|
this.$widget = $(TPL);
|
||||||
|
// Remove once bootstrap is fixed.
|
||||||
|
// @ts-ignore
|
||||||
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
|
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
|
||||||
this.$form = this.$widget.find(".export-form");
|
this.$form = this.$widget.find(".export-form");
|
||||||
this.$noteTitle = this.$widget.find(".export-note-title");
|
this.$noteTitle = this.$widget.find(".export-note-title");
|
||||||
@ -136,7 +159,7 @@ export default class ExportDialog extends BasicWidget {
|
|||||||
this.$opmlVersions = this.$widget.find(".opml-versions");
|
this.$opmlVersions = this.$widget.find(".opml-versions");
|
||||||
|
|
||||||
this.$form.on("submit", () => {
|
this.$form.on("submit", () => {
|
||||||
this.modal.hide();
|
this.modal?.hide();
|
||||||
|
|
||||||
const exportType = this.$widget.find("input[name='export-type']:checked").val();
|
const exportType = this.$widget.find("input[name='export-type']:checked").val();
|
||||||
|
|
||||||
@ -149,13 +172,15 @@ export default class ExportDialog extends BasicWidget {
|
|||||||
|
|
||||||
const exportVersion = exportFormat === "opml" ? this.$widget.find("input[name='opml-version']:checked").val() : "1.0";
|
const exportVersion = exportFormat === "opml" ? this.$widget.find("input[name='opml-version']:checked").val() : "1.0";
|
||||||
|
|
||||||
this.exportBranch(this.branchId, exportType, exportFormat, exportVersion);
|
if (this.branchId) {
|
||||||
|
this.exportBranch(this.branchId, String(exportType), String(exportFormat), String(exportVersion));
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$widget.find("input[name=export-type]").on("change", (e) => {
|
this.$widget.find("input[name=export-type]").on("change", (e) => {
|
||||||
if (e.currentTarget.value === "subtree") {
|
if ((e.currentTarget as HTMLInputElement).value === "subtree") {
|
||||||
if (this.$widget.find("input[name=export-subtree-format]:checked").length === 0) {
|
if (this.$widget.find("input[name=export-subtree-format]:checked").length === 0) {
|
||||||
this.$widget.find("input[name=export-subtree-format]:first").prop("checked", true);
|
this.$widget.find("input[name=export-subtree-format]:first").prop("checked", true);
|
||||||
}
|
}
|
||||||
@ -173,7 +198,7 @@ export default class ExportDialog extends BasicWidget {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.$widget.find("input[name=export-subtree-format]").on("change", (e) => {
|
this.$widget.find("input[name=export-subtree-format]").on("change", (e) => {
|
||||||
if (e.currentTarget.value === "opml") {
|
if ((e.currentTarget as HTMLInputElement).value === "opml") {
|
||||||
this.$opmlVersions.slideDown();
|
this.$opmlVersions.slideDown();
|
||||||
} else {
|
} else {
|
||||||
this.$opmlVersions.slideUp();
|
this.$opmlVersions.slideUp();
|
||||||
@ -181,7 +206,7 @@ export default class ExportDialog extends BasicWidget {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async showExportDialogEvent({ notePath, defaultType }) {
|
async showExportDialogEvent({ notePath, defaultType }: EventData<"showExportDialog">) {
|
||||||
this.taskId = "";
|
this.taskId = "";
|
||||||
this.$exportButton.removeAttr("disabled");
|
this.$exportButton.removeAttr("disabled");
|
||||||
|
|
||||||
@ -201,11 +226,15 @@ export default class ExportDialog extends BasicWidget {
|
|||||||
|
|
||||||
const { noteId, parentNoteId } = treeService.getNoteIdAndParentIdFromUrl(notePath);
|
const { noteId, parentNoteId } = treeService.getNoteIdAndParentIdFromUrl(notePath);
|
||||||
|
|
||||||
|
if (parentNoteId) {
|
||||||
this.branchId = await froca.getBranchId(parentNoteId, noteId);
|
this.branchId = await froca.getBranchId(parentNoteId, noteId);
|
||||||
|
}
|
||||||
|
if (noteId) {
|
||||||
this.$noteTitle.text(await treeService.getNoteTitle(noteId));
|
this.$noteTitle.text(await treeService.getNoteTitle(noteId));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
exportBranch(branchId, type, format, version) {
|
exportBranch(branchId: string, type: string, format: string, version: string) {
|
||||||
this.taskId = utils.randomString(10);
|
this.taskId = utils.randomString(10);
|
||||||
|
|
||||||
const url = openService.getUrlForDownload(`api/branches/${branchId}/export/${type}/${format}/${version}/${this.taskId}`);
|
const url = openService.getUrlForDownload(`api/branches/${branchId}/export/${type}/${format}/${version}/${this.taskId}`);
|
||||||
@ -215,12 +244,14 @@ export default class ExportDialog extends BasicWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ws.subscribeToMessages(async (message) => {
|
ws.subscribeToMessages(async (message) => {
|
||||||
const makeToast = (id, message) => ({
|
function makeToast(id: string, message: string): ToastOptions {
|
||||||
|
return {
|
||||||
id: id,
|
id: id,
|
||||||
title: t("export.export_status"),
|
title: t("export.export_status"),
|
||||||
message: message,
|
message: message,
|
||||||
icon: "arrow-square-up-right"
|
icon: "arrow-square-up-right"
|
||||||
});
|
};
|
||||||
|
};
|
||||||
|
|
||||||
if (message.taskType !== "export") {
|
if (message.taskType !== "export") {
|
||||||
return;
|
return;
|
||||||
@ -261,6 +261,7 @@ export default class NoteDetailWidget extends NoteContextAwareWidget {
|
|||||||
const { ipcRenderer } = utils.dynamicRequire("electron");
|
const { ipcRenderer } = utils.dynamicRequire("electron");
|
||||||
ipcRenderer.send("export-as-pdf", {
|
ipcRenderer.send("export-as-pdf", {
|
||||||
title: this.note.title,
|
title: this.note.title,
|
||||||
|
pageSize: this.note.getAttributeValue("label", "pageSize") ?? "Letter",
|
||||||
landscape: this.note.hasAttribute("label", "printLandscape")
|
landscape: this.note.hasAttribute("label", "printLandscape")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -109,7 +109,8 @@
|
|||||||
"choose_export_type": "Choose export type first please",
|
"choose_export_type": "Choose export type first please",
|
||||||
"export_status": "Export status",
|
"export_status": "Export status",
|
||||||
"export_in_progress": "Export in progress: {{progressCount}}",
|
"export_in_progress": "Export in progress: {{progressCount}}",
|
||||||
"export_finished_successfully": "Export finished successfully."
|
"export_finished_successfully": "Export finished successfully.",
|
||||||
|
"format_pdf": "PDF - for printing or sharing purposes."
|
||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"fullDocumentation": "Help (full documentation is available <a class=\"external\" href=\"https://triliumnext.github.io/Docs/\">online</a>)",
|
"fullDocumentation": "Help (full documentation is available <a class=\"external\" href=\"https://triliumnext.github.io/Docs/\">online</a>)",
|
||||||
|
|||||||
0
src/services/export/pdf.ts
Normal file
0
src/services/export/pdf.ts
Normal file
@ -51,6 +51,7 @@ ipcMain.on("create-extra-window", (event, arg) => {
|
|||||||
interface ExportAsPdfOpts {
|
interface ExportAsPdfOpts {
|
||||||
title: string;
|
title: string;
|
||||||
landscape: boolean;
|
landscape: boolean;
|
||||||
|
pageSize: "A0" | "A1" | "A2" | "A3" | "A4" | "A5" | "A6" | "Legal" | "Letter" | "Tabloid" | "Ledger";
|
||||||
}
|
}
|
||||||
|
|
||||||
ipcMain.on("export-as-pdf", async (e, opts: ExportAsPdfOpts) => {
|
ipcMain.on("export-as-pdf", async (e, opts: ExportAsPdfOpts) => {
|
||||||
@ -76,6 +77,7 @@ ipcMain.on("export-as-pdf", async (e, opts: ExportAsPdfOpts) => {
|
|||||||
try {
|
try {
|
||||||
buffer = await browserWindow.webContents.printToPDF({
|
buffer = await browserWindow.webContents.printToPDF({
|
||||||
landscape: opts.landscape,
|
landscape: opts.landscape,
|
||||||
|
pageSize: opts.pageSize,
|
||||||
generateDocumentOutline: true,
|
generateDocumentOutline: true,
|
||||||
generateTaggedPDF: true,
|
generateTaggedPDF: true,
|
||||||
displayHeaderFooter: true,
|
displayHeaderFooter: true,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user