// Portable grid-column preferences (visibility / order / width / sort). // // Stored in the DB settings table (so they travel with the logbook and // survive a reinstall) AND mirrored to the WebView localStorage as a fast, // flicker-free cache. On a fresh machine localStorage is empty, so we fall // back to the DB copy and re-seed the cache. import { GetUIPref, SetUIPref } from '../../wailsjs/go/main/App'; // The DB copy is ALREADY per-profile (the backend prefixes every ui.* key with // the active profile id). The localStorage cache, however, is one namespace for // the whole WebView, so without scoping it too a profile switch would keep // serving the previous profile's cached layout and the correct per-profile DB // value would never win. lsScope makes the cache per-profile as well; it's set // once the active profile is known and updated on every profile switch. let lsScope = ''; // setGridPrefsProfile scopes the localStorage cache to a profile. Call it before // the grids read their state (at startup) and again whenever the active profile // changes so each profile keeps its own column layout / widths. export function setGridPrefsProfile(id: number | string | null | undefined): void { lsScope = id == null || id === '' ? '' : `p${id}.`; } // lsKey scopes ONLY the localStorage cache key. The DB key passed to // GetUIPref/SetUIPref is left untouched — the backend already scopes it. function lsKey(key: string): string { return lsScope + key; } // loadLocal reads the cached column state synchronously (used in onGridReady // to apply instantly, before the async DB round-trip). export function loadLocal(key: string): any[] | null { try { const raw = localStorage.getItem(lsKey(key)); const v = raw ? JSON.parse(raw) : null; return Array.isArray(v) ? v : null; } catch { return null; } } // loadRemote pulls the portable copy from the DB (null if none / unset). export async function loadRemote(key: string): Promise { try { const v = await GetUIPref(key); const parsed = v ? JSON.parse(v) : null; return Array.isArray(parsed) ? parsed : null; } catch { return null; } } // saveState write-throughs to both the cache and the DB (fire-and-forget). Only // the cache key is profile-scoped; the DB key is scoped by the backend. export function saveState(key: string, state: any[]) { const json = JSON.stringify(state); try { localStorage.setItem(lsKey(key), json); } catch { /* quota / private mode */ } SetUIPref(key, json).catch(() => { /* DB unavailable — cache still holds it */ }); } // seedLocal writes a value into the cache without touching the DB (used after // hydrating the cache from the DB on a fresh machine). export function seedLocal(key: string, state: any[]) { try { localStorage.setItem(lsKey(key), JSON.stringify(state)); } catch { /* ignore */ } }