add css files for components

This commit is contained in:
Armen Rohalov
2025-03-26 20:30:27 +02:00
parent e18157648c
commit 9e6596f1e0
15 changed files with 301 additions and 253 deletions
@@ -0,0 +1,40 @@
.player {
position: relative;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: #000;
overflow: hidden;
}
.video {
width: 100%;
height: auto;
max-height: 100%;
display: block;
object-fit: contain;
pointer-events: none;
}
.player-error {
position: absolute;
top: 10px;
left: 10px;
background: rgba(255, 0, 0, 0.7);
color: white;
padding: 5px;
border-radius: 3px;
font-size: 12px;
z-index: 10;
}
.player-item{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: auto;
}
+150
View File
@@ -0,0 +1,150 @@
import React, { useEffect, useRef, useState } from 'react';
import './VideoPlayer.css';
function VideoPlayer({ children, videoFile, currentTime, videoRef, isPlaying, onSizeChanged, onSetCurrentTime }) {
const containerRef = useRef(null);
const [playbackError, setPlaybackError] = useState(null);
const objectUrlRef = useRef(null);
// Flag to track if time update is coming from natural playback
const isPlaybackUpdateRef = useRef(false);
// Set up the video file when it changes
useEffect(() => {
if (!videoFile || !videoRef.current) return;
try {
// Clean up previous object URL
if (objectUrlRef.current) {
URL.revokeObjectURL(objectUrlRef.current);
}
// Create new object URL and set it directly
const objectUrl = URL.createObjectURL(videoFile);
objectUrlRef.current = objectUrl;
// Reset video and set new source
videoRef.current.pause();
videoRef.current.src = objectUrl;
videoRef.current.load();
setPlaybackError(null);
return () => {
URL.revokeObjectURL(objectUrl);
objectUrlRef.current = null;
};
} catch (err) {
console.error("Error loading video:", err);
setPlaybackError(`Error loading video: ${err.message}`);
}
}, [videoFile]);
// Handle metadata loading and size changes
useEffect(() => {
if (!videoRef.current) return;
const handleMetadata = () => {
if (!videoRef.current) return;
const width = videoRef.current.videoWidth || 640;
const height = videoRef.current.videoHeight || 480;
if (onSizeChanged) {
onSizeChanged(width, height);
}
};
videoRef.current.addEventListener('loadedmetadata', handleMetadata);
return () => {
if (videoRef.current) {
videoRef.current.removeEventListener('loadedmetadata', handleMetadata);
}
};
}, [onSizeChanged]);
// Handle play/pause state
useEffect(() => {
if (!videoRef.current) return;
const attemptPlay = async () => {
try {
if (isPlaying) {
isPlaybackUpdateRef.current = true;
await videoRef.current.play();
setPlaybackError(null);
} else {
videoRef.current.pause();
}
} catch (err) {
console.error("Playback error:", err);
setPlaybackError(`Playback error: ${err.message}`);
}
};
attemptPlay();
}, [isPlaying]);
// Handle current time changes
useEffect(() => {
if (!videoRef.current) return;
// Only update the video's time if it's not coming from natural playback
if (!isPlaybackUpdateRef.current) {
try {
if (videoRef.current.readyState > 0) {
videoRef.current.currentTime = currentTime;
}
} catch (err) {
console.warn("Error setting time:", err);
}
} else {
// Reset the flag after receiving the update
isPlaybackUpdateRef.current = false;
}
}, [currentTime]);
// Set up time update events
useEffect(() => {
if (!videoRef.current) return;
const handleTimeUpdate = () => {
if (videoRef.current && onSetCurrentTime && isPlaying) {
isPlaybackUpdateRef.current = true;
onSetCurrentTime(videoRef.current.currentTime);
}
};
const handleSeeked = () => {
if (videoRef.current && onSetCurrentTime) {
onSetCurrentTime(videoRef.current.currentTime);
}
};
videoRef.current.addEventListener('timeupdate', handleTimeUpdate);
videoRef.current.addEventListener('seeked', handleSeeked);
return () => {
if (videoRef.current) {
videoRef.current.removeEventListener('timeupdate', handleTimeUpdate);
videoRef.current.removeEventListener('seeked', handleSeeked);
}
};
}, [onSetCurrentTime, isPlaying]);
return (
<div className='player' ref={containerRef} >
<video className='video' ref={videoRef} preload="auto" playsInline muted />
{playbackError && (
<div className='player-error' >
{playbackError}
</div>
)}
<div className='player-item'>
{children}
</div>
</div>
);
}
export default VideoPlayer;