'use strict';
(function initChimeraNavigation() {
const contract = window.ChimeraNavigationContract;
if (!contract) {
console.error('[navigation] ChimeraNavigationContract is missing.');
return;
}
const routeById = new Map(contract.routes.map(route => [route.id, route]));
const groupById = new Map(contract.groups.map(group => [group.id, group]));
const expandedGroups = new Set();
const iconPaths = {
home: ' ',
library: ' ',
console: ' ',
payload: ' ',
shield: ' ',
tools: ' ',
settings: ' ',
action: ' ',
more: ' ',
};
let currentRouteId = null;
let activePayloadStage = 'discover';
let navigationSequence = 0;
let commandGameCache = null;
let commandGameCacheAt = 0;
let commandSearchSequence = 0;
let currentTransferState = { jobs: [], activeCount: 0, queuedCount: 0, paused: false };
let currentActionCount = 0;
let expertMode = false;
const tr = (key, fallback) => typeof window.t === 'function' ? window.t(key, fallback) : fallback;
const routeKey = route => `navigation.routes.${route.id.replace(/\//g, '.')}`;
const routeLabel = route => tr(`${routeKey(route)}.label`, route.label);
const routeDescription = route => tr(`${routeKey(route)}.description`, route.description);
const groupLabel = group => tr(`navigation.groups.${group.id}`, group.label);
const activeLocale = () => window.i18n?.current === 'nl' ? 'nl-BE' : 'en-GB';
const escapeText = value => String(value ?? '')
.replace(/&/g, '&').replace(//g, '>')
.replace(/"/g, '"').replace(/'/g, ''');
function icon(name) {
return `${iconPaths[name] || iconPaths.home} `;
}
function normalizeRoute(value) {
let routeId = String(value || '').trim().replace(/^#\/?/, '').replace(/^\/+|\/+$/g, '');
try { routeId = decodeURIComponent(routeId); } catch (_) {}
routeId = contract.legacyAliases[routeId] || routeId;
if (!routeById.has(routeId)) return contract.defaultRoute;
const route = routeById.get(routeId);
if (route.expert && !expertMode) return groupById.get(route.group)?.defaultRoute || contract.defaultRoute;
return routeId;
}
async function syncExpertPermission() {
if (typeof window.pork?.sessionExpertMode !== 'function') return expertMode;
try {
const result = await window.pork.sessionExpertMode(expertMode, expertMode ? 'ENABLE EXPERT MODE' : undefined);
expertMode = result?.enabled === true;
} catch (_) {
expertMode = false;
}
document.body.classList.toggle('chimera-expert-mode', expertMode);
const toggle = document.getElementById('chimera-expert-mode');
if (toggle) toggle.checked = expertMode;
return expertMode;
}
setTimeout(syncExpertPermission);
function routeFromLocation() {
return normalizeRoute(window.location.hash);
}
function routeUrl(routeId) {
return `#/${encodeURI(routeId)}`;
}
function mountSidebar() {
const navList = document.querySelector('#sidebar .nav-list');
if (!navList) return;
navList.className = 'nav-list chimera-nav-root';
navList.setAttribute('aria-label', 'Chimera main navigation');
navList.innerHTML = contract.groups.map(group => {
const isHome = group.routes.length === 1 && group.routes[0].id === 'home';
const routeLinks = group.routes.map(route => `
${escapeText(routeLabel(route))}
${route.risk === 'confirm' ? `! ` : ''}
${route.badge === 'transfer' ? ' ' : ''}
`).join('');
return `
${isHome ? `
${icon(group.icon)}${escapeText(groupLabel(group))}
` : `
${icon(group.icon)}${escapeText(groupLabel(group))} ›
`}
`;
}).join('') + `Expert tools Database, logs and low-level tools `;
document.body.classList.toggle('chimera-expert-mode', expertMode);
const aboutLabel = document.querySelector('#sidebar-donate .donate-label');
if (aboutLabel) {
aboutLabel.removeAttribute('data-i18n');
aboutLabel.textContent = tr('navigation.about', 'About Chimera');
aboutLabel.dataset.i18n = 'navigation.about';
}
}
function mountShell() {
document.body.classList.add('chimera-shell-v2');
const content = document.getElementById('content');
if (!content) return;
const toolbar = document.createElement('div');
toolbar.id = 'chimera-shell-toolbar';
toolbar.innerHTML = `
Console
Disconnected
Search or navigate Ctrl K
Action Center
`;
const mobileToggle = document.getElementById('mobile-nav-toggle');
if (mobileToggle) toolbar.prepend(mobileToggle);
const header = document.createElement('header');
header.id = 'chimera-route-header';
header.innerHTML = `
Explicit confirmation required
↻ Refresh
`;
content.prepend(header);
content.prepend(toolbar);
const palette = document.createElement('div');
palette.id = 'chimera-command-overlay';
palette.className = 'chimera-overlay';
palette.hidden = true;
palette.innerHTML = `
⌕
×
Type to filter features; game search starts after 2 characters.
↑ ↓ select Enter open Esc close
`;
document.body.appendChild(palette);
const drawer = document.createElement('div');
drawer.id = 'chimera-jobs-overlay';
drawer.className = 'chimera-overlay chimera-drawer-overlay';
drawer.hidden = true;
drawer.innerHTML = `
`;
document.body.appendChild(drawer);
}
function mountCompanionDock() {
if (document.getElementById('chimera-companion-dock')) return;
const dock = document.createElement('nav');
dock.id = 'chimera-companion-dock';
dock.className = 'chimera-companion-dock';
dock.setAttribute('aria-label', tr('navigation.companion.label', 'Companion shortcuts'));
dock.dataset.i18nAriaLabel = 'navigation.companion.label';
dock.innerHTML = `
${icon('home')}Home
${icon('library')}Games
${icon('console')}Console
${icon('action')}Actions
${icon('more')}More
`;
document.body.appendChild(dock);
}
function mountHomeCommandCenter() {
const page = document.getElementById('page-dashboard');
const template = document.getElementById('chimera-home-command-center-template');
if (!page || !template || document.getElementById('chimera-home-command-center')) return;
const launchpad = document.createElement('section');
launchpad.id = 'chimera-home-command-center';
launchpad.setAttribute('aria-label', 'Chimera status and next steps');
launchpad.append(template.content.cloneNode(true));
const pageHeader = page.querySelector(':scope > .page-header');
if (pageHeader) pageHeader.insertAdjacentElement('afterend', launchpad);
else page.prepend(launchpad);
}
function mountSettingsNavigator() {
const page = document.getElementById('page-settings');
if (!page || document.getElementById('chimera-settings-navigator')) return;
const cards = [...page.querySelectorAll(':scope > .card')];
if (!cards.length) return;
const categoryFor = (card, label) => {
const id = String(card.id || '');
const value = `${id} ${label}`.toLowerCase();
if (/appearance|language/.test(value)) return 'setup';
if (/console profile|console identity|ftp connection|payload manager|cheats manager|save manager/.test(value)) return 'console';
if (/game source|conversion|remote game|metadata|ps4 package|package preservation/.test(value)) return 'storage';
if (/automation advisor/.test(value)) return 'automation';
if (/two-factor|passkey|security/.test(value)) return 'security';
if (/payload remote|integration|notification|companion/.test(value)) return 'integrations';
return 'advanced';
};
const sections = cards.map((card, index) => {
const heading = card.querySelector('h2, h3, h4');
const label = heading?.textContent?.trim() || `${tr('settingsNavigator.section', 'Section')} ${index + 1}`;
if (!card.id) card.id = `settings-section-${index + 1}`;
card.style.scrollMarginTop = '108px';
const category = categoryFor(card, label);
card.dataset.settingsCategory = category;
return { card, id: card.id, label, category };
});
const categories = [
['setup', tr('settingsNavigator.setup', 'Setup')],
['console', tr('settingsNavigator.console', 'Console')],
['storage', tr('settingsNavigator.storage', 'Storage')],
['automation', tr('settingsNavigator.automation', 'Automation')],
['integrations', tr('settingsNavigator.integrations', 'Integrations')],
['security', tr('settingsNavigator.security', 'Security')],
['advanced', tr('settingsNavigator.advanced', 'Advanced')],
];
let activeCategory = 'setup';
const navigator = document.createElement('section');
navigator.id = 'chimera-settings-navigator';
navigator.className = 'chimera-settings-navigator';
navigator.setAttribute('aria-label', 'Search and navigate settings');
navigator.innerHTML = `
Find a setting quickly
${sections.length} ${tr('settingsNavigator.sections', 'sections')}
${categories.map(([id, label], index) => `${label}${sections.filter(section => section.category === id).length} `).join('')}
`;
const pageHeader = page.querySelector(':scope > .page-header');
if (pageHeader) pageHeader.insertAdjacentElement('afterend', navigator);
else page.prepend(navigator);
const input = navigator.querySelector('#chimera-settings-search');
const clearButton = navigator.querySelector('#chimera-settings-clear');
const status = navigator.querySelector('#chimera-settings-filter-status');
const jump = navigator.querySelector('#chimera-settings-jump');
const syncSections = () => {
sections.forEach((section, index) => {
const liveLabel = section.card.querySelector('h2, h3, h4')?.textContent?.trim() || section.label;
section.label = liveLabel;
if (jump.options[index + 1]) jump.options[index + 1].textContent = liveLabel;
});
};
const applyFilter = value => {
const query = String(value || '').trim().toLocaleLowerCase(activeLocale());
let visible = 0;
sections.forEach(section => {
const searchText = section.card.textContent.toLocaleLowerCase(activeLocale());
const matchesCategory = activeCategory === 'all' || section.category === activeCategory;
const matches = matchesCategory && (!query || searchText.includes(query));
section.card.toggleAttribute('data-settings-filter-hidden', !matches);
if (matches) visible += 1;
});
clearButton.hidden = !query;
status.textContent = query || activeCategory !== 'all'
? `${visible} ${tr('settingsNavigator.of', 'of')} ${sections.length} ${tr('settingsNavigator.sections', 'sections')}`
: `${sections.length} ${tr('settingsNavigator.sections', 'sections')}`;
};
applyFilter('');
navigator.querySelector('.chimera-settings-categories').addEventListener('click', event => {
const button = event.target.closest('[data-settings-category]');
if (!button) return;
activeCategory = button.dataset.settingsCategory;
navigator.querySelectorAll('[data-settings-category]').forEach(candidate => candidate.setAttribute('aria-selected', String(candidate === button)));
applyFilter(input.value);
});
input.addEventListener('input', event => applyFilter(event.target.value));
clearButton.addEventListener('click', () => {
input.value = '';
applyFilter('');
input.focus();
});
jump.addEventListener('focus', syncSections);
jump.addEventListener('pointerdown', syncSections);
jump.addEventListener('change', event => {
const section = sections.find(item => item.id === event.target.value);
if (!section) return;
input.value = '';
activeCategory = section.category;
navigator.querySelectorAll('[data-settings-category]').forEach(candidate => candidate.setAttribute('aria-selected', String(candidate.dataset.settingsCategory === activeCategory)));
applyFilter('');
section.card.scrollIntoView({
behavior: window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth',
block: 'center',
});
event.target.value = '';
});
window.addEventListener('chimera:language-changed', () => {
syncSections();
applyFilter(input.value);
});
window.setTimeout(syncSections, 0);
}
function setExpandedGroup(groupId, expanded) {
if (expanded) {
for (const openGroup of [...expandedGroups]) {
if (openGroup !== groupId) setExpandedGroup(openGroup, false);
}
}
if (expanded) expandedGroups.add(groupId); else expandedGroups.delete(groupId);
const domain = [...document.querySelectorAll('[data-nav-group]')].find(item => item.dataset.navGroup === groupId);
if (!domain) return;
const button = domain.querySelector('[data-group-toggle]');
const routes = domain.querySelector('[data-group-routes]');
if (button) button.setAttribute('aria-expanded', String(expanded));
if (routes) routes.hidden = !expanded;
domain.classList.toggle('expanded', expanded);
}
function updateSidebar(route) {
const group = groupById.get(route.group);
if (group && group.id !== 'home') setExpandedGroup(group.id, true);
document.querySelectorAll('[data-route]:not([data-payload-stage])').forEach(element => {
const active = element.dataset.route === route.id;
element.classList.toggle('active', active);
if (element.matches('a,button')) {
if (active) element.setAttribute('aria-current', 'page');
else element.removeAttribute('aria-current');
}
});
updatePayloadWorkspaceStage(route.id);
document.querySelectorAll('[data-nav-group]').forEach(element => element.classList.toggle('active', element.dataset.navGroup === route.group));
document.querySelectorAll('#chimera-companion-dock [data-companion-group]').forEach(element => {
const active = element.dataset.route === 'library/games'
? route.id === 'library/games'
: element.dataset.companionGroup === route.group;
element.classList.toggle('active', active);
if (active) element.setAttribute('aria-current', 'page');
else element.removeAttribute('aria-current');
});
document.getElementById('chimera-companion-more')?.classList.toggle(
'active',
!['home', 'library', 'console'].includes(route.group),
);
}
function defaultPayloadStage(routeId) {
if (routeId === 'payloads/updates') return 'review';
if (routeId === 'payloads/boot') return 'boot';
if (routeId === 'payloads/installed') return 'discover';
return null;
}
function updatePayloadWorkspaceStage(routeId, requestedStage = null) {
const currentButton = document.querySelector(`[data-payload-stage="${activePayloadStage}"]`);
const stage = requestedStage
|| (currentButton?.dataset.route === routeId ? activePayloadStage : defaultPayloadStage(routeId));
if (!stage) return;
activePayloadStage = stage;
const stages = ['discover', 'review', 'stage', 'boot'];
const currentIndex = stages.indexOf(stage);
document.querySelectorAll('[data-payload-stage]').forEach(button => {
const buttonIndex = stages.indexOf(button.dataset.payloadStage);
const current = button.dataset.payloadStage === stage;
button.classList.toggle('is-current', current);
button.classList.toggle('is-complete', buttonIndex >= 0 && buttonIndex < currentIndex);
button.setAttribute('aria-pressed', String(current));
if (current) button.setAttribute('aria-current', 'step');
else button.removeAttribute('aria-current');
});
}
function localizeSidebar() {
contract.routes.forEach(route => {
document.querySelectorAll(`.chimera-route-link[data-route="${route.id}"]`).forEach(link => {
const label = link.querySelector(':scope > span:first-child');
if (label) label.textContent = routeLabel(route);
link.title = routeDescription(route);
});
});
contract.groups.forEach(group => {
const label = document.querySelector(`[data-nav-group="${group.id}"] .chimera-domain-button > span:not(.chimera-domain-chevron)`);
if (label) label.textContent = groupLabel(group);
});
const aboutLabel = document.querySelector('#sidebar-donate .donate-label');
if (aboutLabel) aboutLabel.textContent = tr('navigation.about', 'About Chimera');
}
function updateRouteHeader(route) {
const group = groupById.get(route.group);
const localizedGroup = groupLabel(group);
const localizedLabel = routeLabel(route);
const localizedDescription = routeDescription(route);
const breadcrumbs = document.getElementById('chimera-breadcrumbs');
if (breadcrumbs) breadcrumbs.innerHTML = route.id === 'home'
? 'Home '
: `${escapeText(localizedGroup)} / ${escapeText(localizedLabel)} `;
const title = document.getElementById('chimera-route-title');
const description = document.getElementById('chimera-route-description');
const risk = document.getElementById('chimera-route-risk');
if (title) title.textContent = localizedLabel;
if (description) description.textContent = localizedDescription;
if (risk) risk.hidden = route.risk !== 'confirm';
document.title = `${localizedLabel} — Chimera`;
}
function clearRouteFocus() {
document.querySelectorAll('[data-route-hidden="true"]').forEach(element => element.removeAttribute('data-route-hidden'));
document.querySelectorAll('[data-route-focus]').forEach(element => element.removeAttribute('data-route-focus'));
}
function hideElement(element) {
if (element) element.setAttribute('data-route-hidden', 'true');
}
function showOnlyPageChildren(pageId, allowedIds) {
const page = document.getElementById(pageId);
if (!page) return;
const allowed = new Set(allowedIds);
[...page.children].forEach(child => {
if (child.classList.contains('page-header') || child.hasAttribute('data-route-persistent')) return;
if (!child.id || !allowed.has(child.id)) hideElement(child);
});
}
function applyJailbreakFocus(focus) {
if (!focus) return;
const profiles = {
payloads: ['ps5-payload-manager-card', 'console-services-card', 'payload-update-card', 'payload-manager-card'],
boot: ['payload-manager-card', 'y2jb-generator-card', 'bdjb-generator-card'],
power: ['system-state-card'],
};
showOnlyPageChildren('page-jailbreak', profiles[focus] || profiles.payloads);
const workspaceNav = document.querySelector('#page-jailbreak > .payload-workspace-nav');
if (workspaceNav && focus === 'power') hideElement(workspaceNav);
const sectionVisibility = {
payloads: ['payload-local-section', 'payload-sender-section'],
boot: ['payload-autoloader-section', 'autoloader-snapshots-section'],
};
if (sectionVisibility[focus]) {
const visible = new Set(sectionVisibility[focus]);
document.querySelectorAll('#payload-manager-card > .jb-section').forEach(section => {
if (!visible.has(section.id)) hideElement(section);
});
}
document.getElementById('page-jailbreak')?.setAttribute('data-route-focus', focus);
}
function applyReliabilityFocus(focus) {
if (!focus) return;
const visibleIds = {
replication: ['operations-reliability-warning', 'operations-replication-card'],
monitoring: ['operations-monitoring-card'],
security: ['operations-sessions-card', 'operations-password-card'],
}[focus];
if (!visibleIds) return;
const visible = new Set(visibleIds);
document.querySelectorAll('[data-operations-panel="reliability"] .card[id]').forEach(card => {
if (!visible.has(card.id)) hideElement(card);
});
document.querySelectorAll('[data-operations-panel="reliability"] .operations-two-column').forEach(column => {
const cards = [...column.querySelectorAll(':scope > .card')];
if (cards.length && cards.every(card => card.hasAttribute('data-route-hidden'))) hideElement(column);
});
document.querySelector('[data-operations-panel="reliability"]')?.setAttribute('data-route-focus', focus);
}
function applyRouteFocus(route) {
if (route.page === 'jailbreak') return applyJailbreakFocus(route.focus);
if (route.page === 'operations' && route.panel === 'reliability') return applyReliabilityFocus(route.focus);
}
function activatePage(page) {
document.querySelectorAll('.page').forEach(element => element.classList.toggle('active', element.id === `page-${page}`));
const isEmbed = page === 'savemgr';
document.getElementById('content')?.classList.toggle('embed-page-active', isEmbed);
if (!isEmbed) {
const content = document.getElementById('content');
if (content) content.scrollTop = 0;
}
closeMobileNav();
if (typeof syncPinStates === 'function') syncPinStates();
if (typeof scheduleBackgroundWarm === 'function') scheduleBackgroundWarm(800);
}
function selectEcosystemPanel(tab) {
document.querySelectorAll('.ecosystem-tab').forEach(button => {
const active = button.dataset.ecosystemTab === tab;
button.classList.toggle('active', active);
button.setAttribute('aria-selected', String(active));
button.tabIndex = active ? 0 : -1;
});
document.querySelectorAll('.ecosystem-panel').forEach(panel => {
const active = panel.dataset.ecosystemPanel === tab;
panel.classList.toggle('active', active);
panel.hidden = !active;
});
}
async function loadEcosystemRoute(route, force) {
const wasStale = force || pageIsStale('ecosystem');
window.chimeraRequestedEcosystemTab = route.tab;
await ensurePageReady('ecosystem', { force: !!force });
selectEcosystemPanel(route.tab);
if (!wasStale && typeof loadEcosystemTab === 'function') await loadEcosystemTab(route.tab);
}
async function loadOperationsRoute(route, force) {
await ensurePageReady('operations', { force: !!force });
document.querySelectorAll('.operations-tab').forEach(button => {
const active = button.dataset.operationsTab === route.panel;
button.classList.toggle('active', active);
button.setAttribute('aria-selected', String(active));
button.tabIndex = active ? 0 : -1;
});
document.querySelectorAll('.operations-panel').forEach(panel => {
const active = panel.dataset.operationsPanel === route.panel;
panel.classList.toggle('active', active);
panel.hidden = !active;
});
if (route.panel === 'shadowmount' && typeof loadOperationsShadowMount === 'function') await loadOperationsShadowMount();
if (route.panel === 'packages' && typeof loadOperationsPackages === 'function') await loadOperationsPackages();
if (route.panel === 'reliability' && typeof loadOperationsReliability === 'function') await loadOperationsReliability({ focus: route.focus });
if (route.panel === 'audit' && typeof loadOperationsAudit === 'function') await loadOperationsAudit();
if (route.panel === 'diagnostics' && typeof loadKlog === 'function') await loadKlog();
}
async function hydrateRoute(route, force) {
if (route.page === 'ecosystem') await loadEcosystemRoute(route, force);
else if (route.page === 'operations') await loadOperationsRoute(route, force);
else await ensurePageReady(route.page, { force: !!force });
}
function writeHistory(routeId, mode) {
const url = routeUrl(routeId);
if (mode === 'push') window.history.pushState({ chimeraRoute: routeId }, '', url);
if (mode === 'replace') window.history.replaceState({ chimeraRoute: routeId }, '', url);
}
async function navigateRoute(value, options = {}) {
const routeId = normalizeRoute(value);
const route = routeById.get(routeId);
const historyMode = options.history ?? 'push';
if (!route) return;
if (currentRouteId === routeId && !options.force) {
closeMobileNav();
if (historyMode === 'replace') writeHistory(routeId, 'replace');
return;
}
const sequence = ++navigationSequence;
clearRouteFocus();
currentRouteId = routeId;
if (historyMode !== 'none') writeHistory(routeId, historyMode);
updateSidebar(route);
updateRouteHeader(route);
// Apply deep-route disclosure while the destination page is still hidden.
// This prevents unrelated Reliability cards from flashing for one frame.
applyRouteFocus(route);
activatePage(route.page);
document.body.setAttribute('data-chimera-route', route.id);
const refresh = document.getElementById('chimera-route-refresh');
const availability = document.getElementById('chimera-route-availability');
if (availability) availability.hidden = true;
if (refresh) { refresh.disabled = true; refresh.textContent = tr('common.loading', 'Loading…'); }
try {
await window.chimeraI18nReady;
if (sequence !== navigationSequence) return;
await hydrateRoute(route, options.force);
if (sequence !== navigationSequence) return;
applyRouteFocus(route);
} catch (error) {
if (typeof isExpectedUnavailable === 'function' && isExpectedUnavailable(error)) {
console.info(`[navigation] ${route.id} temporarily unavailable: ${error.message}`);
if (availability) {
availability.textContent = `${tr('navigation.unavailable', 'Unavailable')}: ${friendlyMessage(error?.message || error)}`;
availability.hidden = false;
}
} else {
console.error(`[navigation] ${route.id}`, error);
const failure = `${tr('navigation.loadFailed', 'Could not fully load')} ${routeLabel(route)}: ${friendlyMessage(error?.message || error)}`;
if (availability) {
availability.textContent = `${failure}. ${tr('navigation.retryHint', 'Use Refresh to retry.')}`;
availability.hidden = false;
} else if (typeof showToast === 'function') {
showToast(failure, 'error', 9000);
}
}
} finally {
if (sequence === navigationSequence && refresh) { refresh.disabled = false; refresh.innerHTML = `↻ ${escapeText(tr('common.refresh', 'Refresh'))} `; }
}
}
function openCommandPalette() {
const overlay = document.getElementById('chimera-command-overlay');
if (!overlay) return;
document.body.classList.add('chimera-modal-open');
const input = document.getElementById('chimera-command-input');
input.value = '';
document.getElementById('chimera-command-clear')?.setAttribute('hidden', '');
renderCommandResults('');
if (typeof openAccessibleDialog === 'function') openAccessibleDialog(overlay, input);
else { overlay.hidden = false; requestAnimationFrame(() => input.focus()); }
}
function closeCommandPalette() {
const overlay = document.getElementById('chimera-command-overlay');
if (typeof closeAccessibleDialog === 'function') closeAccessibleDialog(overlay);
else if (overlay) overlay.hidden = true;
if (document.getElementById('chimera-jobs-overlay')?.hidden !== false) document.body.classList.remove('chimera-modal-open');
}
function routeMatches(route, query) {
const group = groupById.get(route.group);
return [route.label, routeLabel(route), route.description, routeDescription(route), route.id, group?.label, groupLabel(group), ...(route.keywords || [])].join(' ').toLocaleLowerCase(activeLocale()).includes(query);
}
function commandRouteMarkup(routes) {
if (!routes.length) return '';
return `${escapeText(tr('navigation.search.features', 'Features'))}
${routes.map(route => {
const group = groupById.get(route.group);
return `${icon(group.icon)} ${escapeText(routeLabel(route))} ${escapeText(groupLabel(group))} · ${escapeText(routeDescription(route))} ↵ `;
}).join('')}`;
}
function commandGameMarkup(games) {
if (!games.length) return '';
return `Games
${games.map(game => {
const name = game.prospero_name || game.title || game.game_id;
return `${game.prospero_icon_url ? ` ` : '◫'} ${escapeText(name)} ${escapeText(game.game_id)}${game.prospero_publisher ? ` · ${escapeText(game.prospero_publisher)}` : ''} ↵ `;
}).join('')}`;
}
function recentCommandQueries() {
try {
const value = JSON.parse(localStorage.getItem('chimera.search.recent') || '[]');
return Array.isArray(value) ? value.filter(item => typeof item === 'string' && item.trim()).slice(0, 6) : [];
} catch (_) { return []; }
}
function rememberCommandQuery(value) {
const query = String(value || '').trim();
if (query.length < 2) return;
const recent = [query, ...recentCommandQueries().filter(item => item.toLocaleLowerCase(activeLocale()) !== query.toLocaleLowerCase(activeLocale()))].slice(0, 6);
localStorage.setItem('chimera.search.recent', JSON.stringify(recent));
}
function recentCommandMarkup() {
const recent = recentCommandQueries();
if (!recent.length) return '';
return `${escapeText(tr('navigation.search.recent', 'Recent searches'))}
${recent.map(query => `${escapeText(query)} `).join('')}
`;
}
function resetCommandSelection() {
const first = document.querySelector('#chimera-command-results .chimera-command-result');
if (first) {
first.classList.add('selected');
first.setAttribute('aria-selected', 'true');
}
}
function updateCommandStatus(message, busy = false) {
const results = document.getElementById('chimera-command-results');
const status = document.getElementById('chimera-command-status');
if (results) results.setAttribute('aria-busy', String(busy));
if (status) status.textContent = message;
}
async function getCommandGames(query = '') {
if (!window.pork.isWebMode && Array.isArray(state?.games) && state.games.length) return state.games;
const cacheKey = String(query || '').trim().toLocaleLowerCase(activeLocale());
if (commandGameCache?.key === cacheKey && Date.now() - commandGameCacheAt < 60_000) return commandGameCache.games;
const result = await window.pork.listGames(cacheKey ? { search: cacheKey, limit: 24 } : { limit: 24 });
commandGameCache = { key: cacheKey, games: Array.isArray(result) ? result : (result?.games || []) };
commandGameCacheAt = Date.now();
return commandGameCache.games;
}
async function renderCommandResults(value) {
const results = document.getElementById('chimera-command-results');
if (!results) return;
const query = String(value || '').trim().toLocaleLowerCase(activeLocale());
const sequence = ++commandSearchSequence;
const clearButton = document.getElementById('chimera-command-clear');
if (clearButton) clearButton.hidden = !query;
const availableRoutes = contract.routes.filter(route => expertMode || !route.expert);
const routes = (query ? availableRoutes.filter(route => routeMatches(route, query)) : availableRoutes.filter(route => ['home', 'library/games', 'console/status', 'payloads/installed', 'tools/transfers', 'settings/general'].includes(route.id))).slice(0, 12);
const recentMarkup = query ? '' : recentCommandMarkup();
results.innerHTML = `${recentMarkup}${commandRouteMarkup(routes)}` || `${escapeText(tr('navigation.search.noFeature', 'No feature found. Keep typing to search games.'))}
`;
resetCommandSelection();
if (query.length < 2) {
updateCommandStatus(query
? `${routes.length} ${tr('navigation.search.featuresLower', 'features')} · ${tr('navigation.search.oneMore', 'type 1 more character for games')}`
: `${routes.length} ${tr('navigation.search.quickRoutes', 'quick routes')}`);
return;
}
updateCommandStatus(`${routes.length} ${tr('navigation.search.featuresLower', 'features')} · ${tr('navigation.search.searchingGames', 'searching games…')}`, true);
try {
const games = (await getCommandGames(query)).filter(game => [game.prospero_name, game.title, game.game_id, game.prospero_publisher].filter(Boolean).join(' ').toLocaleLowerCase(activeLocale()).includes(query)).slice(0, 8);
if (sequence !== commandSearchSequence) return;
results.innerHTML = `${commandRouteMarkup(routes)}${commandGameMarkup(games)}` || `${escapeText(tr('navigation.search.noMatches', 'No matches found.'))}
`;
resetCommandSelection();
updateCommandStatus(`${routes.length + games.length} ${tr('navigation.search.results', 'results')}`);
} catch (_) {
if (!routes.length && sequence === commandSearchSequence) results.innerHTML = `${escapeText(tr('navigation.search.gamesUnavailable', 'Game search is currently unavailable.'))}
`;
if (sequence === commandSearchSequence) updateCommandStatus(routes.length
? `${routes.length} ${tr('navigation.search.featuresLower', 'features')} · ${tr('navigation.search.gamesUnavailableShort', 'games unavailable')}`
: tr('navigation.search.noResults', 'No results'));
}
}
async function activateCommandResult(button) {
if (!button) return;
rememberCommandQuery(document.getElementById('chimera-command-input')?.value);
closeCommandPalette();
if (button.dataset.commandRoute) return navigateRoute(button.dataset.commandRoute);
if (button.dataset.commandGame) {
await navigateRoute('library/games');
const input = document.getElementById('games-search');
if (input) {
input.value = button.dataset.commandGame;
input.dispatchEvent(new Event('input', { bubbles: true }));
}
}
}
function moveCommandSelection(direction) {
const buttons = [...document.querySelectorAll('#chimera-command-results .chimera-command-result')];
if (!buttons.length) return;
let index = buttons.findIndex(button => button.classList.contains('selected'));
buttons.forEach(button => {
button.classList.remove('selected');
button.setAttribute('aria-selected', 'false');
});
index = (index + direction + buttons.length) % buttons.length;
buttons[index].classList.add('selected');
buttons[index].setAttribute('aria-selected', 'true');
buttons[index].scrollIntoView({ block: 'nearest' });
}
function transferStatusLabel(status) {
const fallback = {
queued: 'Queued', active: 'Active', done: 'Completed', error: 'Error',
cancelled: 'Cancelled', interrupted: 'Interrupted', retrying: 'Retry scheduled',
}[status] || status || 'Unknown';
return tr(`navigation.jobs.status.${status || 'unknown'}`, fallback);
}
function renderJobs(stateValue) {
currentTransferState = stateValue || currentTransferState;
const active = Number(currentTransferState.activeCount || 0);
const queued = Number(currentTransferState.queuedCount || 0);
const count = active + queued;
const homeTransferTruth = document.getElementById('home-truth-transfers');
if (homeTransferTruth) {
homeTransferTruth.textContent = active
? `${active} active`
: queued
? `${queued} queued`
: currentTransferState.paused
? 'Queue paused'
: 'No active work';
}
const badge = document.getElementById('chimera-job-count');
const navBadge = document.getElementById('nav-transfer-badge');
if (badge) {
const total = count + currentActionCount;
badge.hidden = total === 0;
badge.textContent = String(total);
}
if (navBadge) {
navBadge.hidden = count === 0;
navBadge.textContent = String(count);
}
const companionBadge = document.getElementById('chimera-companion-count');
if (companionBadge) {
const total = count + currentActionCount;
companionBadge.hidden = total === 0;
companionBadge.textContent = String(total);
}
document.querySelector('.chimera-jobs-pulse')?.classList.toggle('active', active > 0);
const summary = document.getElementById('chimera-jobs-summary');
const list = document.getElementById('chimera-jobs-list');
if (summary) summary.innerHTML = `${active} ${escapeText(tr('navigation.jobs.active', 'active'))}
${queued} ${escapeText(tr('navigation.jobs.queued', 'queued'))}
${escapeText(currentTransferState.paused ? tr('common.yes', 'Yes') : tr('common.no', 'No'))} ${escapeText(tr('navigation.jobs.paused', 'paused'))}
`;
if (!list) return;
const jobs = (currentTransferState.jobs || []).filter(job => job.status !== 'cancelled').slice(-20).reverse();
list.innerHTML = jobs.length ? jobs.map(job => {
const progress = Math.max(0, Math.min(100, Number(job.progress?.percent || (job.status === 'done' ? 100 : 0))));
return `${escapeText(job.label || job.progress?.file || 'Transfer')} ${escapeText(transferStatusLabel(job.status))}${job.progress?.file ? ` · ${escapeText(job.progress.file)}` : ''}
${Math.round(progress)}%
${job.error ? `${escapeText(job.error)} ` : ''} `;
}).join('') : `${escapeText(tr('navigation.jobs.emptyTitle', 'No transfers'))} ${escapeText(tr('navigation.jobs.emptyDetail', 'New uploads and downloads will appear here automatically.'))}
`;
}
function actionRoute(action = {}) {
if (action.tab) return contract.routes.find(route => route.page === 'ecosystem' && route.tab === action.tab)?.id || 'console/status';
if (action.panel) return contract.routes.find(route => route.page === 'operations' && route.panel === action.panel)?.id || 'settings/automation';
return contract.legacyAliases[action.page] || (routeById.has(action.page) ? action.page : 'console/status');
}
function renderActions(packet) {
const list = document.getElementById('chimera-action-list');
if (!list) return;
const report = packet?.report || null;
const alerts = (report?.alerts || []).filter(alert => !alert.acknowledged).slice(0, 12);
currentActionCount = alerts.length;
const badge = document.getElementById('chimera-job-count');
if (badge) {
const total = Number(currentTransferState.activeCount || 0) + Number(currentTransferState.queuedCount || 0) + currentActionCount;
badge.hidden = total === 0;
badge.textContent = String(total);
}
const companionBadge = document.getElementById('chimera-companion-count');
if (companionBadge) {
const total = Number(currentTransferState.activeCount || 0) + Number(currentTransferState.queuedCount || 0) + currentActionCount;
companionBadge.hidden = total === 0;
companionBadge.textContent = String(total);
}
if (!report) {
list.innerHTML = `${escapeText(tr('navigation.actionCenter.notScanned', 'No health scan yet'))} ${escapeText(tr('navigation.actionCenter.notScannedDetail', 'Open Console health to run the first bounded scan.'))}
`;
return;
}
list.innerHTML = alerts.length ? alerts.map(alert => {
const count = String(alert.title || '').match(/\d+(?:\/\d+)?/)?.[0] || '';
const values = { count };
const translatedTitle = window.tf?.(`navigation.alerts.${alert.id}.title`, alert.title, values) || alert.title;
const translatedDetail = window.tf?.(`navigation.alerts.${alert.id}.detail`, alert.detail, values) || alert.detail;
return `
${escapeText(translatedTitle)} ${escapeText(translatedDetail)}
${escapeText(tr('common.open', 'Open'))}
`;
}).join('') : `✓ ${escapeText(tr('navigation.actionCenter.clear', 'Nothing needs attention'))} ${escapeText(tr('navigation.actionCenter.clearDetail', 'No open alerts were found in the latest health scan.'))}
`;
}
async function openJobsDrawer() {
const overlay = document.getElementById('chimera-jobs-overlay');
if (!overlay) return;
document.body.classList.add('chimera-modal-open');
const [transfers, health] = await Promise.allSettled([
window.pork.transferState(),
window.pork.ecosystemHealthLatest(),
]);
renderJobs(transfers.status === 'fulfilled' ? transfers.value : currentTransferState);
renderActions(health.status === 'fulfilled' ? health.value : null);
const closeButton = overlay.querySelector('[data-jobs-close]');
if (typeof openAccessibleDialog === 'function') openAccessibleDialog(overlay, closeButton);
else { overlay.hidden = false; requestAnimationFrame(() => closeButton?.focus()); }
}
function closeJobsDrawer() {
const overlay = document.getElementById('chimera-jobs-overlay');
if (typeof closeAccessibleDialog === 'function') closeAccessibleDialog(overlay);
else if (overlay) overlay.hidden = true;
if (document.getElementById('chimera-command-overlay')?.hidden !== false) document.body.classList.remove('chimera-modal-open');
}
function openAboutDialog() {
const overlay = document.getElementById('chimera-about-overlay');
if (!overlay) return;
const closeButton = overlay.querySelector('[data-about-close]');
if (typeof openAccessibleDialog === 'function') openAccessibleDialog(overlay, closeButton);
else { overlay.hidden = false; requestAnimationFrame(() => closeButton?.focus()); }
}
function closeAboutDialog() {
const overlay = document.getElementById('chimera-about-overlay');
if (typeof closeAccessibleDialog === 'function') closeAccessibleDialog(overlay);
else if (overlay) overlay.hidden = true;
}
function bindEvents() {
document.addEventListener('click', async event => {
const routeTarget = event.target.closest('[data-route]');
if (routeTarget) {
event.preventDefault();
closeCommandPalette();
closeJobsDrawer();
closeAboutDialog();
const requestedStage = routeTarget.dataset.payloadStage
|| (!routeTarget.closest('.payload-workspace-nav') ? defaultPayloadStage(routeTarget.dataset.route) : null);
if (requestedStage) activePayloadStage = requestedStage;
await navigateRoute(routeTarget.dataset.route);
const focusTarget = routeTarget.dataset.focusTarget
? document.getElementById(routeTarget.dataset.focusTarget)
: null;
if (focusTarget) {
focusTarget.scrollIntoView({
behavior: window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth',
block: 'center',
});
requestAnimationFrame(() => focusTarget.focus({ preventScroll: true }));
}
if (requestedStage) updatePayloadWorkspaceStage(routeTarget.dataset.route, requestedStage);
const payloadTarget = routeTarget.dataset.payloadTarget
? document.getElementById(routeTarget.dataset.payloadTarget)
: null;
if (payloadTarget) {
payloadTarget.scrollIntoView({ behavior: 'smooth', block: 'start' });
payloadTarget.classList.remove('payload-workspace-highlight');
requestAnimationFrame(() => payloadTarget.classList.add('payload-workspace-highlight'));
window.setTimeout(() => payloadTarget.classList.remove('payload-workspace-highlight'), 1800);
}
return;
}
const groupToggle = event.target.closest('[data-group-toggle]');
if (groupToggle) {
const groupId = groupToggle.dataset.groupToggle;
setExpandedGroup(groupId, !expandedGroups.has(groupId));
}
const commandResult = event.target.closest('[data-command-route], [data-command-game]');
if (commandResult) activateCommandResult(commandResult);
const commandQuery = event.target.closest('[data-command-query]');
if (commandQuery) {
const input = document.getElementById('chimera-command-input');
if (input) {
input.value = commandQuery.dataset.commandQuery;
renderCommandResults(input.value);
input.focus();
}
}
if (event.target.closest('[data-command-close]') || event.target.id === 'chimera-command-overlay') closeCommandPalette();
if (event.target.closest('[data-jobs-close]') || event.target.id === 'chimera-jobs-overlay') closeJobsDrawer();
if (event.target.closest('[data-about-close]') || event.target.id === 'chimera-about-overlay') closeAboutDialog();
});
document.getElementById('chimera-command-open')?.addEventListener('click', openCommandPalette);
document.getElementById('chimera-jobs-open')?.addEventListener('click', openJobsDrawer);
document.getElementById('chimera-companion-actions')?.addEventListener('click', openJobsDrawer);
document.getElementById('chimera-companion-more')?.addEventListener('click', event => {
document.getElementById('mobile-nav-toggle')?.click();
event.currentTarget.setAttribute('aria-expanded', String(document.body.classList.contains('mobile-nav-open')));
});
document.getElementById('chimera-route-refresh')?.addEventListener('click', () => navigateRoute(currentRouteId, { history: 'none', force: true }));
document.getElementById('chimera-expert-mode')?.addEventListener('change', async event => {
expertMode = event.target.checked;
document.body.classList.toggle('chimera-expert-mode', expertMode);
await syncExpertPermission();
window.dispatchEvent(new CustomEvent('chimera:expert-mode-changed', {
detail: { enabled: expertMode },
}));
if (!expertMode && routeById.get(currentRouteId)?.expert) navigateRoute(currentRouteId, { history: 'replace', force: true });
});
document.getElementById('chimera-command-input')?.addEventListener('input', event => renderCommandResults(event.target.value));
document.getElementById('chimera-command-clear')?.addEventListener('click', () => {
const input = document.getElementById('chimera-command-input');
if (!input) return;
input.value = '';
renderCommandResults('');
input.focus();
});
document.getElementById('chimera-command-input')?.addEventListener('keydown', event => {
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') { event.preventDefault(); moveCommandSelection(event.key === 'ArrowDown' ? 1 : -1); }
if (event.key === 'Enter') { event.preventDefault(); activateCommandResult(document.querySelector('#chimera-command-results .chimera-command-result.selected')); }
});
document.addEventListener('keydown', event => {
if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'k') { event.preventDefault(); openCommandPalette(); }
if (event.key === 'Escape') { closeCommandPalette(); closeJobsDrawer(); closeAboutDialog(); }
});
const syncFromLocation = () => navigateRoute(routeFromLocation(), { history: 'none' });
window.addEventListener('popstate', syncFromLocation);
window.addEventListener('hashchange', syncFromLocation);
window.addEventListener('chimera:language-changed', () => {
localizeSidebar();
const route = routeById.get(currentRouteId);
if (route) updateRouteHeader(route);
const input = document.getElementById('chimera-command-input');
if (input && document.getElementById('chimera-command-overlay')?.hidden === false) renderCommandResults(input.value);
renderJobs(currentTransferState);
if (document.getElementById('chimera-jobs-overlay')?.hidden === false) {
window.pork.ecosystemHealthLatest().then(renderActions).catch(() => renderActions(null));
}
});
window.pork?.on?.('transfer:update', renderJobs);
}
mountSidebar();
mountShell();
mountCompanionDock();
mountHomeCommandCenter();
mountSettingsNavigator();
bindEvents();
window.chimeraOpenAbout = openAboutDialog;
const compatibleNavigate = page => navigateRoute(contract.legacyAliases[page] || page);
navigate = compatibleNavigate;
window.navigate = compatibleNavigate;
window.chimeraNavigate = navigateRoute;
window.chimeraNavigationContract = contract;
const initialRoute = routeFromLocation();
const initialGroup = routeById.get(initialRoute)?.group;
if (initialGroup && initialGroup !== 'home') expandedGroups.add(initialGroup);
requestAnimationFrame(() => navigateRoute(initialRoute, { history: 'replace' }));
window.pork?.transferState?.().then(renderJobs).catch(() => {});
window.pork?.ecosystemHealthLatest?.().then(renderActions).catch(() => {});
})();