1import { sessionKey } from "./constants.js";2import { state } from "./state.js";34// Kept per volume rather than as a single place, so wandering off to another5// volume and coming back does not cost the reader where they were in this one.6export function saveSession() {7 // Nothing is written while a world is being swapped in: the arrangement is8 // half the old one and half the new until it settles.9 if (!state.world || !state.lens || state.settling) return;10 const view = state.engine?.getView();11 try {12 const stored = allSessions();13 stored.last = state.volume.slug;14 stored.volumes[state.volume.slug] = {15 volume: state.volume.slug,16 world: state.world.slug,17 lens: state.world.lenses.indexOf(state.lens),18 center: view?.getCenter(),19 zoom: view?.getZoom(),20 hidden: [...state.hiddenCollections],21 collapsed: [...state.collapsedSections],22 expanded: [...state.expandedCollections],23 labels: [...state.labelOverrides],24 overviewDocked: state.overviewDocked,25 dockFolded: state.dockFolded,26 dockDismissed: state.dockDismissed,27 };28 localStorage.setItem(sessionKey, JSON.stringify(stored));29 } catch {30 // A browsing session that cannot be written is not worth failing over.31 }32}3334export function allSessions() {35 try {36 const stored = JSON.parse(localStorage.getItem(sessionKey) || "null");37 if (stored && stored.volumes) return stored;38 } catch {39 // Falls through to a fresh record.40 }41 return { last: "", volumes: {} };42}4344export function readSession(volumeSlug) {45 const stored = allSessions();46 const wanted = volumeSlug || stored.last;47 const entry = wanted && stored.volumes[wanted];48 return entry && entry.volume && entry.world ? entry : null;49}5051export function readRoute() {52 const [volume, world] = decodeURIComponent(location.hash.replace(/^#\/?/, ""))53 .split("/")54 .map((part) => part.trim());55 return { volume, world };56}5758export function writeRoute() {59 if (!state.volume || !state.world) return;60 const route = `#${state.volume.slug}/${state.world.slug}`;61 if (location.hash === route) return;62 // Replaced rather than pushed: this records a location, not a trail.63 history.replaceState(null, "", route);64}