diff --git a/extension/src/popup/components/devices.ts b/extension/src/popup/components/devices.ts index c10956f..5b7c0d4 100644 --- a/extension/src/popup/components/devices.ts +++ b/extension/src/popup/components/devices.ts @@ -2,6 +2,7 @@ import { setState, sendMessage, navigate, escapeHtml } from '../../shared/state'; import type { Device } from '../../shared/types'; +import { relativeTime } from '../../shared/relative-time'; interface RevokedEntry { name: string; @@ -10,16 +11,6 @@ interface RevokedEntry { revoked_by: string; } -function relativeTime(unixSec: number): string { - const now = Math.floor(Date.now() / 1000); - const diff = now - unixSec; - if (diff < 60) return 'just now'; - if (diff < 3600) return `${Math.floor(diff / 60)}m ago`; - if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`; - if (diff < 2592000) return `${Math.floor(diff / 86400)}d ago`; - return `${Math.floor(diff / 2592000)}mo ago`; -} - function detectDefaultDeviceName(): string { const ua = navigator.userAgent ?? ''; const platform = (navigator.platform ?? '').toLowerCase(); diff --git a/extension/src/popup/components/field-history.ts b/extension/src/popup/components/field-history.ts index 1edf1f2..8cf1454 100644 --- a/extension/src/popup/components/field-history.ts +++ b/extension/src/popup/components/field-history.ts @@ -3,19 +3,9 @@ import { getState, setState, sendMessage, navigate, escapeHtml } from '../../shared/state'; import { colorizePassword } from '../../shared/password-coloring'; import type { FieldHistoryView } from '../../shared/types'; +import { relativeTime } from '../../shared/relative-time'; import { GLYPH_COPY } from '../../shared/glyphs'; -function relativeTime(unixSec: number): string { - const now = Math.floor(Date.now() / 1000); - const diff = now - unixSec; - if (diff < 60) return 'just now'; - if (diff < 3600) return `${Math.floor(diff / 60)}m ago`; - if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`; - if (diff < 604800) return `${Math.floor(diff / 86400)}d ago`; - if (diff < 2592000) return `${Math.floor(diff / 604800)}w ago`; - return `${Math.floor(diff / 2592000)}mo ago`; -} - const revealedSet = new Set(); // Map from entry key → plaintext value; populated on each render so we never diff --git a/extension/src/popup/components/settings-vault.ts b/extension/src/popup/components/settings-vault.ts index 288c032..14749c6 100644 --- a/extension/src/popup/components/settings-vault.ts +++ b/extension/src/popup/components/settings-vault.ts @@ -6,6 +6,7 @@ import { getState, setState, sendMessage, navigate, escapeHtml, openVaultTab } f import type { VaultSettings, TrashRetention, HistoryRetention, GeneratorRequest, } from '../../shared/types'; +import { relativeTime } from '../../shared/relative-time'; import { openGeneratorPanel, closeGeneratorPanel, isGeneratorPanelOpen } from './generator-panel'; import { GLYPH_NEXT } from '../../shared/glyphs'; @@ -65,17 +66,6 @@ function generatorSummary(req: GeneratorRequest): string { return `BIP39, ${req.word_count} words, "${req.separator}" separator, ${req.capitalization}`; } -// --- Time formatting --- - -function relativeTime(unixSec: number): string { - const now = Math.floor(Date.now() / 1000); - const diff = now - unixSec; - if (diff < 60) return 'just now'; - if (diff < 3600) return `${Math.floor(diff / 60)}m ago`; - if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`; - return `${Math.floor(diff / 86400)}d ago`; -} - // --- Render --- export function renderVaultSettings(app: HTMLElement): void { diff --git a/extension/src/popup/components/trash.ts b/extension/src/popup/components/trash.ts index 27c32a5..9c26383 100644 --- a/extension/src/popup/components/trash.ts +++ b/extension/src/popup/components/trash.ts @@ -2,6 +2,7 @@ import { getState, setState, sendMessage, navigate, escapeHtml } from '../../shared/state'; import type { ItemId, ManifestEntry, VaultSettings } from '../../shared/types'; +import { relativeTime, daysUntilPurge } from '../../shared/relative-time'; import { GLYPH_TYPE_LOGIN, GLYPH_TYPE_SECURE_NOTE, GLYPH_TYPE_IDENTITY, GLYPH_TYPE_CARD, GLYPH_TYPE_KEY, GLYPH_TYPE_DOCUMENT, GLYPH_TYPE_TOTP, @@ -17,21 +18,6 @@ const TYPE_ICONS: Record = { totp: GLYPH_TYPE_TOTP, }; -function relativeTime(unixSec: number): string { - const now = Math.floor(Date.now() / 1000); - const diff = now - unixSec; - if (diff < 60) return 'just now'; - if (diff < 3600) return `${Math.floor(diff / 60)}m ago`; - if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`; - return `${Math.floor(diff / 86400)}d ago`; -} - -function daysUntilPurge(trashedAt: number, retention: VaultSettings['trash_retention']): number | null { - if (retention.kind === 'forever') return null; - const trashedDaysAgo = Math.floor((Date.now() / 1000 - trashedAt) / 86400); - return Math.max(0, retention.value - trashedDaysAgo); -} - export function teardown(): void { // No cleanup needed } diff --git a/extension/src/vault/vault.ts b/extension/src/vault/vault.ts index 2f8f0a0..4ef0196 100644 --- a/extension/src/vault/vault.ts +++ b/extension/src/vault/vault.ts @@ -10,6 +10,7 @@ import type { } from '../shared/types'; import { registerHost } from '../shared/state'; import { lookupErrorCopy, type ErrorCta } from '../shared/error-copy'; +import { relativeTime } from '../shared/relative-time'; import { GLYPH_TRASH, GLYPH_DEVICES, GLYPH_SETTINGS, GLYPH_LOCK, GLYPH_TYPE_LOGIN, GLYPH_TYPE_SECURE_NOTE, GLYPH_TYPE_TOTP, @@ -122,14 +123,6 @@ function typeLabel(t: ItemType): string { return labels[t]; } -function relativeTime(unixSec: number): string { - const diffS = Math.floor(Date.now() / 1000) - unixSec; - if (diffS < 60) return 'just now'; - if (diffS < 3600) return `${Math.floor(diffS / 60)}m ago`; - if (diffS < 86400) return `${Math.floor(diffS / 3600)}h ago`; - return `${Math.floor(diffS / 86400)}d ago`; -} - // --------------------------------------------------------------------------- // Hash routing // ---------------------------------------------------------------------------