import MeridianWM from './wm.js'; import State from './state.js'; import Bus from './bus.js'; const Registry = (() => { const APPS = {}; let _launcherOpen = false; function registerApp(def) { if (def.id) { APPS[def.id] = def; } } function unregisterApp(id) { delete APPS[id]; } function getApp(id) { return APPS[id] || null; } function launchApp(id) { const def = APPS[id]; if (!def) { console.warn(`App ${id} not registered`); return; } const title = def.title || id; const w = def.width || 640; const h = def.height || 480; // Create window with a render-callback; wm will mount container then call it. const win = MeridianWM.openWindow({ app: id, title, w, h, content: (container) => { // Tag container for per-app CSS scoping container.setAttribute('data-app', id); const api = { state: State, bus: Bus, close: () => MeridianWM.closeWindow(win && win.id), setTitle: (t) => { const el = document.getElementById(win && win.id); if (el) { const titleEl = el.querySelector('.m-window-title'); if (titleEl) titleEl.textContent = t; } }, }; try { def.render(container, api); } catch (e) { container.textContent = `Error loading ${id}: ${e.message}`; console.error(`[${id}] render error`, e); } }, }); closeLauncher(); } function getRegisteredApps() { return Object.values(APPS); } function toggleLauncher() { _launcherOpen = !_launcherOpen; const popover = document.getElementById('launcher-popover'); const btn = document.getElementById('launcher'); if (popover) { if (_launcherOpen) { renderLauncherApps(popover); popover.classList.remove('hidden'); } else { popover.classList.add('hidden'); } } if (btn) { btn.classList.toggle('active', _launcherOpen); } return _launcherOpen; } function closeLauncher() { _launcherOpen = false; const popover = document.getElementById('launcher-popover'); const btn = document.getElementById('launcher'); if (popover) popover.classList.add('hidden'); if (btn) btn.classList.remove('active'); } function renderLauncherApps(popover) { const apps = getRegisteredApps(); popover.innerHTML = ''; if (apps.length === 0) { popover.innerHTML = '