Replaces the previously any-typed StateHost contract with a typed interface. Adds double-registration guard and __resetHostForTests for vitest. sendMessage wrapper is currently a pass-through; Phase 4 will fill its body with the vault_locked intercept lifted from vault.ts. Widens PopupState/View on shared/popup-state.ts to cover vault-tab-only views (history, backup, import) and vault-tab-only fields (unlocked, drawerOpen, typePanelOpen) so VaultState satisfies StateHost.getState() without a cast. The popup surface ignores the new optional fields. Drops the `any` annotations on vault.ts's registerHost callbacks now that the typed StateHost contract infers them from PopupState. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
58 lines
1.7 KiB
TypeScript
58 lines
1.7 KiB
TypeScript
// State shared between popup and vault surfaces. Kept here (not in popup/) so
|
|
// shared/state.ts can import without creating a popup→shared circular dep.
|
|
|
|
import type {
|
|
Item,
|
|
ItemId,
|
|
ItemType,
|
|
ManifestEntry,
|
|
GeneratorRequest,
|
|
VaultSettings,
|
|
} from './types';
|
|
|
|
export type View =
|
|
| 'locked'
|
|
| 'list'
|
|
| 'detail'
|
|
| 'add'
|
|
| 'edit'
|
|
| 'settings'
|
|
| 'settings-vault'
|
|
| 'trash'
|
|
| 'devices'
|
|
| 'field-history'
|
|
// Vault-tab-only views; popup never navigates to these. Kept in the union so
|
|
// a single typed StateHost contract serves both surfaces (popup + vault).
|
|
| 'history'
|
|
| 'backup'
|
|
| 'import';
|
|
|
|
export interface PopupState {
|
|
view: View;
|
|
entries: Array<[ItemId, ManifestEntry]>;
|
|
selectedId: ItemId | null;
|
|
selectedItem: Item | null;
|
|
selectedIndex: number;
|
|
searchQuery: string;
|
|
activeGroup: string | null;
|
|
error: string | null;
|
|
loading: boolean;
|
|
// Captured tab snapshot taken at popup-open. Used by fill_credentials
|
|
// to guard against TOCTOU navigation — the SW re-checks this URL's
|
|
// hostname against the tab's live URL before forwarding fill_credentials
|
|
// to the content script. See router/popup-only.ts#handleFillCredentials.
|
|
capturedTabId: number | null;
|
|
capturedUrl: string;
|
|
newType: ItemType | null;
|
|
vaultSettings: VaultSettings | null;
|
|
generatorDefaults: GeneratorRequest | null;
|
|
historyItemId: ItemId | null;
|
|
// Vault-tab-only fields. The popup surface leaves these at their defaults
|
|
// (unlocked=false implicit via separate lock-screen view, drawer/panel false).
|
|
// Kept on the shared shape so VaultState satisfies StateHost.getState()
|
|
// without a cast.
|
|
unlocked?: boolean;
|
|
drawerOpen?: boolean;
|
|
typePanelOpen?: boolean;
|
|
}
|