mirror of
https://gh-proxy.org/https://github.com/tiajinsha/JKVideo
synced 2026-07-07 23:18:38 +08:00
feat: add orientation lock and dual-instance fullscreen to VideoPlayer
This commit is contained in:
@@ -1,10 +1,8 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState, useRef, useEffect } from 'react';
|
||||||
import { View, StyleSheet, Dimensions, Text, Platform, Modal, StatusBar } from 'react-native';
|
import { View, StyleSheet, Text, Platform, Modal, StatusBar, useWindowDimensions } from 'react-native';
|
||||||
|
import * as ScreenOrientation from 'expo-screen-orientation';
|
||||||
import { NativeVideoPlayer } from './NativeVideoPlayer';
|
import { NativeVideoPlayer } from './NativeVideoPlayer';
|
||||||
import type { PlayUrlResponse } from '../services/types';
|
import type { PlayUrlResponse, DanmakuItem } from '../services/types';
|
||||||
|
|
||||||
const { width } = Dimensions.get('window');
|
|
||||||
const VIDEO_HEIGHT = width * 0.5625;
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
playData: PlayUrlResponse | null;
|
playData: PlayUrlResponse | null;
|
||||||
@@ -14,14 +12,38 @@ interface Props {
|
|||||||
onMiniPlayer?: () => void;
|
onMiniPlayer?: () => void;
|
||||||
bvid?: string;
|
bvid?: string;
|
||||||
cid?: number;
|
cid?: number;
|
||||||
|
danmakus?: DanmakuItem[];
|
||||||
|
onTimeUpdate?: (t: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function VideoPlayer({ playData, qualities, currentQn, onQualityChange, onMiniPlayer, bvid, cid }: Props) {
|
export function VideoPlayer({ playData, qualities, currentQn, onQualityChange, onMiniPlayer, bvid, cid, danmakus, onTimeUpdate }: Props) {
|
||||||
const [fullscreen, setFullscreen] = useState(false);
|
const [fullscreen, setFullscreen] = useState(false);
|
||||||
|
const { width } = useWindowDimensions();
|
||||||
|
const VIDEO_HEIGHT = width * 0.5625;
|
||||||
|
const lastTimeRef = useRef(0);
|
||||||
|
|
||||||
|
const handleEnterFullscreen = async () => {
|
||||||
|
setFullscreen(true);
|
||||||
|
if (Platform.OS !== 'web')
|
||||||
|
await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleExitFullscreen = async () => {
|
||||||
|
setFullscreen(false);
|
||||||
|
if (Platform.OS !== 'web')
|
||||||
|
await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT_UP);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
if (Platform.OS !== 'web')
|
||||||
|
ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT_UP);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
if (!playData) {
|
if (!playData) {
|
||||||
return (
|
return (
|
||||||
<View style={[styles.container, styles.placeholder]}>
|
<View style={[{ width, height: VIDEO_HEIGHT, backgroundColor: '#000' }, styles.placeholder]}>
|
||||||
<Text style={styles.placeholderText}>视频加载中...</Text>
|
<Text style={styles.placeholderText}>视频加载中...</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
@@ -30,7 +52,7 @@ export function VideoPlayer({ playData, qualities, currentQn, onQualityChange, o
|
|||||||
if (Platform.OS === 'web') {
|
if (Platform.OS === 'web') {
|
||||||
const url = playData.durl?.[0]?.url ?? '';
|
const url = playData.durl?.[0]?.url ?? '';
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={{ width, height: VIDEO_HEIGHT, backgroundColor: '#000' }}>
|
||||||
<video
|
<video
|
||||||
src={url}
|
src={url}
|
||||||
style={{ width: '100%', height: '100%', backgroundColor: '#000' } as any}
|
style={{ width: '100%', height: '100%', backgroundColor: '#000' } as any}
|
||||||
@@ -43,29 +65,37 @@ export function VideoPlayer({ playData, qualities, currentQn, onQualityChange, o
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<NativeVideoPlayer
|
{/* Portrait player: unmount when fullscreen */}
|
||||||
playData={playData}
|
{!fullscreen && (
|
||||||
qualities={qualities}
|
<NativeVideoPlayer
|
||||||
currentQn={currentQn}
|
playData={playData}
|
||||||
onQualityChange={onQualityChange}
|
qualities={qualities}
|
||||||
onFullscreen={() => setFullscreen(true)}
|
currentQn={currentQn}
|
||||||
onMiniPlayer={onMiniPlayer}
|
onQualityChange={onQualityChange}
|
||||||
bvid={bvid}
|
onFullscreen={handleEnterFullscreen}
|
||||||
cid={cid}
|
onMiniPlayer={onMiniPlayer}
|
||||||
/>
|
bvid={bvid}
|
||||||
|
cid={cid}
|
||||||
|
isFullscreen={false}
|
||||||
|
onTimeUpdate={(t) => { lastTimeRef.current = t; onTimeUpdate?.(t); }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<Modal visible={fullscreen} animationType="fade" statusBarTranslucent>
|
<Modal visible={fullscreen} animationType="fade" statusBarTranslucent>
|
||||||
<StatusBar hidden />
|
<StatusBar hidden />
|
||||||
<View style={styles.fullscreenContainer}>
|
<View style={{ flex: 1, backgroundColor: '#000' }}>
|
||||||
<NativeVideoPlayer
|
<NativeVideoPlayer
|
||||||
playData={playData}
|
playData={playData}
|
||||||
qualities={qualities}
|
qualities={qualities}
|
||||||
currentQn={currentQn}
|
currentQn={currentQn}
|
||||||
onQualityChange={onQualityChange}
|
onQualityChange={onQualityChange}
|
||||||
onFullscreen={() => setFullscreen(false)}
|
onFullscreen={handleExitFullscreen}
|
||||||
bvid={bvid}
|
bvid={bvid}
|
||||||
cid={cid}
|
cid={cid}
|
||||||
style={{ width: '100%', height: '100%' } as any}
|
danmakus={danmakus}
|
||||||
|
isFullscreen={true}
|
||||||
|
initialTime={lastTimeRef.current}
|
||||||
|
onTimeUpdate={(t) => { lastTimeRef.current = t; onTimeUpdate?.(t); }}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</Modal>
|
</Modal>
|
||||||
@@ -74,8 +104,6 @@ export function VideoPlayer({ playData, qualities, currentQn, onQualityChange, o
|
|||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: { width, height: VIDEO_HEIGHT, backgroundColor: '#000' },
|
|
||||||
placeholder: { justifyContent: 'center', alignItems: 'center' },
|
placeholder: { justifyContent: 'center', alignItems: 'center' },
|
||||||
placeholderText: { color: '#fff', fontSize: 14 },
|
placeholderText: { color: '#fff', fontSize: 14 },
|
||||||
fullscreenContainer: { flex: 1, backgroundColor: '#000' },
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user