import { HISTORY_MAX_ENTRIES, type HistoryEntry } from '@shared/ipc' import { isValidHistoryEntry } from './core/validation' import { createJsonStore } from './jsonStore' // Plain JSON in userData (portable build redirects userData next to the exe). // Kept simple per the build plan; can migrate to better-sqlite3 later. Atomic // writes, corruption backup, and caching come from the shared jsonStore (R1–R3). // The row cap (HISTORY_MAX_ENTRIES) is shared with the renderer's optimistic list. // // Per-entry validation (isValidHistoryEntry) so a hand-edited or corrupted // history.json can't feed the UI (or openPath) entries with the wrong shape — // invalid rows are dropped rather than trusted. (audit S5) const store = createJsonStore('history.json', isValidHistoryEntry, HISTORY_MAX_ENTRIES) export function listHistory(): HistoryEntry[] { return store.read() } export function addHistory(entry: HistoryEntry): HistoryEntry[] { // De-dupe by id AND url (M35): a History re-download re-queues via addFromUrl, // which mints a NEW id, so id-only de-dup would let the same video accumulate a // fresh row on every re-download. Dropping any prior entry with the same url // keeps one row per video, refreshed to the top. const prior = listHistory().filter((e) => e.id !== entry.id && e.url !== entry.url) return store.write([entry, ...prior]) } export function removeHistory(id: string): HistoryEntry[] { return store.write(listHistory().filter((e) => e.id !== id)) } export function removeManyHistory(ids: string[]): HistoryEntry[] { const remove = new Set(ids) return store.write(listHistory().filter((e) => !remove.has(e.id))) } export function clearHistory(): HistoryEntry[] { return store.write([]) }