/* * Museum Gallery — Information Wall boot (non-primary surface). * * Structurally identical in principle to artifact.boot.js: no Core here, * only an attachment to the Control Room's Core over surface-bus.js, and a * clear waiting state if that Core is not reachable. */ (function () { 'use strict'; var Shell = window.XZBTShell; var el = Shell.el; var statusEl = el('status'); var announcer = new Shell.Announcer({ node: el('announcement'), idleText: 'Waiting for shared state.' }); var toggleButton = el('toggle-button'); var ARTIFACT_LABELS = { 'the-orrery': 'The Orrery', 'star-map': 'Star Map', meteorite: 'Meteorite Fragment' }; var latest = null; // read-only mirror; see artifact.boot.js for the rationale function render() { if (!latest) return; Shell.setText(el('artifact-name'), ARTIFACT_LABELS[latest['artifact.selected']] || latest['artifact.selected']); Shell.setText(el('labels-readout'), latest['labels.enabled'] ? 'Labels: ON' : 'Labels: OFF'); } var link = window.MuseumGallerySurfaceBus.attach({ timeoutMs: 1500, onSnapshot: function (snapshot) { latest = snapshot.values; Shell.setText(statusEl, 'Attached to Control Room.'); statusEl.classList.remove('is-waiting'); toggleButton.disabled = false; render(); }, onEvent: function (event) { if (!latest) return; if (event.type === 'state.changed' || event.type === 'selection.changed') { latest[event.target] = event.value; render(); } else if (event.type === 'action.executed' && event.target === 'action.spotlight-flash') { announcer.flash('Spotlight flashed.'); } }, onTimeout: function () { Shell.setText(statusEl, 'Waiting for the Control Room surface to be open…'); statusEl.classList.add('is-waiting'); toggleButton.disabled = true; } }); toggleButton.addEventListener('click', function () { if (!latest) return; /* Same canonical mutation path proof as the Artifact Display's cycle * button, exercising a boolean state target instead of a selection. */ link.mutate('set', 'labels.enabled', !latest['labels.enabled']); }); /* Same rationale as artifact.boot.js: `__xzbtSurfaceDispose` is the * deterministic path (called synchronously by local-surfaces.js right * before it removes this frame); `beforeunload` remains only as a * best-effort fallback for the cases NGN can't foresee (e.g. the tab * closing on its own). detach() is idempotent either way. */ window.__xzbtSurfaceDispose = function () { link.detach(); }; window.addEventListener('beforeunload', function () { link.detach(); }); window.__museumGalleryDebug = { link: link }; })();