expo-video 3.0.9 → 3.0.10
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.
- package/CHANGELOG.md +6 -0
- package/android/build.gradle +2 -2
- package/build/VideoView.web.d.ts.map +1 -1
- package/build/VideoView.web.js +43 -9
- package/build/VideoView.web.js.map +1 -1
- package/expo-module.config.json +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/{3.0.9/expo.modules.video-3.0.9.aar → 3.0.10/expo.modules.video-3.0.10.aar} +0 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.10/expo.modules.video-3.0.10.aar.md5 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.10/expo.modules.video-3.0.10.aar.sha1 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.10/expo.modules.video-3.0.10.aar.sha256 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.10/expo.modules.video-3.0.10.aar.sha512 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/{3.0.9/expo.modules.video-3.0.9.module → 3.0.10/expo.modules.video-3.0.10.module} +17 -17
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.10/expo.modules.video-3.0.10.module.md5 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.10/expo.modules.video-3.0.10.module.sha1 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.10/expo.modules.video-3.0.10.module.sha256 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.10/expo.modules.video-3.0.10.module.sha512 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/{3.0.9/expo.modules.video-3.0.9.pom → 3.0.10/expo.modules.video-3.0.10.pom} +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.10/expo.modules.video-3.0.10.pom.md5 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.10/expo.modules.video-3.0.10.pom.sha1 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.10/expo.modules.video-3.0.10.pom.sha256 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.10/expo.modules.video-3.0.10.pom.sha512 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml +4 -4
- package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.md5 +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.sha1 +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.sha256 +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.sha512 +1 -1
- package/package.json +2 -2
- package/src/VideoView.web.tsx +57 -9
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.9/expo.modules.video-3.0.9.aar.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.9/expo.modules.video-3.0.9.aar.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.9/expo.modules.video-3.0.9.aar.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.9/expo.modules.video-3.0.9.aar.sha512 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.9/expo.modules.video-3.0.9.module.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.9/expo.modules.video-3.0.9.module.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.9/expo.modules.video-3.0.9.module.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.9/expo.modules.video-3.0.9.module.sha512 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.9/expo.modules.video-3.0.9.pom.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.9/expo.modules.video-3.0.9.pom.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.9/expo.modules.video-3.0.9.pom.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.9/expo.modules.video-3.0.9.pom.sha512 +0 -1
- /package/local-maven-repo/host/exp/exponent/expo.modules.video/{3.0.9/expo.modules.video-3.0.9-sources.jar → 3.0.10/expo.modules.video-3.0.10-sources.jar} +0 -0
- /package/local-maven-repo/host/exp/exponent/expo.modules.video/{3.0.9/expo.modules.video-3.0.9-sources.jar.md5 → 3.0.10/expo.modules.video-3.0.10-sources.jar.md5} +0 -0
- /package/local-maven-repo/host/exp/exponent/expo.modules.video/{3.0.9/expo.modules.video-3.0.9-sources.jar.sha1 → 3.0.10/expo.modules.video-3.0.10-sources.jar.sha1} +0 -0
- /package/local-maven-repo/host/exp/exponent/expo.modules.video/{3.0.9/expo.modules.video-3.0.9-sources.jar.sha256 → 3.0.10/expo.modules.video-3.0.10-sources.jar.sha256} +0 -0
- /package/local-maven-repo/host/exp/exponent/expo.modules.video/{3.0.9/expo.modules.video-3.0.9-sources.jar.sha512 → 3.0.10/expo.modules.video-3.0.10-sources.jar.sha512} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,12 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 3.0.10 — 2025-09-04
|
|
14
|
+
|
|
15
|
+
### 🐛 Bug fixes
|
|
16
|
+
|
|
17
|
+
- [Web] Fix fullscreen enter/exit methods and listeners not working in Safari on iOS. ([#39320](https://github.com/expo/expo/pull/39320) by [@behenate](https://github.com/behenate))
|
|
18
|
+
|
|
13
19
|
## 3.0.9 — 2025-09-03
|
|
14
20
|
|
|
15
21
|
### 🛠 Breaking changes
|
package/android/build.gradle
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoView.web.d.ts","sourceRoot":"","sources":["../src/VideoView.web.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA6D,MAAM,OAAO,CAAC;AAGlF,OAAO,WAA6B,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"VideoView.web.d.ts","sourceRoot":"","sources":["../src/VideoView.web.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA6D,MAAM,OAAO,CAAC;AAGlF,OAAO,WAA6B,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AA6BxD,wBAAgB,2BAA2B,IAAI,OAAO,CAErD;AAED,eAAO,MAAM,SAAS;aAAiC,WAAW;kDA8OhE,CAAC;AAEH,eAAe,SAAS,CAAC"}
|
package/build/VideoView.web.js
CHANGED
|
@@ -24,7 +24,7 @@ export const VideoView = forwardRef((props, ref) => {
|
|
|
24
24
|
const videoRef = useRef(null);
|
|
25
25
|
const mediaNodeRef = useRef(null);
|
|
26
26
|
const hasToSetupAudioContext = useRef(false);
|
|
27
|
-
const
|
|
27
|
+
const fullscreenChangeListeners = useRef(null);
|
|
28
28
|
const isWaitingForFirstFrame = useRef(false);
|
|
29
29
|
/**
|
|
30
30
|
* Audio context is used to mute all but one video when multiple video views are playing from one player simultaneously.
|
|
@@ -45,10 +45,25 @@ export const VideoView = forwardRef((props, ref) => {
|
|
|
45
45
|
}, [props.useAudioNodePlayback]);
|
|
46
46
|
useImperativeHandle(ref, () => ({
|
|
47
47
|
enterFullscreen: async () => {
|
|
48
|
-
if (!props.allowsFullscreen) {
|
|
48
|
+
if (!props.allowsFullscreen || !videoRef.current) {
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
|
-
|
|
51
|
+
// Cast the video to any to avoid ts errors. Methods such as webkitRequestFullscreen,
|
|
52
|
+
// webkitEnterFullScreen, msRequestFullscreen are not typed even though they exist.
|
|
53
|
+
const video = videoRef.current;
|
|
54
|
+
if (video.requestFullscreen) {
|
|
55
|
+
await video.requestFullscreen();
|
|
56
|
+
}
|
|
57
|
+
else if (video.webkitRequestFullscreen) {
|
|
58
|
+
// @ts-ignore webkitRequestFullscreen can exist on Apple devices
|
|
59
|
+
await video.webkitRequestFullscreen();
|
|
60
|
+
}
|
|
61
|
+
else if (video.webkitEnterFullScreen) {
|
|
62
|
+
await video.webkitEnterFullScreen();
|
|
63
|
+
}
|
|
64
|
+
else if (video.msRequestFullscreen) {
|
|
65
|
+
await video.msRequestFullscreen();
|
|
66
|
+
}
|
|
52
67
|
},
|
|
53
68
|
exitFullscreen: async () => {
|
|
54
69
|
await document.exitFullscreen();
|
|
@@ -149,14 +164,33 @@ export const VideoView = forwardRef((props, ref) => {
|
|
|
149
164
|
}
|
|
150
165
|
}
|
|
151
166
|
function setupFullscreenListener() {
|
|
152
|
-
|
|
153
|
-
videoRef.current
|
|
167
|
+
cleanupFullscreenListener();
|
|
168
|
+
const video = videoRef.current;
|
|
169
|
+
if (!video)
|
|
170
|
+
return;
|
|
171
|
+
const fullscreenListeners = {
|
|
172
|
+
default: fullscreenListener,
|
|
173
|
+
safariEnter: () => props.onFullscreenEnter?.(),
|
|
174
|
+
safariExit: () => props.onFullscreenExit?.(),
|
|
175
|
+
msListener: fullscreenListener,
|
|
176
|
+
};
|
|
177
|
+
fullscreenChangeListeners.current = fullscreenListeners;
|
|
178
|
+
// Standard Fullscreen API
|
|
179
|
+
video.addEventListener('fullscreenchange', fullscreenListeners.default);
|
|
180
|
+
// Safari (webkit)
|
|
181
|
+
video.addEventListener('webkitbeginfullscreen', fullscreenListeners.safariEnter);
|
|
182
|
+
video.addEventListener('webkitendfullscreen', fullscreenListeners.safariExit);
|
|
183
|
+
// IE11 (ms)
|
|
184
|
+
document.addEventListener('MSFullscreenChange', fullscreenListeners.msListener);
|
|
154
185
|
}
|
|
155
186
|
function cleanupFullscreenListener() {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
187
|
+
const video = videoRef.current;
|
|
188
|
+
if (!video || !fullscreenChangeListeners.current)
|
|
189
|
+
return;
|
|
190
|
+
video.removeEventListener('fullscreenchange', fullscreenChangeListeners.current.default);
|
|
191
|
+
video.removeEventListener('webkitbeginfullscreen', fullscreenChangeListeners.current?.safariEnter);
|
|
192
|
+
video.removeEventListener('webkitendfullscreen', fullscreenChangeListeners.current.safariExit);
|
|
193
|
+
document.removeEventListener('MSFullscreenChange', fullscreenChangeListeners.current.msListener);
|
|
160
194
|
}
|
|
161
195
|
useEffect(() => {
|
|
162
196
|
if (videoRef.current) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoView.web.js","sourceRoot":"","sources":["../src/VideoView.web.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useEffect, useRef, forwardRef, useImperativeHandle } from 'react';\nimport { StyleSheet } from 'react-native';\n\nimport VideoPlayer, { getSourceUri } from './VideoPlayer.web';\nimport type { VideoViewProps } from './VideoView.types';\n\nfunction createAudioContext(): AudioContext | null {\n return typeof window !== 'undefined' ? new window.AudioContext() : null;\n}\n\nfunction createZeroGainNode(audioContext: AudioContext | null): GainNode | null {\n const zeroGainNode = audioContext?.createGain() ?? null;\n\n if (audioContext && zeroGainNode) {\n zeroGainNode.gain.value = 0;\n zeroGainNode.connect(audioContext.destination);\n }\n return zeroGainNode;\n}\n\nfunction mapStyles(style: VideoViewProps['style']): React.CSSProperties {\n const flattenedStyles = StyleSheet.flatten(style);\n // Looking through react-native-web source code they also just pass styles directly without further conversions, so it's just a cast.\n return flattenedStyles as React.CSSProperties;\n}\n\nexport function isPictureInPictureSupported(): boolean {\n return typeof document === 'object' && typeof document.exitPictureInPicture === 'function';\n}\n\nexport const VideoView = forwardRef((props: { player?: VideoPlayer } & VideoViewProps, ref) => {\n const videoRef = useRef<null | HTMLVideoElement>(null);\n const mediaNodeRef = useRef<null | MediaElementAudioSourceNode>(null);\n const hasToSetupAudioContext = useRef(false);\n const fullscreenChangeListener = useRef<null | (() => void)>(null);\n const isWaitingForFirstFrame = useRef(false);\n\n /**\n * Audio context is used to mute all but one video when multiple video views are playing from one player simultaneously.\n * Using audio context nodes allows muting videos without displaying the mute icon in the video player.\n * We have to keep the context that called createMediaElementSource(videoRef), as the method can't be called\n * for the second time with another context and there is no way to unbind the video and audio context afterward.\n */\n const audioContextRef = useRef<null | AudioContext>(null);\n const zeroGainNodeRef = useRef<null | GainNode>(null);\n\n useEffect(() => {\n if (props.useAudioNodePlayback) {\n maybeSetupAudioContext();\n attachAudioNodes();\n } else {\n detachAudioNodes();\n }\n }, [props.useAudioNodePlayback]);\n\n useImperativeHandle(ref, () => ({\n enterFullscreen: async () => {\n if (!props.allowsFullscreen) {\n return;\n }\n await videoRef.current?.requestFullscreen();\n },\n exitFullscreen: async () => {\n await document.exitFullscreen();\n },\n startPictureInPicture: async () => {\n await videoRef.current?.requestPictureInPicture();\n },\n stopPictureInPicture: async () => {\n try {\n await document.exitPictureInPicture();\n } catch (e) {\n if (e instanceof DOMException && e.name === 'InvalidStateError') {\n console.warn('The VideoView is not in Picture-in-Picture mode.');\n } else {\n throw e;\n }\n }\n },\n }));\n\n useEffect(() => {\n const onEnter = () => {\n props.onPictureInPictureStart?.();\n };\n const onLeave = () => {\n props.onPictureInPictureStop?.();\n };\n const onLoadStart = () => {\n isWaitingForFirstFrame.current = true;\n };\n const onCanPlay = () => {\n if (isWaitingForFirstFrame.current) {\n props.onFirstFrameRender?.();\n }\n isWaitingForFirstFrame.current = false;\n };\n videoRef.current?.addEventListener('enterpictureinpicture', onEnter);\n videoRef.current?.addEventListener('leavepictureinpicture', onLeave);\n videoRef.current?.addEventListener('loadstart', onLoadStart);\n videoRef.current?.addEventListener('loadeddata', onCanPlay);\n\n return () => {\n videoRef.current?.removeEventListener('enterpictureinpicture', onEnter);\n videoRef.current?.removeEventListener('leavepictureinpicture', onLeave);\n videoRef.current?.removeEventListener('loadstart', onLoadStart);\n videoRef.current?.removeEventListener('loadeddata', onCanPlay);\n };\n }, [videoRef, props.onPictureInPictureStop, props.onPictureInPictureStart]);\n\n // Adds the video view as a candidate for being the audio source for the player (when multiple views play from one\n // player only one will emit audio).\n function attachAudioNodes() {\n if (!props.useAudioNodePlayback) {\n return;\n }\n const audioContext = audioContextRef.current;\n const zeroGainNode = zeroGainNodeRef.current;\n const mediaNode = mediaNodeRef.current;\n\n if (audioContext && zeroGainNode && mediaNode) {\n props.player.mountAudioNode(audioContext, zeroGainNode, mediaNode);\n } else {\n console.warn(\n \"Couldn't mount audio node, this might affect the audio playback when using multiple video views with the same player.\"\n );\n }\n }\n\n function detachAudioNodes() {\n if (!props.useAudioNodePlayback) {\n return;\n }\n const audioContext = audioContextRef.current;\n const mediaNode = mediaNodeRef.current;\n if (audioContext && mediaNode && videoRef.current) {\n props.player.unmountAudioNode(videoRef.current, audioContext, mediaNode);\n }\n }\n\n function maybeSetupAudioContext() {\n if (\n !hasToSetupAudioContext.current ||\n !navigator.userActivation.hasBeenActive ||\n !videoRef.current ||\n !props.useAudioNodePlayback\n ) {\n return;\n }\n const audioContext = createAudioContext();\n\n detachAudioNodes();\n audioContextRef.current = audioContext;\n zeroGainNodeRef.current = createZeroGainNode(audioContextRef.current);\n mediaNodeRef.current = audioContext\n ? audioContext.createMediaElementSource(videoRef.current)\n : null;\n attachAudioNodes();\n hasToSetupAudioContext.current = false;\n }\n\n function fullscreenListener() {\n if (document.fullscreenElement === videoRef.current) {\n props.onFullscreenEnter?.();\n } else {\n props.onFullscreenExit?.();\n }\n }\n\n function setupFullscreenListener() {\n fullscreenChangeListener.current = fullscreenListener;\n videoRef.current?.addEventListener('fullscreenchange', fullscreenChangeListener.current);\n }\n\n function cleanupFullscreenListener() {\n if (fullscreenChangeListener.current) {\n videoRef.current?.removeEventListener('fullscreenchange', fullscreenChangeListener.current);\n fullscreenChangeListener.current = null;\n }\n }\n\n useEffect(() => {\n if (videoRef.current) {\n props.player?.mountVideoView(videoRef.current);\n }\n setupFullscreenListener();\n attachAudioNodes();\n\n return () => {\n if (videoRef.current) {\n props.player?.unmountVideoView(videoRef.current);\n }\n cleanupFullscreenListener();\n detachAudioNodes();\n };\n }, [props.player]);\n\n return (\n <video\n controls={props.nativeControls ?? true}\n controlsList={props.allowsFullscreen ? undefined : 'nofullscreen'}\n crossOrigin={props.crossOrigin}\n style={{\n ...mapStyles(props.style),\n objectFit: props.contentFit,\n }}\n onPlay={() => {\n maybeSetupAudioContext();\n }}\n // The player can autoplay when muted, unmuting by a user should create the audio context\n onVolumeChange={() => {\n maybeSetupAudioContext();\n }}\n ref={(newRef) => {\n // This is called with a null value before `player.unmountVideoView` is called,\n // we can't assign null to videoRef if we want to unmount it from the player.\n if (newRef && !newRef.isEqualNode(videoRef.current)) {\n videoRef.current = newRef;\n hasToSetupAudioContext.current = props.useAudioNodePlayback ?? false;\n maybeSetupAudioContext();\n }\n }}\n disablePictureInPicture={!props.allowsPictureInPicture}\n playsInline={props.playsInline}\n src={getSourceUri(props.player?.src) ?? ''}\n />\n );\n});\n\nexport default VideoView;\n"]}
|
|
1
|
+
{"version":3,"file":"VideoView.web.js","sourceRoot":"","sources":["../src/VideoView.web.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAClF,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAoB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAU9D,SAAS,kBAAkB;IACzB,OAAO,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1E,CAAC;AAED,SAAS,kBAAkB,CAAC,YAAiC;IAC3D,MAAM,YAAY,GAAG,YAAY,EAAE,UAAU,EAAE,IAAI,IAAI,CAAC;IAExD,IAAI,YAAY,IAAI,YAAY,EAAE,CAAC;QACjC,YAAY,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QAC5B,YAAY,CAAC,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,SAAS,SAAS,CAAC,KAA8B;IAC/C,MAAM,eAAe,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAClD,qIAAqI;IACrI,OAAO,eAAsC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,2BAA2B;IACzC,OAAO,OAAO,QAAQ,KAAK,QAAQ,IAAI,OAAO,QAAQ,CAAC,oBAAoB,KAAK,UAAU,CAAC;AAC7F,CAAC;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,KAAgD,EAAE,GAAG,EAAE,EAAE;IAC5F,MAAM,QAAQ,GAAG,MAAM,CAA0B,IAAI,CAAC,CAAC;IACvD,MAAM,YAAY,GAAG,MAAM,CAAqC,IAAI,CAAC,CAAC;IACtE,MAAM,sBAAsB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,yBAAyB,GAAG,MAAM,CAAmC,IAAI,CAAC,CAAC;IACjF,MAAM,sBAAsB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAE7C;;;;;OAKG;IACH,MAAM,eAAe,GAAG,MAAM,CAAsB,IAAI,CAAC,CAAC;IAC1D,MAAM,eAAe,GAAG,MAAM,CAAkB,IAAI,CAAC,CAAC;IAEtD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,KAAK,CAAC,oBAAoB,EAAE,CAAC;YAC/B,sBAAsB,EAAE,CAAC;YACzB,gBAAgB,EAAE,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,gBAAgB,EAAE,CAAC;QACrB,CAAC;IACH,CAAC,EAAE,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAEjC,mBAAmB,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;QAC9B,eAAe,EAAE,KAAK,IAAI,EAAE;YAC1B,IAAI,CAAC,KAAK,CAAC,gBAAgB,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACjD,OAAO;YACT,CAAC;YACD,qFAAqF;YACrF,mFAAmF;YACnF,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAc,CAAC;YAEtC,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;gBAC5B,MAAM,KAAK,CAAC,iBAAiB,EAAE,CAAC;YAClC,CAAC;iBAAM,IAAI,KAAK,CAAC,uBAAuB,EAAE,CAAC;gBACzC,gEAAgE;gBAChE,MAAM,KAAK,CAAC,uBAAuB,EAAE,CAAC;YACxC,CAAC;iBAAM,IAAI,KAAK,CAAC,qBAAqB,EAAE,CAAC;gBACvC,MAAM,KAAK,CAAC,qBAAqB,EAAE,CAAC;YACtC,CAAC;iBAAM,IAAI,KAAK,CAAC,mBAAmB,EAAE,CAAC;gBACrC,MAAM,KAAK,CAAC,mBAAmB,EAAE,CAAC;YACpC,CAAC;QACH,CAAC;QACD,cAAc,EAAE,KAAK,IAAI,EAAE;YACzB,MAAM,QAAQ,CAAC,cAAc,EAAE,CAAC;QAClC,CAAC;QACD,qBAAqB,EAAE,KAAK,IAAI,EAAE;YAChC,MAAM,QAAQ,CAAC,OAAO,EAAE,uBAAuB,EAAE,CAAC;QACpD,CAAC;QACD,oBAAoB,EAAE,KAAK,IAAI,EAAE;YAC/B,IAAI,CAAC;gBACH,MAAM,QAAQ,CAAC,oBAAoB,EAAE,CAAC;YACxC,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,YAAY,YAAY,IAAI,CAAC,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;oBAChE,OAAO,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;gBACnE,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,CAAC;gBACV,CAAC;YACH,CAAC;QACH,CAAC;KACF,CAAC,CAAC,CAAC;IAEJ,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,KAAK,CAAC,uBAAuB,EAAE,EAAE,CAAC;QACpC,CAAC,CAAC;QACF,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,KAAK,CAAC,sBAAsB,EAAE,EAAE,CAAC;QACnC,CAAC,CAAC;QACF,MAAM,WAAW,GAAG,GAAG,EAAE;YACvB,sBAAsB,CAAC,OAAO,GAAG,IAAI,CAAC;QACxC,CAAC,CAAC;QACF,MAAM,SAAS,GAAG,GAAG,EAAE;YACrB,IAAI,sBAAsB,CAAC,OAAO,EAAE,CAAC;gBACnC,KAAK,CAAC,kBAAkB,EAAE,EAAE,CAAC;YAC/B,CAAC;YACD,sBAAsB,CAAC,OAAO,GAAG,KAAK,CAAC;QACzC,CAAC,CAAC;QACF,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC,uBAAuB,EAAE,OAAO,CAAC,CAAC;QACrE,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC,uBAAuB,EAAE,OAAO,CAAC,CAAC;QACrE,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QAC7D,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;QAE5D,OAAO,GAAG,EAAE;YACV,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC,uBAAuB,EAAE,OAAO,CAAC,CAAC;YACxE,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC,uBAAuB,EAAE,OAAO,CAAC,CAAC;YACxE,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;YAChE,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;QACjE,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC;IAE5E,kHAAkH;IAClH,oCAAoC;IACpC,SAAS,gBAAgB;QACvB,IAAI,CAAC,KAAK,CAAC,oBAAoB,EAAE,CAAC;YAChC,OAAO;QACT,CAAC;QACD,MAAM,YAAY,GAAG,eAAe,CAAC,OAAO,CAAC;QAC7C,MAAM,YAAY,GAAG,eAAe,CAAC,OAAO,CAAC;QAC7C,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC;QAEvC,IAAI,YAAY,IAAI,YAAY,IAAI,SAAS,EAAE,CAAC;YAC9C,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,YAAY,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;QACrE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CACV,uHAAuH,CACxH,CAAC;QACJ,CAAC;IACH,CAAC;IAED,SAAS,gBAAgB;QACvB,IAAI,CAAC,KAAK,CAAC,oBAAoB,EAAE,CAAC;YAChC,OAAO;QACT,CAAC;QACD,MAAM,YAAY,GAAG,eAAe,CAAC,OAAO,CAAC;QAC7C,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC;QACvC,IAAI,YAAY,IAAI,SAAS,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YAClD,KAAK,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IAED,SAAS,sBAAsB;QAC7B,IACE,CAAC,sBAAsB,CAAC,OAAO;YAC/B,CAAC,SAAS,CAAC,cAAc,CAAC,aAAa;YACvC,CAAC,QAAQ,CAAC,OAAO;YACjB,CAAC,KAAK,CAAC,oBAAoB,EAC3B,CAAC;YACD,OAAO;QACT,CAAC;QACD,MAAM,YAAY,GAAG,kBAAkB,EAAE,CAAC;QAE1C,gBAAgB,EAAE,CAAC;QACnB,eAAe,CAAC,OAAO,GAAG,YAAY,CAAC;QACvC,eAAe,CAAC,OAAO,GAAG,kBAAkB,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QACtE,YAAY,CAAC,OAAO,GAAG,YAAY;YACjC,CAAC,CAAC,YAAY,CAAC,wBAAwB,CAAC,QAAQ,CAAC,OAAO,CAAC;YACzD,CAAC,CAAC,IAAI,CAAC;QACT,gBAAgB,EAAE,CAAC;QACnB,sBAAsB,CAAC,OAAO,GAAG,KAAK,CAAC;IACzC,CAAC;IAED,SAAS,kBAAkB;QACzB,IAAI,QAAQ,CAAC,iBAAiB,KAAK,QAAQ,CAAC,OAAO,EAAE,CAAC;YACpD,KAAK,CAAC,iBAAiB,EAAE,EAAE,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,gBAAgB,EAAE,EAAE,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,SAAS,uBAAuB;QAC9B,yBAAyB,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,MAAM,mBAAmB,GAA8B;YACrD,OAAO,EAAE,kBAAkB;YAC3B,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,iBAAiB,EAAE,EAAE;YAC9C,UAAU,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,gBAAgB,EAAE,EAAE;YAC5C,UAAU,EAAE,kBAAkB;SAC/B,CAAC;QAEF,yBAAyB,CAAC,OAAO,GAAG,mBAAmB,CAAC;QAExD,0BAA0B;QAC1B,KAAK,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAExE,kBAAkB;QAClB,KAAK,CAAC,gBAAgB,CAAC,uBAAuB,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC;QACjF,KAAK,CAAC,gBAAgB,CAAC,qBAAqB,EAAE,mBAAmB,CAAC,UAAU,CAAC,CAAC;QAE9E,YAAY;QACZ,QAAQ,CAAC,gBAAgB,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAClF,CAAC;IAED,SAAS,yBAAyB;QAChC,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,KAAK,IAAI,CAAC,yBAAyB,CAAC,OAAO;YAAE,OAAO;QAEzD,KAAK,CAAC,mBAAmB,CAAC,kBAAkB,EAAE,yBAAyB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACzF,KAAK,CAAC,mBAAmB,CACvB,uBAAuB,EACvB,yBAAyB,CAAC,OAAO,EAAE,WAAW,CAC/C,CAAC;QACF,KAAK,CAAC,mBAAmB,CAAC,qBAAqB,EAAE,yBAAyB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC/F,QAAQ,CAAC,mBAAmB,CAC1B,oBAAoB,EACpB,yBAAyB,CAAC,OAAO,CAAC,UAAU,CAC7C,CAAC;IACJ,CAAC;IAED,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACrB,KAAK,CAAC,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjD,CAAC;QACD,uBAAuB,EAAE,CAAC;QAC1B,gBAAgB,EAAE,CAAC;QAEnB,OAAO,GAAG,EAAE;YACV,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACrB,KAAK,CAAC,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACnD,CAAC;YACD,yBAAyB,EAAE,CAAC;YAC5B,gBAAgB,EAAE,CAAC;QACrB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAEnB,OAAO,CACL,CAAC,KAAK,CACJ,QAAQ,CAAC,CAAC,KAAK,CAAC,cAAc,IAAI,IAAI,CAAC,CACvC,YAAY,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,CAClE,WAAW,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAC/B,KAAK,CAAC,CAAC;YACL,GAAG,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC;YACzB,SAAS,EAAE,KAAK,CAAC,UAAU;SAC5B,CAAC,CACF,MAAM,CAAC,CAAC,GAAG,EAAE;YACX,sBAAsB,EAAE,CAAC;QAC3B,CAAC,CAAC;IACF,yFAAyF;IACzF,cAAc,CAAC,CAAC,GAAG,EAAE;YACnB,sBAAsB,EAAE,CAAC;QAC3B,CAAC,CAAC,CACF,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE;YACd,+EAA+E;YAC/E,6EAA6E;YAC7E,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBACpD,QAAQ,CAAC,OAAO,GAAG,MAAM,CAAC;gBAC1B,sBAAsB,CAAC,OAAO,GAAG,KAAK,CAAC,oBAAoB,IAAI,KAAK,CAAC;gBACrE,sBAAsB,EAAE,CAAC;YAC3B,CAAC;QACH,CAAC,CAAC,CACF,uBAAuB,CAAC,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC,CACvD,WAAW,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAC/B,GAAG,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,EAC3C,CACH,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,eAAe,SAAS,CAAC","sourcesContent":["import React, { useEffect, useRef, forwardRef, useImperativeHandle } from 'react';\nimport { StyleSheet } from 'react-native';\n\nimport VideoPlayer, { getSourceUri } from './VideoPlayer.web';\nimport type { VideoViewProps } from './VideoView.types';\n\ntype FullscreenChangeListeners = {\n default: () => void;\n safariEnter: () => void;\n safariExit: () => void;\n msListener: () => void;\n};\n\nfunction createAudioContext(): AudioContext | null {\n return typeof window !== 'undefined' ? new window.AudioContext() : null;\n}\n\nfunction createZeroGainNode(audioContext: AudioContext | null): GainNode | null {\n const zeroGainNode = audioContext?.createGain() ?? null;\n\n if (audioContext && zeroGainNode) {\n zeroGainNode.gain.value = 0;\n zeroGainNode.connect(audioContext.destination);\n }\n return zeroGainNode;\n}\n\nfunction mapStyles(style: VideoViewProps['style']): React.CSSProperties {\n const flattenedStyles = StyleSheet.flatten(style);\n // Looking through react-native-web source code they also just pass styles directly without further conversions, so it's just a cast.\n return flattenedStyles as React.CSSProperties;\n}\n\nexport function isPictureInPictureSupported(): boolean {\n return typeof document === 'object' && typeof document.exitPictureInPicture === 'function';\n}\n\nexport const VideoView = forwardRef((props: { player?: VideoPlayer } & VideoViewProps, ref) => {\n const videoRef = useRef<null | HTMLVideoElement>(null);\n const mediaNodeRef = useRef<null | MediaElementAudioSourceNode>(null);\n const hasToSetupAudioContext = useRef(false);\n const fullscreenChangeListeners = useRef<null | FullscreenChangeListeners>(null);\n const isWaitingForFirstFrame = useRef(false);\n\n /**\n * Audio context is used to mute all but one video when multiple video views are playing from one player simultaneously.\n * Using audio context nodes allows muting videos without displaying the mute icon in the video player.\n * We have to keep the context that called createMediaElementSource(videoRef), as the method can't be called\n * for the second time with another context and there is no way to unbind the video and audio context afterward.\n */\n const audioContextRef = useRef<null | AudioContext>(null);\n const zeroGainNodeRef = useRef<null | GainNode>(null);\n\n useEffect(() => {\n if (props.useAudioNodePlayback) {\n maybeSetupAudioContext();\n attachAudioNodes();\n } else {\n detachAudioNodes();\n }\n }, [props.useAudioNodePlayback]);\n\n useImperativeHandle(ref, () => ({\n enterFullscreen: async () => {\n if (!props.allowsFullscreen || !videoRef.current) {\n return;\n }\n // Cast the video to any to avoid ts errors. Methods such as webkitRequestFullscreen,\n // webkitEnterFullScreen, msRequestFullscreen are not typed even though they exist.\n const video = videoRef.current as any;\n\n if (video.requestFullscreen) {\n await video.requestFullscreen();\n } else if (video.webkitRequestFullscreen) {\n // @ts-ignore webkitRequestFullscreen can exist on Apple devices\n await video.webkitRequestFullscreen();\n } else if (video.webkitEnterFullScreen) {\n await video.webkitEnterFullScreen();\n } else if (video.msRequestFullscreen) {\n await video.msRequestFullscreen();\n }\n },\n exitFullscreen: async () => {\n await document.exitFullscreen();\n },\n startPictureInPicture: async () => {\n await videoRef.current?.requestPictureInPicture();\n },\n stopPictureInPicture: async () => {\n try {\n await document.exitPictureInPicture();\n } catch (e) {\n if (e instanceof DOMException && e.name === 'InvalidStateError') {\n console.warn('The VideoView is not in Picture-in-Picture mode.');\n } else {\n throw e;\n }\n }\n },\n }));\n\n useEffect(() => {\n const onEnter = () => {\n props.onPictureInPictureStart?.();\n };\n const onLeave = () => {\n props.onPictureInPictureStop?.();\n };\n const onLoadStart = () => {\n isWaitingForFirstFrame.current = true;\n };\n const onCanPlay = () => {\n if (isWaitingForFirstFrame.current) {\n props.onFirstFrameRender?.();\n }\n isWaitingForFirstFrame.current = false;\n };\n videoRef.current?.addEventListener('enterpictureinpicture', onEnter);\n videoRef.current?.addEventListener('leavepictureinpicture', onLeave);\n videoRef.current?.addEventListener('loadstart', onLoadStart);\n videoRef.current?.addEventListener('loadeddata', onCanPlay);\n\n return () => {\n videoRef.current?.removeEventListener('enterpictureinpicture', onEnter);\n videoRef.current?.removeEventListener('leavepictureinpicture', onLeave);\n videoRef.current?.removeEventListener('loadstart', onLoadStart);\n videoRef.current?.removeEventListener('loadeddata', onCanPlay);\n };\n }, [videoRef, props.onPictureInPictureStop, props.onPictureInPictureStart]);\n\n // Adds the video view as a candidate for being the audio source for the player (when multiple views play from one\n // player only one will emit audio).\n function attachAudioNodes() {\n if (!props.useAudioNodePlayback) {\n return;\n }\n const audioContext = audioContextRef.current;\n const zeroGainNode = zeroGainNodeRef.current;\n const mediaNode = mediaNodeRef.current;\n\n if (audioContext && zeroGainNode && mediaNode) {\n props.player.mountAudioNode(audioContext, zeroGainNode, mediaNode);\n } else {\n console.warn(\n \"Couldn't mount audio node, this might affect the audio playback when using multiple video views with the same player.\"\n );\n }\n }\n\n function detachAudioNodes() {\n if (!props.useAudioNodePlayback) {\n return;\n }\n const audioContext = audioContextRef.current;\n const mediaNode = mediaNodeRef.current;\n if (audioContext && mediaNode && videoRef.current) {\n props.player.unmountAudioNode(videoRef.current, audioContext, mediaNode);\n }\n }\n\n function maybeSetupAudioContext() {\n if (\n !hasToSetupAudioContext.current ||\n !navigator.userActivation.hasBeenActive ||\n !videoRef.current ||\n !props.useAudioNodePlayback\n ) {\n return;\n }\n const audioContext = createAudioContext();\n\n detachAudioNodes();\n audioContextRef.current = audioContext;\n zeroGainNodeRef.current = createZeroGainNode(audioContextRef.current);\n mediaNodeRef.current = audioContext\n ? audioContext.createMediaElementSource(videoRef.current)\n : null;\n attachAudioNodes();\n hasToSetupAudioContext.current = false;\n }\n\n function fullscreenListener() {\n if (document.fullscreenElement === videoRef.current) {\n props.onFullscreenEnter?.();\n } else {\n props.onFullscreenExit?.();\n }\n }\n\n function setupFullscreenListener() {\n cleanupFullscreenListener();\n const video = videoRef.current;\n if (!video) return;\n const fullscreenListeners: FullscreenChangeListeners = {\n default: fullscreenListener,\n safariEnter: () => props.onFullscreenEnter?.(),\n safariExit: () => props.onFullscreenExit?.(),\n msListener: fullscreenListener,\n };\n\n fullscreenChangeListeners.current = fullscreenListeners;\n\n // Standard Fullscreen API\n video.addEventListener('fullscreenchange', fullscreenListeners.default);\n\n // Safari (webkit)\n video.addEventListener('webkitbeginfullscreen', fullscreenListeners.safariEnter);\n video.addEventListener('webkitendfullscreen', fullscreenListeners.safariExit);\n\n // IE11 (ms)\n document.addEventListener('MSFullscreenChange', fullscreenListeners.msListener);\n }\n\n function cleanupFullscreenListener() {\n const video = videoRef.current;\n if (!video || !fullscreenChangeListeners.current) return;\n\n video.removeEventListener('fullscreenchange', fullscreenChangeListeners.current.default);\n video.removeEventListener(\n 'webkitbeginfullscreen',\n fullscreenChangeListeners.current?.safariEnter\n );\n video.removeEventListener('webkitendfullscreen', fullscreenChangeListeners.current.safariExit);\n document.removeEventListener(\n 'MSFullscreenChange',\n fullscreenChangeListeners.current.msListener\n );\n }\n\n useEffect(() => {\n if (videoRef.current) {\n props.player?.mountVideoView(videoRef.current);\n }\n setupFullscreenListener();\n attachAudioNodes();\n\n return () => {\n if (videoRef.current) {\n props.player?.unmountVideoView(videoRef.current);\n }\n cleanupFullscreenListener();\n detachAudioNodes();\n };\n }, [props.player]);\n\n return (\n <video\n controls={props.nativeControls ?? true}\n controlsList={props.allowsFullscreen ? undefined : 'nofullscreen'}\n crossOrigin={props.crossOrigin}\n style={{\n ...mapStyles(props.style),\n objectFit: props.contentFit,\n }}\n onPlay={() => {\n maybeSetupAudioContext();\n }}\n // The player can autoplay when muted, unmuting by a user should create the audio context\n onVolumeChange={() => {\n maybeSetupAudioContext();\n }}\n ref={(newRef) => {\n // This is called with a null value before `player.unmountVideoView` is called,\n // we can't assign null to videoRef if we want to unmount it from the player.\n if (newRef && !newRef.isEqualNode(videoRef.current)) {\n videoRef.current = newRef;\n hasToSetupAudioContext.current = props.useAudioNodePlayback ?? false;\n maybeSetupAudioContext();\n }\n }}\n disablePictureInPicture={!props.allowsPictureInPicture}\n playsInline={props.playsInline}\n src={getSourceUri(props.player?.src) ?? ''}\n />\n );\n});\n\nexport default VideoView;\n"]}
|
package/expo-module.config.json
CHANGED
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4370033dcfecb3eb931316a56a2ae911
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
de4d82e89ccd0d94a601a26a44ebfc0696e0bd70
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
42073035495bb534c34347050767c72cd27cab426a3c28d5ba1ac06bf8cd9aa1
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
c09f69a702edac9b878f3b2daec4ec30c0029136c343b0b00d9fffd7aef9e9946d43a24d8d51e8a4c5fec5f03aae8ca2858bae296fd7b66c9539b8e16392c347
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"component": {
|
|
4
4
|
"group": "host.exp.exponent",
|
|
5
5
|
"module": "expo.modules.video",
|
|
6
|
-
"version": "3.0.
|
|
6
|
+
"version": "3.0.10",
|
|
7
7
|
"attributes": {
|
|
8
8
|
"org.gradle.status": "release"
|
|
9
9
|
}
|
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
},
|
|
25
25
|
"files": [
|
|
26
26
|
{
|
|
27
|
-
"name": "expo.modules.video-3.0.
|
|
28
|
-
"url": "expo.modules.video-3.0.
|
|
29
|
-
"size":
|
|
30
|
-
"sha512": "
|
|
31
|
-
"sha256": "
|
|
32
|
-
"sha1": "
|
|
33
|
-
"md5": "
|
|
27
|
+
"name": "expo.modules.video-3.0.10.aar",
|
|
28
|
+
"url": "expo.modules.video-3.0.10.aar",
|
|
29
|
+
"size": 499109,
|
|
30
|
+
"sha512": "c09f69a702edac9b878f3b2daec4ec30c0029136c343b0b00d9fffd7aef9e9946d43a24d8d51e8a4c5fec5f03aae8ca2858bae296fd7b66c9539b8e16392c347",
|
|
31
|
+
"sha256": "42073035495bb534c34347050767c72cd27cab426a3c28d5ba1ac06bf8cd9aa1",
|
|
32
|
+
"sha1": "de4d82e89ccd0d94a601a26a44ebfc0696e0bd70",
|
|
33
|
+
"md5": "4370033dcfecb3eb931316a56a2ae911"
|
|
34
34
|
}
|
|
35
35
|
]
|
|
36
36
|
},
|
|
@@ -113,13 +113,13 @@
|
|
|
113
113
|
],
|
|
114
114
|
"files": [
|
|
115
115
|
{
|
|
116
|
-
"name": "expo.modules.video-3.0.
|
|
117
|
-
"url": "expo.modules.video-3.0.
|
|
118
|
-
"size":
|
|
119
|
-
"sha512": "
|
|
120
|
-
"sha256": "
|
|
121
|
-
"sha1": "
|
|
122
|
-
"md5": "
|
|
116
|
+
"name": "expo.modules.video-3.0.10.aar",
|
|
117
|
+
"url": "expo.modules.video-3.0.10.aar",
|
|
118
|
+
"size": 499109,
|
|
119
|
+
"sha512": "c09f69a702edac9b878f3b2daec4ec30c0029136c343b0b00d9fffd7aef9e9946d43a24d8d51e8a4c5fec5f03aae8ca2858bae296fd7b66c9539b8e16392c347",
|
|
120
|
+
"sha256": "42073035495bb534c34347050767c72cd27cab426a3c28d5ba1ac06bf8cd9aa1",
|
|
121
|
+
"sha1": "de4d82e89ccd0d94a601a26a44ebfc0696e0bd70",
|
|
122
|
+
"md5": "4370033dcfecb3eb931316a56a2ae911"
|
|
123
123
|
}
|
|
124
124
|
]
|
|
125
125
|
},
|
|
@@ -133,8 +133,8 @@
|
|
|
133
133
|
},
|
|
134
134
|
"files": [
|
|
135
135
|
{
|
|
136
|
-
"name": "expo.modules.video-3.0.
|
|
137
|
-
"url": "expo.modules.video-3.0.
|
|
136
|
+
"name": "expo.modules.video-3.0.10-sources.jar",
|
|
137
|
+
"url": "expo.modules.video-3.0.10-sources.jar",
|
|
138
138
|
"size": 63354,
|
|
139
139
|
"sha512": "f04da6fb2f5c1ba96f029687f46e31c261026c814121a81cdc257af33fa1383b5de77a8862123e632c93888bfce716edcc2acdd0d07460c678917139a9901b11",
|
|
140
140
|
"sha256": "5efae1439855a664269c02cbb19144477c94a4ac3af7dbd6a7874739d851cd4b",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
25e140e4d43cd0e9a84d7b34659556d3
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
b5603f1bcbf0a8baf032222a005a545b462f6934
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2b84a50ff9a7876de406f3f8ca184c496dd7575b2adab26b47427b38dd144a5c
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ac671e3f2cf649c8bda5cd3b18b3da3ad67e50e2c15c0deb1283287f4771a435921bcd17ec888f1b02524ab24e9785cfa09b9461935c11b09a66faa33fdf09e5
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<modelVersion>4.0.0</modelVersion>
|
|
10
10
|
<groupId>host.exp.exponent</groupId>
|
|
11
11
|
<artifactId>expo.modules.video</artifactId>
|
|
12
|
-
<version>3.0.
|
|
12
|
+
<version>3.0.10</version>
|
|
13
13
|
<packaging>aar</packaging>
|
|
14
14
|
<name>expo.modules.video</name>
|
|
15
15
|
<url>https://github.com/expo/expo</url>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
886d6ab112ab316477ff7c2f7bc42fee
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
acd2ba6426f0e986c00bc4fe24fe385619c7c41c
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
d07392689aa8a6721550c6da2138c7ffeadd61d1d29fc47c6970074eccd79ec8
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
d8fc8bafd12e53f95787dd6b6402967e690674c5e3ab6eed183dbc91fc88616659002774cc3227be66185eed5336299938eb28951695373710a2f2464c71cea2
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
<groupId>host.exp.exponent</groupId>
|
|
4
4
|
<artifactId>expo.modules.video</artifactId>
|
|
5
5
|
<versioning>
|
|
6
|
-
<latest>3.0.
|
|
7
|
-
<release>3.0.
|
|
6
|
+
<latest>3.0.10</latest>
|
|
7
|
+
<release>3.0.10</release>
|
|
8
8
|
<versions>
|
|
9
|
-
<version>3.0.
|
|
9
|
+
<version>3.0.10</version>
|
|
10
10
|
</versions>
|
|
11
|
-
<lastUpdated>
|
|
11
|
+
<lastUpdated>20250904150716</lastUpdated>
|
|
12
12
|
</versioning>
|
|
13
13
|
</metadata>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
0fb7d17a8edffaa8ee48a8709f7f6dca
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
f229fb8dedc06833d16a6d7999b5e6bfbf3c520e
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
9bd232a97850733d9904d4c3a35f2ecd3d2d6c2fe9a735343c6aaccf5b115101
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
0116a51bbf7573570a8182de37f7f0f86c20c86e8e3f78fe012549a2a0483b72a1bd5d2b5df7fbedd7582bc42d90f1da1f7ff72963574dcab9d1a17d1ffd2fe3
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-video",
|
|
3
3
|
"title": "Expo Video",
|
|
4
|
-
"version": "3.0.
|
|
4
|
+
"version": "3.0.10",
|
|
5
5
|
"description": "A cross-platform, performant video component for React Native and Expo with Web support",
|
|
6
6
|
"main": "build/index.js",
|
|
7
7
|
"types": "build/index.d.ts",
|
|
@@ -38,5 +38,5 @@
|
|
|
38
38
|
"react": "*",
|
|
39
39
|
"react-native": "*"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "8cafaff8076e443e6c80e8013ec809f4f290f24d"
|
|
42
42
|
}
|
package/src/VideoView.web.tsx
CHANGED
|
@@ -4,6 +4,13 @@ import { StyleSheet } from 'react-native';
|
|
|
4
4
|
import VideoPlayer, { getSourceUri } from './VideoPlayer.web';
|
|
5
5
|
import type { VideoViewProps } from './VideoView.types';
|
|
6
6
|
|
|
7
|
+
type FullscreenChangeListeners = {
|
|
8
|
+
default: () => void;
|
|
9
|
+
safariEnter: () => void;
|
|
10
|
+
safariExit: () => void;
|
|
11
|
+
msListener: () => void;
|
|
12
|
+
};
|
|
13
|
+
|
|
7
14
|
function createAudioContext(): AudioContext | null {
|
|
8
15
|
return typeof window !== 'undefined' ? new window.AudioContext() : null;
|
|
9
16
|
}
|
|
@@ -32,7 +39,7 @@ export const VideoView = forwardRef((props: { player?: VideoPlayer } & VideoView
|
|
|
32
39
|
const videoRef = useRef<null | HTMLVideoElement>(null);
|
|
33
40
|
const mediaNodeRef = useRef<null | MediaElementAudioSourceNode>(null);
|
|
34
41
|
const hasToSetupAudioContext = useRef(false);
|
|
35
|
-
const
|
|
42
|
+
const fullscreenChangeListeners = useRef<null | FullscreenChangeListeners>(null);
|
|
36
43
|
const isWaitingForFirstFrame = useRef(false);
|
|
37
44
|
|
|
38
45
|
/**
|
|
@@ -55,10 +62,23 @@ export const VideoView = forwardRef((props: { player?: VideoPlayer } & VideoView
|
|
|
55
62
|
|
|
56
63
|
useImperativeHandle(ref, () => ({
|
|
57
64
|
enterFullscreen: async () => {
|
|
58
|
-
if (!props.allowsFullscreen) {
|
|
65
|
+
if (!props.allowsFullscreen || !videoRef.current) {
|
|
59
66
|
return;
|
|
60
67
|
}
|
|
61
|
-
|
|
68
|
+
// Cast the video to any to avoid ts errors. Methods such as webkitRequestFullscreen,
|
|
69
|
+
// webkitEnterFullScreen, msRequestFullscreen are not typed even though they exist.
|
|
70
|
+
const video = videoRef.current as any;
|
|
71
|
+
|
|
72
|
+
if (video.requestFullscreen) {
|
|
73
|
+
await video.requestFullscreen();
|
|
74
|
+
} else if (video.webkitRequestFullscreen) {
|
|
75
|
+
// @ts-ignore webkitRequestFullscreen can exist on Apple devices
|
|
76
|
+
await video.webkitRequestFullscreen();
|
|
77
|
+
} else if (video.webkitEnterFullScreen) {
|
|
78
|
+
await video.webkitEnterFullScreen();
|
|
79
|
+
} else if (video.msRequestFullscreen) {
|
|
80
|
+
await video.msRequestFullscreen();
|
|
81
|
+
}
|
|
62
82
|
},
|
|
63
83
|
exitFullscreen: async () => {
|
|
64
84
|
await document.exitFullscreen();
|
|
@@ -168,15 +188,43 @@ export const VideoView = forwardRef((props: { player?: VideoPlayer } & VideoView
|
|
|
168
188
|
}
|
|
169
189
|
|
|
170
190
|
function setupFullscreenListener() {
|
|
171
|
-
|
|
172
|
-
videoRef.current
|
|
191
|
+
cleanupFullscreenListener();
|
|
192
|
+
const video = videoRef.current;
|
|
193
|
+
if (!video) return;
|
|
194
|
+
const fullscreenListeners: FullscreenChangeListeners = {
|
|
195
|
+
default: fullscreenListener,
|
|
196
|
+
safariEnter: () => props.onFullscreenEnter?.(),
|
|
197
|
+
safariExit: () => props.onFullscreenExit?.(),
|
|
198
|
+
msListener: fullscreenListener,
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
fullscreenChangeListeners.current = fullscreenListeners;
|
|
202
|
+
|
|
203
|
+
// Standard Fullscreen API
|
|
204
|
+
video.addEventListener('fullscreenchange', fullscreenListeners.default);
|
|
205
|
+
|
|
206
|
+
// Safari (webkit)
|
|
207
|
+
video.addEventListener('webkitbeginfullscreen', fullscreenListeners.safariEnter);
|
|
208
|
+
video.addEventListener('webkitendfullscreen', fullscreenListeners.safariExit);
|
|
209
|
+
|
|
210
|
+
// IE11 (ms)
|
|
211
|
+
document.addEventListener('MSFullscreenChange', fullscreenListeners.msListener);
|
|
173
212
|
}
|
|
174
213
|
|
|
175
214
|
function cleanupFullscreenListener() {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
215
|
+
const video = videoRef.current;
|
|
216
|
+
if (!video || !fullscreenChangeListeners.current) return;
|
|
217
|
+
|
|
218
|
+
video.removeEventListener('fullscreenchange', fullscreenChangeListeners.current.default);
|
|
219
|
+
video.removeEventListener(
|
|
220
|
+
'webkitbeginfullscreen',
|
|
221
|
+
fullscreenChangeListeners.current?.safariEnter
|
|
222
|
+
);
|
|
223
|
+
video.removeEventListener('webkitendfullscreen', fullscreenChangeListeners.current.safariExit);
|
|
224
|
+
document.removeEventListener(
|
|
225
|
+
'MSFullscreenChange',
|
|
226
|
+
fullscreenChangeListeners.current.msListener
|
|
227
|
+
);
|
|
180
228
|
}
|
|
181
229
|
|
|
182
230
|
useEffect(() => {
|
package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.9/expo.modules.video-3.0.9.aar.md5
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
3a9f65c14799d372d9ff3cf1e911e79c
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
5173ce3f6b4ff3693b325a6e0858571f9c162e38
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
87fe6f2ca3a6fca794a15b4555d1ea3cdd3b38c82c48b75fd03c4f55ec7941e0
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
d7750e9155149c0131d04463b2eba12059ecc2bb5e5e3c800e90f5d5df85fe67d26b2e73ac96f8c5772212249ab2dcc4bbbc522bf3f1adad03e76337457155c3
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
d44ac55ef0407adb74d51faf881324b4
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
bcfdcd2863cb298115305a36039218cbdf1e734b
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
a3b7d4fac71a2213fe70909b50efa3b53b0337997839223162f049a372e18955
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
9ce60e3520dc6b2f3fa0eb62a0e0c3204c8d575043cd8544bc7b0ffbf68722597c0d7a0d221b87f92174833292216bdd15c1ad87e3840297b7ec87e7b02cd169
|
package/local-maven-repo/host/exp/exponent/expo.modules.video/3.0.9/expo.modules.video-3.0.9.pom.md5
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
10183bdde61466b8e56a43155f9761ad
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0c7b1efb0eeee962d4bf702c2ff3979e7e1e11cd
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
61fcc640dddd65c9ae1d73f7d7fa9868a915dd873a74266323310fec53dfeb97
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
aa9e0a17692fe2e4e09198ff75ff7ef4231db7041b74daf28b2c7a4dd3088133fb0237417548fd817622fde5677452e97ef168682c23d6e0aa10f1ea0113ddd7
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|