import { api } from '../api.js'; import { on, off, requestScreenshot, startRemote, stopRemote, sendTouch, sendKey, sendCommand } from '../socket.js'; import { showToast } from '../components/toast.js'; import { esc } from '../utils.js'; import { t, tn } from '../i18n.js'; let currentDevice = null; let statusHandler = null; let screenshotHandler = null; let playbackHandler = null; let logHandler = null; let screenshotInterval = null; let remoteActive = false; function formatBytes(mb) { if (mb === null || mb === undefined) return '--'; if (mb >= 1024) return `${(mb / 1024).toFixed(1)} GB`; return `${mb} MB`; } function formatUptime(seconds) { if (!seconds) return '--'; const d = Math.floor(seconds / 86400); const h = Math.floor((seconds % 86400) / 3600); const m = Math.floor((seconds % 3600) / 60); if (d > 0) return `${d}d ${h}h ${m}m`; if (h > 0) return `${h}h ${m}m`; return `${m}m`; } // #74/#75: device clock + skew indicator. Compares the device's reported UTC to the // server's receipt time; a gap > 2 min means the device clock is wrong, so per-item // schedules will fire at the wrong local time — surface it instead of a support mystery. function renderDeviceClock(device) { const tz = device.reported_timezone || device.timezone || '--'; if (!device.reported_utc || !device.reported_at) return tz; const skewSec = Math.abs(Math.round(device.reported_utc / 1000) - device.reported_at); let local = ''; try { local = new Date(device.reported_utc).toLocaleString(undefined, { timeZone: device.reported_timezone || undefined, hour: '2-digit', minute: '2-digit', month: 'short', day: 'numeric' }); } catch (e) { /* bad tz id -> skip local render */ } const warn = skewSec > 120 ? `
${device.assignments?.length ? tn('device.playlist_count', device.assignments.length) : t('device.no_content_assigned')}
${t('device.remote.start_prompt')}
${esc(err.message)}
${t('device.playlist.empty_desc')}
${t('device.assign.no_media')}
`}