115 lines
4.1 KiB
JavaScript
115 lines
4.1 KiB
JavaScript
// ── 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);
|
|
})();
|