Files
racket-wiki/static/js/wiki/cmap/cmap-navigation-controller.js
T
2026-09-03 17:03:20 +02:00

63 lines
1.9 KiB
JavaScript

"use strict";
/** Coordinate CMap routes, parent contexts and browser-history state. */
export class CmapNavigationController {
constructor({ navigateToHash, cmapRoute, getEditor, getCurrentMap,
getParentMap, storage, historyObject = window.history, locationObject = window.location }) {
this.navigateToHash = navigateToHash;
this.cmapRoute = cmapRoute;
this.getEditor = getEditor;
this.getCurrentMap = getCurrentMap;
this.getParentMap = getParentMap;
this.storage = storage;
this.history = historyObject;
this.location = locationObject;
}
open(slug) {
return this.navigateToHash(this.cmapRoute(slug));
}
openLinked(record) {
if (!record?.cmapSlug) return false;
this.rememberContext();
this.open(record.cmapSlug).catch((error) => console.error(error));
return true;
}
openParent() {
const source = this.getParentMap();
if (source?.slug) {
this.open(source.slug).catch((error) => console.error(error));
return true;
}
const editor = this.getEditor();
return Boolean(editor?.openParentMap());
}
requestTransition(action) {
return this.storage.requestTransition(action);
}
rememberContext() {
const editor = this.getEditor();
const current = this.getCurrentMap();
const root = editor?.activeMapRoot;
if (!current?.slug || !root) return;
this.history.replaceState({ ...this.history.state, cmapContext: {
mapSlug: current.slug,
rootItemId: Number(root.id)
} }, "", this.location.href);
}
async restoreContext(slug) {
const context = this.history.state?.cmapContext;
if (!context || context.mapSlug !== slug) return false;
const editor = this.getEditor();
const root = editor?.itemRecord(context.rootItemId);
if (root?.kind === "submap" && root.separateMap) editor.openSubmapMap(root);
this.history.replaceState({ ...this.history.state, cmapContext: null }, "", this.location.href);
return true;
}
}