From bec58ab1389ce048cf9ff17673d3db2ced0786cb Mon Sep 17 00:00:00 2001 From: ZGaetano Date: Fri, 22 May 2026 12:49:33 -0400 Subject: [PATCH] screens-asset: fix thumbGrad crash, parseDuration NaN, guard missing ACTIVITY --- services/web-ui/public/screens-asset.jsx | 200 +++++++++++------------ 1 file changed, 92 insertions(+), 108 deletions(-) diff --git a/services/web-ui/public/screens-asset.jsx b/services/web-ui/public/screens-asset.jsx index b66e1cc..165f3fa 100644 --- a/services/web-ui/public/screens-asset.jsx +++ b/services/web-ui/public/screens-asset.jsx @@ -2,18 +2,33 @@ const { COMMENTS: SEED_COMMENTS } = window.ZAMPP_DATA; +// Simple gradient palette — replaces the missing thumbGrad function +const _FRAME_GRADIENTS = [ + 'linear-gradient(135deg,#1a1f2e 0%,#2a3045 100%)', + 'linear-gradient(135deg,#1e2030 0%,#2d2040 100%)', + 'linear-gradient(135deg,#0d1520 0%,#1a2535 100%)', + 'linear-gradient(135deg,#1f1a2e 0%,#2a2040 100%)', + 'linear-gradient(135deg,#0f1e18 0%,#1a3028 100%)', + 'linear-gradient(135deg,#1e1510 0%,#302018 100%)', + 'linear-gradient(135deg,#1a1020 0%,#281830 100%)', + 'linear-gradient(135deg,#101828 0%,#182438 100%)', + 'linear-gradient(135deg,#1e2820 0%,#283830 100%)', + 'linear-gradient(135deg,#201820 0%,#302030 100%)', + 'linear-gradient(135deg,#181e28 0%,#202838 100%)', +]; + function AssetDetail({ asset, onClose }) { const [playing, setPlaying] = React.useState(false); - const [currentMs, setCurrentMs] = React.useState(720000); + const [currentMs, setCurrentMs] = React.useState(0); const [tab, setTab] = React.useState("comments"); const [showResolved, setShowResolved] = React.useState(false); - const [comments, setComments] = React.useState(SEED_COMMENTS); + const [comments, setComments] = React.useState(SEED_COMMENTS || []); const [newComment, setNewComment] = React.useState(""); const totalMs = parseDuration(asset.duration); React.useEffect(() => { - if (!playing) return; + if (!playing || totalMs <= 0) return; const i = setInterval(() => { setCurrentMs(t => { const next = t + 100; @@ -24,7 +39,7 @@ function AssetDetail({ asset, onClose }) { return () => clearInterval(i); }, [playing, totalMs]); - const seek = (ms) => setCurrentMs(Math.max(0, Math.min(totalMs, ms))); + const seek = (ms) => setCurrentMs(Math.max(0, Math.min(totalMs || 0, ms))); const addComment = () => { if (!newComment.trim()) return; const t = msToTimecode(currentMs); @@ -51,14 +66,12 @@ function AssetDetail({ asset, onClose }) {
{asset.name} - v3
- {asset.project}·{asset.bin}·updated {asset.updated} + {asset.project}·updated {asset.updated}
- @@ -70,11 +83,21 @@ function AssetDetail({ asset, onClose }) {
- {!playing && ( + {!playing && totalMs > 0 && ( )} + {totalMs <= 0 && ( +
+
+
+ {asset.status === 'processing' ? 'Processing…' : asset.status === 'live' ? 'Live recording in progress' : 'Preview not yet available'} +
+ +
+
+ )}
{visibleComments .filter(c => Math.abs(parseDuration(c.time) - currentMs) < 200) @@ -90,26 +113,31 @@ function AssetDetail({ asset, onClose }) { LIVE · REC
)} -
- {msToTimecode(currentMs)} - / {asset.duration} + {totalMs > 0 && ( +
+ {msToTimecode(currentMs)} + / {asset.duration} +
+ )} +
+ + {totalMs > 0 && ( +
+ + {msToTimecode(currentMs)} + + {asset.duration} +
+ +
-
+ )} -
- - {msToTimecode(currentMs)} - - {asset.duration} -
- - - -
- - + {totalMs > 0 && ( + + )}
@@ -117,7 +145,7 @@ function AssetDetail({ asset, onClose }) { Comments {comments.length} -
{tab === "comments" && (
@@ -170,20 +194,21 @@ function PlaybackBar({ current, total, onSeek, comments }) { const p = (e.clientX - r.left) / r.width; onSeek(Math.max(0, Math.min(1, p)) * total); }; - const pct = (current / total) * 100; + const pct = total > 0 ? (current / total) * 100 : 0; return (
{comments.map(c => { - const x = (parseDuration(c.time) / total) * 100; + const ct = parseDuration(c.time); + if (!ct || total <= 0) return null; + const x = (ct / total) * 100; return (
{ e.stopPropagation(); onSeek(parseDuration(c.time)); }} + onClick={(e) => { e.stopPropagation(); onSeek(ct); }} > {c.avatar}
@@ -197,23 +222,26 @@ function FilmStrip({ seed, current, total, onSeek, comments }) { const ref = React.useRef(null); const frames = 28; const handle = (e) => { + if (!ref.current || total <= 0) return; const r = ref.current.getBoundingClientRect(); onSeek(((e.clientX - r.left) / r.width) * total); }; + const pct = total > 0 ? (current / total) * 100 : 0; return (
{Array.from({ length: frames }).map((_, i) => ( -
+
))} -
+
{comments.map(c => { - const x = (parseDuration(c.time) / total) * 100; + const ct = parseDuration(c.time); + if (!ct || total <= 0) return null; + const x = (ct / total) * 100; return ( -
+
{c.avatar}
); @@ -243,7 +271,7 @@ function CommentsList({ comments, onSeek, onResolve }) { {c.real}
-
@@ -262,15 +290,14 @@ function CommentComposer({ asset, currentMs, value, onChange, onSubmit }) {
Reviewers
- {["KM", "ZG", "MO", "JT"].map((a, i) => ( + {["ZG"].map((a, i) => (
{a}
))} - +
@ {msToTimecode(currentMs)} - Drawing tools