// The order of the pages in the rail is the account's: kept here for instant use and saved // with the UI prefs, so it follows the login. Pages the saved order doesn't name (added since) // go after the ones it does, in their built-in order. import { useEffect, useState } from 'react' const KEY = 'hamlab.rail' // Pages that were renamed, so an order saved before it still puts the page where it was put: // Top became Processes, Space became Usage, Cron became Jobs. A page that was removed // outright (Dashboard) is not here — orderBy drops ids that match no page. const RENAMED: Record = { top: 'procs', space: 'usage', cron: 'jobs' } export function getRailOrder(): string[] { let raw: unknown try { raw = JSON.parse(localStorage.getItem(KEY) ?? '[]') } catch { return [] } if (!Array.isArray(raw)) return [] const seen = new Set() const out: string[] = [] for (const x of raw) { if (typeof x !== 'string') continue const id = RENAMED[x] ?? x if (seen.has(id)) continue // a merged page keeps the earlier of the two slots seen.add(id) out.push(id) } return out } export function setRailOrder(ids: string[], save = true) { localStorage.setItem(KEY, JSON.stringify(ids)) window.dispatchEvent(new Event('hamlab:rail')) if (save) import('./accents').then((m) => m.savePrefs()) } export function resetRailOrder() { localStorage.removeItem(KEY); window.dispatchEvent(new Event('hamlab:rail')); import('./accents').then((m) => m.savePrefs()) } export function useRailOrder(): string[] { const [order, setOrder] = useState(getRailOrder) useEffect(() => { const h = () => setOrder(getRailOrder()) window.addEventListener('hamlab:rail', h) return () => window.removeEventListener('hamlab:rail', h) }, []) return order } export function orderBy(items: T[], order: string[]): T[] { const by = new Map(items.map((g) => [g.id, g])) const named = order.map((id) => by.get(id)).filter((g): g is T => !!g) const seen = new Set(named.map((g) => g.id)) return [...named, ...items.filter((g) => !seen.has(g.id))] }