mirror of
https://github.com/myronblair/kino-app
synced 2026-07-28 13:33:49 -05:00
auto-commit for df4b0748-985b-4592-8c48-1e56102f3613
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import api, { getStreamUrl } from "../lib/api";
|
||||
import { ArrowLeft } from "lucide-react";
|
||||
|
||||
export default function Player() {
|
||||
const { id } = useParams();
|
||||
const nav = useNavigate();
|
||||
const [movie, setMovie] = useState(null);
|
||||
const videoRef = useRef(null);
|
||||
const lastSent = useRef(0);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
(async () => {
|
||||
const { data } = await api.get(`/movies/${id}`);
|
||||
if (cancelled) return;
|
||||
setMovie(data);
|
||||
// Restore progress
|
||||
try {
|
||||
const { data: p } = await api.get(`/progress/${id}`);
|
||||
if (videoRef.current && p?.position_seconds) {
|
||||
videoRef.current.currentTime = p.position_seconds;
|
||||
}
|
||||
} catch {}
|
||||
})();
|
||||
return () => { cancelled = true; };
|
||||
}, [id]);
|
||||
|
||||
const onTimeUpdate = () => {
|
||||
const v = videoRef.current;
|
||||
if (!v || !v.duration) return;
|
||||
const now = Date.now();
|
||||
if (now - lastSent.current < 5000) return;
|
||||
lastSent.current = now;
|
||||
api.post("/progress", {
|
||||
movie_id: id,
|
||||
position_seconds: v.currentTime,
|
||||
duration_seconds: v.duration,
|
||||
}).catch(() => {});
|
||||
};
|
||||
|
||||
if (!movie) {
|
||||
return (
|
||||
<div className="min-h-screen bg-black flex items-center justify-center text-[#8A8A8A]" data-testid="player-loading">
|
||||
Loading…
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 bg-black z-50 flex flex-col" data-testid="player-page">
|
||||
<button
|
||||
onClick={() => nav(-1)}
|
||||
className="absolute top-6 left-6 z-10 flex items-center gap-2 text-white/80 hover:text-white bg-black/60 hover:bg-black px-4 py-2 transition-colors duration-300"
|
||||
data-testid="player-back-button"
|
||||
>
|
||||
<ArrowLeft size={16} strokeWidth={1.5} />
|
||||
<span className="text-xs uppercase tracking-[0.2em]">Back</span>
|
||||
</button>
|
||||
|
||||
<div className="absolute top-6 right-6 z-10 text-right">
|
||||
<h2 className="font-display text-xl text-white tracking-tight" data-testid="player-title">
|
||||
{movie.title}
|
||||
</h2>
|
||||
<p className="text-[10px] uppercase tracking-[0.3em] text-[#8A8A8A]">{movie.year} · {movie.rating}</p>
|
||||
</div>
|
||||
|
||||
<video
|
||||
ref={videoRef}
|
||||
src={getStreamUrl(movie)}
|
||||
controls
|
||||
autoPlay
|
||||
className="w-full h-full object-contain bg-black"
|
||||
onTimeUpdate={onTimeUpdate}
|
||||
data-testid="player-video"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user