diff --git a/apps/client/src/services/toast.ts b/apps/client/src/services/toast.ts index 5325a06bc..5b834de20 100644 --- a/apps/client/src/services/toast.ts +++ b/apps/client/src/services/toast.ts @@ -8,46 +8,50 @@ export interface ToastOptions { delay?: number; autohide?: boolean; closeAfter?: number; + progress?: number; } -function toast(options: ToastOptions) { - const $toast = $(options.title +function toast({ title, icon, message, id, delay, autohide, progress }: ToastOptions) { + const $toast = $(title ? `\ ` : ` ` ); - $toast.toggleClass("no-title", !options.title); - $toast.find(".toast-title").text(options.title ?? ""); - $toast.find(".toast-body").html(options.message); + $toast.toggleClass("no-title", !title); + $toast.find(".toast-title").text(title ?? ""); + $toast.find(".toast-body").html(message); + $toast.find(".toast-progress").css("width", `${(progress ?? 0) * 100}%`); - if (options.id) { - $toast.attr("id", `toast-${options.id}`); + if (id) { + $toast.attr("id", `toast-${id}`); } $("#toast-container").append($toast); $toast.toast({ - delay: options.delay || 3000, - autohide: !!options.autohide + delay: delay || 3000, + autohide: !!autohide }); $toast.on("hidden.bs.toast", (e) => e.target.remove()); @@ -62,6 +66,7 @@ function showPersistent(options: ToastOptions) { if ($toast.length > 0) { $toast.find(".toast-body").html(options.message); + $toast.find(".toast-progress").css("width", `${(options.progress ?? 0) * 100}%`); } else { options.autohide = false; diff --git a/apps/client/src/stylesheets/style.css b/apps/client/src/stylesheets/style.css index 7b95d13df..b22289273 100644 --- a/apps/client/src/stylesheets/style.css +++ b/apps/client/src/stylesheets/style.css @@ -1137,6 +1137,7 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href --bs-toast-color: var(--main-text-color); z-index: 9999999999 !important; pointer-events: all; + overflow: hidden; } .toast-header { @@ -1169,6 +1170,16 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href background-color: unset !important; } +.toast .toast-progress { + position: absolute; + bottom: 0; + inset-inline-start: 0; + inset-inline-end: 0; + background-color: var(--toast-text-color) !important; + height: 4px; + transition: width 0.1s linear; +} + .ck-mentions .ck-button { font-size: var(--detail-font-size) !important; padding: 5px; diff --git a/apps/client/src/widgets/NoteDetail.tsx b/apps/client/src/widgets/NoteDetail.tsx index 5d5e5b02a..943322f9e 100644 --- a/apps/client/src/widgets/NoteDetail.tsx +++ b/apps/client/src/widgets/NoteDetail.tsx @@ -139,11 +139,7 @@ export default function NoteDetail() { useTriliumEvent("printActiveNote", () => { if (!noteContext?.isActive() || !note) return; - toast.showPersistent({ - icon: "bx bx-loader-circle bx-spin", - message: t("note_detail.printing"), - id: "printing" - }); + showToast("printing"); if (isElectron()) { const { ipcRenderer } = dynamicRequire("electron"); @@ -163,7 +159,7 @@ export default function NoteDetail() { } iframe.contentWindow.addEventListener("note-load-progress", (e) => { - console.log("Got ", e); + showToast("printing", e.detail.progress); }); iframe.contentWindow.addEventListener("note-ready", () => { @@ -326,3 +322,12 @@ function checkFullHeight(noteContext: NoteContext | undefined, type: ExtendedNot || noteContext?.viewScope?.viewMode === "attachments" || isBackendNote; } + +function showToast(type: "printing" | "exporting_pdf", progress: number = 0) { + toast.showPersistent({ + icon: "bx bx-loader-circle bx-spin", + message: t("note_detail.printing"), + id: "printing", + progress + }); +} diff --git a/apps/client/src/widgets/collections/legacy/ListPrintView.tsx b/apps/client/src/widgets/collections/legacy/ListPrintView.tsx index 3fc1be0b4..07e140b17 100644 --- a/apps/client/src/widgets/collections/legacy/ListPrintView.tsx +++ b/apps/client/src/widgets/collections/legacy/ListPrintView.tsx @@ -18,6 +18,7 @@ export function ListPrintView({ note, noteIds: unfilteredNoteIds, onReady, onPro const noteIdsSet = new Set(); froca.getNotes(noteIds).then(async (notes) => { + const noteIdsWithChildren = await note.getSubtreeNoteIds(true); const notesWithContent: NotesWithContent[] = []; async function processNote(note: FNote, depth: number) { @@ -34,7 +35,7 @@ export function ListPrintView({ note, noteIds: unfilteredNoteIds, onReady, onPro notesWithContent.push({ note, contentEl }); if (onProgressChanged) { - onProgressChanged((notesWithContent.length / noteIds.length) * 100); + onProgressChanged(notesWithContent.length / noteIdsWithChildren.length); } if (note.hasChildren()) {