feat(ext/popup): field history view — masked values with reveal toggle

Shows current + historical values for tracked fields (password/concealed).
Click to reveal, copy button per entry (plaintext stored in a module-level
Map, never embedded in the DOM). Grouped by field name if multiple tracked
fields exist. Adds historyItemId to PopupState and 'field-history' to View.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
adlee-was-taken
2026-04-27 00:23:54 -04:00
parent 7fe54472b3
commit 3b4788e5dc
4 changed files with 289 additions and 1 deletions

View File

@@ -11,6 +11,7 @@ import { renderItemDetail } from './components/item-detail';
import { renderItemForm } from './components/item-form';
import { renderSettings } from './components/settings';
import { renderVaultSettings } from './components/settings-vault';
import { renderFieldHistory } from './components/field-history';
// --- Escape HTML to prevent XSS ---
export function escapeHtml(str: string): string {
@@ -24,7 +25,7 @@ export function escapeHtml(str: string): string {
// --- State ---
export type View = 'locked' | 'list' | 'detail' | 'add' | 'edit' | 'settings' | 'settings-vault';
export type View = 'locked' | 'list' | 'detail' | 'add' | 'edit' | 'settings' | 'settings-vault' | 'field-history';
export interface PopupState {
view: View;
@@ -45,6 +46,7 @@ export interface PopupState {
newType: import('../shared/types').ItemType | null;
vaultSettings: import('../shared/types').VaultSettings | null;
generatorDefaults: import('../shared/types').GeneratorRequest | null;
historyItemId: import('../shared/types').ItemId | null;
}
let currentState: PopupState = {
@@ -62,6 +64,7 @@ let currentState: PopupState = {
newType: null,
vaultSettings: null,
generatorDefaults: null,
historyItemId: null,
};
export function getState(): PopupState {
@@ -150,6 +153,9 @@ function render(): void {
case 'settings-vault':
renderVaultSettings(app);
break;
case 'field-history':
renderFieldHistory(app);
break;
}
}