"use client"; import React, { useState, useRef, useEffect } from "react"; import { Play, Pause, FastForward, Rewind } from "@phosphor-icons/react"; import styles from "./trainOfThoughtVideoPlayer.module.css"; interface TrainOfThoughtFrame { text: string; image?: string; timestamp: number; } interface TrainOfThoughtVideoPlayerProps { frames: TrainOfThoughtFrame[]; autoPlay?: boolean; playbackSpeed?: number; } export default function TrainOfThoughtVideoPlayer({ frames, autoPlay = true, playbackSpeed = 1000, // ms per frame }: TrainOfThoughtVideoPlayerProps) { const [currentFrameIndex, setCurrentFrameIndex] = useState(0); const [isPlaying, setIsPlaying] = useState(autoPlay); const [isAutoTracking, setIsAutoTracking] = useState(true); const intervalRef = useRef(null); // Auto-advance to latest frame when new frames are added useEffect(() => { if (isAutoTracking && frames.length > 0) { setCurrentFrameIndex(frames.length - 1); } }, [frames.length, isAutoTracking]); // Handle playback useEffect(() => { if (isPlaying && frames.length > 1) { intervalRef.current = setInterval(() => { setCurrentFrameIndex((prev) => { const next = prev + 1; if (next >= frames.length) { setIsPlaying(false); return prev; } return next; }); }, playbackSpeed); } else { if (intervalRef.current) { clearInterval(intervalRef.current); intervalRef.current = null; } } return () => { if (intervalRef.current) { clearInterval(intervalRef.current); } }; }, [isPlaying, frames.length, playbackSpeed]); const currentFrame = frames[currentFrameIndex]; const handleSeek = (index: number) => { setCurrentFrameIndex(index); setIsAutoTracking(false); setIsPlaying(false); }; const handlePlay = () => { setIsPlaying(!isPlaying); setIsAutoTracking(false); }; const handlePrevious = () => { if (currentFrameIndex > 0) { setCurrentFrameIndex(currentFrameIndex - 1); setIsAutoTracking(false); setIsPlaying(false); } }; const handleNext = () => { if (currentFrameIndex < frames.length - 1) { setCurrentFrameIndex(currentFrameIndex + 1); setIsAutoTracking(false); setIsPlaying(false); } }; const handleAutoTrack = () => { setIsAutoTracking(true); setCurrentFrameIndex(frames.length - 1); setIsPlaying(false); }; if (!frames.length) { return null; } return (
{currentFrame?.image && ( {`Train )}
{currentFrame?.text}
handleSeek(parseInt(e.target.value))} className={styles.timelineSlider} />
{frames.map((frame, index) => (
handleSeek(index)} title={`Frame ${index + 1}: ${frame.text.slice(0, 50)}...`} /> ))}
{currentFrameIndex + 1} / {frames.length}
); }