feat(ext/popup): open setup via chrome.tabs.create, drop setup view from popup

The popup is too constrained for multi-step setup (Chrome closes it when
focus shifts to a file picker). Previously the popup rendered a pass-through
setup-wizard component that itself opened setup.html in a tab. Cut the
middleman: if not configured, directly chrome.tabs.create the setup page
and window.close() the popup.

- Remove 'setup' from the View union and the setup case from render().
- Delete setup-wizard component entirely — setup.html is the canonical flow.
- Drop renderSetupWizard import.

The @ts-nocheck stays on popup.ts until Slice 6 (item-* rewrites).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
adlee-was-taken
2026-04-20 20:33:49 -04:00
parent 2ff3ab1d7f
commit fbb64729ce
2 changed files with 3 additions and 37 deletions

View File

@@ -1,31 +0,0 @@
/// Setup prompt — directs users to the full-page setup wizard.
///
/// The popup is too constrained for file pickers and multi-step forms
/// (Chrome closes it when focus shifts). All real setup happens in
/// setup.html, which pushes config to chrome.storage.local when done.
import { escapeHtml } from '../popup';
export function renderSetupWizard(app: HTMLElement): void {
app.innerHTML = `
<div class="pad" style="padding-top:24px;text-align:center;">
<img class="brand-logo" src="icons/relicario-logo.svg" alt="">
<div class="brand" style="font-size:16px;margin-bottom:4px;">relicario</div>
<p class="secondary" style="margin-bottom:20px;">two-factor vault</p>
<p class="muted" style="margin-bottom:16px;font-size:11px;line-height:1.6;">
No vault configured yet. Open the setup wizard to
create a new vault or connect to an existing one.
</p>
<button class="btn btn-primary" id="open-setup-btn" style="width:100%;">
open setup wizard
</button>
</div>
`;
document.getElementById('open-setup-btn')?.addEventListener('click', () => {
chrome.tabs.create({ url: chrome.runtime.getURL('setup.html') });
window.close();
});
}

View File

@@ -10,7 +10,6 @@ import { renderUnlock } from './components/unlock';
import { renderEntryList } from './components/entry-list'; import { renderEntryList } from './components/entry-list';
import { renderEntryDetail } from './components/entry-detail'; import { renderEntryDetail } from './components/entry-detail';
import { renderEntryForm } from './components/entry-form'; import { renderEntryForm } from './components/entry-form';
import { renderSetupWizard } from './components/setup-wizard';
import { renderSettings } from './components/settings'; import { renderSettings } from './components/settings';
// --- Escape HTML to prevent XSS --- // --- Escape HTML to prevent XSS ---
@@ -22,7 +21,7 @@ export function escapeHtml(str: string): string {
// --- State --- // --- State ---
export type View = 'setup' | 'locked' | 'list' | 'detail' | 'add' | 'edit' | 'settings'; export type View = 'locked' | 'list' | 'detail' | 'add' | 'edit' | 'settings';
export interface PopupState { export interface PopupState {
view: View; view: View;
@@ -80,9 +79,6 @@ function render(): void {
if (!app) return; if (!app) return;
switch (currentState.view) { switch (currentState.view) {
case 'setup':
renderSetupWizard(app);
break;
case 'locked': case 'locked':
renderUnlock(app); renderUnlock(app);
break; break;
@@ -112,7 +108,8 @@ async function init(): Promise<void> {
if (setupResp.ok) { if (setupResp.ok) {
const data = setupResp.data as { isConfigured: boolean }; const data = setupResp.data as { isConfigured: boolean };
if (!data.isConfigured) { if (!data.isConfigured) {
navigate('setup'); await chrome.tabs.create({ url: chrome.runtime.getURL('setup.html') });
window.close();
return; return;
} }
} }