From f1621df3e21c754d149f6f407cc0f953988845ed Mon Sep 17 00:00:00 2001 From: adlee-was-taken Date: Sat, 30 May 2026 21:41:50 -0400 Subject: [PATCH] refactor(ext/shared): move View + PopupState to shared/popup-state.ts Foundation for Plan C Phase 1: shared/state.ts (next task) needs to import PopupState without creating a popup->shared circular dep. popup.ts now re-exports from the new location so existing callers don't break in this task. Task 1.4 will sweep them onto the canonical import path. Co-Authored-By: Claude Opus 4.7 --- extension/src/popup/popup.ts | 25 ++-------------- extension/src/shared/popup-state.ts | 45 +++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 23 deletions(-) create mode 100644 extension/src/shared/popup-state.ts diff --git a/extension/src/popup/popup.ts b/extension/src/popup/popup.ts index d098185..e344a3c 100644 --- a/extension/src/popup/popup.ts +++ b/extension/src/popup/popup.ts @@ -67,29 +67,8 @@ function parseUrlParams(): { view?: View; type?: string; id?: string } | null { // --- State --- -export type View = 'locked' | 'list' | 'detail' | 'add' | 'edit' | 'settings' | 'settings-vault' | 'trash' | 'devices' | 'field-history'; - -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: import('../shared/types').ItemType | null; - vaultSettings: import('../shared/types').VaultSettings | null; - generatorDefaults: import('../shared/types').GeneratorRequest | null; - historyItemId: import('../shared/types').ItemId | null; -} +export type { View, PopupState } from '../shared/popup-state'; +import type { View, PopupState } from '../shared/popup-state'; let currentState: PopupState = { view: 'locked', diff --git a/extension/src/shared/popup-state.ts b/extension/src/shared/popup-state.ts new file mode 100644 index 0000000..eb2c728 --- /dev/null +++ b/extension/src/shared/popup-state.ts @@ -0,0 +1,45 @@ +// 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'; + +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; +}