import { useState, useEffect } from "react"; import { cn } from "@renderer/lib/utils"; import { Button, Popover, PopoverContent, PopoverAnchor, } from "@renderer/components/ui"; import { LookupResult } from "@renderer/components"; import { LanguagesIcon, PlayIcon } from "lucide-react"; export const AudioCaption = (props: { audioId: string; currentTime: number; transcription: TranscriptionGroupType; onSeek?: (time: number) => void; className?: string; isPlaying: boolean; setIsPlaying: (isPlaying: boolean) => void; }) => { const { transcription, currentTime, onSeek, className, isPlaying, setIsPlaying, } = props; const [activeIndex, setActiveIndex] = useState(0); const [selected, setSelected] = useState<{ index: number; word: string; position?: { top: number; left: number; }; }>(); useEffect(() => { if (!transcription) return; const time = Math.round(currentTime * 1000); const index = transcription.segments.findIndex( (w) => time >= w.offsets.from && time < w.offsets.to ); if (index !== activeIndex) { setActiveIndex(index); } }, [currentTime, transcription]); if (!transcription) return null; if (Math.round(currentTime * 1000) < transcription.offsets.from) return null; return (
{(transcription.segments || []).map((w, index) => ( { setSelected({ index, word: w.text, position: { top: event.currentTarget.offsetTop + event.currentTarget.offsetHeight, left: event.currentTarget.offsetLeft, }, }); setIsPlaying(false); if (onSeek) onSeek(w.offsets.from / 1000); }} > {w.text} ))} { if (!value) setSelected(null); }} > {selected?.word && ( w.text).join(" ").trim()} audioId={props.audioId} onPlay={() => { setIsPlaying(true); }} /> )}
); }; const AudioCaptionSelectionMenu = (props: { word: string; context: string; audioId: string; onPlay: () => void; }) => { const { word, context, audioId, onPlay } = props; const [translating, setTranslating] = useState(false); if (!word) return null; if (translating) { return ( ); } return (
); };