Merge pull request #244 from ateendra24/fix-issue-226
feat: add fullscreen video player
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Pause, Play } from "lucide-react";
|
||||
import { Maximize, Minimize, Pause, Play } from "lucide-react";
|
||||
import { useScopedT } from "@/contexts/I18nContext";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Button } from "../ui/button";
|
||||
@@ -7,6 +7,8 @@ interface PlaybackControlsProps {
|
||||
isPlaying: boolean;
|
||||
currentTime: number;
|
||||
duration: number;
|
||||
isFullscreen?: boolean;
|
||||
onToggleFullscreen?: () => void;
|
||||
onTogglePlayPause: () => void;
|
||||
onSeek: (time: number) => void;
|
||||
}
|
||||
@@ -15,6 +17,8 @@ export default function PlaybackControls({
|
||||
isPlaying,
|
||||
currentTime,
|
||||
duration,
|
||||
isFullscreen = false,
|
||||
onToggleFullscreen,
|
||||
onTogglePlayPause,
|
||||
onSeek,
|
||||
}: PlaybackControlsProps) {
|
||||
@@ -87,6 +91,21 @@ export default function PlaybackControls({
|
||||
<span className="text-[9px] font-medium text-slate-500 tabular-nums w-[30px]">
|
||||
{formatTime(duration)}
|
||||
</span>
|
||||
|
||||
{onToggleFullscreen && (
|
||||
<Button
|
||||
onClick={onToggleFullscreen}
|
||||
size="icon"
|
||||
className="w-7 h-7 rounded-full transition-all duration-200 border border-transparent hover:bg-white/10 text-white hover:border-white/10 shrink-0 shadow-none ml-0.5"
|
||||
aria-label={isFullscreen ? t("playback.exitFullscreen") : t("playback.fullscreen")}
|
||||
>
|
||||
{isFullscreen ? (
|
||||
<Minimize className="w-3.5 h-3.5" />
|
||||
) : (
|
||||
<Maximize className="w-3.5 h-3.5" />
|
||||
)}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -119,8 +119,11 @@ export default function VideoEditor() {
|
||||
fileName: string;
|
||||
format: string;
|
||||
} | null>(null);
|
||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||
|
||||
const playerContainerRef = useRef<HTMLDivElement>(null);
|
||||
const videoPlaybackRef = useRef<VideoPlaybackRef>(null);
|
||||
|
||||
const nextZoomIdRef = useRef(1);
|
||||
const nextTrimIdRef = useRef(1);
|
||||
const nextSpeedIdRef = useRef(1);
|
||||
@@ -539,6 +542,21 @@ export default function VideoEditor() {
|
||||
}
|
||||
}
|
||||
|
||||
const toggleFullscreen = useCallback(() => {
|
||||
setIsFullscreen((prev) => !prev);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isFullscreen) return;
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.key === "Escape") {
|
||||
setIsFullscreen(false);
|
||||
}
|
||||
};
|
||||
window.addEventListener("keydown", handleKeyDown);
|
||||
return () => window.removeEventListener("keydown", handleKeyDown);
|
||||
}, [isFullscreen]);
|
||||
|
||||
function handleSeek(time: number) {
|
||||
const video = videoPlaybackRef.current?.video;
|
||||
if (!video) return;
|
||||
@@ -1425,7 +1443,14 @@ export default function VideoEditor() {
|
||||
<PanelGroup direction="vertical" className="gap-3">
|
||||
{/* Top section: video preview and controls */}
|
||||
<Panel defaultSize={70} maxSize={70} minSize={40}>
|
||||
<div className="w-full h-full flex flex-col items-center justify-center bg-black/40 rounded-2xl border border-white/5 shadow-2xl overflow-hidden">
|
||||
<div
|
||||
ref={playerContainerRef}
|
||||
className={
|
||||
isFullscreen
|
||||
? "fixed inset-0 z-[99999] w-full h-full flex flex-col items-center justify-center bg-[#09090b]"
|
||||
: "w-full h-full flex flex-col items-center justify-center bg-black/40 rounded-2xl border border-white/5 shadow-2xl overflow-hidden relative"
|
||||
}
|
||||
>
|
||||
{/* Video preview */}
|
||||
<div className="w-full flex justify-center items-center flex-auto mt-1.5">
|
||||
<div
|
||||
@@ -1487,6 +1512,8 @@ export default function VideoEditor() {
|
||||
isPlaying={isPlaying}
|
||||
currentTime={currentTime}
|
||||
duration={duration}
|
||||
isFullscreen={isFullscreen}
|
||||
onToggleFullscreen={toggleFullscreen}
|
||||
onTogglePlayPause={togglePlayPause}
|
||||
onSeek={handleSeek}
|
||||
/>
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
},
|
||||
"playback": {
|
||||
"play": "Play",
|
||||
"pause": "Pause"
|
||||
"pause": "Pause",
|
||||
"fullscreen": "Fullscreen",
|
||||
"exitFullscreen": "Exit Fullscreen"
|
||||
},
|
||||
"locale": {
|
||||
"name": "English",
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
},
|
||||
"playback": {
|
||||
"play": "Reproducir",
|
||||
"pause": "Pausar"
|
||||
"pause": "Pausar",
|
||||
"fullscreen": "Pantalla completa",
|
||||
"exitFullscreen": "Salir de pantalla completa"
|
||||
},
|
||||
"locale": {
|
||||
"name": "Español",
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
},
|
||||
"playback": {
|
||||
"play": "播放",
|
||||
"pause": "暂停"
|
||||
"pause": "暂停",
|
||||
"fullscreen": "全屏",
|
||||
"exitFullscreen": "退出全屏"
|
||||
},
|
||||
"locale": {
|
||||
"name": "中文",
|
||||
|
||||
Reference in New Issue
Block a user