export interface QuickLink { id: string; score: number; lastAccessed: number; } const RETURNED_LENGTH: number = 6; const MAX_SCORE: number = 50; const MAX_ENTRIES: number = RETURNED_LENGTH * 4; class QuickLinksService { #links = $state([]); constructor() { if (typeof window !== 'undefined') { const saved = localStorage.getItem('ql'); if (saved) { try { this.#links = JSON.parse(saved); } catch { this.#links = []; } } } } get list(): QuickLink[] { return this.#links.slice(0, RETURNED_LENGTH); } recordVisit(id: string) { if (id == '') return; const existing = this.#links.find((l) => l.id === id); if (existing) { existing.score += 1; existing.lastAccessed = Date.now(); } else { this.#links.push({ id: id, score: 1, lastAccessed: Date.now() }); } // Score decay - if MAX_SCORE reached, divide all by two if (this.#links.some((l) => l.score > MAX_SCORE)) { this.#links.forEach((l) => { l.score = Math.max(1, Math.floor(l.score / 2)); }); } // Sort & Prune const sorted = [...this.#links].sort( (a, b) => b.score - a.score || b.lastAccessed - a.lastAccessed ); this.#links = sorted.slice(0, MAX_ENTRIES); if (typeof window !== 'undefined') { localStorage.setItem('ql', JSON.stringify(this.#links)); } } reset() { this.#links = []; if (typeof window !== 'undefined') { localStorage.removeItem('ql'); } } } export const quickLinks = new QuickLinksService();