Files
relicario/extension/src/popup/components/unlock.ts
adlee-was-taken 3238ef4dd4 refactor(ext/popup): remove last @ts-nocheck, align to typed-item types
Clears the final four transitional @ts-nocheck shields:
- popup.ts (already mostly updated in Slice 6 prior tasks; nocheck just
  removed and the init fallback switched to list_items / ItemId typing)
- unlock.ts (list_entries → list_items; ManifestEntry typing)
- settings.ts (RelicarioSettings → DeviceSettings; pure type rename, UX
  unchanged)

Also drops the stale `idfoto-extension` name in bun.lock (workspace was
renamed; lock file still carried the old name).

Verification:
  git grep -n '@ts-nocheck' extension/src/  → 0 hits
  bun run build + build:firefox             → both green
  bun run test                              → 52/52 passing
  cargo test --workspace                    → green

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 21:44:12 -04:00

58 lines
2.1 KiB
TypeScript

/// Unlock view — passphrase input with ENTER to submit.
import { getState, setState, sendMessage, navigate, escapeHtml } from '../popup';
import type { ItemId, ManifestEntry } from '../../shared/types';
export function renderUnlock(app: HTMLElement): void {
const state = getState();
app.innerHTML = `
<div class="pad" style="text-align:center; padding-top:40px;">
<img class="brand-logo" src="icons/relicario-logo.svg" alt="">
<div class="brand">relicario</div>
<p class="muted" style="margin:8px 0 24px;">two-factor vault</p>
<div class="form-group">
<input
type="password"
id="passphrase-input"
placeholder="passphrase"
autocomplete="off"
${state.loading ? 'disabled' : ''}
>
</div>
${state.loading ? '<div style="margin:12px 0;"><span class="spinner"></span></div>' : ''}
${state.error ? `<div class="error">${escapeHtml(state.error)}</div>` : ''}
<div style="margin-top:24px;">
<button class="btn" id="settings-btn" style="font-size:11px;">settings</button>
</div>
</div>
`;
const input = document.getElementById('passphrase-input') as HTMLInputElement;
if (input && !state.loading) {
input.focus();
input.addEventListener('keydown', async (e) => {
if (e.key === 'Enter') {
const passphrase = input.value;
if (!passphrase) return;
setState({ loading: true, error: null });
const resp = await sendMessage({ type: 'unlock', passphrase });
if (resp.ok) {
const listResp = await sendMessage({ type: 'list_items' });
if (listResp.ok) {
const data = listResp.data as { items: Array<[ItemId, ManifestEntry]> };
navigate('list', { entries: data.items });
} else {
setState({ loading: false, error: listResp.error });
}
} else {
setState({ loading: false, error: resp.error });
}
}
});
}
const settingsBtn = document.getElementById('settings-btn');
settingsBtn?.addEventListener('click', () => navigate('settings'));
}