From 77b63ed9422ee83dccf56e8d32f9b04300018418 Mon Sep 17 00:00:00 2001 From: lekt8 Date: Wed, 3 Jun 2026 02:48:25 +0800 Subject: [PATCH] Keep Cookbook download-failure toasts visible long enough to read (#1412) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Cookbook download path showed its error toasts with the default ~1.2s duration, so an actionable message like "tmux is required for Cookbook background downloads/serves … install it with your OS package manager" vanished before it could be read (issue #1355). The serve path already uses multi-second durations. Give the three "Download failed" toasts a 9s duration to match. Co-authored-by: Claude Opus 4.8 (1M context) --- static/js/cookbookDownload.js | 8 +++--- .../test_cookbook_download_toast_duration.py | 27 +++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 tests/test_cookbook_download_toast_duration.py diff --git a/static/js/cookbookDownload.js b/static/js/cookbookDownload.js index 4eb0038..4fe2d4b 100644 --- a/static/js/cookbookDownload.js +++ b/static/js/cookbookDownload.js @@ -555,18 +555,20 @@ export async function _runModelDownload(panel, model, backend, hostOverride) { body: JSON.stringify(payload), }); if (!res.ok) { - uiModule.showToast('Download failed: HTTP ' + res.status); + // Errors carry actionable text (e.g. "tmux is required …"); keep them up + // long enough to read, matching the serve path's duration (issue #1355). + uiModule.showToast('Download failed: HTTP ' + res.status, 9000); return; } const data = await res.json(); if (!data.ok) { - uiModule.showToast('Download failed: ' + (data.error || '')); + uiModule.showToast('Download failed: ' + (data.error || ''), 9000); return; } _addTask(data.session_id, shortName, 'download', payload); uiModule.showToast(`Downloading ${shortName}...`); } catch (e) { - uiModule.showToast('Download failed: ' + e.message); + uiModule.showToast('Download failed: ' + e.message, 9000); } } diff --git a/tests/test_cookbook_download_toast_duration.py b/tests/test_cookbook_download_toast_duration.py new file mode 100644 index 0000000..33afc52 --- /dev/null +++ b/tests/test_cookbook_download_toast_duration.py @@ -0,0 +1,27 @@ +"""Regression guard for issue #1355 — the Cookbook *download* error toast used +the default ~1.2s duration, so an actionable message like "tmux is required …" +vanished before it could be read. The serve path already used multi-second +durations; the download-failure toasts now match. + +cookbookDownload.js pulls in browser globals so it can't run under node; this +guards the durations at the source level. +""" +import re +from pathlib import Path + +SRC = Path(__file__).resolve().parent.parent / "static/js/cookbookDownload.js" +_MIN_MS = 5000 + + +def test_download_failure_toasts_stay_visible(): + # Each download-failure toast is a single line; assert each carries an + # explicit duration >= _MIN_MS so the actionable error stays readable. + lines = [ + ln for ln in SRC.read_text(encoding="utf-8").splitlines() + if "showToast(" in ln and "Download failed:" in ln + ] + assert lines, "expected at least one 'Download failed' showToast call" + for ln in lines: + m = re.search(r",\s*(\d{3,})\s*\)\s*;?\s*$", ln) + assert m, f"download-failure toast has no explicit duration: {ln.strip()}" + assert int(m.group(1)) >= _MIN_MS, f"duration too short to read: {ln.strip()}"