/* * state.js * All mutable application state — loaded first so every other module * can read and write these globals without forward-reference issues. * * Provides: * S — main UI state (tree data, selection, loading flags) * _plugins — plugin manifest populated from GET /api/config * _batchState — current batch-processing progress * _batchPollTimer — setInterval handle for batch polling * _bnd — live boundary-canvas state (written by canvas-boundary.js, * read by detail-render.js) * _photoQueue — photo queue session state (written by photo.js, * read by events.js) */ // ── Main UI state ─────────────────────────────────────────────────────────── let S = { tree: null, expanded: new Set(), selected: null, // {type:'cabinet'|'shelf'|'book', id} _photoTarget: null, // {type, id} _loading: {}, // {`${pluginId}:${entityId}`: true} _cropMode: null, // {type, id} while crop UI is active }; // ── Plugin registry ───────────────────────────────────────────────────────── let _plugins = []; // populated from GET /api/config // ── Batch processing state ────────────────────────────────────────────────── let _batchState = {running: false, total: 0, done: 0, errors: 0, current: ''}; let _batchPollTimer = null; // ── Boundary canvas live state ─────────────────────────────────────────────── // Owned by canvas-boundary.js; declared here so detail-render.js can read it // without a circular load dependency. let _bnd = null; // {wrap,img,canvas,axis,boundaries[],pluginResults{},selectedPlugin,segments[],nodeId,nodeType} // ── Photo queue session state ──────────────────────────────────────────────── // Owned by photo.js; declared here so events.js can read/write it. let _photoQueue = null; // {books:[...], index:0, processing:false}