import { useState } from "react"; import { Clock, AlertTriangle, CheckCircle2, Edit2, ChevronDown, ChevronUp } from "lucide-react"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; import type { SrtSegment, Anomaly } from "@shared/schema"; interface SrtViewerProps { segments: SrtSegment[]; anomalies: Anomaly[]; onSegmentClick?: (segmentId: number) => void; onSegmentUpdate?: (segmentId: number, newText: string) => void; onTimeJump?: (time: number) => void; onPause?: () => void; highlightedSegmentId?: number; currentTime?: number; } export function SrtViewer({ segments, anomalies, onSegmentClick, onSegmentUpdate, onTimeJump, onPause, highlightedSegmentId, currentTime = 0 }: SrtViewerProps) { const [isExpanded, setIsExpanded] = useState(true); const [editingSegmentId, setEditingSegmentId] = useState(null); const [editText, setEditText] = useState(""); const parseTime = (timeStr: string) => { const [time, ms] = timeStr.split(","); const [h, m, s] = time.split(":").map(Number); return h * 3600 + m * 60 + s + Number(ms) / 1000; }; const getSegmentAnomalies = (segmentId: number) => { return anomalies.filter(a => a.segmentId === segmentId); }; const handleEditClick = (segment: SrtSegment) => { setEditingSegmentId(segment.id); setEditText(segment.text); onPause?.(); }; const handleSaveEdit = (segmentId: number) => { if (onSegmentUpdate) { onSegmentUpdate(segmentId, editText); } setEditingSegmentId(null); }; const handleCancelEdit = () => { setEditingSegmentId(null); setEditText(""); }; const unresolvedCount = anomalies.filter(a => !a.resolved).length; const resolvedCount = anomalies.filter(a => a.resolved).length; const highlightAnomalies = (text: string, segmentAnomalies: Anomaly[]) => { if (segmentAnomalies.length === 0) return text; let result = text; const unresolvedAnomalies = segmentAnomalies.filter(a => !a.resolved); unresolvedAnomalies.forEach(anomaly => { const escapedText = anomaly.flaggedText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); const regex = new RegExp(`(${escapedText})`, 'gi'); result = result.replace(regex, `$1`); }); return result; }; return (

SRT Preview

{segments.length} segments
{unresolvedCount > 0 && ( {unresolvedCount} issues )} {resolvedCount > 0 && ( {resolvedCount} resolved )} {isExpanded ? : }
{segments.map((segment) => { const segmentAnomalies = getSegmentAnomalies(segment.id); const hasUnresolved = segmentAnomalies.some(a => !a.resolved); const start = parseTime(segment.startTime); const end = parseTime(segment.endTime); const isActive = currentTime >= start && currentTime <= end; const isHighlighted = highlightedSegmentId === segment.id || isActive; const isEditing = editingSegmentId === segment.id; return (
{ if (!isEditing) { onSegmentClick?.(segment.id); onTimeJump?.(start); } }} data-testid={`segment-${segment.id}`} >
#{segment.id}
{segment.startTime} {segment.endTime}
{isEditing ? (
e.stopPropagation()}>