mirror of
https://github.com/azaion/ui.git
synced 2026-06-21 19:31:10 +00:00
add css files for components
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user