/**
* VideoPlayerModal 视频播放弹窗组件
* 全屏模态播放视频,基于 expo-video
*/
import React, { useCallback } from 'react';
import {
Modal,
View,
StyleSheet,
Dimensions,
TouchableOpacity,
Text,
StatusBar,
} from 'react-native';
import { VideoView, useVideoPlayer } from 'expo-video';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { spacing, fontSizes, borderRadius } from '../../theme';
const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get('window');
export interface VideoPlayerModalProps {
/** 是否可见 */
visible: boolean;
/** 视频 URL */
url: string;
/** 关闭回调 */
onClose: () => void;
}
/**
* 视频播放器内容 - 独立组件,仅在弹窗可见时挂载,避免预加载
*/
const VideoPlayerContent: React.FC<{ url: string; onClose: () => void }> = ({ url, onClose }) => {
const insets = useSafeAreaInsets();
const player = useVideoPlayer(url, (p) => {
p.loop = false;
p.play();
});
const handleClose = useCallback(() => {
player.pause();
onClose();
}, [player, onClose]);
return (
{/* 顶部关闭按钮 */}
视频
{/* 视频播放区域 */}
);
};
/**
* 视频播放弹窗 - 仅在可见时渲染播放器,避免提前加载视频资源
*/
export const VideoPlayerModal: React.FC = ({
visible,
url,
onClose,
}) => {
return (
{visible && url ? (
) : (
)}
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#000',
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: spacing.md,
paddingBottom: spacing.md,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
position: 'absolute',
top: 0,
left: 0,
right: 0,
zIndex: 10,
},
closeButton: {
width: 40,
height: 40,
borderRadius: borderRadius.full,
backgroundColor: 'rgba(255, 255, 255, 0.2)',
justifyContent: 'center',
alignItems: 'center',
},
title: {
color: '#FFF',
fontSize: fontSizes.md,
fontWeight: '600',
},
placeholder: {
width: 40,
},
videoContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
video: {
width: SCREEN_WIDTH,
height: SCREEN_HEIGHT,
},
});
export default VideoPlayerModal;