fix(web-ui): playout fmtDuration no longer clobbers global asset duration formatter
screens-playout.jsx declared a top-level function fmtDuration(secs) that, in the shared global script scope, overwrote data.jsx's fmtDuration(ms). After the playout redesign loaded, normalizeAsset(duration_ms) hit the seconds-based version, rendering every asset duration x1000 (15000ms shown as 4:10:00). Rename the playout-local helpers to playoutFmtDur/playoutFmtTC. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
7b878d48c9
commit
b92a5bc7f7
1 changed files with 13 additions and 13 deletions
|
|
@ -36,7 +36,7 @@ async function poFetch(path, opts) {
|
||||||
|
|
||||||
// ── Helpers ───────────────────────────────────────────────────────────────────
|
// ── Helpers ───────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
function fmtDuration(secs) {
|
function playoutFmtDur(secs) {
|
||||||
if (!secs || secs < 0) return '—';
|
if (!secs || secs < 0) return '—';
|
||||||
const s = Math.floor(secs);
|
const s = Math.floor(secs);
|
||||||
const h = Math.floor(s / 3600);
|
const h = Math.floor(s / 3600);
|
||||||
|
|
@ -47,7 +47,7 @@ function fmtDuration(secs) {
|
||||||
return h > 0 ? `${h}:${mm}:${ssStr}` : `${m}:${ssStr}`;
|
return h > 0 ? `${h}:${mm}:${ssStr}` : `${m}:${ssStr}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function fmtTimecode(secs) {
|
function playoutFmtTC(secs) {
|
||||||
// HH:MM:SS:FF at 29.97 (rounded)
|
// HH:MM:SS:FF at 29.97 (rounded)
|
||||||
const s = Math.floor(secs);
|
const s = Math.floor(secs);
|
||||||
const h = Math.floor(s / 3600);
|
const h = Math.floor(s / 3600);
|
||||||
|
|
@ -317,7 +317,7 @@ function Playlist({ channel, playlistId, items, activeIndex, onReload }) {
|
||||||
<div className="po-playlist-head">
|
<div className="po-playlist-head">
|
||||||
<span className="po-section-label">Playlist</span>
|
<span className="po-section-label">Playlist</span>
|
||||||
<span className="mono muted" style={{ fontSize: 11, marginLeft: 'auto' }}>
|
<span className="mono muted" style={{ fontSize: 11, marginLeft: 'auto' }}>
|
||||||
{items.length} clip{items.length !== 1 ? 's' : ''} · {fmtDuration(totalSecs)}
|
{items.length} clip{items.length !== 1 ? 's' : ''} · {playoutFmtDur(totalSecs)}
|
||||||
</span>
|
</span>
|
||||||
{dropErr && <span className="po-drop-err">{dropErr}</span>}
|
{dropErr && <span className="po-drop-err">{dropErr}</span>}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -338,7 +338,7 @@ function Playlist({ channel, playlistId, items, activeIndex, onReload }) {
|
||||||
{isActive ? <span className="po-pl-onair">▶</span> : index + 1}
|
{isActive ? <span className="po-pl-onair">▶</span> : index + 1}
|
||||||
</span>
|
</span>
|
||||||
<span className="po-pl-name">{it.clip_name || it.asset_id}</span>
|
<span className="po-pl-name">{it.clip_name || it.asset_id}</span>
|
||||||
<span className="mono po-pl-dur">{fmtDuration(dur)}</span>
|
<span className="mono po-pl-dur">{playoutFmtDur(dur)}</span>
|
||||||
<span className={'badge po-pl-badge ' + (
|
<span className={'badge po-pl-badge ' + (
|
||||||
it.media_status === 'ready' ? 'success' :
|
it.media_status === 'ready' ? 'success' :
|
||||||
it.media_status === 'staging' ? 'warn' :
|
it.media_status === 'staging' ? 'warn' :
|
||||||
|
|
@ -552,7 +552,7 @@ function ProgramMonitor({ channel, engine, elapsed }) {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{onAir && (
|
{onAir && (
|
||||||
<div className="po-tc-overlay mono">{fmtTimecode(elapsed)}</div>
|
<div className="po-tc-overlay mono">{playoutFmtTC(elapsed)}</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="po-meters-wrap">
|
<div className="po-meters-wrap">
|
||||||
|
|
@ -580,7 +580,7 @@ function ProgramMonitor({ channel, engine, elapsed }) {
|
||||||
</span>
|
</span>
|
||||||
{timeRemaining > 0 && (
|
{timeRemaining > 0 && (
|
||||||
<span className="po-clip-remain" title="Time remaining in clip">
|
<span className="po-clip-remain" title="Time remaining in clip">
|
||||||
-{fmtDuration(timeRemaining)}
|
-{playoutFmtDur(timeRemaining)}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{engine.loop && <span title="Loop">↺</span>}
|
{engine.loop && <span title="Loop">↺</span>}
|
||||||
|
|
@ -761,8 +761,8 @@ function NowPlayingCard({ engine, elapsed, items }) {
|
||||||
<div className="po-nowplaying-fill" style={{ width: (progress * 100) + '%' }} />
|
<div className="po-nowplaying-fill" style={{ width: (progress * 100) + '%' }} />
|
||||||
</div>
|
</div>
|
||||||
<div className="po-nowplaying-times mono">
|
<div className="po-nowplaying-times mono">
|
||||||
<span className="po-nowplaying-elapsed">{fmtDuration(elapsed)}</span>
|
<span className="po-nowplaying-elapsed">{playoutFmtDur(elapsed)}</span>
|
||||||
<span className="po-nowplaying-remain muted">-{fmtDuration(timeRemaining)}</span>
|
<span className="po-nowplaying-remain muted">-{playoutFmtDur(timeRemaining)}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{nextItem && (
|
{nextItem && (
|
||||||
|
|
@ -813,7 +813,7 @@ function Timeline({ items, activeIndex, elapsed, breaks }) {
|
||||||
<div className="po-tl">
|
<div className="po-tl">
|
||||||
<div className="po-tl-head">
|
<div className="po-tl-head">
|
||||||
<span className="po-section-label">Timeline</span>
|
<span className="po-section-label">Timeline</span>
|
||||||
<span className="mono muted" style={{ fontSize: 11 }}>{fmtDuration(totalSecs)} total</span>
|
<span className="mono muted" style={{ fontSize: 11 }}>{playoutFmtDur(totalSecs)} total</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="po-tl-track-wrap">
|
<div className="po-tl-track-wrap">
|
||||||
{activeIndex >= 0 && (
|
{activeIndex >= 0 && (
|
||||||
|
|
@ -833,9 +833,9 @@ function Timeline({ items, activeIndex, elapsed, breaks }) {
|
||||||
<div key={it.id}
|
<div key={it.id}
|
||||||
className={'po-tl-clip' + (isActive ? ' po-tl-clip--active' : '')}
|
className={'po-tl-clip' + (isActive ? ' po-tl-clip--active' : '')}
|
||||||
style={{ width: pct + '%', '--clip-color': color }}
|
style={{ width: pct + '%', '--clip-color': color }}
|
||||||
title={`${it.clip_name || it.asset_id} · ${fmtDuration(dur)}`}>
|
title={`${it.clip_name || it.asset_id} · ${playoutFmtDur(dur)}`}>
|
||||||
<span className="po-tl-clip-name">{it.clip_name || it.asset_id}</span>
|
<span className="po-tl-clip-name">{it.clip_name || it.asset_id}</span>
|
||||||
<span className="po-tl-clip-dur mono">{fmtDuration(dur)}</span>
|
<span className="po-tl-clip-dur mono">{playoutFmtDur(dur)}</span>
|
||||||
{it.media_status === 'staging' && (
|
{it.media_status === 'staging' && (
|
||||||
<span className="po-tl-staging-dot" title="Staging…" />
|
<span className="po-tl-staging-dot" title="Staging…" />
|
||||||
)}
|
)}
|
||||||
|
|
@ -849,7 +849,7 @@ function Timeline({ items, activeIndex, elapsed, breaks }) {
|
||||||
<div className="po-tl-ruler">
|
<div className="po-tl-ruler">
|
||||||
{totalSecs > 0 && Array.from({ length: 5 }).map((_, i) => (
|
{totalSecs > 0 && Array.from({ length: 5 }).map((_, i) => (
|
||||||
<span key={i} className="po-tl-ruler-mark mono" style={{ left: (i * 25) + '%' }}>
|
<span key={i} className="po-tl-ruler-mark mono" style={{ left: (i * 25) + '%' }}>
|
||||||
{fmtDuration((totalSecs * i) / 4)}
|
{playoutFmtDur((totalSecs * i) / 4)}
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -907,7 +907,7 @@ function AsRunDrawer({ channel, refreshKey, open, onClose }) {
|
||||||
<td>{r.clip_name || r.item_id || '—'}</td>
|
<td>{r.clip_name || r.item_id || '—'}</td>
|
||||||
<td className="mono">
|
<td className="mono">
|
||||||
{r.duration_s != null
|
{r.duration_s != null
|
||||||
? fmtDuration(Number(r.duration_s))
|
? playoutFmtDur(Number(r.duration_s))
|
||||||
: (r.ended_at ? '—' : 'on air')}
|
: (r.ended_at ? '—' : 'on air')}
|
||||||
</td>
|
</td>
|
||||||
<td className={'po-asrun-result po-asrun-' + (r.result || 'played')}>
|
<td className={'po-asrun-result po-asrun-' + (r.result || 'played')}>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue