Add company dashboard improvements and upload/auth features
This commit is contained in:
@@ -8,16 +8,15 @@
|
||||
html, body { height: 100%; width: 100%; margin: 0; background: #000; overflow: hidden; }
|
||||
#stage { position: fixed; inset: 0; width: 100vw; height: 100vh; background: #000; }
|
||||
img, video, iframe { width: 100%; height: 100%; object-fit: contain; border: 0; }
|
||||
.notice { position: fixed; left: 12px; bottom: 12px; color: #bbb; font: 14px/1.3 sans-serif; }
|
||||
/* removed bottom-left status text */
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="stage"></div>
|
||||
<div class="notice" id="notice"></div>
|
||||
<script>
|
||||
const token = "{{ display.token }}";
|
||||
const stage = document.getElementById('stage');
|
||||
const notice = document.getElementById('notice');
|
||||
function setNotice(_text) { /* intentionally no-op: notice UI removed */ }
|
||||
|
||||
const isPreview = new URLSearchParams(window.location.search).get('preview') === '1';
|
||||
|
||||
@@ -39,6 +38,9 @@
|
||||
let idx = 0;
|
||||
let timer = null;
|
||||
|
||||
let es = null;
|
||||
let esRetryMs = 1000;
|
||||
|
||||
async function fetchPlaylist() {
|
||||
const qs = sid ? `?sid=${encodeURIComponent(sid)}` : '';
|
||||
const res = await fetch(`/api/display/${token}/playlist${qs}`, { cache: 'no-store' });
|
||||
@@ -56,7 +58,7 @@
|
||||
|
||||
function next() {
|
||||
if (!playlist || !playlist.items || playlist.items.length === 0) {
|
||||
notice.textContent = 'No playlist assigned.';
|
||||
setNotice('No playlist assigned.');
|
||||
clearStage();
|
||||
return;
|
||||
}
|
||||
@@ -65,7 +67,7 @@
|
||||
idx = (idx + 1) % playlist.items.length;
|
||||
|
||||
clearStage();
|
||||
notice.textContent = playlist.playlist ? `${playlist.display} — ${playlist.playlist.name}` : playlist.display;
|
||||
setNotice(playlist.playlist ? `${playlist.display} — ${playlist.playlist.name}` : playlist.display);
|
||||
|
||||
if (item.type === 'image') {
|
||||
const el = document.createElement('img');
|
||||
@@ -109,10 +111,14 @@
|
||||
next();
|
||||
} catch (e) {
|
||||
clearStage();
|
||||
notice.textContent = e && e.message ? e.message : 'Unable to load playlist.';
|
||||
setNotice(e && e.message ? e.message : 'Unable to load playlist.');
|
||||
// keep retrying; if a slot frees up the display will start automatically.
|
||||
}
|
||||
// refresh playlist every 60s
|
||||
|
||||
// Open live event stream: when server signals a change, reload playlist immediately.
|
||||
connectEvents();
|
||||
|
||||
// Fallback refresh (in case SSE is blocked by a proxy/network): every 5 minutes.
|
||||
setInterval(async () => {
|
||||
try {
|
||||
playlist = await fetchPlaylist();
|
||||
@@ -122,9 +128,47 @@
|
||||
}
|
||||
} catch(e) {
|
||||
clearStage();
|
||||
notice.textContent = e && e.message ? e.message : 'Unable to load playlist.';
|
||||
setNotice(e && e.message ? e.message : 'Unable to load playlist.');
|
||||
}
|
||||
}, 60000);
|
||||
}, 300000);
|
||||
}
|
||||
|
||||
function connectEvents() {
|
||||
if (isPreview) return; // preview shouldn't consume a slot / keep a long-lived connection
|
||||
|
||||
try { if (es) es.close(); } catch(e) { /* ignore */ }
|
||||
|
||||
const qs = sid ? `?sid=${encodeURIComponent(sid)}` : '';
|
||||
es = new EventSource(`/api/display/${token}/events${qs}`);
|
||||
|
||||
es.addEventListener('changed', async () => {
|
||||
try {
|
||||
const newPlaylist = await fetchPlaylist();
|
||||
|
||||
// If content changed, restart from the beginning.
|
||||
const oldStr = JSON.stringify(playlist);
|
||||
const newStr = JSON.stringify(newPlaylist);
|
||||
playlist = newPlaylist;
|
||||
if (oldStr !== newStr) {
|
||||
idx = 0;
|
||||
next();
|
||||
}
|
||||
|
||||
esRetryMs = 1000; // reset backoff on success
|
||||
} catch(e) {
|
||||
// leave current playback; we'll retry via reconnect handler
|
||||
}
|
||||
});
|
||||
|
||||
es.onerror = () => {
|
||||
try { es.close(); } catch(e) { /* ignore */ }
|
||||
es = null;
|
||||
|
||||
// Exponential backoff up to 30s
|
||||
const wait = esRetryMs;
|
||||
esRetryMs = Math.min(30000, Math.floor(esRetryMs * 1.7));
|
||||
setTimeout(connectEvents, wait);
|
||||
};
|
||||
}
|
||||
|
||||
start();
|
||||
|
||||
Reference in New Issue
Block a user