feat: Enhance MediaPlayer with cues_en support and refactor its layout to separate interactive cues from a new full transcription text display.

This commit is contained in:
2026-01-29 15:09:47 -03:00
parent 5a6017609e
commit a8bc54bfa8
+42 -39
View File
@@ -9,6 +9,7 @@ interface MediaPlayerProps {
en?: string;
es?: string;
cues?: { start: number; end: number; text: string }[];
cues_en?: { start: number; end: number; text: string }[];
} | null;
locked?: boolean;
onEnded?: () => void;
@@ -139,9 +140,11 @@ export default function MediaPlayer({ src, type, transcription, locked, onEnded,
};
return (
<div className={`grid grid-cols-1 ${shouldShowTranscription && transcription?.cues ? 'xl:grid-cols-12' : ''} gap-8 h-full`}>
<div className="flex flex-col gap-6 w-full">
{/* Top Row: Media + Interactive Sidebar */}
<div className={`grid grid-cols-1 ${shouldShowTranscription && activeCues.length > 0 ? 'xl:grid-cols-12' : ''} gap-6 w-full`}>
{/* Media Content */}
<div className={`${shouldShowTranscription && transcription?.cues ? 'xl:col-span-8' : ''} space-y-4 relative group`}>
<div className={`${shouldShowTranscription && activeCues.length > 0 ? 'xl:col-span-8' : 'w-full'} relative`}>
{renderMedia()}
{locked && (
@@ -153,37 +156,13 @@ export default function MediaPlayer({ src, type, transcription, locked, onEnded,
<p className="text-sm text-gray-300 max-w-xs">This content can only be played once according to the activity rules.</p>
</div>
)}
{/* Simple Transcript (Fallback or Mobile) */}
{shouldShowTranscription && !transcription?.cues && (
<div className="glass p-6 space-y-4 border border-blue-500/20">
<div className="flex justify-between items-center">
<h4 className="text-lg font-semibold flex items-center gap-2">
Transcription <span className="text-xs bg-blue-500/20 text-blue-400 px-2 py-1 rounded">AI Enhanced</span>
</h4>
<div className="flex bg-white/5 rounded-lg p-1">
<button
onClick={() => setLanguage("en")}
className={`px-3 py-1 text-xs rounded-md transition-all ${language === "en" ? "bg-blue-500 text-white shadow-lg" : "text-gray-400 hover:text-white"}`}
>EN</button>
<button
onClick={() => setLanguage("es")}
className={`px-3 py-1 text-xs rounded-md transition-all ${language === "es" ? "bg-blue-500 text-white shadow-lg" : "text-gray-400 hover:text-white"}`}
>ES</button>
</div>
</div>
<div className="text-sm text-gray-400 leading-relaxed max-h-40 overflow-y-auto italic bg-white/5 p-4 rounded-lg">
&quot;{transcription[language] || "Transcription not available."}&quot;
</div>
</div>
)}
</div>
{/* Interactive Sidebar */}
{shouldShowTranscription && transcription?.cues && (
<div className="xl:col-span-4 glass border-white/5 bg-white/5 rounded-2xl overflow-hidden flex flex-col h-[500px] xl:h-auto border border-blue-500/10">
{/* Interactive Sidebar (Cues Only) */}
{shouldShowTranscription && activeCues.length > 0 && (
<div className="xl:col-span-4 glass border-white/5 bg-white/5 rounded-2xl overflow-hidden flex flex-col h-[300px] xl:h-[unset] xl:max-h-full border border-blue-500/10 self-stretch">
<div className="p-4 border-b border-white/5 flex items-center justify-between bg-white/5">
<h4 className="text-xs font-black uppercase tracking-widest text-gray-400">Interactive Content</h4>
<h4 className="text-[10px] font-black uppercase tracking-widest text-gray-500">Interactive Content</h4>
<div className="flex bg-white/5 rounded-lg p-1">
<button
onClick={() => setLanguage("en")}
@@ -196,24 +175,19 @@ export default function MediaPlayer({ src, type, transcription, locked, onEnded,
</div>
</div>
<div className="flex-1 overflow-y-auto p-4 space-y-3 custom-scrollbar">
{language === "en" && transcription.en && !transcription.cues.some(c => c.text === transcription.en) && (
<p className="text-sm text-gray-500 italic mb-4 p-4 bg-blue-500/5 rounded-xl border border-blue-500/10">
{transcription.en}
</p>
)}
{transcription.cues.map((cue, idx) => (
{activeCues.map((cue, idx) => (
<button
key={idx}
onClick={() => handleSeek(cue.start)}
className={`text-left p-3 rounded-xl transition-all border group relative ${currentTime >= cue.start && currentTime <= cue.end
? "bg-blue-500/20 border-blue-500/40 text-white shadow-lg shadow-blue-500/10"
className={`text-left p-3 rounded-xl transition-all border group relative w-full ${currentTime >= cue.start && currentTime <= cue.end
? "bg-blue-500/20 border-blue-500/40 text-white"
: "bg-white/5 border-transparent text-gray-400 hover:bg-white/10 hover:border-white/10"
}`}
>
<span className={`text-[9px] font-mono mb-1 block ${currentTime >= cue.start && currentTime <= cue.end ? 'text-blue-300' : 'text-gray-600'}`}>
{Math.floor(cue.start / 60)}:{String(Math.floor(cue.start % 60)).padStart(2, '0')}
</span>
<p className="text-sm leading-relaxed font-medium">
<p className="text-xs leading-relaxed font-medium line-clamp-2">
{cue.text}
</p>
</button>
@@ -222,5 +196,34 @@ export default function MediaPlayer({ src, type, transcription, locked, onEnded,
</div>
)}
</div>
{/* Bottom Row: Full Transcription Text */}
{shouldShowTranscription && (
<div className="glass p-6 rounded-2xl border-white/5 bg-white/5 flex flex-col gap-4">
<div className="flex items-center justify-between border-b border-white/5 pb-3">
<h4 className="text-xs font-black uppercase tracking-widest text-gray-500 flex items-center gap-2">
<span>📝</span> Full Transcription ({language.toUpperCase()})
</h4>
{!transcription.cues && (
<div className="flex bg-white/5 rounded-lg p-1">
<button
onClick={() => setLanguage("en")}
className={`px-2 py-1 text-[10px] font-bold rounded ${language === "en" ? "bg-blue-500 text-white" : "text-gray-500 hover:text-white"}`}
>EN</button>
<button
onClick={() => setLanguage("es")}
className={`px-2 py-1 text-[10px] font-bold rounded ${language === "es" ? "bg-blue-500 text-white" : "text-gray-500 hover:text-white"}`}
>ES</button>
</div>
)}
</div>
<div className="text-sm text-gray-400 leading-relaxed italic max-h-60 overflow-y-auto custom-scrollbar pr-4">
&quot;{transcription[language] || "Transcription not available."}&quot;
</div>
</div>
)}
</div>
);
}
);
}