160 lines
3.8 KiB
JavaScript
160 lines
3.8 KiB
JavaScript
import React, { useState, useRef } from 'react';
|
|
import {
|
|
IconButton,
|
|
Slider,
|
|
Box,
|
|
} from '@material-ui/core';
|
|
import { makeStyles } from '@material-ui/core/styles';
|
|
|
|
import PlayArrowIcon from '@material-ui/icons/PlayArrow';
|
|
import PauseIcon from '@material-ui/icons/Pause';
|
|
|
|
const useStyles = makeStyles((theme) => ({
|
|
root: {
|
|
position: 'relative',
|
|
width: '100%',
|
|
height: '100%',
|
|
backgroundColor: '#000',
|
|
},
|
|
videoContainer: {
|
|
width: '100%',
|
|
height: '100%',
|
|
'& video': {
|
|
width: '100%',
|
|
height: '100%',
|
|
objectFit: 'cover',
|
|
},
|
|
},
|
|
controls: {
|
|
position: 'absolute',
|
|
bottom: 0,
|
|
left: 0,
|
|
right: 0,
|
|
padding: theme.spacing(1, 2),
|
|
background: 'linear-gradient(to top, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0) 100%)',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: theme.spacing(2),
|
|
},
|
|
playButton: {
|
|
color: '#fff',
|
|
'&:hover': {
|
|
backgroundColor: 'rgba(255,255,255,0.1)',
|
|
},
|
|
},
|
|
slider: {
|
|
color: '#1976d2',
|
|
flex: 1,
|
|
'& .MuiSlider-rail': {
|
|
backgroundColor: 'rgba(255,255,255,0.3)',
|
|
},
|
|
'& .MuiSlider-track': {
|
|
backgroundColor: '#1976d2',
|
|
},
|
|
'& .MuiSlider-thumb': {
|
|
width: 12,
|
|
height: 12,
|
|
backgroundColor: '#fff',
|
|
'&:hover, &.Mui-focusVisible': {
|
|
boxShadow: '0 0 0 8px rgba(25,118,210,0.16)',
|
|
},
|
|
},
|
|
},
|
|
timeDisplay: {
|
|
color: '#fff',
|
|
fontSize: '0.875rem',
|
|
minWidth: 100,
|
|
textAlign: 'right',
|
|
},
|
|
dateDisplay: {
|
|
position: 'absolute',
|
|
top: theme.spacing(2),
|
|
left: theme.spacing(2),
|
|
color: '#fff',
|
|
fontSize: '1.25rem',
|
|
fontWeight: 500,
|
|
textShadow: '1px 1px 2px rgba(0,0,0,0.5)',
|
|
},
|
|
}));
|
|
|
|
const VideoPlayer = ({ videoUrl, date }) => {
|
|
const classes = useStyles();
|
|
const [playing, setPlaying] = useState(false);
|
|
const [progress, setProgress] = useState(0);
|
|
const [currentTime, setCurrentTime] = useState(0);
|
|
const [duration, setDuration] = useState(0);
|
|
const videoRef = useRef(null);
|
|
|
|
const handlePlayPause = () => {
|
|
if (playing) {
|
|
videoRef.current.pause();
|
|
} else {
|
|
videoRef.current.play();
|
|
}
|
|
setPlaying(!playing);
|
|
};
|
|
|
|
const handleTimeUpdate = () => {
|
|
const video = videoRef.current;
|
|
if (video) {
|
|
const progress = (video.currentTime / video.duration) * 100;
|
|
setProgress(progress);
|
|
setCurrentTime(video.currentTime);
|
|
}
|
|
};
|
|
|
|
const handleLoadedMetadata = () => {
|
|
setDuration(videoRef.current.duration);
|
|
};
|
|
|
|
const handleSliderChange = (event, newValue) => {
|
|
const time = (newValue / 100) * duration;
|
|
videoRef.current.currentTime = time;
|
|
setProgress(newValue);
|
|
};
|
|
|
|
const formatTime = (time) => {
|
|
const minutes = Math.floor(time / 60);
|
|
const seconds = Math.floor(time % 60);
|
|
return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
|
};
|
|
|
|
return (
|
|
<div className={classes.root}>
|
|
<div className={classes.videoContainer}>
|
|
<video
|
|
ref={videoRef}
|
|
onTimeUpdate={handleTimeUpdate}
|
|
onLoadedMetadata={handleLoadedMetadata}
|
|
>
|
|
<source src={videoUrl} type="video/mp4" />
|
|
</video>
|
|
</div>
|
|
|
|
<div className={classes.dateDisplay}>
|
|
{date}
|
|
</div>
|
|
|
|
<div className={classes.controls}>
|
|
<IconButton
|
|
className={classes.playButton}
|
|
onClick={handlePlayPause}
|
|
>
|
|
{playing ? <PauseIcon /> : <PlayArrowIcon />}
|
|
</IconButton>
|
|
|
|
<Slider
|
|
className={classes.slider}
|
|
value={progress}
|
|
onChange={handleSliderChange}
|
|
/>
|
|
|
|
<Box className={classes.timeDisplay}>
|
|
{formatTime(currentTime)} / {formatTime(duration)}
|
|
</Box>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default VideoPlayer; |