/** Device-local presentation state; the YAML document remains the only query config. */ const stores = new Map void> }>() const KEY_PREFIX = 'reams.base.view.' let subscriberCount = 0 export function savedBaseView(id: string): string | undefined { try { return localStorage.getItem(`${KEY_PREFIX}${id}`) || undefined } catch { return undefined } } export function hasSavedBaseSelection(id: string): boolean { try { return localStorage.getItem(`${KEY_PREFIX}${id}`) !== null } catch { return false } } function onStorage(event: StorageEvent): void { if (event.storageArea !== localStorage || event.key !== null && !event.key.startsWith(KEY_PREFIX)) return const ids = event.key === null ? [...stores.keys()] : [event.key.slice(KEY_PREFIX.length)] for (const id of ids) { const current = stores.get(id) if (!current) continue const next = savedBaseView(id) if (current.selected === next) continue current.selected = next for (const listener of [...current.listeners]) listener() } } function store(id: string) { let current = stores.get(id) if (!current) { current = { selected: savedBaseView(id), listeners: new Set() } stores.set(id, current) } return current } export function selectedBaseView(id: string): string | undefined { return stores.get(id)?.selected ?? savedBaseView(id) } export function subscribeBaseSelection(id: string, listener: () => void): () => void { const current = store(id) current.listeners.add(listener) if (subscriberCount++ === 0) window.addEventListener('storage', onStorage) let active = true return () => { if (!active) return active = false current.listeners.delete(listener) if (!current.listeners.size && stores.get(id) === current) stores.delete(id) if (--subscriberCount === 0) window.removeEventListener('storage', onStorage) } } export function selectBaseView(id: string, name: string | undefined): void { const current = store(id) if (current.selected === name) { if (!current.listeners.size) stores.delete(id) return } current.selected = name const key = `${KEY_PREFIX}${id}` try { // Empty string means the user deliberately chose the first view; unlike // removing the key, it must override older workspace layout snapshots. localStorage.setItem(key, name ?? '') } catch { /* Selection still works in this tab when device storage is unavailable. */ } for (const listener of [...current.listeners]) listener() if (!current.listeners.size) stores.delete(id) }