From 911881880dffbcac0aad85fe8f6e45924abc1094 Mon Sep 17 00:00:00 2001 From: Anton Date: Tue, 13 Oct 2026 19:45:26 +0300 Subject: [PATCH] Web: show the brush preset storage banner only while a change is unsaved (#4918) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the browser denies IndexedDB from the start (a sandboxed iframe without allow-same-origin, blocked site data), the banner "Brush preset changes are not saved: SecurityError … Browser storage is unavailable" stays above the app for the whole session, before any preset was touched and with nothing to dismiss. Show it only while a preset change is unsaved. Nothing is lost before the first change; that change brings the same banner with the reason. Write errors and rejected records keep showing it, as both leave changes unsaved. Co-authored-by: kuvshin888 <192736288+kuvshin888@users.noreply.github.com> --- apps/photocraft-web/src/preset_bridge.rs | 1 + apps/photocraft-web/src/web.rs | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/photocraft-web/src/preset_bridge.rs b/apps/photocraft-web/src/preset_bridge.rs index 6c9ef84add..a7445bbc14 100644 --- a/apps/photocraft-web/src/preset_bridge.rs +++ b/apps/photocraft-web/src/preset_bridge.rs @@ -337,6 +337,7 @@ mod tests { let b = Bridge::default(); b.unavailable("SecurityError".into()); let (mut s, _) = session(b.clone()); + assert!(!b.unsaved(), "nothing is lost before the first change, so the web shell shows no banner"); import(&mut s); assert!(s.tools.presets.iter().any(|p| p.name == "Browser seam brush")); assert!(b.unsaved()); diff --git a/apps/photocraft-web/src/web.rs b/apps/photocraft-web/src/web.rs index 8d7e8e0826..a5c9d8a565 100644 --- a/apps/photocraft-web/src/web.rs +++ b/apps/photocraft-web/src/web.rs @@ -305,7 +305,12 @@ impl eframe::App for WebShell { } fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame) { - if let Some(error) = self.presets.error() { + // Only while a preset change is unsaved. Storage the browser denies from the start (a + // sandboxed iframe, blocked site data) loses nothing until the first change, and that + // change brings the banner with the reason. + if self.presets.unsaved() + && let Some(error) = self.presets.error() + { egui::Panel::top("browser_preset_storage").show(ui, |ui| { let tokens = photocraft_ui_egui::theme::Tokens::for_kind(self.app.ui.theme); // Put retry first so floating brush windows cannot cover the control.