Stabilizza regia, live web e sync punteggi app nativa.
Corregge scadenza token regia oltre le 8h, tabellone HTML sulla pagina live, pulsanti pausa/ripresa in regia, link admin e broadcast ActionCable diretto. App Android: overlay branding, sync score da regia via WebSocket con reconnect e poll. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -233,6 +233,90 @@ body.admin-body {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.admin-links-panel {
|
||||
margin: 1.25rem 0 1.5rem;
|
||||
padding: 1rem 1.1rem;
|
||||
background: var(--card-bg, #14141c);
|
||||
border: 1px solid var(--card-border, #2a2a36);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.admin-links-panel h3 {
|
||||
margin: 0 0 0.6rem;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.admin-links-panel h3 + h3 {
|
||||
margin-top: 1.1rem;
|
||||
}
|
||||
|
||||
.admin-link-list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.admin-link-list li,
|
||||
.admin-link-generated {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem 0.75rem;
|
||||
align-items: baseline;
|
||||
margin-bottom: 0.45rem;
|
||||
}
|
||||
|
||||
.admin-link-label {
|
||||
min-width: 6.5rem;
|
||||
color: var(--muted, #9ca3af);
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.admin-link-url {
|
||||
color: var(--red, #e53935);
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.admin-link-code {
|
||||
display: block;
|
||||
margin: 0.35rem 0 0.5rem;
|
||||
padding: 0.45rem 0.6rem;
|
||||
background: #0a0a0e;
|
||||
border-radius: 6px;
|
||||
font-size: 0.78rem;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.admin-link-compact {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.35rem;
|
||||
}
|
||||
|
||||
.admin-link-chip {
|
||||
display: inline-block;
|
||||
padding: 0.15rem 0.45rem;
|
||||
border-radius: 999px;
|
||||
background: #2a2a36;
|
||||
color: #eee;
|
||||
font-size: 0.72rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.admin-link-chip:hover {
|
||||
background: #3a3a48;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.admin-link-chip--regia {
|
||||
background: #3d2a00;
|
||||
color: #f9a825;
|
||||
}
|
||||
|
||||
.admin-inline-form {
|
||||
display: inline-block;
|
||||
margin-top: 0.35rem;
|
||||
}
|
||||
|
||||
.admin-input {
|
||||
padding: 0.45rem 0.6rem;
|
||||
border: 1px solid #444;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
statusUrl: root.dataset.statusUrl,
|
||||
scoreUrl: root.dataset.scoreUrl,
|
||||
pauseUrl: root.dataset.pauseUrl,
|
||||
resumeUrl: root.dataset.resumeUrl,
|
||||
stopUrl: root.dataset.stopUrl,
|
||||
cableUrl: root.dataset.cableUrl,
|
||||
hlsUrl: root.dataset.hlsUrl,
|
||||
@@ -30,13 +31,15 @@
|
||||
modalConfirm: document.getElementById("modal-confirm"),
|
||||
modalCancel: document.getElementById("modal-cancel"),
|
||||
preview: document.getElementById("regia-preview"),
|
||||
previewPlaceholder: document.getElementById("regia-preview-placeholder")
|
||||
previewPlaceholder: document.getElementById("regia-preview-placeholder"),
|
||||
btnPause: document.getElementById("btn-pause")
|
||||
};
|
||||
|
||||
let pendingAction = null;
|
||||
let hls = null;
|
||||
let previewStarted = false;
|
||||
let wasPausedPreview = false;
|
||||
let streamPaused = root.dataset.initialPaused === "true";
|
||||
|
||||
function hlsUrlFresh() {
|
||||
const sep = cfg.hlsUrl.includes("?") ? "&" : "?";
|
||||
@@ -108,7 +111,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
function syncPauseButton(data) {
|
||||
if (!els.btnPause) return;
|
||||
const paused = !!(data.paused || data.status === "paused");
|
||||
streamPaused = paused;
|
||||
els.btnPause.textContent = paused ? "Riprendi diretta" : "Metti in pausa";
|
||||
}
|
||||
|
||||
function setBadge(data) {
|
||||
syncPauseButton(data);
|
||||
if (data.stream_closed) {
|
||||
els.badge.textContent = "Terminata";
|
||||
els.badge.className = "regia-badge regia-badge--ended";
|
||||
@@ -139,6 +150,8 @@
|
||||
}
|
||||
|
||||
async function handleAction(action) {
|
||||
const prevHome = els.homePoints?.textContent;
|
||||
const prevAway = document.getElementById("away-points")?.textContent;
|
||||
try {
|
||||
const data = await postScore(action);
|
||||
applyScorePayload(data);
|
||||
@@ -152,6 +165,9 @@
|
||||
openModal("Partita vinta", `${winner} ha vinto la partita. Chiudere la diretta?`, () => stopStream());
|
||||
}
|
||||
} catch (e) {
|
||||
if (prevHome != null && els.homePoints) els.homePoints.textContent = prevHome;
|
||||
const awayEl = document.getElementById("away-points");
|
||||
if (prevAway != null && awayEl) awayEl.textContent = prevAway;
|
||||
toast(e.message || "Errore");
|
||||
}
|
||||
}
|
||||
@@ -284,10 +300,19 @@
|
||||
showPreviewPlaceholder("Diretta terminata");
|
||||
}
|
||||
|
||||
async function pauseStream() {
|
||||
await fetch(cfg.pauseUrl, { method: "POST", headers: { Accept: "application/json" } });
|
||||
toast("Diretta in pausa — copertina in onda");
|
||||
pollStatus();
|
||||
async function togglePauseStream() {
|
||||
const url = streamPaused ? cfg.resumeUrl : cfg.pauseUrl;
|
||||
const res = await fetch(url, { method: "POST", headers: { Accept: "application/json" } });
|
||||
if (!res.ok) {
|
||||
const body = await res.json().catch(() => ({}));
|
||||
throw new Error(body.error || (streamPaused ? "Errore ripresa diretta" : "Errore pausa diretta"));
|
||||
}
|
||||
const data = await res.json();
|
||||
const wasPaused = streamPaused;
|
||||
applyScorePayload(data);
|
||||
setBadge(data);
|
||||
syncPreviewFromStatus(data);
|
||||
toast(wasPaused ? "Diretta ripresa" : "Diretta in pausa — copertina in onda");
|
||||
}
|
||||
|
||||
async function stopStream() {
|
||||
@@ -302,7 +327,7 @@
|
||||
return data;
|
||||
}
|
||||
|
||||
document.getElementById("btn-pause")?.addEventListener("click", () => pauseStream().catch((e) => toast(e.message)));
|
||||
els.btnPause?.addEventListener("click", () => togglePauseStream().catch((e) => toast(e.message)));
|
||||
document.getElementById("btn-stop")?.addEventListener("click", () => stopStream().catch((e) => toast(e.message)));
|
||||
|
||||
async function shareLink() {
|
||||
|
||||
Reference in New Issue
Block a user