import Link from "next/link"; import { ArrowDownUp, Download, Maximize, Maximize2, Minimize, Minimize2, Pause, Play, Repeat1, RotateCcw, RotateCw, Volume2, VolumeX, FileText, } from "lucide-react"; import type { RefObject } from "react"; import type { LoopMode, ObjectFit, User } from "../types.ts"; import { formatRelativeTime, formatTime, formatAbsoluteUTC } from "../utils"; import { ProgressBar } from "./ProgressBar"; import { SegmentedProgressBar } from "./SegmentedProgressBar"; import { MoreMenu, MoreMenuItem } from "./MoreMenu"; interface MediaControlsProps { isVideo: boolean; isPlaying: boolean; progress: number; volume: number; rate: number; rotation: number; objectFit: ObjectFit; loopMode: LoopMode; isFullscreen: boolean; author: User; createdAt: string | Date; desc: string; // 视频专用 videoRef?: RefObject; // 图文专用 currentIndex?: number; totalSegments?: number; segmentProgress?: number; musicUrl?: string | null; audioRef?: RefObject; // 转录相关 hasTranscript?: boolean; onShowTranscript?: () => void; // 回调 onTogglePlay: () => void; onSeek: (ratio: number) => void; onVolumeChange: (volume: number) => void; onRateChange: (rate: number) => void; onRotationChange: (rotation: number) => void; onObjectFitChange: (fit: ObjectFit) => void; onLoopModeChange: (mode: LoopMode) => void; onDownload: () => void; onToggleFullscreen: () => void; } export function MediaControls({ isVideo, isPlaying, progress, volume, rate, rotation, objectFit, loopMode, isFullscreen, author, createdAt, desc, videoRef, currentIndex = 0, totalSegments = 0, segmentProgress = 0, musicUrl, audioRef, hasTranscript = false, onShowTranscript, onTogglePlay, onSeek, onVolumeChange, onRateChange, onRotationChange, onObjectFitChange, onLoopModeChange, onDownload, onToggleFullscreen, }: MediaControlsProps) { return (
{/* 描述行 */}
{author.sec_uid ? ( {author.nickname} ) : (
{author.nickname}
)} · {formatRelativeTime(createdAt)}
{desc ? (

{desc}

) : null} {/* 进度条:图文=分段;视频=单段 */} {!isVideo && totalSegments > 0 ? ( ) : ( )} {/* 控制按钮行 - 响应式布局 */}
{/* 左侧:播放控制 + 时间/进度 */}
{/* 播放进度显示 - 所有设备都显示 */}
{isVideo ? ( (() => { const v = videoRef?.current; const current = v?.currentTime ?? 0; const total = v?.duration ?? 0; return total > 0 ? `${formatTime(current)} / ${formatTime(total)}` : "--:-- / --:--"; })() ) : ( `${currentIndex + 1} / ${totalSegments}` )}
{/* 倍速 - 中等屏幕以上显示,仅视频 */} {isVideo && ( )}
{/* 中间:音量控制 - 中等屏幕以上显示 */}
{/* 旋转按钮 - 小屏幕以上显示 */} onVolumeChange(parseFloat(e.target.value))} className="w-20 lg:w-28 accent-white cursor-pointer" aria-label="音量" />
{/* 右侧:功能按钮组 */}
{/* 音量按钮 - 仅在小屏幕显示(中等屏幕以上有滑块) */} {/* 循环模式 - 中等屏幕以上显示 */} {/* 适配模式 - 小屏幕以上显示 */} {/* 转录文本 - 仅视频且有转录时显示,中等屏幕以上 */} {isVideo && hasTranscript && onShowTranscript && ( )} {/* 下载 - 中等屏幕以上显示 */} {/* 更多菜单 - 只在有按钮被折叠时显示 */} {/* sm屏幕以下会隐藏适配模式,md屏幕以下会隐藏循环、转录、下载、倍速 */}
{/* 小屏幕隐藏的适配模式 */}
: } label={objectFit === "contain" ? "填充模式" : "适应模式"} onClick={() => onObjectFitChange(objectFit === "contain" ? "cover" : "contain")} />
{/* 中等屏幕以下隐藏的循环模式 */}
: } label={loopMode === "loop" ? "循环播放" : "顺序播放"} onClick={() => onLoopModeChange(loopMode === "loop" ? "sequential" : "loop")} />
{/* 中等屏幕以下隐藏的转录按钮 */} {isVideo && hasTranscript && onShowTranscript && (
} label="显示转录" onClick={onShowTranscript} />
)} {/* 中等屏幕以下隐藏的下载 */}
} label={isVideo ? "下载视频" : "下载图片"} onClick={onDownload} />
{/* 仅在视频模式下显示的倍速(中等屏幕以下) */} {isVideo && (
{rate}x} label="播放速度" onClick={() => { const steps = [1, 1.25, 1.5, 2, 0.75, 0.5]; const i = steps.indexOf(rate); const next = steps[(i + 1) % steps.length]; onRateChange(next); }} />
)}
{/* 全屏 - 所有设备都显示 */}
{/* 图文 BGM(隐藏控件,仅用于播放) */} {!isVideo && musicUrl ?
); }