fix no clips on home page login
This commit is contained in:
@@ -137,7 +137,7 @@ const Home = () => {
|
|||||||
setVods(topSix);
|
setVods(topSix);
|
||||||
setCounts(prev => ({ ...prev, vods: data.length }));
|
setCounts(prev => ({ ...prev, vods: data.length }));
|
||||||
})
|
})
|
||||||
}, []);
|
}, [user]);
|
||||||
|
|
||||||
const handleDropMarker = async () => {
|
const handleDropMarker = async () => {
|
||||||
if (markerBusy) return;
|
if (markerBusy) return;
|
||||||
@@ -274,9 +274,9 @@ const Home = () => {
|
|||||||
fps={vod.fps}
|
fps={vod.fps}
|
||||||
fileSize={vod.fileSize}
|
fileSize={vod.fileSize}
|
||||||
mediaApiPath="/api/v1/vods"
|
mediaApiPath="/api/v1/vods"
|
||||||
playerPath="/vod"
|
playerPath="/video"
|
||||||
itemLabel="vod"
|
itemLabel="vod"
|
||||||
onEdit={() => navigate(`/vods/${vod.id}/edit`)}
|
onEdit={() => navigate(`/video/${vod.id}/edit`)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -298,9 +298,9 @@ const Home = () => {
|
|||||||
fps={clip.fps}
|
fps={clip.fps}
|
||||||
fileSize={clip.fileSize}
|
fileSize={clip.fileSize}
|
||||||
mediaApiPath="/api/v1/clips"
|
mediaApiPath="/api/v1/clips"
|
||||||
playerPath="/clip"
|
playerPath="/video"
|
||||||
itemLabel="clip"
|
itemLabel="clip"
|
||||||
onEdit={() => navigate(`/clip/${clip.id}/edit`)}
|
onEdit={() => navigate(`/video/${clip.id}/edit`)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -69,10 +69,6 @@ const MediaPlayer = ({ noun, getMediaUrl, fetchDetails }: MediaPlayerProps) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// ── Data loading ────────────────────────────────────────────────────────
|
// ── Data loading ────────────────────────────────────────────────────────
|
||||||
// The video stream itself is loaded by the <video> element from `mediaUrl`,
|
|
||||||
// which lets the browser fetch it incrementally via Range requests. We only
|
|
||||||
// need to fetch the metadata here; it shares the media endpoint's auth, so a
|
|
||||||
// 401/403 here also stands in for the stream being inaccessible.
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!id) { setError(`${noun} ID is required.`); return; }
|
if (!id) { setError(`${noun} ID is required.`); return; }
|
||||||
|
|
||||||
@@ -82,6 +78,7 @@ const MediaPlayer = ({ noun, getMediaUrl, fetchDetails }: MediaPlayerProps) => {
|
|||||||
if (e instanceof AuthError) setNotAuthenticated(true);
|
if (e instanceof AuthError) setNotAuthenticated(true);
|
||||||
else setError(`Failed to load ${noun.toLowerCase()} details.`);
|
else setError(`Failed to load ${noun.toLowerCase()} details.`);
|
||||||
});
|
});
|
||||||
|
|
||||||
}, [id, noun, fetchDetails]);
|
}, [id, noun, fetchDetails]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -103,7 +100,6 @@ const MediaPlayer = ({ noun, getMediaUrl, fetchDetails }: MediaPlayerProps) => {
|
|||||||
scheduleHide();
|
scheduleHide();
|
||||||
}, [scheduleHide]);
|
}, [scheduleHide]);
|
||||||
|
|
||||||
// ── Fullscreen ──────────────────────────────────────────────────────────
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const onChange = () => setIsFullscreen(!!document.fullscreenElement);
|
const onChange = () => setIsFullscreen(!!document.fullscreenElement);
|
||||||
document.addEventListener('fullscreenchange', onChange);
|
document.addEventListener('fullscreenchange', onChange);
|
||||||
@@ -259,7 +255,7 @@ const MediaPlayer = ({ noun, getMediaUrl, fetchDetails }: MediaPlayerProps) => {
|
|||||||
<div className="h-full flex flex-col px-13 py-8 gap-4">
|
<div className="h-full flex flex-col px-13 py-8 gap-4">
|
||||||
<button
|
<button
|
||||||
onClick={() => navigate(-1)}
|
onClick={() => navigate(-1)}
|
||||||
className={clsx(quietLinkClass, "flex items-center gap-1.5 flex-shrink-0")}
|
className={clsx(quietLinkClass, "flex items-center gap-1.5 shrink-0")}
|
||||||
>
|
>
|
||||||
<ArrowLeft size={15} />
|
<ArrowLeft size={15} />
|
||||||
Back
|
Back
|
||||||
@@ -307,7 +303,7 @@ const MediaPlayer = ({ noun, getMediaUrl, fetchDetails }: MediaPlayerProps) => {
|
|||||||
{/* Action flash — a badge that swells and fades on play, pause and seek. */}
|
{/* Action flash — a badge that swells and fades on play, pause and seek. */}
|
||||||
{flash && FlashIcon && (
|
{flash && FlashIcon && (
|
||||||
<div key={flash.id} className="absolute inset-0 flex items-center justify-center pointer-events-none">
|
<div key={flash.id} className="absolute inset-0 flex items-center justify-center pointer-events-none">
|
||||||
<div className="animate-flash-badge flex h-[74px] w-[74px] items-center justify-center rounded-full bg-player/55 backdrop-blur-[2px] text-on-dark">
|
<div className="animate-flash-badge flex h-18.5 w-18.5 items-center justify-center rounded-full bg-player/55 backdrop-blur-[2px] text-on-dark">
|
||||||
<FlashIcon size={30} fill="currentColor" strokeWidth={1} />
|
<FlashIcon size={30} fill="currentColor" strokeWidth={1} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -316,8 +312,8 @@ const MediaPlayer = ({ noun, getMediaUrl, fetchDetails }: MediaPlayerProps) => {
|
|||||||
{/* Controls overlay — pointer-events-none so video clicks pass through */}
|
{/* Controls overlay — pointer-events-none so video clicks pass through */}
|
||||||
<div className={`absolute inset-0 flex flex-col justify-end transition-opacity duration-300 pointer-events-none ${controlsVisible ? 'opacity-100' : 'opacity-0'}`}>
|
<div className={`absolute inset-0 flex flex-col justify-end transition-opacity duration-300 pointer-events-none ${controlsVisible ? 'opacity-100' : 'opacity-0'}`}>
|
||||||
{/* Gradients — top one carries the title, bottom one the controls */}
|
{/* Gradients — top one carries the title, bottom one the controls */}
|
||||||
<div className="absolute inset-x-0 top-0 h-28 bg-gradient-to-b from-black/55 to-transparent" />
|
<div className="absolute inset-x-0 top-0 h-28 bg-linear-to-b from-black/55 to-transparent" />
|
||||||
<div className="absolute inset-0 bg-gradient-to-t from-black/75 via-black/10 to-transparent" />
|
<div className="absolute inset-0 bg-linear-to-t from-black/75 via-black/10 to-transparent" />
|
||||||
|
|
||||||
{/* Title plate */}
|
{/* Title plate */}
|
||||||
<div className={clsx(
|
<div className={clsx(
|
||||||
@@ -365,7 +361,7 @@ const MediaPlayer = ({ noun, getMediaUrl, fetchDetails }: MediaPlayerProps) => {
|
|||||||
{/* Time under the cursor */}
|
{/* Time under the cursor */}
|
||||||
{hoverTime !== null && (
|
{hoverTime !== null && (
|
||||||
<div
|
<div
|
||||||
className="absolute bottom-4 -translate-x-1/2 rounded-[6px] bg-player/85 px-1.5 py-0.5 font-data text-[11px] text-on-dark tabular-nums pointer-events-none"
|
className="absolute bottom-4 -translate-x-1/2 rounded-md bg-player/85 px-1.5 py-0.5 font-data text-[11px] text-on-dark tabular-nums pointer-events-none"
|
||||||
style={{ left: `${hoverPct}%` }}
|
style={{ left: `${hoverPct}%` }}
|
||||||
>
|
>
|
||||||
{formatTime(hoverTime)}
|
{formatTime(hoverTime)}
|
||||||
@@ -416,7 +412,7 @@ const MediaPlayer = ({ noun, getMediaUrl, fetchDetails }: MediaPlayerProps) => {
|
|||||||
<p className="font-data text-[12px] text-faint-mono">loading video…</p>
|
<p className="font-data text-[12px] text-faint-mono">loading video…</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Card className="p-5 flex-shrink-0 flex flex-wrap items-end justify-between gap-x-8 gap-y-3">
|
<Card className="p-5 shrink-0 flex flex-wrap items-end justify-between gap-x-8 gap-y-3">
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
<p className={kickerClass}>{noun}</p>
|
<p className={kickerClass}>{noun}</p>
|
||||||
<p className="font-heading text-[25px] tracking-[-0.015em] leading-tight pt-1">
|
<p className="font-heading text-[25px] tracking-[-0.015em] leading-tight pt-1">
|
||||||
|
|||||||
Reference in New Issue
Block a user