react-native-expo-video-player 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,91 @@
1
+ import React from 'react';
2
+ import { View, StyleSheet, useWindowDimensions } from 'react-native';
3
+ import { VideoView } from 'expo-video';
4
+ import { VideoControls } from './VideoControls';
5
+ import type { ExpoVideoPlayerProps, VideoPlayerTheme } from './types';
6
+
7
+ const DEFAULT_THEME: VideoPlayerTheme = { primary: '#2979FF' };
8
+ const DEFAULT_SPEED_OPTIONS = [0.5, 0.75, 1, 1.25, 1.5, 2];
9
+
10
+ /**
11
+ * 开箱即用的视频播放器组件,基于 `expo-video` 构建。
12
+ *
13
+ * 提供自定义浮层控制栏:播放/暂停、进度条、倍速切换、
14
+ * 全屏切换、全屏手势(音量/亮度/快进快退)。
15
+ *
16
+ * 所有原生 `VideoView` 属性(如 `contentFit`、`allowsPictureInPicture`、
17
+ * `surfaceType`、`onFirstFrameRender`、`onPictureInPictureStart` 等)
18
+ * 均会透传给底层 `VideoView` 组件。
19
+ *
20
+ * 可使用本包的 `useFullscreen()` hook 管理全屏状态,
21
+ * 也可自行提供 `isFullscreen` / `onToggleFullscreen`。
22
+ */
23
+ export const ExpoVideoPlayer: React.FC<ExpoVideoPlayerProps> = ({
24
+ player,
25
+ theme,
26
+ isFullscreen = false,
27
+ onToggleFullscreen = () => {},
28
+ onBack = () => {},
29
+ speedOptions = DEFAULT_SPEED_OPTIONS,
30
+ speedLabel = '倍速',
31
+ autoHideTimeout = 3000,
32
+ enableGestures = true,
33
+ showSpeedPicker = true,
34
+ showFullscreenButton = true,
35
+ showQualityPicker = false,
36
+ qualityLabel = '画质',
37
+ qualityOptions = [],
38
+ onQualityChange = () => {},
39
+ thumbImage,
40
+ width: propWidth,
41
+ height: propHeight,
42
+ // --- 剩余属性全部透传给 VideoView ---
43
+ ...videoViewProps
44
+ }) => {
45
+ const { width: windowWidth, height: windowHeight } = useWindowDimensions();
46
+ const resolvedTheme = { ...DEFAULT_THEME, ...theme };
47
+
48
+ const videoWidth = isFullscreen ? windowWidth : (propWidth ?? windowWidth);
49
+ const videoHeight = isFullscreen ? windowHeight : (propHeight ?? videoWidth * 9 / 16);
50
+
51
+ return (
52
+ <View style={isFullscreen ? styles.fullscreenContainer : { width: videoWidth, height: videoHeight }}>
53
+ <VideoView
54
+ player={player}
55
+ style={styles.video}
56
+ nativeControls={false}
57
+ {...videoViewProps}
58
+ />
59
+ <VideoControls
60
+ player={player}
61
+ theme={resolvedTheme}
62
+ isFullscreen={isFullscreen}
63
+ onToggleFullscreen={onToggleFullscreen}
64
+ onBack={onBack}
65
+ speedOptions={speedOptions}
66
+ speedLabel={speedLabel}
67
+ autoHideTimeout={autoHideTimeout}
68
+ enableGestures={enableGestures}
69
+ showSpeedPicker={showSpeedPicker}
70
+ showFullscreenButton={showFullscreenButton}
71
+ showQualityPicker={showQualityPicker}
72
+ qualityLabel={qualityLabel}
73
+ qualityOptions={qualityOptions}
74
+ onQualityChange={onQualityChange}
75
+ thumbImage={thumbImage}
76
+ />
77
+ </View>
78
+ );
79
+ };
80
+
81
+ const styles = StyleSheet.create({
82
+ fullscreenContainer: {
83
+ ...StyleSheet.absoluteFillObject,
84
+ backgroundColor: '#000',
85
+ zIndex: 999,
86
+ },
87
+ video: {
88
+ width: '100%',
89
+ height: '100%',
90
+ },
91
+ });
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+ import { Text, StyleSheet, type TextStyle } from 'react-native';
3
+
4
+ /**
5
+ * 基于 Unicode 符号的轻量级图标组件,无需引入外部图标库。
6
+ * 如需替换图标,使用者可通过 render props 自行覆盖。
7
+ */
8
+
9
+ const ICONS: Record<string, string> = {
10
+ play: '▶',
11
+ pause: '❚❚',
12
+ 'arrow-left': '←',
13
+ fullscreen: '⛶',
14
+ 'fullscreen-exit': '⛶',
15
+ 'fast-forward': '⏩',
16
+ rewind: '⏪',
17
+ 'volume-off': '🔇',
18
+ 'volume-medium': '🔉',
19
+ 'volume-high': '🔊',
20
+ 'brightness-4': '☀',
21
+ 'brightness-6': '☀',
22
+ 'brightness-7': '☀',
23
+ };
24
+
25
+ interface IconProps {
26
+ name: string;
27
+ size?: number;
28
+ color?: string;
29
+ style?: TextStyle;
30
+ }
31
+
32
+ export const PlayerIcon: React.FC<IconProps> = ({ name, size = 22, color = '#fff', style }) => {
33
+ const icon = ICONS[name] || '?';
34
+ return (
35
+ <Text style={[styles.icon, { fontSize: size * 0.75, color, lineHeight: size }, style]}>
36
+ {icon}
37
+ </Text>
38
+ );
39
+ };
40
+
41
+ const styles = StyleSheet.create({
42
+ icon: {
43
+ textAlign: 'center',
44
+ },
45
+ });