diff --git a/delphi-backend/assets/assets.res b/delphi-backend/assets/assets.res index b7359cd..7a54d96 100644 Binary files a/delphi-backend/assets/assets.res and b/delphi-backend/assets/assets.res differ diff --git a/js/app.js b/js/app.js index a2977ea..08ea7f7 100644 --- a/js/app.js +++ b/js/app.js @@ -10402,6 +10402,18 @@ async function init() { if (e.key !== 'Escape') return; if (!$('#slideover').classList.contains('is-open')) return; if (document.querySelector('.modal:not(.is-hidden)')) return; + // Settings panel takes priority — when both Settings AND the + // editor are open, the first Esc should close Settings (the + // thing the user just opened on top), the second Esc handles + // the editor's dirty-check. Let the Settings Esc handler run. + if ($('#settingsPanel').classList.contains('is-open')) return; + // Stop here so the global "Esc closes confirmModal" handler + // doesn't fire on the SAME keystroke and immediately dismiss + // the discard-confirm dialog that requestCloseSlideOver just + // opened — that bug left the user with no visible feedback at + // all (modal opened and closed in one tick). + e.preventDefault(); + e.stopPropagation(); requestCloseSlideOver(); }, true); // Click-outside closes too. mousedown origin is captured so a @@ -10585,8 +10597,13 @@ async function init() { if (e.key !== 'Escape') return; if (!$('#settingsPanel').classList.contains('is-open')) return; if (document.querySelector('.modal:not(.is-hidden)')) return; + // Don't let the global Esc-fallback handler fire on the same + // keystroke — its slideover-close branch would pop the discard + // confirm in the background while Settings closes, surprising + // the user who expected one Esc = close one panel. + e.stopPropagation(); closeSettings(); - }); + }, true); // Settings search box: live filter on every input. Escape clears the // query (without closing the panel — the existing Esc handler also