From 9bc96aeb8335c0b921899683094f02d3072bcb84 Mon Sep 17 00:00:00 2001 From: maziggy Date: Tue, 4 Aug 2026 12:54:24 +0200 Subject: [PATCH] Hold error and warning toasts for twice as long Every pop-up notification auto-dismissed after three seconds regardless of what it said. That suits "Settings saved" -- a confirmation of something the user just did, skimmed rather than read -- but errors and warnings are a different kind of message. They carry a reason, often one relayed from the printer or the backend, and they run to a couple of lines. Three seconds was not enough to finish reading one, and there is no notification history to go back to once it slides away. Errors and warnings now hold for six seconds; success and info keep the three-second default. The duration was a bare literal in showToast and is now derived from the toast type, with the long window expressed as twice the base so the two cannot drift apart if the base is retuned. showPersistentToast never had an auto-dismiss timer and is untouched, as is the background dispatch toast -- its timer measures "the summary has stopped changing" rather than reading time. Manual dismissal is unchanged for every type. --- CHANGELOG.md | 3 + .../__tests__/contexts/ToastContext.test.tsx | 63 +++- frontend/src/contexts/ToastContext.tsx | 14 +- .../{index-CFRqaod2.js => index-B2_C9nlv.js} | 306 +++++++++--------- static/index.html | 2 +- 5 files changed, 231 insertions(+), 157 deletions(-) rename static/assets/{index-CFRqaod2.js => index-B2_C9nlv.js} (84%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fe69b42b..5823b8193 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ All notable changes to Bambuddy will be documented in this file. ### Added - **Temperatures on the streaming overlay, and a builder for its URL (#1422, reporter @SMAW)** — The overlay at `/overlay/{printer}` draws live print data over a full-screen camera view for OBS, a wall display or any browser source. It could already be tuned — which fields, what size, what frame rate — but only through query parameters documented in the wiki, and temperatures were not among the fields on offer. Both are now addressed. Nozzle, bed and chamber readings join the list, shown with the target while the heater is still climbing and with the target dropped once it is reached, so a settled hotend reads "220°C" rather than "220 / 220°C" for the rest of the print. Both nozzles appear on a dual-nozzle printer. They are drawn whether or not a print is running, since a preheating machine is exactly when they are worth watching, and each reading appears only when the printer genuinely reports it — chamber temperature stays absent on P1 and A1 models, which publish a value with no sensor behind it. And **Settings → API Keys → Streaming Overlay** now builds the URL for you: pick the printer, tick the fields, set size and frame rate, paste in a token if login is enabled, and copy the result, with an optional preview alongside it. The preview stays off until you ask for it so that leaving the settings page open does not hold a viewer on the printer's single camera connection. Making that preview possible needed one narrow change to the security headers: the overlay path now sends `frame-ancestors 'self'` instead of `'none'`, so Bambuddy's own UI can embed it. Every other page still refuses to be framed at all, `'self'` permits a framer only on this same origin, and embedding the overlay from another host — Home Assistant on a different port, say — is unchanged and still requires `TRUSTED_FRAME_ORIGINS`. Temperatures are not in the default field set, so an overlay URL already pasted into a scene looks exactly the same after upgrading. Translated in all locales, wiki updated, covered by backend and frontend tests. +### Changed +- **Error and warning toasts now stay up twice as long** — Every pop-up notification disappeared after three seconds regardless of what it said. That is about right for "Settings saved", which confirms something you just did and is skimmed rather than read, but errors and warnings are a different kind of message: they carry a reason, often one relayed from the printer or the backend, and they run to a couple of lines. Three seconds was not long enough to finish reading one, and a missed error message is gone for good — there is no notification history to go back to. Errors and warnings now hold for six seconds. Success and informational toasts keep the three-second default, so the common case of clicking something and seeing it confirmed is unchanged, and the close button and the manual dismiss work exactly as before on all of them. The background print-dispatch toast is unaffected: it stays up while it has work in progress and clears itself shortly after the last job settles. Covered by frontend tests. + ### Fixed - **A drying cycle no longer reports itself finished a minute after it starts (#2759)** — Starting the dryer on an AMS 2 Pro holding two PETG and two PLA spools and picking PLA showed "PLA @ 45°C" for about a minute, then switched to "PETG @ 65°C" for the remaining twelve hours. Bambu never echoes back which filament or temperature a cycle is running, so the badge reads the target Bambuddy cached when it sent the command — and that cache had been thrown away. Between accepting the command and settling its countdown the firmware publishes one update with the remaining time at zero while the unit is still in its Checking phase; the reporter's log caught 720 minutes, then 0, then 719. Bambuddy read the zero as the cycle ending. Losing the cached target left the badge to guess the filament from the first loaded slot, which happened to be PETG, and its RFID-recommended 65°C — a confident wrong answer for a cycle running PLA at 45. The same false ending also armed smart-plug auto-off-after-drying, so anyone with that switched on had power scheduled to cut one minute into a twelve-hour dry. A remaining time of zero is now only treated as the end of a cycle when the AMS also reports an idle phase, which the firmware already publishes alongside it; stopping a dry early still ends it immediately, and a unit that reports no phase at all still ends its cycles as before. The fallback guess has been tightened to match: it now answers only when every loaded spool is the same filament, and on a mixed unit the badge shows the countdown alone rather than naming a temperature the cycle isn't using. Covered by backend tests. - **A print that never starts now says AMS drying was running, instead of blaming the SD card (#2758)** — Sending a job to an X2D with two AMS units mid-drying failed silently: the file uploaded, the printer accepted it and then simply stayed idle. Bambuddy waited out the start watchdog, re-uploaded the whole 3MF, waited again, and after three attempts gave up with advice to check the printer's screen and the SD card — while Bambu Studio, asked directly, said it could not start the job because of the drying. Bambuddy now watches the AMS drying telemetry it already receives across the dispatch window and, when a job never starts while a unit was drying, names the units in the failure message and records the correlation in the log from the first attempt rather than only after the retries are spent. This is deliberately a diagnosis and not a rule: the printers concerned support drying *continuing* through a print, so drying and printing are not in conflict as such, and the report also involved one AMS drying without its external power supply — which would make the start-of-print calibration a power problem rather than a drying one. Stopping the cycle automatically would therefore be acting on a guess, and could tear down drying the hardware was happy to continue. Until it is known which of the two is the real obstacle, Bambuddy tells you what it saw and leaves the call to you. The message for a stalled dispatch with no drying involved is unchanged. Wiki updated. Covered by backend tests. diff --git a/frontend/src/__tests__/contexts/ToastContext.test.tsx b/frontend/src/__tests__/contexts/ToastContext.test.tsx index ddd4e82fc..aa1743643 100644 --- a/frontend/src/__tests__/contexts/ToastContext.test.tsx +++ b/frontend/src/__tests__/contexts/ToastContext.test.tsx @@ -12,7 +12,7 @@ * paths no-op instead of crashing. */ -import { describe, it, expect, beforeEach, vi } from 'vitest'; +import { describe, it, expect, afterEach, beforeEach, vi } from 'vitest'; import { act, render, renderHook } from '@testing-library/react'; import { type ReactNode } from 'react'; import { ToastProvider, useToast } from '../../contexts/ToastContext'; @@ -163,3 +163,64 @@ describe('ToastContext viewport suppression', () => { expect(toast?.style.maxWidth).toContain('safe-area-inset-right'); }); }); + +describe('ToastContext auto-dismiss timing by type', () => { + // Errors and warnings carry more text than a success confirmation — a + // backend failure reason often runs to a couple of lines — so they hold + // for 6s while success/info keep the 3s default. + function TypedToastProbe({ type }: { type: 'success' | 'error' | 'warning' | 'info' }) { + const { showToast } = useToast(); + return