fix(ui): boot sobrevive a estado de abas corrompido (Firefox)

Erro relatado: 'can't access property "key", opened[want] is undefined'.
Causa: persistTabs gravava active = -1 quando findIndex não achava a aba
ativa (corrida em pagehide/fechamento); restoreTabs usava o índice cru →
opened[-1] undefined derrubava o boot inteiro.

- persistTabs: grava Math.max(0, index) — nunca negativo
- restoreTabs: clamp do índice salvo para [0, len-1]
- boot: try/catch em restoreTabs com fallback de rascunho novo — estado
  corrompido algum (JSON lixo, ids fantasmas, índices inválidos) não impede
  mais o app de abrir
- sw.js: CACHE bump para notas-shell-v3

Testado: {open:[{id:fantasma}],active:-1} e {active:5} com rascunho → boot
limpo, rascunho restaurado, sem toast de erro.
This commit is contained in:
lgcosta committed 2026-11-05 08:30:17 -03:00
1 parent 650229bdb4
commit 0d0482e4b6
2 files changed
+12 -4

No files matched your search

+11 -3
View File
@@ -385,7 +385,7 @@
const content = t.content.length > DRAFT_MAX ? t.content.slice(0, DRAFT_MAX) : t.content;
return { draft: { title: t.title, format: t.format, categories: t.categories, content } };
});
const active = state.tabs.findIndex((t) => t.key === state.activeKey);
const active = Math.max(0, state.tabs.findIndex((t) => t.key === state.activeKey));
localStorage.setItem(TABS_KEY, JSON.stringify({ open, active }));
} catch { /* quota cheia: ignora */ }
}, 400);
@@ -415,8 +415,10 @@
}
if (!opened.length) opened.push(newTab());
}
// índice salvo pode ser inválido (-1 de sessão encerrada sem aba ativa, etc.)
state.tabs = opened;
const want = saved && Number.isInteger(saved.active) ? Math.min(saved.active, opened.length - 1) : 0;
const raw = saved && Number.isInteger(saved.active) ? saved.active : 0;
const want = Math.min(Math.max(0, raw), opened.length - 1);
activateTab(opened[want].key);
}
@@ -2026,7 +2028,13 @@
async function boot() {
applyPrefs();
await Promise.all([loadNotes(), loadAggregates()]);
await restoreTabs();
try {
await restoreTabs();
} catch (err) {
console.error('restoreTabs falhou', err);
state.tabs = [newTab()];
activateTab(state.tabs[0].key);
}
updateStatus();
state.booted = true;
refreshInstallUI();
+1 -1
View File
@@ -1,7 +1,7 @@
/* Service Worker do Notas — caches versionados.
* BUMP de CACHE em todo deploy que mude shell/assets (o activate limpa os antigos).
*/
const CACHE = 'notas-shell-v2';
const CACHE = 'notas-shell-v3';
const SHELL = [
'/',
'/css/app.css',