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()) {