'use client'; import { memo, type RefObject } from 'react'; import { AlertCircle, Clock, Gauge, Maximize, MessageSquare, MessageSquareOff, Minimize, Pause, Play, SkipBack, SkipForward, Volume2, VolumeX, Loader2, } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { cn } from '@/lib/utils'; import { AnnotationCanvas, type AnnotationCanvasHandle, type AnnotationStroke, } from '@/components/annotation-canvas'; import { SILENT_ABOVE_SPEED } from '@/components/video-page/hooks/video-player-utils'; import { SubtitleControls } from '@/components/video-page/subtitle-controls'; import type { BunnyQualityOption, CommentMarker, Subtitle, SubtitleTrackOption, } from '@/components/video-page/types'; interface PlayerCoreProps { activeVersionId: string | null; activeProviderId: string | undefined; embedUrl: string; videoRef: RefObject; iframeRef: RefObject; bunnyViewportRef: RefObject; timelineRef: RefObject; progressRef: RefObject; playheadRef: RefObject; scrubReadoutRef: RefObject; videoContainerRef: RefObject; showScrubReadout: boolean; isFullscreenMode: boolean; cursorIdle: boolean; isPlaying: boolean; handlePlayPause: () => void; handleVideoMouseMove: () => void; handleVideoMouseLeave: () => void; isBunnyPortraitSource: boolean; bunnyPortraitFrameWidth: number; showBunnyProcessingOverlay: boolean; showBunnyErrorOverlay: boolean; showResumePrompt: boolean; savedProgress: number | null; formatTime: (value: number) => string; handleResumeFromSaved: () => void; handleDismissResume: () => void; isAnnotating: boolean; annotationCanvasRef: RefObject; setAnnotationStrokes: (strokes: AnnotationStroke[] | null) => void; setIsAnnotating: (value: boolean) => void; setViewingAnnotation: (strokes: AnnotationStroke[] | null) => void; viewingAnnotation: AnnotationStroke[] | null; isEditingAnnotation: boolean; editAnnotationCanvasRef: RefObject; editAnnotationInitialStrokes?: AnnotationStroke[]; setEditAnnotationData: (value: string | null | undefined) => void; setIsEditingAnnotation: (value: boolean) => void; currentTime: number; duration: number; isFrameMode: boolean; frameStepLabel: string; handleSkip: (seconds: number) => void; handleFrameModeToggle: () => void; handleMuteToggle: () => void; isMuted: boolean; selectedQualityLabel: string; selectedQualityLevel: number; qualityOptions: BunnyQualityOption[]; handleQualityChange: (level: number) => void; /** Uploaded tracks, rendered as elements. Empty for a YouTube version. */ subtitles: Subtitle[]; /** * What the CC menu offers, which is the list above for our own player and YouTube's * own caption list for an embedded YouTube version. */ subtitleTracks: SubtitleTrackOption[]; /** * Changes when a track has to be re-fetched. It is part of each key because * remounting the element is the only way to make the browser parse the file again. */ subtitleTrackKey: string; activeSubtitleLanguage: string | null; onSelectSubtitleLanguage: (language: string | null) => void; canManageSubtitles: boolean; onUploadSubtitle: (file: File, language: string, label: string) => Promise; onDeleteSubtitle: (subtitleId: string) => Promise; isUploadingSubtitle: boolean; playbackSpeed: number; speedOptions: number[]; handleSpeedChange: (speed: number) => void; toggleFullscreen: () => void; showComments: boolean; setShowComments: (value: boolean) => void; setIsMobileCommentsOpen: (value: boolean) => void; handleTimelineMouseDown: (e: React.MouseEvent) => void; handleTimelineMouseMove: (e: React.MouseEvent) => void; handleSeekToTimestamp: ( timestamp: number, annotation?: string | null, options?: { pauseAfterSeek?: boolean; timestampEnd?: number | null } ) => void; commentMarkers: CommentMarker[]; } export const PlayerCore = memo(function PlayerCore({ activeVersionId, activeProviderId, embedUrl, videoRef, iframeRef, bunnyViewportRef, timelineRef, progressRef, playheadRef, scrubReadoutRef, videoContainerRef, showScrubReadout, isFullscreenMode, cursorIdle, isPlaying, handlePlayPause, handleVideoMouseMove, handleVideoMouseLeave, isBunnyPortraitSource, bunnyPortraitFrameWidth, showBunnyProcessingOverlay, showBunnyErrorOverlay, showResumePrompt, savedProgress, formatTime, handleResumeFromSaved, handleDismissResume, isAnnotating, annotationCanvasRef, setAnnotationStrokes, setIsAnnotating, setViewingAnnotation, viewingAnnotation, isEditingAnnotation, editAnnotationCanvasRef, editAnnotationInitialStrokes, setEditAnnotationData, setIsEditingAnnotation, currentTime, duration, isFrameMode, frameStepLabel, handleSkip, handleFrameModeToggle, handleMuteToggle, isMuted, selectedQualityLabel, selectedQualityLevel, qualityOptions, handleQualityChange, subtitles, subtitleTracks, subtitleTrackKey, activeSubtitleLanguage, onSelectSubtitleLanguage, canManageSubtitles, onUploadSubtitle, onDeleteSubtitle, isUploadingSubtitle, playbackSpeed, speedOptions, handleSpeedChange, toggleFullscreen, showComments, setShowComments, setIsMobileCommentsOpen, handleTimelineMouseDown, handleTimelineMouseMove, handleSeekToTimestamp, commentMarkers, }: PlayerCoreProps) { return ( <>
{activeProviderId === 'bunny' || activeProviderId === 'r2' ? (
0 ? { width: `${bunnyPortraitFrameWidth}px` } : undefined } >
) : (