// features/apps/index.js — the App Center grid (/apps, /apps/). // // window.appsManager is a system-loader singleton (created by // initializeComponents); mount() calls .initialize(), never `new`. Routes // '/apps' and '/apps*' are registered BEFORE the app-detail feature's '/app*' // so findRouteHandler's longest-prefix wildcard match resolves /apps* here // (the manifest order guarantees this). unmount() is a no-op: the singleton and // its constructor-time taskRefresh registrations are shared with app-detail and // the dashboard and must outlive this view. LP.features.register({ id: 'apps', routes: ['/apps', '/apps*'], async mount(ctx) { // Category from the path (/apps/), else legacy ?= / ?apps=. const seg = window.location.pathname.replace(/^\/apps\/?/, '').split('/')[0]; if (seg) { window.appsCategory = decodeURIComponent(seg); } else { const search = window.location.search || ''; if (search.includes('?=')) { window.appsCategory = (window.location.pathname + search).split('?=')[1] || 'all'; } else { window.appsCategory = new URLSearchParams(search).get('apps') || 'all'; } } // Load the unified layout only if it isn't already present — preserves grid // state when moving between categories / back from app-detail (legacy behaviour). if (!document.querySelector('.apps-layout')) { const html = await ctx.loadFragment('/components/apps/apps-unified-layout.html'); ctx.setContent(html, 'Applications'); } if (!window.appsManager) { throw new Error('AppsManager not initialized by SystemLoader'); } await window.appsManager.initialize(); }, async unmount() { // Nothing to release — AppsManager is a shared system-loader singleton. // The dirty-config nav guard (window.__appConfigNavGuard) fires in // navigate() BEFORE unmount and is owned by AppsManager, so we leave it. }, });