react-native-video-provider 0.2.4 → 0.2.6

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/README.md CHANGED
@@ -18,8 +18,14 @@ Feed ──▶ Detail ──▶ Fullscreen (rotation unlocked) ──▶ Floatin
18
18
  navigation, tab switches, unmounts, Fast Refresh
19
19
  - 🔁 **Same-video handoff** — `setSource` with the same `id` is a no-op for
20
20
  the engine; the player just re-parents to the new surface
21
+ - 📱 **Single-engine feed** — `VideoFeed`, a TikTok/Reels-style list where
22
+ only the scrolled-into-focus video plays, on one player, flat memory
21
23
  - 📺 **Fullscreen** — built-in host that unlocks rotation while visible and
22
24
  restores the previous orientation lock on exit
25
+ - 🧭 **Orientation control** — force portrait/landscape (+ inverted) per
26
+ player, scoped to fullscreen, or as a standing lock
27
+ - ⏸️ **Focus-aware** — auto-pause on app background and on screen navigation
28
+ (React Navigation's `useIsFocused()`)
23
29
  - 🎈 **Floating player** — built-in draggable in-app window
24
30
  - 🖼 **Picture in Picture** — Android + iOS
25
31
  - ⚡ **New Architecture native** — TurboModule + Fabric, typed end to end
@@ -31,11 +37,15 @@ See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the full design and
31
37
  ## Installation
32
38
 
33
39
  ```sh
34
- npm install react-native-video-provider
40
+ npm install react-native-video-provider react-native-svg
35
41
  cd ios && pod install
36
42
  ```
37
43
 
38
- Requires React Native 0.80+ with the New Architecture enabled.
44
+ `react-native-svg` is a peer dependency (used by the built-in control icons).
45
+
46
+ Requires the New Architecture. Works on React Native **0.79+** — the
47
+ TurboModule spec uses direct codegen-type imports so it parses on 0.79's
48
+ codegen as well as 0.80+.
39
49
 
40
50
  ## Quick start
41
51
 
@@ -99,6 +109,14 @@ const { enter, toggle } = useFullscreen();
99
109
  enter('landscape');
100
110
  ```
101
111
 
112
+ Set `fullscreenOrientation` to a **landscape** value and physically rotating
113
+ the device to landscape auto-enters fullscreen (rotating back to portrait
114
+ exits) — YouTube-style. Requires the app to allow landscape at the OS level:
115
+
116
+ ```tsx
117
+ <VideoPlayer source={video} fullscreenOrientation="landscape" />
118
+ ```
119
+
102
120
  Or as a standing lock, independent of fullscreen:
103
121
 
104
122
  ```tsx
@@ -131,7 +149,76 @@ player.attach('feed'); // render here
131
149
  ```
132
150
 
133
151
  `<VideoPlayer>` is the convenience wrapper that does `setSource` + `attach` +
134
- optional controls in one component.
152
+ optional controls in one component. Handy props:
153
+
154
+ ```tsx
155
+ <VideoPlayer
156
+ source={video}
157
+ autoplay muted repeat // playback flags
158
+ resizeMode="contain" // contain | cover | stretch
159
+ controls // built-in chrome (SVG icons)
160
+ onLoadComplete={(m) => {}} // duration/dimensions ready
161
+ onBuffering={(b) => {}}
162
+ onError={(e) => {}}
163
+ ref={playerRef} // → the VideoManager (playerRef.current.seek(…))
164
+ />
165
+ ```
166
+
167
+ Pass `live` for a live stream: the controls hide the seek bar/times and show
168
+ just mute + fullscreen. `liveIcon` renders a live indicator (e.g. a Lottie
169
+ badge), and `thumbnail` shows a poster over the video during the initial load:
170
+
171
+ ```tsx
172
+ <VideoPlayer
173
+ source={liveSource}
174
+ live
175
+ liveIcon={() => <LottieView source={liveAnim} autoPlay loop style={{ width: 44, height: 20 }} />}
176
+ thumbnail={() => <Image source={{ uri: poster }} style={StyleSheet.absoluteFill} resizeMode="cover" />}
177
+ />
178
+ ```
179
+
180
+ ## Video feed (single engine, only the focused one plays)
181
+
182
+ `<VideoFeed>` is a TikTok/Reels-style vertical feed. It renders many videos in
183
+ a FlatList but plays **only the one scrolled into focus** — on the same single
184
+ engine, so memory and CPU stay flat no matter how long the feed. Each item is
185
+ just a surface; scrolling hands the one player off to the focused item.
186
+
187
+ ```tsx
188
+ import { VideoFeed } from 'react-native-video-provider';
189
+
190
+ <VideoFeed
191
+ data={videos} // [{ id, uri, title? }, …] — each needs a stable id
192
+ renderOverlay={({ item, focused }) => (
193
+ <Caption title={item.title} paused={!focused} />
194
+ )}
195
+ />
196
+ ```
197
+
198
+ Any extra `FlatList` prop passes through (`onEndReached` for infinite scroll,
199
+ `ListHeaderComponent`, …).
200
+
201
+ ## Pausing on focus loss
202
+
203
+ Both `<VideoPlayer>` and `<VideoFeed>` pause automatically when the **app is
204
+ backgrounded** (opt out with `pauseOnFocusLost={false}` for background audio).
205
+
206
+ For **screen navigation** (navigating to another screen while the app stays
207
+ foregrounded), pass your navigation library's focus flag — React Navigation
208
+ keeps screens mounted, so there is no other reliable signal:
209
+
210
+ ```tsx
211
+ import { useIsFocused } from '@react-navigation/native';
212
+
213
+ function Screen() {
214
+ const isFocused = useIsFocused();
215
+ return <VideoPlayer source={video} isFocused={isFocused} />;
216
+ // VideoFeed takes the same prop.
217
+ }
218
+ ```
219
+
220
+ `false` pauses; returning to `true` resumes (reclaiming the engine if another
221
+ video took it while you were away).
135
222
 
136
223
  ## State & events
137
224
 
@@ -57,3 +57,28 @@ dependencies {
57
57
  implementation "androidx.media3:media3-ui:${media3Version}"
58
58
  implementation "androidx.core:core-ktx:1.13.1"
59
59
  }
60
+
61
+ // Print the package banner while the app compiles. Best-effort and fully
62
+ // guarded — a missing node binary or any failure never breaks the build.
63
+ tasks.register("auVideoBanner") {
64
+ doLast {
65
+ try {
66
+ def script = new File(projectDir, "../scripts/postinstall.js")
67
+ if (script.exists()) {
68
+ def banner = providers.exec {
69
+ commandLine "node", script.absolutePath, "--force"
70
+ }.standardOutput.asText.get()
71
+ logger.lifecycle(banner.trim())
72
+ }
73
+ } catch (Exception e) {
74
+ // Never fail the build over a banner (e.g. node not on PATH).
75
+ logger.info("auVideoBanner skipped: ${e.message}")
76
+ }
77
+ }
78
+ }
79
+
80
+ afterEvaluate {
81
+ tasks.matching { it.name == "preBuild" }.configureEach {
82
+ dependsOn("auVideoBanner")
83
+ }
84
+ }
@@ -284,9 +284,31 @@ object PlayerCore {
284
284
  )
285
285
  currentSurfaceId = surfaceId
286
286
  pendingSurfaceId = null
287
+ reassertVideoOutput(pv, surfaceId, container)
287
288
  listener?.onAttach(surfaceId)
288
289
  }
289
290
 
291
+ /**
292
+ * Re-parenting the PlayerView destroys and recreates its TextureView
293
+ * SurfaceTexture. VOD re-renders the last decoded frame onto the new
294
+ * surface immediately, but a LIVE stream (no buffered frame to re-render)
295
+ * can stay black. Re-binding the player to the view on the next frame
296
+ * forces the video output onto the fresh surface. No-op-safe for VOD.
297
+ */
298
+ private fun reassertVideoOutput(
299
+ pv: PlayerView,
300
+ surfaceId: String,
301
+ container: AuVideoSurfaceView,
302
+ ) {
303
+ mainHandler.post {
304
+ if (currentSurfaceId == surfaceId && pv.parent === container) {
305
+ val exo = player ?: return@post
306
+ pv.player = null
307
+ pv.player = exo
308
+ }
309
+ }
310
+ }
311
+
290
312
  // --------------------------------------------------------------- events
291
313
 
292
314
  private val playerListener = object : Player.Listener {
@@ -6,7 +6,7 @@ import { useVideoManager } from "../provider/VideoContext.js";
6
6
  import { usePlayback } from "../hooks/usePlayback.js";
7
7
  import { formatTime } from "../utils/formatTime.js";
8
8
  import { GestureOverlay } from "./GestureOverlay.js";
9
- import { CloseIcon } from "./icons.js";
9
+ import { BackIcon } from "./icons.js";
10
10
  import SvgIcons from "./SvgIcons.js";
11
11
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
12
12
  /**
@@ -18,21 +18,17 @@ export function VideoControls({
18
18
  doubleTapSeek = 10,
19
19
  hideAfter = 3000,
20
20
  showFullscreenButton = true,
21
+ live = false,
22
+ liveIcon,
21
23
  onClose
22
24
  }) {
23
25
  const manager = useVideoManager();
24
- const status = usePlayback(s => s.status);
25
26
  const playing = usePlayback(s => s.playing);
26
27
  const buffering = usePlayback(s => s.buffering);
27
- const loading = usePlayback(s => s.loading);
28
28
  const position = usePlayback(s => s.position);
29
29
  const duration = usePlayback(s => s.duration);
30
30
  const muted = usePlayback(s => s.muted);
31
31
  const fullscreen = usePlayback(s => s.fullscreen);
32
-
33
- // No known duration once loaded — a live stream or a video with no fixed
34
- // end. There's nothing to seek, so hide the seek bar entirely.
35
- const live = status !== 'idle' && !loading && duration <= 0;
36
32
  const [visible, setVisible] = useState(true);
37
33
  const hideTimer = useRef(null);
38
34
  const trackWidth = useRef(0);
@@ -110,7 +106,7 @@ export function VideoControls({
110
106
  style: styles.button,
111
107
  onPress: onClose,
112
108
  hitSlop: 8,
113
- children: /*#__PURE__*/_jsx(CloseIcon, {
109
+ children: /*#__PURE__*/_jsx(BackIcon, {
114
110
  size: 18,
115
111
  color: "#fff"
116
112
  })
@@ -139,7 +135,7 @@ export function VideoControls({
139
135
  }), /*#__PURE__*/_jsx(View, {
140
136
  style: styles.bottomRow,
141
137
  children: live ? /*#__PURE__*/_jsxs(_Fragment, {
142
- children: [muteButton, /*#__PURE__*/_jsx(View, {
138
+ children: [liveIcon ? liveIcon() : null, muteButton, /*#__PURE__*/_jsx(View, {
143
139
  style: styles.spacer
144
140
  }), fullscreenButton]
145
141
  }) : /*#__PURE__*/_jsxs(_Fragment, {
@@ -1 +1 @@
1
- {"version":3,"names":["useCallback","useEffect","useRef","useState","Pressable","StyleSheet","Text","View","useVideoManager","usePlayback","formatTime","GestureOverlay","CloseIcon","SvgIcons","jsx","_jsx","jsxs","_jsxs","Fragment","_Fragment","VideoControls","doubleTapSeek","hideAfter","showFullscreenButton","onClose","manager","status","s","playing","buffering","loading","position","duration","muted","fullscreen","live","visible","setVisible","hideTimer","trackWidth","scheduleHide","current","clearTimeout","setTimeout","toggleVisible","v","onTrackLayout","e","nativeEvent","layout","width","onTrackPress","ratio","locationX","seek","progress","Math","min","muteButton","style","styles","button","onPress","unmute","mute","hitSlop","children","icon","size","fill","type","fullscreenButton","toggleFullscreen","absoluteFill","pointerEvents","onSingleTap","onDoubleTapLeft","seekBy","onDoubleTapRight","chrome","topRow","color","playButton","toggle","playIcon","bottomRow","spacer","time","track","onLayout","trackBg","trackFill","create","top","left","right","bottom","backgroundColor","justifyContent","flexDirection","padding","alignSelf","fontSize","alignItems","paddingHorizontal","paddingBottom","gap","fontVariant","flex","height","borderRadius"],"sourceRoot":"../../../src","sources":["components/VideoControls.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["useCallback","useEffect","useRef","useState","Pressable","StyleSheet","Text","View","useVideoManager","usePlayback","formatTime","GestureOverlay","BackIcon","SvgIcons","jsx","_jsx","jsxs","_jsxs","Fragment","_Fragment","VideoControls","doubleTapSeek","hideAfter","showFullscreenButton","live","liveIcon","onClose","manager","playing","s","buffering","position","duration","muted","fullscreen","visible","setVisible","hideTimer","trackWidth","scheduleHide","current","clearTimeout","setTimeout","toggleVisible","v","onTrackLayout","e","nativeEvent","layout","width","onTrackPress","ratio","locationX","seek","progress","Math","min","muteButton","style","styles","button","onPress","unmute","mute","hitSlop","children","icon","size","fill","type","fullscreenButton","toggleFullscreen","absoluteFill","pointerEvents","onSingleTap","onDoubleTapLeft","seekBy","onDoubleTapRight","chrome","topRow","color","playButton","toggle","playIcon","bottomRow","spacer","time","track","onLayout","trackBg","trackFill","create","top","left","right","bottom","backgroundColor","justifyContent","flexDirection","padding","alignSelf","fontSize","alignItems","paddingHorizontal","paddingBottom","gap","fontVariant","flex","height","borderRadius"],"sourceRoot":"../../../src","sources":["components/VideoControls.tsx"],"mappings":"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","ignoreList":[]}
@@ -38,6 +38,7 @@ export function VideoFeed({
38
38
  renderOverlay,
39
39
  onFocusChange,
40
40
  pauseOnUnmount = true,
41
+ isFocused,
41
42
  ...rest
42
43
  }) {
43
44
  const manager = useVideoManager();
@@ -70,6 +71,25 @@ export function VideoFeed({
70
71
  }
71
72
  };
72
73
  }, [manager, pauseOnUnmount]);
74
+ useEffect(() => {
75
+ if (isFocused === undefined) {
76
+ return;
77
+ }
78
+ if (!isFocused) {
79
+ if (manager.store.getState().surfaceId === feedSurfaceId(focusedId ?? '')) {
80
+ manager.pause();
81
+ }
82
+ return;
83
+ }
84
+ // Screen regained focus — resume the item that was in view.
85
+ const item = data.find(d => d.id === focusedId);
86
+ if (item) {
87
+ manager.setSource(item, {
88
+ autoplay: true,
89
+ surfaceId: feedSurfaceId(item.id)
90
+ });
91
+ }
92
+ }, [manager, isFocused, focusedId, data]);
73
93
  const focus = useCallback((item, index) => {
74
94
  setFocusedId(item?.id ?? null);
75
95
  if (item) {
@@ -1 +1 @@
1
- {"version":3,"names":["useCallback","useEffect","useRef","useState","FlatList","StyleSheet","useWindowDimensions","View","useVideoManager","VideoSurface","jsx","_jsx","jsxs","_jsxs","feedSurfaceId","id","VideoFeed","data","itemHeight","resizeMode","muted","repeat","visibilityThreshold","renderOverlay","onFocusChange","pauseOnUnmount","rest","manager","height","windowHeight","focusedId","setFocusedId","mute","unmute","setRepeat","setResizeMode","pause","focus","item","index","setSource","autoplay","surfaceId","latest","current","viewabilityConfig","itemVisiblePercentThreshold","minimumViewTime","onViewableItemsChanged","viewableItems","focusedToken","find","v","isViewable","renderItem","style","styles","children","absoluteFill","focused","keyExtractor","getItemLayout","_","length","offset","showsVerticalScrollIndicator","snapToInterval","snapToAlignment","decelerationRate","create","width","backgroundColor","overflow"],"sourceRoot":"../../../src","sources":["components/VideoFeed.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["useCallback","useEffect","useRef","useState","FlatList","StyleSheet","useWindowDimensions","View","useVideoManager","VideoSurface","jsx","_jsx","jsxs","_jsxs","feedSurfaceId","id","VideoFeed","data","itemHeight","resizeMode","muted","repeat","visibilityThreshold","renderOverlay","onFocusChange","pauseOnUnmount","isFocused","rest","manager","height","windowHeight","focusedId","setFocusedId","mute","unmute","setRepeat","setResizeMode","pause","undefined","store","getState","surfaceId","item","find","d","setSource","autoplay","focus","index","latest","current","viewabilityConfig","itemVisiblePercentThreshold","minimumViewTime","onViewableItemsChanged","viewableItems","focusedToken","v","isViewable","renderItem","style","styles","children","absoluteFill","focused","keyExtractor","getItemLayout","_","length","offset","showsVerticalScrollIndicator","snapToInterval","snapToAlignment","decelerationRate","create","width","backgroundColor","overflow"],"sourceRoot":"../../../src","sources":["components/VideoFeed.tsx"],"mappings":";;AAAA,SACEA,WAAW,EACXC,SAAS,EACTC,MAAM,EACNC,QAAQ,QAEH,OAAO;AACd,SACEC,QAAQ,EACRC,UAAU,EACVC,mBAAmB,EACnBC,IAAI,QAEC,cAAc;AACrB,SAASC,eAAe,QAAQ,6BAA0B;AAE1D,SAASC,YAAY,QAAQ,mBAAgB;;AAE7C;AAAA,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AACA,OAAO,MAAMC,aAAa,GAAIC,EAAU,IAAK,QAAQA,EAAE,EAAE;;AAEzD;;AAiDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,SAASA,CAAwB;EAC/CC,IAAI;EACJC,UAAU;EACVC,UAAU;EACVC,KAAK,GAAG,IAAI;EACZC,MAAM,GAAG,IAAI;EACbC,mBAAmB,GAAG,EAAE;EACxBC,aAAa;EACbC,aAAa;EACbC,cAAc,GAAG,IAAI;EACrBC,SAAS;EACT,GAAGC;AACc,CAAC,EAAE;EACpB,MAAMC,OAAO,GAAGpB,eAAe,CAAC,CAAC;EACjC,MAAM;IAAEqB,MAAM,EAAEC;EAAa,CAAC,GAAGxB,mBAAmB,CAAC,CAAC;EACtD,MAAMuB,MAAM,GAAGX,UAAU,IAAIY,YAAY;EACzC,MAAM,CAACC,SAAS,EAAEC,YAAY,CAAC,GAAG7B,QAAQ,CAAgB,IAAI,CAAC;;EAE/D;EACAF,SAAS,CAAC,MAAM;IACd,IAAImB,KAAK,EAAE;MACTQ,OAAO,CAACK,IAAI,CAAC,CAAC;IAChB,CAAC,MAAM;MACLL,OAAO,CAACM,MAAM,CAAC,CAAC;IAClB;EACF,CAAC,EAAE,CAACN,OAAO,EAAER,KAAK,CAAC,CAAC;EAEpBnB,SAAS,CAAC,MAAM;IACd2B,OAAO,CAACO,SAAS,CAACd,MAAM,CAAC;EAC3B,CAAC,EAAE,CAACO,OAAO,EAAEP,MAAM,CAAC,CAAC;EAErBpB,SAAS,CAAC,MAAM;IACd,IAAIkB,UAAU,EAAE;MACdS,OAAO,CAACQ,aAAa,CAACjB,UAAU,CAAC;IACnC;EACF,CAAC,EAAE,CAACS,OAAO,EAAET,UAAU,CAAC,CAAC;EAEzBlB,SAAS,CAAC,MAAM;IACd,OAAO,MAAM;MACX,IAAIwB,cAAc,EAAE;QAClBG,OAAO,CAACS,KAAK,CAAC,CAAC;MACjB;IACF,CAAC;EACH,CAAC,EAAE,CAACT,OAAO,EAAEH,cAAc,CAAC,CAAC;EAE7BxB,SAAS,CAAC,MAAM;IACd,IAAIyB,SAAS,KAAKY,SAAS,EAAE;MAC3B;IACF;IACA,IAAI,CAACZ,SAAS,EAAE;MACd,IACEE,OAAO,CAACW,KAAK,CAACC,QAAQ,CAAC,CAAC,CAACC,SAAS,KAAK3B,aAAa,CAACiB,SAAS,IAAI,EAAE,CAAC,EACrE;QACAH,OAAO,CAACS,KAAK,CAAC,CAAC;MACjB;MACA;IACF;IACA;IACA,MAAMK,IAAI,GAAGzB,IAAI,CAAC0B,IAAI,CAAEC,CAAC,IAAKA,CAAC,CAAC7B,EAAE,KAAKgB,SAAS,CAAC;IACjD,IAAIW,IAAI,EAAE;MACRd,OAAO,CAACiB,SAAS,CAACH,IAAI,EAAE;QACtBI,QAAQ,EAAE,IAAI;QACdL,SAAS,EAAE3B,aAAa,CAAC4B,IAAI,CAAC3B,EAAE;MAClC,CAAC,CAAC;IACJ;EACF,CAAC,EAAE,CAACa,OAAO,EAAEF,SAAS,EAAEK,SAAS,EAAEd,IAAI,CAAC,CAAC;EAEzC,MAAM8B,KAAK,GAAG/C,WAAW,CACvB,CAAC0C,IAAc,EAAEM,KAAa,KAAK;IACjChB,YAAY,CAACU,IAAI,EAAE3B,EAAE,IAAI,IAAI,CAAC;IAC9B,IAAI2B,IAAI,EAAE;MACR;MACA;MACA;MACAd,OAAO,CAACiB,SAAS,CAACH,IAAI,EAAE;QACtBI,QAAQ,EAAE,IAAI;QACdL,SAAS,EAAE3B,aAAa,CAAC4B,IAAI,CAAC3B,EAAE;MAClC,CAAC,CAAC;IACJ;IACAS,aAAa,GAAGkB,IAAI,EAAEM,KAAK,CAAC;EAC9B,CAAC,EACD,CAACpB,OAAO,EAAEJ,aAAa,CACzB,CAAC;;EAED;EACA;EACA,MAAMyB,MAAM,GAAG/C,MAAM,CAAC;IAAE6C,KAAK;IAAE9B;EAAK,CAAC,CAAC;EACtCgC,MAAM,CAACC,OAAO,GAAG;IAAEH,KAAK;IAAE9B;EAAK,CAAC;EAEhC,MAAMkC,iBAAiB,GAAGjD,MAAM,CAAC;IAC/BkD,2BAA2B,EAAE9B,mBAAmB;IAChD+B,eAAe,EAAE;EACnB,CAAC,CAAC,CAACH,OAAO;EAEV,MAAMI,sBAAsB,GAAGpD,MAAM,CACnC,CAAC;IAAEqD;EAAkD,CAAC,KAAK;IACzD,MAAMC,YAAY,GAAGD,aAAa,CAACZ,IAAI,CAAEc,CAAC,IAAKA,CAAC,CAACC,UAAU,CAAC;IAC5D,IAAIF,YAAY,EAAE;MAChBP,MAAM,CAACC,OAAO,CAACH,KAAK,CAACS,YAAY,CAACd,IAAI,EAAOc,YAAY,CAACR,KAAK,IAAI,CAAC,CAAC;IACvE;EACF,CACF,CAAC,CAACE,OAAO;EAET,MAAMS,UAAU,GAAG3D,WAAW,CAC5B,CAAC;IAAE0C,IAAI;IAAEM;EAAkC,CAAC,kBAC1CnC,KAAA,CAACN,IAAI;IAACqD,KAAK,EAAE,CAACC,MAAM,CAACnB,IAAI,EAAE;MAAEb;IAAO,CAAC,CAAE;IAAAiC,QAAA,gBACrCnD,IAAA,CAACF,YAAY;MACXgC,SAAS,EAAE3B,aAAa,CAAC4B,IAAI,CAAC3B,EAAE,CAAE;MAClC6C,KAAK,EAAEvD,UAAU,CAAC0D;IAAa,CAChC,CAAC,EACDxC,aAAa,GAAG;MAAEmB,IAAI;MAAEM,KAAK;MAAEgB,OAAO,EAAEtB,IAAI,CAAC3B,EAAE,KAAKgB;IAAU,CAAC,CAAC;EAAA,CAC7D,CACP,EACD,CAACF,MAAM,EAAEN,aAAa,EAAEQ,SAAS,CACnC,CAAC;EAED,oBACEpB,IAAA,CAACP,QAAQ;IACPa,IAAI,EAAEA,IAAK;IACXgD,YAAY,EAAGvB,IAAI,IAAKA,IAAI,CAAC3B,EAAG;IAChC4C,UAAU,EAAEA,UAAW;IACvBL,sBAAsB,EAAEA,sBAAuB;IAC/CH,iBAAiB,EAAEA,iBAAkB;IACrCe,aAAa,EAAEA,CAACC,CAAC,EAAEnB,KAAK,MAAM;MAC5BoB,MAAM,EAAEvC,MAAM;MACdwC,MAAM,EAAExC,MAAM,GAAGmB,KAAK;MACtBA;IACF,CAAC,CAAE;IACHsB,4BAA4B,EAAE,KAAM;IACpCC,cAAc,EAAE1C,MAAO;IACvB2C,eAAe,EAAC,OAAO;IACvBC,gBAAgB,EAAC,MAAM;IAAA,GACnB9C;EAAI,CACT,CAAC;AAEN;AAEA,MAAMkC,MAAM,GAAGxD,UAAU,CAACqE,MAAM,CAAC;EAC/BhC,IAAI,EAAE;IACJiC,KAAK,EAAE,MAAM;IACbC,eAAe,EAAE,MAAM;IACvBC,QAAQ,EAAE;EACZ;AACF,CAAC,CAAC","ignoreList":[]}
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
 
3
- import { forwardRef, useEffect, useImperativeHandle } from 'react';
4
- import { AppState, StyleSheet, View } from 'react-native';
3
+ import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
4
+ import { AppState, Dimensions, StyleSheet, View } from 'react-native';
5
5
  import { useVideoManager } from "../provider/VideoContext.js";
6
+ import { usePlayback } from "../hooks/usePlayback.js";
6
7
  import { useVideoEvents } from "../hooks/useVideoEvents.js";
7
8
  import { VideoControls } from "./VideoControls.js";
8
9
  import { VideoSurface } from "./VideoSurface.js";
@@ -31,6 +32,10 @@ export const VideoPlayer = /*#__PURE__*/forwardRef(({
31
32
  orientation,
32
33
  fullscreenOrientation,
33
34
  pauseOnFocusLost = true,
35
+ isFocused,
36
+ live = false,
37
+ liveIcon,
38
+ thumbnail,
34
39
  onLoadComplete,
35
40
  onBuffering,
36
41
  onError,
@@ -39,10 +44,21 @@ export const VideoPlayer = /*#__PURE__*/forwardRef(({
39
44
  }, ref) => {
40
45
  const manager = useVideoManager();
41
46
  const id = surfaceId ?? `player:${source.id}`;
47
+
48
+ // Poster is shown only during the initial load — `loading` is true from
49
+ // setSource until onLoad, and stays false for mid-stream buffering.
50
+ const loading = usePlayback(s => s.loading);
51
+
52
+ // Read the latest source without retriggering effects on every render
53
+ // (source is usually a fresh object literal each render).
54
+ const sourceRef = useRef(source);
55
+ sourceRef.current = source;
42
56
  useImperativeHandle(ref, () => manager, [manager]);
43
57
  useEffect(() => {
58
+ // Don't autoplay a player that mounts already unfocused (isFocused
59
+ // false), else it'd flash play → pause on the next screen.
44
60
  manager.setSource(source, {
45
- autoplay,
61
+ autoplay: autoplay && isFocused !== false,
46
62
  surfaceId: id
47
63
  });
48
64
  // Attach on mount / when the video identity changes. Other source
@@ -84,6 +100,37 @@ export const VideoPlayer = /*#__PURE__*/forwardRef(({
84
100
  manager.setFullscreenOrientation(fullscreenOrientation);
85
101
  return () => manager.setFullscreenOrientation(null);
86
102
  }, [manager, fullscreenOrientation]);
103
+
104
+ // Auto fullscreen on physical rotation (YouTube-style): when
105
+ // `fullscreenOrientation` is a landscape value, rotating the device to
106
+ // landscape enters fullscreen and rotating back to portrait exits.
107
+ // Enters with 'auto' (not a forced lock) so the device sensor keeps
108
+ // driving and rotating back can exit. Requires the app to actually allow
109
+ // landscape (Info.plist / AndroidManifest) — otherwise the window never
110
+ // reports landscape and this stays inert.
111
+ useEffect(() => {
112
+ const wantsLandscape = fullscreenOrientation === 'landscape' || fullscreenOrientation === 'inverted-landscape';
113
+ if (!wantsLandscape) {
114
+ return;
115
+ }
116
+ const onChange = ({
117
+ window
118
+ }) => {
119
+ const landscape = window.width > window.height;
120
+ const state = manager.store.getState();
121
+ // Ignore when another video owns the engine and we're not fullscreen.
122
+ if (state.surfaceId !== id && !state.fullscreen) {
123
+ return;
124
+ }
125
+ if (landscape && !state.fullscreen) {
126
+ manager.enterFullscreen('auto');
127
+ } else if (!landscape && state.fullscreen) {
128
+ manager.exitFullscreen();
129
+ }
130
+ };
131
+ const sub = Dimensions.addEventListener('change', onChange);
132
+ return () => sub.remove();
133
+ }, [manager, id, fullscreenOrientation]);
87
134
  useEffect(() => {
88
135
  if (!pauseOnFocusLost) {
89
136
  return;
@@ -97,6 +144,29 @@ export const VideoPlayer = /*#__PURE__*/forwardRef(({
97
144
  });
98
145
  return () => sub.remove();
99
146
  }, [manager, id, pauseOnFocusLost]);
147
+ useEffect(() => {
148
+ if (isFocused === undefined) {
149
+ return;
150
+ }
151
+ const state = manager.store.getState();
152
+ if (isFocused) {
153
+ // Regained screen focus. If the engine is still ours, just resume;
154
+ // otherwise it moved to another video while we were blurred — reclaim
155
+ // it (same-id handoff means no reload if it never actually left).
156
+ if (state.surfaceId === id && state.currentVideo?.id === sourceRef.current.id) {
157
+ manager.play();
158
+ } else {
159
+ manager.setSource(sourceRef.current, {
160
+ autoplay: true,
161
+ surfaceId: id
162
+ });
163
+ }
164
+ } else if (state.surfaceId === id) {
165
+ // Lost screen focus while playing our video — pause. Guarded so we
166
+ // never pause a video that has already handed off elsewhere.
167
+ manager.pause();
168
+ }
169
+ }, [manager, id, isFocused]);
100
170
  useVideoEvents({
101
171
  onLoad: onLoadComplete,
102
172
  onBuffer: e => onBuffering?.(e.buffering),
@@ -108,7 +178,14 @@ export const VideoPlayer = /*#__PURE__*/forwardRef(({
108
178
  children: [/*#__PURE__*/_jsx(VideoSurface, {
109
179
  surfaceId: id,
110
180
  style: styles.surface
111
- }), controls ? /*#__PURE__*/_jsx(VideoControls, {}) : null]
181
+ }), thumbnail && loading ? /*#__PURE__*/_jsx(View, {
182
+ style: styles.surface,
183
+ pointerEvents: "none",
184
+ children: thumbnail()
185
+ }) : null, controls ? /*#__PURE__*/_jsx(VideoControls, {
186
+ live: live,
187
+ liveIcon: liveIcon
188
+ }) : null]
112
189
  });
113
190
  });
114
191
  VideoPlayer.displayName = 'VideoPlayer';
@@ -1 +1 @@
1
- {"version":3,"names":["forwardRef","useEffect","useImperativeHandle","AppState","StyleSheet","View","useVideoManager","useVideoEvents","VideoControls","VideoSurface","jsx","_jsx","jsxs","_jsxs","VideoPlayer","source","autoplay","surfaceId","controls","resizeMode","repeat","muted","orientation","fullscreenOrientation","pauseOnFocusLost","onLoadComplete","onBuffering","onError","style","rest","ref","manager","id","setSource","setResizeMode","undefined","setRepeat","mute","unmute","setOrientation","setFullscreenOrientation","sub","addEventListener","next","store","getState","pause","remove","onLoad","onBuffer","e","buffering","styles","container","children","surface","displayName","create","backgroundColor","overflow","position","top","left","right","bottom"],"sourceRoot":"../../../src","sources":["components/VideoPlayer.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["forwardRef","useEffect","useImperativeHandle","useRef","AppState","Dimensions","StyleSheet","View","useVideoManager","usePlayback","useVideoEvents","VideoControls","VideoSurface","jsx","_jsx","jsxs","_jsxs","VideoPlayer","source","autoplay","surfaceId","controls","resizeMode","repeat","muted","orientation","fullscreenOrientation","pauseOnFocusLost","isFocused","live","liveIcon","thumbnail","onLoadComplete","onBuffering","onError","style","rest","ref","manager","id","loading","s","sourceRef","current","setSource","setResizeMode","undefined","setRepeat","mute","unmute","setOrientation","setFullscreenOrientation","wantsLandscape","onChange","window","landscape","width","height","state","store","getState","fullscreen","enterFullscreen","exitFullscreen","sub","addEventListener","remove","next","pause","currentVideo","play","onLoad","onBuffer","e","buffering","styles","container","children","surface","pointerEvents","displayName","create","backgroundColor","overflow","position","top","left","right","bottom"],"sourceRoot":"../../../src","sources":["components/VideoPlayer.tsx"],"mappings":"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","ignoreList":[]}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- import Svg, { Line, Path, Polygon, Rect } from 'react-native-svg';
3
+ import Svg, { ClipPath, Defs, G, Line, Path, Polygon, Rect } from 'react-native-svg';
4
4
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
5
5
  export function PlayIcon({
6
6
  size,
@@ -41,6 +41,37 @@ export function PauseIcon({
41
41
  export function CloseIcon({
42
42
  size,
43
43
  color
44
+ }) {
45
+ return /*#__PURE__*/_jsxs(Svg, {
46
+ width: size || 20,
47
+ height: size || 21,
48
+ viewBox: "0 0 20 21",
49
+ fill: "none",
50
+ children: [/*#__PURE__*/_jsx(G, {
51
+ clipPath: "url(#clip0_25_6005)",
52
+ children: /*#__PURE__*/_jsx(Path, {
53
+ d: "M12.5 16.3069L6.25 10.0569L12.5 3.80688",
54
+ stroke: color || '#000000',
55
+ strokeWidth: 1.25,
56
+ strokeLinecap: "round",
57
+ strokeLinejoin: "round"
58
+ })
59
+ }), /*#__PURE__*/_jsx(Defs, {
60
+ children: /*#__PURE__*/_jsx(ClipPath, {
61
+ id: "clip0_25_6005",
62
+ children: /*#__PURE__*/_jsx(Rect, {
63
+ width: size || 20,
64
+ height: size || 21,
65
+ fill: "white",
66
+ transform: "translate(0 0.0568848)"
67
+ })
68
+ })
69
+ })]
70
+ });
71
+ }
72
+ export function BackIcon({
73
+ size,
74
+ color
44
75
  }) {
45
76
  return /*#__PURE__*/_jsxs(Svg, {
46
77
  width: size,
@@ -1 +1 @@
1
- {"version":3,"names":["Svg","Line","Path","Polygon","Rect","jsx","_jsx","jsxs","_jsxs","PlayIcon","size","color","width","height","viewBox","fill","children","points","PauseIcon","x","y","CloseIcon","stroke","strokeWidth","strokeLinecap","x1","y1","x2","y2","VolumeOnIcon","strokeLinejoin","d","VolumeOffIcon","EnterFullscreenIcon","ExitFullscreenIcon"],"sourceRoot":"../../../src","sources":["components/icons.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["Svg","ClipPath","Defs","G","Line","Path","Polygon","Rect","jsx","_jsx","jsxs","_jsxs","PlayIcon","size","color","width","height","viewBox","fill","children","points","PauseIcon","x","y","CloseIcon","clipPath","d","stroke","strokeWidth","strokeLinecap","strokeLinejoin","id","transform","BackIcon","x1","y1","x2","y2","VolumeOnIcon","VolumeOffIcon","EnterFullscreenIcon","ExitFullscreenIcon"],"sourceRoot":"../../../src","sources":["components/icons.tsx"],"mappings":"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","ignoreList":[]}
@@ -1,3 +1,4 @@
1
+ import { type ReactNode } from 'react';
1
2
  export interface VideoControlsProps {
2
3
  /** Seconds jumped by double-tap. Default 10. */
3
4
  doubleTapSeek?: number;
@@ -5,6 +6,16 @@ export interface VideoControlsProps {
5
6
  hideAfter?: number;
6
7
  /** Show the fullscreen toggle button. Default true. */
7
8
  showFullscreenButton?: boolean;
9
+ /**
10
+ * Mark this as a live stream: hides the seek bar/times and moves mute to
11
+ * the bottom-left. Default false.
12
+ */
13
+ live?: boolean;
14
+ /**
15
+ * Render a live indicator (e.g. a Lottie animation or a "LIVE" badge),
16
+ * shown in the control bar only while `live`.
17
+ */
18
+ liveIcon?: () => ReactNode;
8
19
  /** Called by the close (✕) button; button hidden when omitted. */
9
20
  onClose?: () => void;
10
21
  }
@@ -13,5 +24,5 @@ export interface VideoControlsProps {
13
24
  * toggles, with tap-to-show / double-tap-to-seek gestures. Apps wanting a
14
25
  * custom design can ignore this and build on usePlayback()/useVideo().
15
26
  */
16
- export declare function VideoControls({ doubleTapSeek, hideAfter, showFullscreenButton, onClose, }: VideoControlsProps): import("react").JSX.Element;
27
+ export declare function VideoControls({ doubleTapSeek, hideAfter, showFullscreenButton, live, liveIcon, onClose, }: VideoControlsProps): import("react").JSX.Element;
17
28
  //# sourceMappingURL=VideoControls.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"VideoControls.d.ts","sourceRoot":"","sources":["../../../../src/components/VideoControls.tsx"],"names":[],"mappings":"AAgBA,MAAM,WAAW,kBAAkB;IACjC,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,EAC5B,aAAkB,EAClB,SAAgB,EAChB,oBAA2B,EAC3B,OAAO,GACR,EAAE,kBAAkB,+BAsJpB"}
1
+ {"version":3,"file":"VideoControls.d.ts","sourceRoot":"","sources":["../../../../src/components/VideoControls.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAgBf,MAAM,WAAW,kBAAkB;IACjC,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,SAAS,CAAC;IAC3B,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,EAC5B,aAAkB,EAClB,SAAgB,EAChB,oBAA2B,EAC3B,IAAY,EACZ,QAAQ,EACR,OAAO,GACR,EAAE,kBAAkB,+BAiJpB"}
@@ -27,6 +27,13 @@ export interface VideoFeedProps<T extends VideoSource> extends Omit<FlatListProp
27
27
  onFocusChange?: (item: T | null, index: number) => void;
28
28
  /** Pause playback when the feed unmounts. Default `true`. */
29
29
  pauseOnUnmount?: boolean;
30
+ /**
31
+ * Screen-focus flag from your navigation library — e.g. React Navigation's
32
+ * `useIsFocused()`. `false` pauses the feed; returning to `true` resumes the
33
+ * item that was in view. Needed because navigating away keeps the feed
34
+ * mounted and the app foregrounded. Leave undefined if you don't navigate.
35
+ */
36
+ isFocused?: boolean;
30
37
  }
31
38
  /**
32
39
  * A single-engine video feed: render many videos in a scrollable list, but
@@ -45,5 +52,5 @@ export interface VideoFeedProps<T extends VideoSource> extends Omit<FlatListProp
45
52
  * />
46
53
  * ```
47
54
  */
48
- export declare function VideoFeed<T extends VideoSource>({ data, itemHeight, resizeMode, muted, repeat, visibilityThreshold, renderOverlay, onFocusChange, pauseOnUnmount, ...rest }: VideoFeedProps<T>): import("react").JSX.Element;
55
+ export declare function VideoFeed<T extends VideoSource>({ data, itemHeight, resizeMode, muted, repeat, visibilityThreshold, renderOverlay, onFocusChange, pauseOnUnmount, isFocused, ...rest }: VideoFeedProps<T>): import("react").JSX.Element;
49
56
  //# sourceMappingURL=VideoFeed.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"VideoFeed.d.ts","sourceRoot":"","sources":["../../../../src/components/VideoFeed.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAgB,CAAC;AAG9D,8CAA8C;AAC9C,eAAO,MAAM,aAAa,GAAI,IAAI,MAAM,WAAiB,CAAC;AAS1D,MAAM,WAAW,mBAAmB,CAAC,CAAC;IACpC,IAAI,EAAE,CAAC,CAAC;IACR,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,WAAW,CAAE,SAAQ,IAAI,CACjE,aAAa,CAAC,CAAC,CAAC,EACd,MAAM,GACN,YAAY,GACZ,cAAc,GACd,wBAAwB,GACxB,mBAAmB,GACnB,eAAe,CAClB;IACC,6EAA6E;IAC7E,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,kFAAkF;IAClF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,yEAAyE;IACzE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,6EAA6E;IAC7E,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,+EAA+E;IAC/E,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;IAC5D,wEAAwE;IACxE,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,6DAA6D;IAC7D,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,WAAW,EAAE,EAC/C,IAAI,EACJ,UAAU,EACV,UAAU,EACV,KAAY,EACZ,MAAa,EACb,mBAAwB,EACxB,aAAa,EACb,aAAa,EACb,cAAqB,EACrB,GAAG,IAAI,EACR,EAAE,cAAc,CAAC,CAAC,CAAC,+BAqGnB"}
1
+ {"version":3,"file":"VideoFeed.d.ts","sourceRoot":"","sources":["../../../../src/components/VideoFeed.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAgB,CAAC;AAG9D,8CAA8C;AAC9C,eAAO,MAAM,aAAa,GAAI,IAAI,MAAM,WAAiB,CAAC;AAS1D,MAAM,WAAW,mBAAmB,CAAC,CAAC;IACpC,IAAI,EAAE,CAAC,CAAC;IACR,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,WAAW,CAAE,SAAQ,IAAI,CACjE,aAAa,CAAC,CAAC,CAAC,EACd,MAAM,GACN,YAAY,GACZ,cAAc,GACd,wBAAwB,GACxB,mBAAmB,GACnB,eAAe,CAClB;IACC,6EAA6E;IAC7E,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,kFAAkF;IAClF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,yEAAyE;IACzE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,6EAA6E;IAC7E,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,+EAA+E;IAC/E,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;IAC5D,wEAAwE;IACxE,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,6DAA6D;IAC7D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,WAAW,EAAE,EAC/C,IAAI,EACJ,UAAU,EACV,UAAU,EACV,KAAY,EACZ,MAAa,EACb,mBAAwB,EACxB,aAAa,EACb,aAAa,EACb,cAAqB,EACrB,SAAS,EACT,GAAG,IAAI,EACR,EAAE,cAAc,CAAC,CAAC,CAAC,+BA2HnB"}
@@ -1,3 +1,4 @@
1
+ import { type ReactNode } from 'react';
1
2
  import { type ViewProps } from 'react-native';
2
3
  import { VideoManager } from '../core/VideoManager.js';
3
4
  import type { VideoEventMap } from '../types/events.js';
@@ -30,6 +31,11 @@ export interface VideoPlayerProps extends ViewProps {
30
31
  * `'portrait'` for a vertical video). Applied when fullscreen opens —
31
32
  * including via the built-in controls' fullscreen button — and restored
32
33
  * when it closes, so the rest of the app is unaffected.
34
+ *
35
+ * When set to a landscape value (`'landscape'` / `'inverted-landscape'`),
36
+ * physically rotating the device to landscape also auto-enters fullscreen,
37
+ * and rotating back to portrait exits it (YouTube-style). This needs the
38
+ * app to allow landscape orientations at the OS level.
33
39
  */
34
40
  fullscreenOrientation?: OrientationLock;
35
41
  /**
@@ -39,6 +45,35 @@ export interface VideoPlayerProps extends ViewProps {
39
45
  * Only the focused player acts, so a video attached elsewhere is untouched.
40
46
  */
41
47
  pauseOnFocusLost?: boolean;
48
+ /**
49
+ * Screen-focus flag from your navigation library — e.g. React Navigation's
50
+ * `useIsFocused()`. `false` pauses this player; returning to `true` reclaims
51
+ * the engine and resumes this video. This is the only reliable way to pause
52
+ * on screen navigation (React Navigation keeps screens mounted and the app
53
+ * stays foregrounded, so unmount/AppState never fire). Leave undefined if
54
+ * you don't use navigation.
55
+ *
56
+ * ```tsx
57
+ * const isFocused = useIsFocused(); // @react-navigation/native
58
+ * <VideoPlayer source={video} isFocused={isFocused} />
59
+ * ```
60
+ */
61
+ isFocused?: boolean;
62
+ /**
63
+ * Mark this as a live stream: the built-in controls hide the seek bar/times
64
+ * and show `liveIcon` (if given). Default false.
65
+ */
66
+ live?: boolean;
67
+ /**
68
+ * Render a live indicator shown in the controls while `live` — e.g. a
69
+ * Lottie animation or a "LIVE" badge: `liveIcon={() => <LottieView … />}`.
70
+ */
71
+ liveIcon?: () => ReactNode;
72
+ /**
73
+ * Render a poster shown over the video only during the initial load
74
+ * (before the first frame) — e.g. `thumbnail={() => <Image … />}`.
75
+ */
76
+ thumbnail?: () => ReactNode;
42
77
  /** Fires once metadata (duration, dimensions) is available. */
43
78
  onLoadComplete?: (info: VideoEventMap['onLoad']) => void;
44
79
  /** Fires whenever buffering starts or stops. */
@@ -1 +1 @@
1
- {"version":3,"file":"VideoPlayer.d.ts","sourceRoot":"","sources":["../../../../src/components/VideoPlayer.tsx"],"names":[],"mappings":"AACA,OAAO,EAA8B,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAsB,CAAC;AAGpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAiB,CAAC;AACrD,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EACV,UAAU,EACV,WAAW,EACZ,MAAM,mBAAgB,CAAC;AAIxB,MAAM,WAAW,gBAAiB,SAAQ,SAAS;IACjD,MAAM,EAAE,WAAW,CAAC;IACpB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,iDAAiD;IACjD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,qBAAqB;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,eAAe,CAAC;IACxC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,+DAA+D;IAC/D,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;IACzD,gDAAgD;IAChD,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACvC;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,2GAoGvB,CAAC"}
1
+ {"version":3,"file":"VideoPlayer.d.ts","sourceRoot":"","sources":["../../../../src/components/VideoPlayer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAsB,CAAC;AAIpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAiB,CAAC;AACrD,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EACV,UAAU,EACV,WAAW,EACZ,MAAM,mBAAgB,CAAC;AAIxB,MAAM,WAAW,gBAAiB,SAAQ,SAAS;IACjD,MAAM,EAAE,WAAW,CAAC;IACpB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,iDAAiD;IACjD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,qBAAqB;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B;;;;;;;;;;OAUG;IACH,qBAAqB,CAAC,EAAE,eAAe,CAAC;IACxC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,SAAS,CAAC;IAC3B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,SAAS,CAAC;IAC5B,+DAA+D;IAC/D,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;IACzD,gDAAgD;IAChD,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACvC;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,2GAyLvB,CAAC"}
@@ -5,6 +5,7 @@ interface IconProps {
5
5
  export declare function PlayIcon({ size, color }: IconProps): import("react").JSX.Element;
6
6
  export declare function PauseIcon({ size, color }: IconProps): import("react").JSX.Element;
7
7
  export declare function CloseIcon({ size, color }: IconProps): import("react").JSX.Element;
8
+ export declare function BackIcon({ size, color }: IconProps): import("react").JSX.Element;
8
9
  export declare function VolumeOnIcon({ size, color }: IconProps): import("react").JSX.Element;
9
10
  export declare function VolumeOffIcon({ size, color }: IconProps): import("react").JSX.Element;
10
11
  export declare function EnterFullscreenIcon({ size, color }: IconProps): import("react").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../../../src/components/icons.tsx"],"names":[],"mappings":"AAEA,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,+BAMlD;AAED,wBAAgB,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,+BAOnD;AAED,wBAAgB,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,+BAenD;AAED,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,+BAgBtD;AAED,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,+BAiBvD;AAED,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,+BAkB7D;AAED,wBAAgB,kBAAkB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,+BAkB5D"}
1
+ {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../../../src/components/icons.tsx"],"names":[],"mappings":"AAUA,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,+BAMlD;AAED,wBAAgB,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,+BAOnD;AAED,wBAAgB,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,+BAwBnD;AAED,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,+BAelD;AAED,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,+BAgBtD;AAED,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,+BAiBvD;AAED,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,+BAkB7D;AAED,wBAAgB,kBAAkB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,+BAkB5D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-video-provider",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "Singleton-engine video library for React Native (one native player, many surfaces)",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -1,11 +1,21 @@
1
1
  'use strict';
2
2
 
3
3
  /**
4
- * Prints a banner after install. Wrapped so it can NEVER fail a consumer's
5
- * `npm install` — any error is swallowed and the process always exits 0.
6
- * Skipped in CI and non-interactive shells to avoid polluting build logs.
4
+ * Prints a banner. Wrapped so it can NEVER fail a consumer's `npm install`
5
+ * or native build — any error is swallowed and the process always exits 0.
6
+ *
7
+ * Run modes:
8
+ * node scripts/postinstall.js → install banner (skipped in CI /
9
+ * non-interactive shells)
10
+ * node scripts/postinstall.js --force → always print (used by the
11
+ * Android build so it shows while
12
+ * compiling the app, where stdout
13
+ * is not a TTY)
7
14
  */
8
15
 
16
+ const force =
17
+ process.argv.includes('--force') || process.env.AU_VIDEO_BANNER === '1';
18
+
9
19
  const BANNER = `
10
20
  ++
11
21
  +++ +++ +++++++++++ ++
@@ -24,10 +34,14 @@ const BANNER = `
24
34
 
25
35
  try {
26
36
  const quiet = process.env.CI || process.env.npm_config_loglevel === 'silent';
27
- if (!quiet && process.stdout && process.stdout.isTTY) {
28
- const cyan = '\x1b[36m';
29
- const dim = '\x1b[2m';
30
- const reset = '\x1b[0m';
37
+ const show = force || (!quiet && process.stdout && process.stdout.isTTY);
38
+ if (show) {
39
+ // Colorize only in a real terminal — under Gradle/CI (--force, not a TTY)
40
+ // stay plain so the log doesn't fill with raw escape codes.
41
+ const color = process.stdout && process.stdout.isTTY;
42
+ const cyan = color ? '\x1b[36m' : '';
43
+ const dim = color ? '\x1b[2m' : '';
44
+ const reset = color ? '\x1b[0m' : '';
31
45
  process.stdout.write(cyan + BANNER + reset + '\n');
32
46
  process.stdout.write(
33
47
  dim +
@@ -1,4 +1,10 @@
1
- import { useCallback, useEffect, useRef, useState } from 'react';
1
+ import {
2
+ useCallback,
3
+ useEffect,
4
+ useRef,
5
+ useState,
6
+ type ReactNode,
7
+ } from 'react';
2
8
  import {
3
9
  Pressable,
4
10
  StyleSheet,
@@ -11,7 +17,7 @@ import { useVideoManager } from '../provider/VideoContext';
11
17
  import { usePlayback } from '../hooks/usePlayback';
12
18
  import { formatTime } from '../utils/formatTime';
13
19
  import { GestureOverlay } from './GestureOverlay';
14
- import { CloseIcon } from './icons';
20
+ import { BackIcon } from './icons';
15
21
  import SvgIcons from './SvgIcons';
16
22
 
17
23
  export interface VideoControlsProps {
@@ -21,6 +27,16 @@ export interface VideoControlsProps {
21
27
  hideAfter?: number;
22
28
  /** Show the fullscreen toggle button. Default true. */
23
29
  showFullscreenButton?: boolean;
30
+ /**
31
+ * Mark this as a live stream: hides the seek bar/times and moves mute to
32
+ * the bottom-left. Default false.
33
+ */
34
+ live?: boolean;
35
+ /**
36
+ * Render a live indicator (e.g. a Lottie animation or a "LIVE" badge),
37
+ * shown in the control bar only while `live`.
38
+ */
39
+ liveIcon?: () => ReactNode;
24
40
  /** Called by the close (✕) button; button hidden when omitted. */
25
41
  onClose?: () => void;
26
42
  }
@@ -34,22 +50,18 @@ export function VideoControls({
34
50
  doubleTapSeek = 10,
35
51
  hideAfter = 3000,
36
52
  showFullscreenButton = true,
53
+ live = false,
54
+ liveIcon,
37
55
  onClose,
38
56
  }: VideoControlsProps) {
39
57
  const manager = useVideoManager();
40
- const status = usePlayback((s) => s.status);
41
58
  const playing = usePlayback((s) => s.playing);
42
59
  const buffering = usePlayback((s) => s.buffering);
43
- const loading = usePlayback((s) => s.loading);
44
60
  const position = usePlayback((s) => s.position);
45
61
  const duration = usePlayback((s) => s.duration);
46
62
  const muted = usePlayback((s) => s.muted);
47
63
  const fullscreen = usePlayback((s) => s.fullscreen);
48
64
 
49
- // No known duration once loaded — a live stream or a video with no fixed
50
- // end. There's nothing to seek, so hide the seek bar entirely.
51
- const live = status !== 'idle' && !loading && duration <= 0;
52
-
53
65
  const [visible, setVisible] = useState(true);
54
66
  const hideTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
55
67
  const trackWidth = useRef(0);
@@ -131,7 +143,7 @@ export function VideoControls({
131
143
  <View style={styles.topRow}>
132
144
  {onClose ? (
133
145
  <Pressable style={styles.button} onPress={onClose} hitSlop={8}>
134
- <CloseIcon size={18} color="#fff" />
146
+ <BackIcon size={18} color="#fff" />
135
147
  </Pressable>
136
148
  ) : (
137
149
  <View />
@@ -159,6 +171,7 @@ export function VideoControls({
159
171
  <View style={styles.bottomRow}>
160
172
  {live ? (
161
173
  <>
174
+ {liveIcon ? liveIcon() : null}
162
175
  {muteButton}
163
176
  <View style={styles.spacer} />
164
177
  {fullscreenButton}
@@ -59,6 +59,13 @@ export interface VideoFeedProps<T extends VideoSource> extends Omit<
59
59
  onFocusChange?: (item: T | null, index: number) => void;
60
60
  /** Pause playback when the feed unmounts. Default `true`. */
61
61
  pauseOnUnmount?: boolean;
62
+ /**
63
+ * Screen-focus flag from your navigation library — e.g. React Navigation's
64
+ * `useIsFocused()`. `false` pauses the feed; returning to `true` resumes the
65
+ * item that was in view. Needed because navigating away keeps the feed
66
+ * mounted and the app foregrounded. Leave undefined if you don't navigate.
67
+ */
68
+ isFocused?: boolean;
62
69
  }
63
70
 
64
71
  /**
@@ -88,6 +95,7 @@ export function VideoFeed<T extends VideoSource>({
88
95
  renderOverlay,
89
96
  onFocusChange,
90
97
  pauseOnUnmount = true,
98
+ isFocused,
91
99
  ...rest
92
100
  }: VideoFeedProps<T>) {
93
101
  const manager = useVideoManager();
@@ -122,6 +130,28 @@ export function VideoFeed<T extends VideoSource>({
122
130
  };
123
131
  }, [manager, pauseOnUnmount]);
124
132
 
133
+ useEffect(() => {
134
+ if (isFocused === undefined) {
135
+ return;
136
+ }
137
+ if (!isFocused) {
138
+ if (
139
+ manager.store.getState().surfaceId === feedSurfaceId(focusedId ?? '')
140
+ ) {
141
+ manager.pause();
142
+ }
143
+ return;
144
+ }
145
+ // Screen regained focus — resume the item that was in view.
146
+ const item = data.find((d) => d.id === focusedId);
147
+ if (item) {
148
+ manager.setSource(item, {
149
+ autoplay: true,
150
+ surfaceId: feedSurfaceId(item.id),
151
+ });
152
+ }
153
+ }, [manager, isFocused, focusedId, data]);
154
+
125
155
  const focus = useCallback(
126
156
  (item: T | null, index: number) => {
127
157
  setFocusedId(item?.id ?? null);
@@ -1,7 +1,20 @@
1
- import { forwardRef, useEffect, useImperativeHandle } from 'react';
2
- import { AppState, StyleSheet, View, type ViewProps } from 'react-native';
1
+ import {
2
+ forwardRef,
3
+ useEffect,
4
+ useImperativeHandle,
5
+ useRef,
6
+ type ReactNode,
7
+ } from 'react';
8
+ import {
9
+ AppState,
10
+ Dimensions,
11
+ StyleSheet,
12
+ View,
13
+ type ViewProps,
14
+ } from 'react-native';
3
15
  import { VideoManager } from '../core/VideoManager';
4
16
  import { useVideoManager } from '../provider/VideoContext';
17
+ import { usePlayback } from '../hooks/usePlayback';
5
18
  import { useVideoEvents } from '../hooks/useVideoEvents';
6
19
  import type { VideoEventMap } from '../types/events';
7
20
  import type {
@@ -41,6 +54,11 @@ export interface VideoPlayerProps extends ViewProps {
41
54
  * `'portrait'` for a vertical video). Applied when fullscreen opens —
42
55
  * including via the built-in controls' fullscreen button — and restored
43
56
  * when it closes, so the rest of the app is unaffected.
57
+ *
58
+ * When set to a landscape value (`'landscape'` / `'inverted-landscape'`),
59
+ * physically rotating the device to landscape also auto-enters fullscreen,
60
+ * and rotating back to portrait exits it (YouTube-style). This needs the
61
+ * app to allow landscape orientations at the OS level.
44
62
  */
45
63
  fullscreenOrientation?: OrientationLock;
46
64
  /**
@@ -50,6 +68,35 @@ export interface VideoPlayerProps extends ViewProps {
50
68
  * Only the focused player acts, so a video attached elsewhere is untouched.
51
69
  */
52
70
  pauseOnFocusLost?: boolean;
71
+ /**
72
+ * Screen-focus flag from your navigation library — e.g. React Navigation's
73
+ * `useIsFocused()`. `false` pauses this player; returning to `true` reclaims
74
+ * the engine and resumes this video. This is the only reliable way to pause
75
+ * on screen navigation (React Navigation keeps screens mounted and the app
76
+ * stays foregrounded, so unmount/AppState never fire). Leave undefined if
77
+ * you don't use navigation.
78
+ *
79
+ * ```tsx
80
+ * const isFocused = useIsFocused(); // @react-navigation/native
81
+ * <VideoPlayer source={video} isFocused={isFocused} />
82
+ * ```
83
+ */
84
+ isFocused?: boolean;
85
+ /**
86
+ * Mark this as a live stream: the built-in controls hide the seek bar/times
87
+ * and show `liveIcon` (if given). Default false.
88
+ */
89
+ live?: boolean;
90
+ /**
91
+ * Render a live indicator shown in the controls while `live` — e.g. a
92
+ * Lottie animation or a "LIVE" badge: `liveIcon={() => <LottieView … />}`.
93
+ */
94
+ liveIcon?: () => ReactNode;
95
+ /**
96
+ * Render a poster shown over the video only during the initial load
97
+ * (before the first frame) — e.g. `thumbnail={() => <Image … />}`.
98
+ */
99
+ thumbnail?: () => ReactNode;
53
100
  /** Fires once metadata (duration, dimensions) is available. */
54
101
  onLoadComplete?: (info: VideoEventMap['onLoad']) => void;
55
102
  /** Fires whenever buffering starts or stops. */
@@ -83,6 +130,10 @@ export const VideoPlayer = forwardRef<VideoManager, VideoPlayerProps>(
83
130
  orientation,
84
131
  fullscreenOrientation,
85
132
  pauseOnFocusLost = true,
133
+ isFocused,
134
+ live = false,
135
+ liveIcon,
136
+ thumbnail,
86
137
  onLoadComplete,
87
138
  onBuffering,
88
139
  onError,
@@ -94,10 +145,24 @@ export const VideoPlayer = forwardRef<VideoManager, VideoPlayerProps>(
94
145
  const manager = useVideoManager();
95
146
  const id = surfaceId ?? `player:${source.id}`;
96
147
 
148
+ // Poster is shown only during the initial load — `loading` is true from
149
+ // setSource until onLoad, and stays false for mid-stream buffering.
150
+ const loading = usePlayback((s) => s.loading);
151
+
152
+ // Read the latest source without retriggering effects on every render
153
+ // (source is usually a fresh object literal each render).
154
+ const sourceRef = useRef(source);
155
+ sourceRef.current = source;
156
+
97
157
  useImperativeHandle(ref, () => manager, [manager]);
98
158
 
99
159
  useEffect(() => {
100
- manager.setSource(source, { autoplay, surfaceId: id });
160
+ // Don't autoplay a player that mounts already unfocused (isFocused
161
+ // false), else it'd flash play → pause on the next screen.
162
+ manager.setSource(source, {
163
+ autoplay: autoplay && isFocused !== false,
164
+ surfaceId: id,
165
+ });
101
166
  // Attach on mount / when the video identity changes. Other source
102
167
  // fields (title, headers) don't retrigger: identity is source.id.
103
168
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -143,6 +208,41 @@ export const VideoPlayer = forwardRef<VideoManager, VideoPlayerProps>(
143
208
  return () => manager.setFullscreenOrientation(null);
144
209
  }, [manager, fullscreenOrientation]);
145
210
 
211
+ // Auto fullscreen on physical rotation (YouTube-style): when
212
+ // `fullscreenOrientation` is a landscape value, rotating the device to
213
+ // landscape enters fullscreen and rotating back to portrait exits.
214
+ // Enters with 'auto' (not a forced lock) so the device sensor keeps
215
+ // driving and rotating back can exit. Requires the app to actually allow
216
+ // landscape (Info.plist / AndroidManifest) — otherwise the window never
217
+ // reports landscape and this stays inert.
218
+ useEffect(() => {
219
+ const wantsLandscape =
220
+ fullscreenOrientation === 'landscape' ||
221
+ fullscreenOrientation === 'inverted-landscape';
222
+ if (!wantsLandscape) {
223
+ return;
224
+ }
225
+ const onChange = ({
226
+ window,
227
+ }: {
228
+ window: { width: number; height: number };
229
+ }) => {
230
+ const landscape = window.width > window.height;
231
+ const state = manager.store.getState();
232
+ // Ignore when another video owns the engine and we're not fullscreen.
233
+ if (state.surfaceId !== id && !state.fullscreen) {
234
+ return;
235
+ }
236
+ if (landscape && !state.fullscreen) {
237
+ manager.enterFullscreen('auto');
238
+ } else if (!landscape && state.fullscreen) {
239
+ manager.exitFullscreen();
240
+ }
241
+ };
242
+ const sub = Dimensions.addEventListener('change', onChange);
243
+ return () => sub.remove();
244
+ }, [manager, id, fullscreenOrientation]);
245
+
146
246
  useEffect(() => {
147
247
  if (!pauseOnFocusLost) {
148
248
  return;
@@ -157,6 +257,33 @@ export const VideoPlayer = forwardRef<VideoManager, VideoPlayerProps>(
157
257
  return () => sub.remove();
158
258
  }, [manager, id, pauseOnFocusLost]);
159
259
 
260
+ useEffect(() => {
261
+ if (isFocused === undefined) {
262
+ return;
263
+ }
264
+ const state = manager.store.getState();
265
+ if (isFocused) {
266
+ // Regained screen focus. If the engine is still ours, just resume;
267
+ // otherwise it moved to another video while we were blurred — reclaim
268
+ // it (same-id handoff means no reload if it never actually left).
269
+ if (
270
+ state.surfaceId === id &&
271
+ state.currentVideo?.id === sourceRef.current.id
272
+ ) {
273
+ manager.play();
274
+ } else {
275
+ manager.setSource(sourceRef.current, {
276
+ autoplay: true,
277
+ surfaceId: id,
278
+ });
279
+ }
280
+ } else if (state.surfaceId === id) {
281
+ // Lost screen focus while playing our video — pause. Guarded so we
282
+ // never pause a video that has already handed off elsewhere.
283
+ manager.pause();
284
+ }
285
+ }, [manager, id, isFocused]);
286
+
160
287
  useVideoEvents({
161
288
  onLoad: onLoadComplete,
162
289
  onBuffer: (e) => onBuffering?.(e.buffering),
@@ -166,7 +293,12 @@ export const VideoPlayer = forwardRef<VideoManager, VideoPlayerProps>(
166
293
  return (
167
294
  <View style={[styles.container, style]} {...rest}>
168
295
  <VideoSurface surfaceId={id} style={styles.surface} />
169
- {controls ? <VideoControls /> : null}
296
+ {thumbnail && loading ? (
297
+ <View style={styles.surface} pointerEvents="none">
298
+ {thumbnail()}
299
+ </View>
300
+ ) : null}
301
+ {controls ? <VideoControls live={live} liveIcon={liveIcon} /> : null}
170
302
  </View>
171
303
  );
172
304
  }
@@ -1,4 +1,12 @@
1
- import Svg, { Line, Path, Polygon, Rect } from 'react-native-svg';
1
+ import Svg, {
2
+ ClipPath,
3
+ Defs,
4
+ G,
5
+ Line,
6
+ Path,
7
+ Polygon,
8
+ Rect,
9
+ } from 'react-native-svg';
2
10
 
3
11
  interface IconProps {
4
12
  size: number;
@@ -23,6 +31,32 @@ export function PauseIcon({ size, color }: IconProps) {
23
31
  }
24
32
 
25
33
  export function CloseIcon({ size, color }: IconProps) {
34
+ return (
35
+ <Svg width={size || 20} height={size || 21} viewBox="0 0 20 21" fill="none">
36
+ <G clipPath="url(#clip0_25_6005)">
37
+ <Path
38
+ d="M12.5 16.3069L6.25 10.0569L12.5 3.80688"
39
+ stroke={color || '#000000'}
40
+ strokeWidth={1.25}
41
+ strokeLinecap="round"
42
+ strokeLinejoin="round"
43
+ />
44
+ </G>
45
+ <Defs>
46
+ <ClipPath id="clip0_25_6005">
47
+ <Rect
48
+ width={size || 20}
49
+ height={size || 21}
50
+ fill="white"
51
+ transform="translate(0 0.0568848)"
52
+ />
53
+ </ClipPath>
54
+ </Defs>
55
+ </Svg>
56
+ );
57
+ }
58
+
59
+ export function BackIcon({ size, color }: IconProps) {
26
60
  return (
27
61
  <Svg
28
62
  width={size}