// ── External links — open in default browser via shell ──────────────────────── document.addEventListener('click', e => { const link = e.target.closest('a.external-link[data-url]'); if (link) { e.preventDefault(); window.pork.openShell(link.dataset.url); } }); document.addEventListener('click', e => { const button = e.target.closest('[data-payload-target]'); if (!button) return; const target = document.getElementById(button.dataset.payloadTarget); if (!target) return; target.scrollIntoView({ behavior: window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth', block: 'start', }); target.classList.add('payload-workspace-highlight'); window.setTimeout(() => target.classList.remove('payload-workspace-highlight'), 1200); }); // Pin buttons document.addEventListener('click', async e => { const btn = e.target.closest('.btn-pin'); if (!btn) return; e.stopPropagation(); // prevent tile nav from firing if btn is inside a tile const pinId = btn.dataset.pinId; if (!pinId) return; const s = await window.pork.getSettings(); const pinned = new Set(s.pinnedCards || []); if (pinned.has(pinId)) pinned.delete(pinId); else pinned.add(pinId); await window.pork.setSettings({ pinnedCards: [...pinned] }); // Update pin button visuals everywhere document.querySelectorAll(`.btn-pin[data-pin-id="${pinId}"]`).forEach(b => b.classList.toggle('pinned', pinned.has(pinId)) ); // If on dashboard, refresh pinned grid immediately if (document.querySelector('#page-dashboard.active')) renderPinnedTiles(); }); // Dashboard tiles document.addEventListener('click', e => { const tile = e.target.closest('.dash-pinned-tile[data-nav-page]'); if (tile) navigate(tile.dataset.navPage); }); // Title bar $('btn-min').addEventListener('click', () => window.pork.minimize()); $('btn-max').addEventListener('click', () => window.pork.maximize()); $('btn-cls').addEventListener('click', () => window.pork.close()); $('sidebar-donate').addEventListener('click', event => { event.preventDefault(); if (typeof window.chimeraOpenAbout === 'function') window.chimeraOpenAbout(); else window.pork.openDonate(); }); $('titlebar-x-link').addEventListener('click', e => { e.preventDefault(); showToast('Chimera · private PS4/PS5 operations hub', 'info'); }); // Conversion jobs window.pork.on('conv:job-update', (job) => { if (document.querySelector('#page-games.active')) { patchConvJobCard(job); } }); window.pork.on('conv:queue:paused-change', () => { if (document.querySelector('#page-games.active')) { refreshConvQueuePanel().catch(() => {}); } }); // Init (async function init() { // Load just the startup essentials. Heavy page-specific setup is deferred // until the user actually opens those pages. const s = await window.pork.getSettings().catch(() => ({})); applyDensity(s.interfaceDensity); try { await window.i18n.load(s.language || 'en'); } finally { window.chimeraResolveI18nReady?.(); delete window.chimeraResolveI18nReady; } await loadDashboard(); // Restore FTP connection state immediately so the UI isn't blank while devices enumerate. let connected = false; try { ({ connected } = await window.pork.ftpStatus()); setConnected(connected); $('sb-sync').textContent = `Last connection check · ${new Date().toLocaleTimeString()}`; } catch (_) {} if (!connected && s.autoConnect && s.ftpHost) { setStatus('Auto-connecting…'); try { const autoPorts = (s.ftpPorts && s.ftpPorts.length) ? s.ftpPorts : ['1337', '2121', '21']; await window.pork.ftpConnect({ host: s.ftpHost, ports: autoPorts, user: s.ftpUser || '', password: s.ftpPass || '', }); setConnected(true); setStatus('Connected', 'ok'); $('sb-sync').textContent = `Last connection check · ${new Date().toLocaleTimeString()}`; } catch (_) { setConnected(false); setStatus('Auto-connect failed — enter credentials and connect manually', 'error'); } } scheduleBackgroundWarm(1200); })();