From d036bf0870840ab1de6ed14098187c48429dd9d3 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 20 Dec 2025 19:18:50 +0200 Subject: [PATCH] fix(client): full crash if server fails to obtain list of widgets --- apps/client/src/services/bundle.ts | 58 +++++++++++-------- apps/client/src/services/server.ts | 14 ++--- .../src/translations/en/translation.json | 3 + 3 files changed, 43 insertions(+), 32 deletions(-) diff --git a/apps/client/src/services/bundle.ts b/apps/client/src/services/bundle.ts index e1c38d0d0..146ed4720 100644 --- a/apps/client/src/services/bundle.ts +++ b/apps/client/src/services/bundle.ts @@ -98,36 +98,44 @@ export class WidgetsByParent { } async function getWidgetBundlesByParent() { - const scriptBundles = await server.get("script/widgets"); - const widgetsByParent = new WidgetsByParent(); - for (const bundle of scriptBundles) { - let widget; + try { + const scriptBundles = await server.get("script/widgets"); - try { - widget = await executeBundle(bundle); - if (widget) { - widget._noteId = bundle.noteId; - widgetsByParent.add(widget); + for (const bundle of scriptBundles) { + let widget; + + try { + widget = await executeBundle(bundle); + if (widget) { + widget._noteId = bundle.noteId; + widgetsByParent.add(widget); + } + } catch (e: any) { + const noteId = bundle.noteId; + const note = await froca.getNote(noteId); + toastService.showPersistent({ + id: `custom-script-failure-${noteId}`, + title: t("toast.bundle-error.title"), + icon: "bx bx-error-circle", + message: t("toast.bundle-error.message", { + id: noteId, + title: note?.title, + message: e.message + }) + }); + + logError("Widget initialization failed: ", e); + continue; } - } catch (e: any) { - const noteId = bundle.noteId; - const note = await froca.getNote(noteId); - toastService.showPersistent({ - id: `custom-script-failure-${noteId}`, - title: t("toast.bundle-error.title"), - icon: "bx bx-error-circle", - message: t("toast.bundle-error.message", { - id: noteId, - title: note?.title, - message: e.message - }) - }); - - logError("Widget initialization failed: ", e); - continue; } + } catch (e) { + toastService.showPersistent({ + title: t("toast.widget-list-error.title"), + message: e.toString(), + icon: "bx bx-error-circle" + }); } return widgetsByParent; diff --git a/apps/client/src/services/server.ts b/apps/client/src/services/server.ts index 978aa91ab..b13653cf3 100644 --- a/apps/client/src/services/server.ts +++ b/apps/client/src/services/server.ts @@ -133,11 +133,11 @@ async function call(method: string, url: string, componentId?: string, option }; ipc.send("server-request", { - requestId: requestId, - headers: headers, - method: method, + requestId, + headers, + method, url: `/${window.glob.baseApiUrl}${url}`, - data: data + data }); })) as any; } else { @@ -161,7 +161,7 @@ function ajax(url: string, method: string, data: unknown, headers: Headers, sile const options: JQueryAjaxSettings = { url: window.glob.baseApiUrl + url, type: method, - headers: headers, + headers, timeout: 60000, success: (body, textStatus, jqXhr) => { const respHeaders: Headers = {}; @@ -288,8 +288,8 @@ async function reportError(method: string, url: string, statusCode: number, resp t("server.unknown_http_error_content", { statusCode, method, url, message: messageStr }), 15_000); } - const { throwError } = await import("./ws.js"); - throwError(`${statusCode} ${method} ${url} - ${message}`); + const { logError } = await import("./ws.js"); + logError(`${statusCode} ${method} ${url} - ${message}`); } } diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index b45f26cb5..fac7f588c 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -22,6 +22,9 @@ "bundle-error": { "title": "Failed to load a custom script", "message": "Script from note with ID \"{{id}}\", titled \"{{title}}\" could not be executed due to:\n\n{{message}}" + }, + "widget-list-error": { + "title": "Failed to obtain the list of widgets from the server" } }, "add_link": {