x-movie/src/components/VideoPlayer.jsx
2025-08-14 00:28:29 +08:00

153 lines
4.1 KiB
JavaScript

import React, { useContext, useState, useRef, useEffect } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import Container from '@mui/material/Container';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
import IconButton from '@mui/material/IconButton';
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import ConfigContext from '../Config';
import ReactPlayer from 'react-player';
const VideoPlayer = () => {
const config = useContext(ConfigContext);
const { filename } = useParams();
const navigate = useNavigate();
const playerRef = useRef(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [isMobile, setIsMobile] = useState(false);
// 检测移动设备
useEffect(() => {
const checkMobile = () => {
setIsMobile(window.innerWidth <= 768);
};
checkMobile();
window.addEventListener('resize', checkMobile);
return () => window.removeEventListener('resize', checkMobile);
}, []);
// 解码文件名
const decodedFilename = decodeURIComponent(filename);
const videoUrl = `${window.location.origin}/res/${filename}`;
const handleReady = () => {
setLoading(false);
};
const handleError = (error) => {
console.error('Video error:', error);
setError('视频加载失败');
setLoading(false);
};
// 错误页面
if (error) {
return (
<Container sx={{ mt: 2 }}>
<Box sx={{ display: 'flex', alignItems: 'center', mb: 2 }}>
<IconButton onClick={() => navigate(-1)} sx={{ mr: 1 }}>
<ArrowBackIcon />
</IconButton>
<Typography variant="h6" noWrap>
{decodedFilename}
</Typography>
</Box>
<Box sx={{ textAlign: 'center', p: 4 }}>
<Typography color="error">{error}</Typography>
</Box>
</Container>
);
}
return (
<Box sx={{
bgcolor: 'black',
minHeight: '100vh',
display: 'flex',
flexDirection: 'column'
}}>
{/* 标题栏 */}
<Box sx={{
p: isMobile ? 1 : 2,
display: 'flex',
alignItems: 'center',
bgcolor: 'rgba(0,0,0,0.8)',
color: 'white',
position: 'sticky',
top: 0,
zIndex: 1
}}>
<IconButton
onClick={() => navigate(-1)}
sx={{ color: 'white', mr: 1 }}
size={isMobile ? 'small' : 'medium'}
>
<ArrowBackIcon />
</IconButton>
<Typography
variant={isMobile ? 'subtitle1' : 'h6'}
noWrap
sx={{ flexGrow: 1 }}
>
{decodedFilename}
</Typography>
</Box>
{/* 视频播放器容器 */}
<Box sx={{
flexGrow: 1,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
position: 'relative'
}}>
{loading && (
<Typography sx={{ color: 'white', position: 'absolute' }}>
加载中...
</Typography>
)}
<ReactPlayer
ref={playerRef}
url={videoUrl}
controls
width="100%"
height={isMobile ? "50vh" : "70vh"}
onReady={handleReady}
onError={handleError}
config={{
file: {
attributes: {
playsInline: true, // 重要:移动端内联播放
preload: 'metadata',
disablePictureInPicture: true // 禁用画中画模式
}
}
}}
style={{
maxWidth: '100%',
maxHeight: '100%',
margin: 'auto' // 居中显示
}}
/>
</Box>
{/* 底部信息(移动端显示简化提示) */}
<Box sx={{
p: isMobile ? 1 : 2,
color: 'rgba(255,255,255,0.7)',
textAlign: 'center',
fontSize: '0.8rem'
}}>
<Typography variant="caption">
{isMobile ? '双击可全屏' : '提示:双击视频可全屏播放'}
</Typography>
</Box>
</Box>
);
};
export default VideoPlayer;