From 242cd2a943160d3cdc09a86ecc06d83949375b2e Mon Sep 17 00:00:00 2001 From: ChuckBuilds Date: Thu, 16 Jul 2026 10:28:41 -0400 Subject: [PATCH] feat(web): plugin install auto-enables + persistent restart nudge Getting a plugin onto the display used to take three disconnected manual steps: install from the store, flip its enable toggle, then restart the display service - with no in-UI hint that steps 2 and 3 were needed (only docs/GETTING_STARTED.md mentions it). - installPlugin() now enables the plugin immediately on successful install (owner-confirmed behavior change: always auto-enable, no opt-out; users who don't want it running toggle it off as before), then shows a persistent toast ("... restart the display to show it") with an inline "Restart Now" button wired to the existing restartDisplay() - the same function the three existing Restart Display buttons call. - notification.js: show() accepts optional { actionLabel, onAction } to render one inline action button per toast. Callbacks are stored per notification id and cleaned up on dismiss; a new triggerAction() public method runs the callback and dismisses. The global showNotification() shorthand now forwards a full options object as its second argument (legacy type-string calls unchanged). Scope note: applies to the plugin store's install path (window.installPlugin). The custom-registry install path keeps its existing behavior. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01KEZK1P1Q1fu5pcuVrkrCFZ --- .../static/v3/js/widgets/notification.js | 35 +++++++++++++++++-- web_interface/static/v3/plugins_manager.js | 13 +++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/web_interface/static/v3/js/widgets/notification.js b/web_interface/static/v3/js/widgets/notification.js index 5fa43f0d..f1cf9405 100644 --- a/web_interface/static/v3/js/widgets/notification.js +++ b/web_interface/static/v3/js/widgets/notification.js @@ -58,6 +58,9 @@ // Track active notifications let activeNotifications = []; + // onAction callbacks for notifications with an inline action button, + // keyed by notification id (cleaned up on dismiss). + const actionCallbacks = {}; let notificationCounter = 0; /** @@ -113,6 +116,7 @@ // Remove from tracking array activeNotifications = activeNotifications.filter(id => id !== notificationId); + delete actionCallbacks[notificationId]; } /** @@ -158,6 +162,20 @@ html += `${escapeHtml(message)}`; + // Optional inline action button (e.g. "Restart Now" on a restart nudge). + // The callback is stored by id and invoked via triggerAction, which + // also dismisses the notification. + if (options.actionLabel && typeof options.onAction === 'function') { + actionCallbacks[notificationId] = options.onAction; + html += ` + + `; + } + if (dismissible) { html += `