From 0d0482e4b639b204064ec87a10b1dd2c1c85a567 Mon Sep 17 00:00:00 2001 From: lgcosta Date: Thu, 5 Nov 2026 08:30:17 -0300 Subject: [PATCH] fix(ui): boot sobrevive a estado de abas corrompido (Firefox) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- web/js/app.js | 14 +++++++++++--- web/sw.js | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/web/js/app.js b/web/js/app.js index cb9ecd9..795b953 100644 --- a/web/js/app.js +++ b/web/js/app.js @@ -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(); diff --git a/web/sw.js b/web/sw.js index 71a56c4..e71beec 100644 --- a/web/sw.js +++ b/web/sw.js @@ -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',