fix(esc): reauth / picker / quick-search were missing from the Esc chain

Three static modals had no entry in the fallback Esc handler, so Esc over
them fell through and closed the editor behind (or did nothing when no
editor was open — reauth and the autofill picker could only be dismissed by
mouse).

Also scopes the stray-modal catch added in a95becd to [data-dynamic]. As
written it matched ANY open .modal, so an Esc over reauth / quick-search /
the autofill picker would have removed those static nodes from the DOM for
good, breaking the feature until restart. Only the runtime-built folder
modal carries the marker.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
r-zakarya
2026-07-23 21:17:53 +01:00
parent a95becd582
commit 47c29bd04e
2 changed files with 27 additions and 11 deletions
+2 -2
View File
@@ -62,11 +62,11 @@ Préparer : 3 entrées `A`, `B`, `C`, dont `A` dans le dossier `Work` avec le ta
### A9 · favori / épingle pendant l'édition (non-régression) ### A9 · favori / épingle pendant l'édition (non-régression)
- **ACTION** : `A` ouverte + dirty → cliquer ★ et 📌 sur la ligne `A` → Save - **ACTION** : `A` ouverte + dirty → cliquer ★ et 📌 sur la ligne `A` → Save
- **ATTENDU** : l'entrée reste favorite et épinglée (ces colonnes ne sont pas dans le PUT de l'éditeur). - **ATTENDU** : l'entrée reste favorite et épinglée (ces colonnes ne sont pas dans le PUT de l'éditeur).✅
### A10 · icône / pièce jointe pendant l'édition (non-régression) ### A10 · icône / pièce jointe pendant l'édition (non-régression)
- **ACTION** : `A` ouverte + dirty → Settings → *Fetch missing* favicons (ou upload d'icône) → Save - **ACTION** : `A` ouverte + dirty → Settings → *Fetch missing* favicons (ou upload d'icône) → Save
- **ATTENDU** : l'icône survit au Save (endpoint dédié, hors payload éditeur). - **ATTENDU** : l'icône survit au Save (endpoint dédié, hors payload éditeur).✅ icon not refreshed in edit
### A11 · sync / import pendant que l'éditeur est ouvert — **trou connu** ### A11 · sync / import pendant que l'éditeur est ouvert — **trou connu**
- **ACTION** : `A` ouverte + dirty → lancer *Sync now* (ou importer un JSON en mode overwrite) qui met `A` à jour → Save - **ACTION** : `A` ouverte + dirty → lancer *Sync now* (ou importer un JSON en mode overwrite) qui met `A` à jour → Save
+25 -9
View File
@@ -5592,7 +5592,9 @@ function openFolderModal(existing) {
const old = document.getElementById('folderModal'); const old = document.getElementById('folderModal');
if (old) old.remove(); if (old) old.remove();
const modal = el('div', { id: 'folderModal', class: 'modal' }); // data-dynamic: built at runtime, so the Esc fallback may close it by
// removing the node (static modals must only ever be hidden).
const modal = el('div', { id: 'folderModal', class: 'modal', 'data-dynamic': '1' });
const backdrop = el('div', { class: 'modal-backdrop' }); const backdrop = el('div', { class: 'modal-backdrop' });
backdrop.addEventListener('click', () => modal.remove()); backdrop.addEventListener('click', () => modal.remove());
modal.appendChild(backdrop); modal.appendChild(backdrop);
@@ -8003,14 +8005,28 @@ async function init() {
closeGen(); closeGen();
return; return;
} }
// Any other open modal — the folder modal is built dynamically and if (!$('#reauthModal').classList.contains('is-hidden')) {
// has no id in this list, so without this Esc fell through to the closeReauth(false);
// slideover close below and shut the editor behind it. Closing a return;
// stray .modal is just .remove() (how its backdrop click closes). }
// The static modals above never reach here (their id checks return if (!$('#autofillPickerModal').classList.contains('is-hidden')) {
// first), so this only ever catches the dynamic ones. closeAutofillPicker();
const strayModal = document.querySelector('.modal:not(.is-hidden)'); return;
if (strayModal) { strayModal.remove(); return; } }
if (!$('#quickSearchModal').classList.contains('is-hidden')) {
// Reachable when focus left the search input (clicked a row),
// so the input's own Esc handler doesn't fire.
closeQuickSearchModal();
return;
}
// Modals built at runtime (the folder modal) have no id to test
// here, and without this Esc fell through to the slideover close
// below and shut the editor behind them. Removing the node IS how
// they close — their backdrop click does the same. Scoped to
// [data-dynamic] so it can never delete a static modal from the
// DOM, which would break that feature until the app restarts.
const dynModal = document.querySelector('.modal[data-dynamic]:not(.is-hidden)');
if (dynModal) { dynModal.remove(); return; }
if ($('#slideover').classList.contains('is-open')) { if ($('#slideover').classList.contains('is-open')) {
requestCloseSlideOver(); requestCloseSlideOver();
return; return;