@applicaster/quick-brick-player 13.0.0-alpha.5718191297 → 13.0.0-alpha.5771418585

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/quick-brick-player",
3
- "version": "13.0.0-alpha.5718191297",
3
+ "version": "13.0.0-alpha.5771418585",
4
4
  "description": "Quick Brick Player",
5
5
  "main": "./src/index.ts",
6
6
  "types": "index.d.ts",
@@ -36,11 +36,11 @@
36
36
  },
37
37
  "homepage": "https://github.com/applicaster/quickbrick#readme",
38
38
  "dependencies": {
39
- "@applicaster/quick-brick-mobile-transport-controls": "13.0.0-rc.28",
40
- "@applicaster/quick-brick-tv-transport-controls": "13.0.0-rc.26",
41
- "@applicaster/zapp-react-native-tvos-app": "13.0.0-alpha.5718191297",
42
- "@applicaster/zapp-react-native-ui-components": "13.0.0-alpha.5718191297",
43
- "@applicaster/zapp-react-native-utils": "13.0.0-alpha.5718191297",
39
+ "@applicaster/quick-brick-mobile-transport-controls": "13.0.0-rc.42",
40
+ "@applicaster/quick-brick-tv-transport-controls": "13.0.0-rc.42",
41
+ "@applicaster/zapp-react-native-tvos-app": "13.0.0-alpha.5771418585",
42
+ "@applicaster/zapp-react-native-ui-components": "13.0.0-alpha.5771418585",
43
+ "@applicaster/zapp-react-native-utils": "13.0.0-alpha.5771418585",
44
44
  "keymirror": "^0.1.1",
45
45
  "query-string": "7.1.3",
46
46
  "react-native-web-linear-gradient": "1.1.2",
@@ -15,15 +15,9 @@ import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
15
15
  import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
16
16
  import { PlayerDetails } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/PlayerDetails";
17
17
  import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
18
- import { useCallback, useEffect, useState } from "react";
18
+ import { useEffect, useState } from "react";
19
19
  import { MagicBG } from "./MagicBG";
20
- import {
21
- formatSpeed,
22
- hasDatePassed,
23
- loadItemsFromStorage,
24
- NAMESPACE,
25
- } from "./utils";
26
- import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
20
+ import { formatSpeed } from "./utils";
27
21
  import { addQueryParam, getLiveUrl } from "../Utils";
28
22
  import { useTitleSummaryOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerTitleSummaryOverlay";
29
23
  import {
@@ -40,6 +34,12 @@ import {
40
34
  speed_1_5,
41
35
  speed_2,
42
36
  } from "@applicaster/quick-brick-mobile-transport-controls";
37
+ import {
38
+ SleepTimerController,
39
+ SleepTimerState,
40
+ SLEEP_TIMER_OFF,
41
+ } from "./SleepTimerManager";
42
+ import { SpeedController, PlaybackSpeed, DEFAULT_SPEED } from "./SpeedManager";
43
43
 
44
44
  const { log_debug } = createLogger({
45
45
  subsystem: "UIComponent",
@@ -161,17 +161,29 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
161
161
  configuration?.audio_live_player_update_interval
162
162
  );
163
163
 
164
- const [playbackSpeed, setPlaybackSpeed] = useState({
165
- asset: configuration["speed_1"],
166
- value: 1.0,
167
- });
164
+ const [sleepTimerManager, setSleepTimerManager] =
165
+ useState<SleepTimerController | null>(null);
168
166
 
169
- const [sleepTimer, setSleepTimer] = useState({
170
- label: "playback_sleep_off_label",
171
- value: 0,
172
- });
167
+ const [speedManager, setSpeedManager] = useState<SpeedController | null>(
168
+ null
169
+ );
173
170
 
174
- const [sleepTimerDate, setSleepTimerDate] = useState(0);
171
+ useEffect(() => {
172
+ if (player) {
173
+ setSleepTimerManager(new SleepTimerController(player));
174
+ setSpeedManager(new SpeedController(player));
175
+ } else {
176
+ setSleepTimerManager(null);
177
+ setSpeedManager(null);
178
+ }
179
+ }, [player]);
180
+
181
+ const [playbackSpeed, setPlaybackSpeed] =
182
+ useState<PlaybackSpeed>(DEFAULT_SPEED);
183
+
184
+ const [sleepTimerState, setSleepTimerState] = useState<SleepTimerState>(
185
+ new SleepTimerState(SLEEP_TIMER_OFF, 0)
186
+ );
175
187
 
176
188
  const [defaultDimensions, setDefaultDimensions] =
177
189
  React.useState<Dimensions>(undefined);
@@ -196,90 +208,27 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
196
208
  if (!defaultDimensions) setDefaultDimensions({ width, height });
197
209
  };
198
210
 
199
- const cancelSleepTimer = useCallback(async () => {
200
- player?.cancelSleepTimer();
201
-
202
- setSleepTimer({
203
- label: "playback_sleep_off_label",
204
- value: 0,
205
- });
206
-
207
- setSleepTimerDate(0);
208
-
209
- await localStorage.removeItem("sleep", NAMESPACE);
210
- }, [player, setSleepTimer, setSleepTimerDate]);
211
-
212
- const startSleepTimer = useCallback(
213
- (timerValue: number) => {
214
- try {
215
- const futureSleepDate = Date.now() + timerValue * 60000;
216
-
217
- player?.cancelSleepTimer?.();
218
-
219
- player?.startSleepTimer?.(futureSleepDate);
220
-
221
- return futureSleepDate;
222
- } catch (e) {
223
- return 0;
224
- }
225
- },
226
- [player]
227
- );
228
-
229
- const handleSleep = useCallback(
230
- async (timerValue: number, currentFutureSleepDate = null) => {
231
- if (currentFutureSleepDate) {
232
- if (hasDatePassed(currentFutureSleepDate)) {
233
- await cancelSleepTimer();
234
-
235
- return 0;
236
- }
237
-
238
- return currentFutureSleepDate;
239
- }
240
-
241
- if (timerValue === 0) {
242
- await cancelSleepTimer();
243
-
244
- return timerValue;
245
- }
246
-
247
- return startSleepTimer(timerValue);
248
- },
249
- [startSleepTimer, cancelSleepTimer]
250
- );
251
-
252
211
  useEffect(() => {
253
- const loadSpeed = async () => {
254
- const speed = await loadItemsFromStorage("speed");
212
+ const sleepSubscription =
213
+ sleepTimerManager?.sleepTimerState$.subscribe(setSleepTimerState);
255
214
 
256
- if (playerState.isReadyToPlay && speed) {
257
- setPlaybackSpeed(speed);
258
- player?.setPlaybackRate(speed.value);
259
- }
260
- };
261
-
262
- const loadSleep = async () => {
263
- const sleep = await loadItemsFromStorage("sleep");
215
+ const speedSubscription =
216
+ speedManager?.playbackSpeed$.subscribe(setPlaybackSpeed);
264
217
 
265
- if (playerState.isReadyToPlay && sleep) {
266
- const { futureSleepDate, ...rest } = sleep;
267
- setSleepTimer(rest);
268
- const sleepTimerDate = await handleSleep(sleep.value, futureSleepDate);
269
- setSleepTimerDate(sleepTimerDate);
270
- }
218
+ return () => {
219
+ sleepSubscription?.unsubscribe();
220
+ speedSubscription?.unsubscribe();
271
221
  };
222
+ }, [sleepTimerManager, speedManager]);
272
223
 
273
- void loadSpeed();
274
- void loadSleep();
275
- }, [
276
- playerState.isReadyToPlay,
277
- handleSleep,
278
- setSleepTimer,
279
- setSleepTimerDate,
280
- setPlaybackSpeed,
281
- player,
282
- ]);
224
+ useEffect(() => {
225
+ if (!playerState.isReadyToPlay) {
226
+ return;
227
+ }
228
+
229
+ void speedManager?.loadSpeed();
230
+ void sleepTimerManager?.loadSleep();
231
+ }, [playerState.isReadyToPlay, speedManager, sleepTimerManager]);
283
232
 
284
233
  const getValue = (key: string, stylesObj: {}) =>
285
234
  R.propOr(null, key, stylesObj);
@@ -322,26 +271,16 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
322
271
 
323
272
  const onSpeedSelect = React.useCallback(
324
273
  async (item) => {
325
- setPlaybackSpeed(item);
326
- player?.setPlaybackRate(item.value);
327
- await localStorage.setItem("speed", item, NAMESPACE);
274
+ await speedManager?.setPlaybackSpeed(item);
328
275
  },
329
- [player, setPlaybackSpeed]
276
+ [speedManager]
330
277
  );
331
278
 
332
279
  const onSleepSelect = React.useCallback(
333
280
  async (item) => {
334
- setSleepTimer(item);
335
- const futureSleepDate = await handleSleep(item.value);
336
- setSleepTimerDate(futureSleepDate);
337
-
338
- await localStorage.setItem(
339
- "sleep",
340
- { ...item, futureSleepDate },
341
- NAMESPACE
342
- );
281
+ await sleepTimerManager?.setSleepTimer(item);
343
282
  },
344
- [setSleepTimer, setSleepTimerDate, handleSleep]
283
+ [sleepTimerManager]
345
284
  );
346
285
 
347
286
  const onSpeedButtonPress = React.useCallback(() => {
@@ -373,7 +312,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
373
312
  value: 0,
374
313
  },
375
314
  ].concat(sleeps),
376
- current_selection: sleepTimer,
315
+ current_selection: sleepTimerState.timer,
377
316
  onPress: onSleepSelect,
378
317
  title: configuration["playback_sleep_title"],
379
318
  },
@@ -383,12 +322,20 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
383
322
  });
384
323
  }, [
385
324
  navigator,
386
- sleepTimer,
325
+ sleepTimerState.timer,
387
326
  configuration["playback_sleep_title"],
388
327
  configuration["playback_sleep_off_label"],
389
328
  onSleepSelect,
390
329
  ]);
391
330
 
331
+ // This method does not actually cancel the sleep timer
332
+ // (and should not to avoid race condition),
333
+ // it just performs the cleanup when timer expires
334
+ // TODO: rename it in code above
335
+ const cancelSleepTimer = React.useCallback(() => {
336
+ sleepTimerManager?.onTimerExpired();
337
+ }, [sleepTimerManager]);
338
+
392
339
  const onCloseVideoModal = React.useCallback(() => {
393
340
  playerManager.close();
394
341
  }, [playerManager]);
@@ -436,9 +383,11 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
436
383
  onSleepButtonPress={onSleepButtonPress}
437
384
  playbackSpeedName={formatSpeed(playbackSpeed.value)}
438
385
  playbackSleepName={
439
- sleepTimer.value === 0 ? "sleep_timer" : "sleep_timer_active"
386
+ sleepTimerState.timer.value === 0
387
+ ? "sleep_timer"
388
+ : "sleep_timer_active"
440
389
  }
441
- sleepTimerDate={sleepTimerDate}
390
+ sleepTimerDate={sleepTimerState.timerDate}
442
391
  cancelSleepTimer={cancelSleepTimer}
443
392
  onSkipLive={onSkipLive}
444
393
  onCloseVideoModal={onCloseVideoModal}
@@ -488,8 +437,8 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
488
437
  playNextData,
489
438
  onSkipStart,
490
439
  onSkipLive,
491
- sleepTimer.value,
492
- sleepTimerDate,
440
+ sleepTimerState.timer.value,
441
+ sleepTimerState.timerDate,
493
442
  ]);
494
443
 
495
444
  if (configuration.magic_background) {
@@ -1,13 +1,14 @@
1
1
  import * as React from "react";
2
+ import { useEffect, useMemo, useState } from "react";
2
3
  import * as R from "ramda";
3
4
  import { View } from "react-native";
4
5
  import { dayjs } from "@applicaster/zapp-react-native-utils/dateUtils";
5
6
 
6
7
  import {
7
- ProgressBar,
8
8
  Controls,
9
- TransportInfo,
10
9
  CountDown,
10
+ ProgressBar,
11
+ TransportInfo,
11
12
  } from "@applicaster/quick-brick-mobile-transport-controls";
12
13
 
13
14
  import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
@@ -15,23 +16,22 @@ import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
15
16
  import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
16
17
  import {
17
18
  forwardButton,
19
+ PADDING_HORIZONTAL,
18
20
  playbackButton,
19
21
  rewindButton,
20
- skipToStartButton,
21
22
  skipToLiveButton,
22
- PADDING_HORIZONTAL,
23
- speedButton,
23
+ skipToStartButton,
24
24
  sleepButton,
25
+ speedButton,
25
26
  } from "./defaultLayoutsConts";
26
27
  import { AudioDescription } from "../AudioDescription";
27
28
  import { PlayerImageBackground } from "@applicaster/zapp-react-native-ui-components/Components/PlayerImageBackground";
28
29
  import { useLanguageData } from "@applicaster/zapp-react-native-utils/reactHooks/player";
29
30
  import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
30
- import { useEffect, useMemo, useState } from "react";
31
31
  import {
32
- useModalAnimationContext,
33
32
  AnimationComponent,
34
33
  ComponentAnimationType,
34
+ useModalAnimationContext,
35
35
  } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
36
36
  import DockedLayout from "./DockedLayout";
37
37
  import { isValidDate } from "../../Utils";
@@ -405,7 +405,7 @@ export default function DefaultLayout(props: LayoutProps) {
405
405
  layoutState={layoutState}
406
406
  />
407
407
  <Separator />
408
- {needsToShowProgressBar && (
408
+ {needsToShowProgressBar ? (
409
409
  <View>
410
410
  <ProgressBar
411
411
  content={entry}
@@ -422,17 +422,17 @@ export default function DefaultLayout(props: LayoutProps) {
422
422
  onSkipLive={onSkipLive}
423
423
  />
424
424
 
425
- {showCounter && timeLeft >= 0 && (
425
+ {showCounter && timeLeft >= 0 ? (
426
426
  <CountDown
427
427
  timeLeft={timeLeft}
428
428
  value={value}
429
429
  title={sleepTitle}
430
430
  />
431
- )}
431
+ ) : null}
432
432
 
433
433
  <Separator />
434
434
  </View>
435
- )}
435
+ ) : null}
436
436
  <Controls
437
437
  value={value}
438
438
  visible={true}
@@ -9,18 +9,18 @@ import * as R from "ramda";
9
9
  import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
10
10
 
11
11
  import {
12
+ Button,
12
13
  ContentInfo,
13
- ProgressBar,
14
14
  Controls,
15
- Button,
15
+ ProgressBar,
16
16
  } from "@applicaster/quick-brick-mobile-transport-controls";
17
17
 
18
18
  import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
19
19
  import {
20
- useModalAnimationContext,
21
20
  AnimationComponent,
22
21
  ComponentAnimationType,
23
22
  PlayerAnimationStateEnum,
23
+ useModalAnimationContext,
24
24
  } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
25
25
 
26
26
  type Dimensions = {
@@ -245,18 +245,18 @@ export default function DockedLayout(props: LayoutProps) {
245
245
  ]}
246
246
  >
247
247
  {!playerState.isLive &&
248
- (layoutState.docked || startComponentsAnimation) && (
249
- <ProgressBar
250
- content={entry}
251
- value={value}
252
- visible={visible}
253
- layoutState={layoutState}
254
- onPlayerSeek={onPlayerSeek}
255
- playerState={playerState}
256
- startComponentsAnimation={startComponentsAnimation}
257
- docked
258
- />
259
- )}
248
+ (layoutState.docked || startComponentsAnimation) ? (
249
+ <ProgressBar
250
+ content={entry}
251
+ value={value}
252
+ visible={visible}
253
+ layoutState={layoutState}
254
+ onPlayerSeek={onPlayerSeek}
255
+ playerState={playerState}
256
+ startComponentsAnimation={startComponentsAnimation}
257
+ docked
258
+ />
259
+ ) : null}
260
260
 
261
261
  <View style={styles.content}>
262
262
  <View
@@ -0,0 +1,119 @@
1
+ import { BehaviorSubject } from "rxjs";
2
+ import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
3
+ import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
4
+ import { Player } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/player";
5
+ import { hasDatePassed, NAMESPACE } from "./utils";
6
+
7
+ const { log_debug, log_error } = createLogger({
8
+ subsystem: "Player",
9
+ category: "SleepTimerManager",
10
+ });
11
+
12
+ export type SleepTimer = {
13
+ label: string;
14
+ // interval in minutes for UI at the moment when timer was first started
15
+ value: number;
16
+ };
17
+
18
+ export const SLEEP_TIMER_OFF: SleepTimer = {
19
+ label: "playback_sleep_off_label",
20
+ value: 0,
21
+ };
22
+
23
+ export class SleepTimerState {
24
+ constructor(
25
+ public timer: SleepTimer,
26
+ public timerDate: number
27
+ ) {}
28
+ }
29
+
30
+ const SLEEP_PREFERENCE_KEY = "sleep";
31
+
32
+ export class SleepTimerController {
33
+ private sleepTimerStateSubject = new BehaviorSubject<SleepTimerState>(
34
+ new SleepTimerState(SLEEP_TIMER_OFF, 0)
35
+ );
36
+
37
+ constructor(private player: Player) {}
38
+
39
+ get sleepTimerState$() {
40
+ return this.sleepTimerStateSubject.asObservable();
41
+ }
42
+
43
+ private async scheduleSleep(sleepDate): Promise<boolean> {
44
+ log_debug(`Setting sleep interval to ${sleepDate}`);
45
+
46
+ try {
47
+ this.player.cancelSleepTimer?.();
48
+ this.player.startSleepTimer?.(sleepDate);
49
+
50
+ return true;
51
+ } catch (e) {
52
+ log_error("Failed to start sleep timer", { error: e.message });
53
+
54
+ return false;
55
+ }
56
+ }
57
+
58
+ async setSleepTimer(item: SleepTimer) {
59
+ // User has selected Off state
60
+ if (item.value === 0) {
61
+ log_debug("Cancelling sleep timer");
62
+ this.player.cancelSleepTimer?.();
63
+
64
+ return this.onTimerExpired();
65
+ }
66
+
67
+ log_debug(`Starting sleep timer in ${item.value} minutes`);
68
+
69
+ const futureSleepDate = Date.now() + item.value * 60000;
70
+
71
+ if (await this.scheduleSleep(futureSleepDate)) {
72
+ await localStorage.setItem(
73
+ SLEEP_PREFERENCE_KEY,
74
+ { ...item, futureSleepDate },
75
+ NAMESPACE
76
+ );
77
+
78
+ this.sleepTimerStateSubject.next(
79
+ new SleepTimerState(item, futureSleepDate)
80
+ );
81
+ }
82
+ }
83
+
84
+ async onTimerExpired() {
85
+ await localStorage.removeItem(SLEEP_PREFERENCE_KEY, NAMESPACE);
86
+
87
+ this.sleepTimerStateSubject.next(new SleepTimerState(SLEEP_TIMER_OFF, 0));
88
+ }
89
+
90
+ async loadSleep() {
91
+ const sleep = await localStorage.getItem(SLEEP_PREFERENCE_KEY, NAMESPACE);
92
+
93
+ if (!sleep) return;
94
+
95
+ const { futureSleepDate, ...rest } = sleep;
96
+
97
+ if (!futureSleepDate || hasDatePassed(futureSleepDate)) {
98
+ log_debug("Sleep date has already passed");
99
+ await localStorage.removeItem(SLEEP_PREFERENCE_KEY, NAMESPACE);
100
+
101
+ return;
102
+ }
103
+
104
+ if (await this.scheduleSleep(futureSleepDate)) {
105
+ log_debug(`Sleep state restored, will go to sleep at ${futureSleepDate}`);
106
+
107
+ this.sleepTimerStateSubject.next(
108
+ new SleepTimerState(rest as SleepTimer, futureSleepDate)
109
+ );
110
+ }
111
+ }
112
+
113
+ // Will be called if user closed the player explicitly.
114
+ // TODO: check if it will be called on Android when we need.
115
+ // Probably we will have to handle it on native instead.
116
+ public static async onPlayerDestroy() {
117
+ await localStorage.removeItem(SLEEP_PREFERENCE_KEY, NAMESPACE);
118
+ }
119
+ }
@@ -0,0 +1,52 @@
1
+ import { BehaviorSubject } from "rxjs";
2
+ import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
3
+ import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
4
+ import { Player } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/player";
5
+ import { NAMESPACE } from "./utils";
6
+
7
+ const { log_debug } = createLogger({
8
+ subsystem: "Player",
9
+ category: "PlaybackSpeedManager",
10
+ });
11
+
12
+ export type PlaybackSpeed = {
13
+ asset: string;
14
+ value: number;
15
+ };
16
+
17
+ const SPEED_PREFERENCE_KEY = "speed";
18
+
19
+ export const DEFAULT_SPEED: PlaybackSpeed = {
20
+ asset: "speed_1",
21
+ value: 1.0,
22
+ };
23
+
24
+ // todo: should not be applied to live streams
25
+ export class SpeedController {
26
+ private playbackSpeedSubject = new BehaviorSubject<PlaybackSpeed>(
27
+ DEFAULT_SPEED
28
+ );
29
+
30
+ constructor(private player: Player) {}
31
+
32
+ get playbackSpeed$() {
33
+ return this.playbackSpeedSubject.asObservable();
34
+ }
35
+
36
+ async loadSpeed() {
37
+ const speed = await localStorage.getItem(SPEED_PREFERENCE_KEY, NAMESPACE);
38
+
39
+ // checking for value in case we will pull empty or broken object
40
+ if (speed && speed.value) {
41
+ this.playbackSpeedSubject.next(speed);
42
+ this.player.setPlaybackRate?.(speed.value);
43
+ log_debug(`Speed loaded: ${speed}`);
44
+ }
45
+ }
46
+
47
+ async setPlaybackSpeed(speed: PlaybackSpeed) {
48
+ await localStorage.setItem(SPEED_PREFERENCE_KEY, speed, NAMESPACE);
49
+ this.playbackSpeedSubject.next(speed);
50
+ this.player.setPlaybackRate?.(speed.value);
51
+ }
52
+ }
@@ -990,14 +990,14 @@ export default class VideoPlayer extends React.Component<
990
990
  const renderMobilePlayer = () => {
991
991
  return isFullScreenAudioPlayer && isAudioItem ? (
992
992
  <View style={containerStyle}>
993
- {(!castAction?.state?.connected || supportNativeCast) && (
993
+ {!castAction?.state?.connected || supportNativeCast ? (
994
994
  <this.props.PlayerComponent
995
995
  ref={this._assignRoot}
996
996
  {...nativeEvents}
997
997
  {...nativeProps}
998
998
  listener={this.props.listener}
999
999
  />
1000
- )}
1000
+ ) : null}
1001
1001
  <AudioPlayerWrapper {...sharedWrapperViewProps} />
1002
1002
  </View>
1003
1003
  ) : (
@@ -1012,7 +1012,7 @@ export default class VideoPlayer extends React.Component<
1012
1012
  return (
1013
1013
  <View style={styles.container}>
1014
1014
  <View style={[playerContainerStyles, playerDimensions]}>
1015
- {isAudioItem && (
1015
+ {isAudioItem ? (
1016
1016
  <AnimationComponent
1017
1017
  animationType={ComponentAnimationType.player}
1018
1018
  additionalData={{
@@ -1031,18 +1031,18 @@ export default class VideoPlayer extends React.Component<
1031
1031
  plugin_configuration={this.getPluginConfiguration()}
1032
1032
  />
1033
1033
  </AnimationComponent>
1034
- )}
1034
+ ) : null}
1035
1035
 
1036
- {shouldRenderBackground && (
1036
+ {shouldRenderBackground ? (
1037
1037
  <PlayerImageBackground
1038
1038
  imageKey={backgroundImageKey}
1039
1039
  configuration={this.getPluginConfiguration()}
1040
1040
  entry={entry}
1041
1041
  style={getBackgroundImageStyle(playerDimensions)}
1042
1042
  />
1043
- )}
1043
+ ) : null}
1044
1044
 
1045
- {(!castAction?.state?.connected || supportNativeCast) && (
1045
+ {!castAction?.state?.connected || supportNativeCast ? (
1046
1046
  <AnimationComponent
1047
1047
  animationType={ComponentAnimationType.player}
1048
1048
  additionalData={playerDimensions}
@@ -1064,7 +1064,7 @@ export default class VideoPlayer extends React.Component<
1064
1064
  {this.childrenWithPlayNext()}
1065
1065
  </this.props.PlayerComponent>
1066
1066
  </AnimationComponent>
1067
- )}
1067
+ ) : null}
1068
1068
  </View>
1069
1069
 
1070
1070
  {renderTransportControls(playerDimensions)}