@applicaster/quick-brick-player 12.0.0-alpha.3977160850 → 12.0.0-alpha.4337072244

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": "12.0.0-alpha.3977160850",
3
+ "version": "12.0.0-alpha.4337072244",
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": "12.0.0-rc.28",
40
- "@applicaster/quick-brick-tv-transport-controls": "11.0.0-rc.133",
41
- "@applicaster/zapp-react-native-tvos-app": "12.0.0-alpha.3977160850",
42
- "@applicaster/zapp-react-native-ui-components": "12.0.0-alpha.3977160850",
43
- "@applicaster/zapp-react-native-utils": "12.0.0-alpha.3977160850",
39
+ "@applicaster/quick-brick-mobile-transport-controls": "12.0.0-rc.58",
40
+ "@applicaster/quick-brick-tv-transport-controls": "12.0.0-alpha.4337072244",
41
+ "@applicaster/zapp-react-native-tvos-app": "12.0.0-alpha.4337072244",
42
+ "@applicaster/zapp-react-native-ui-components": "12.0.0-alpha.4337072244",
43
+ "@applicaster/zapp-react-native-utils": "12.0.0-alpha.4337072244",
44
44
  "keymirror": "^0.1.1",
45
45
  "query-string": "7.1.3",
46
46
  "react-native-web-linear-gradient": "1.1.2",
@@ -1,8 +1,9 @@
1
1
  import React, { useEffect, useState } from "react";
2
- import { Image, StyleSheet, View } from "react-native";
2
+ import { StyleSheet, View } from "react-native";
3
3
  import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
4
4
  import { MUTED_USAGE } from "../const";
5
5
  import { LiveImageManager } from "@applicaster/zapp-react-native-ui-components/Components/VideoLive/LiveImageManager";
6
+ import { QBImage as Image } from "@applicaster/zapp-react-native-ui-components/Components/Image";
6
7
 
7
8
  type Asset = string | undefined;
8
9
 
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { ViewStyle, View, ScrollView } from "react-native";
2
+ import { ViewStyle, View } from "react-native";
3
3
 
4
4
  import { SafeAreaView, Edge } from "react-native-safe-area-context";
5
5
  import { usePlayerState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerState";
@@ -24,8 +24,15 @@ import {
24
24
  NAMESPACE,
25
25
  } from "./utils";
26
26
  import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
27
- import { getLiveUrl } from "../Utils";
27
+ import { addQueryParam, getLiveUrl } from "../Utils";
28
28
  import { useTitleSummaryOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerTitleSummaryOverlay";
29
+ import {
30
+ AnimationComponent,
31
+ ComponentAnimationType,
32
+ AnimatedScrollModal,
33
+ } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
34
+ import { PADDING_HORIZONTAL } from "./Layout/defaultLayoutsConts";
35
+ import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
29
36
 
30
37
  const { log_debug } = createLogger({
31
38
  subsystem: "UIComponent",
@@ -68,29 +75,20 @@ export const defaultAspectRatioWidth = (height: number): number =>
68
75
  (height / 9) * 16;
69
76
 
70
77
  const Styles = {
71
- mainContainer: (docked: boolean, style: ViewStyle) => {
78
+ mainContainer: (style: ViewStyle) => {
72
79
  const combinedStyle: ViewStyle = {
73
80
  flex: 1,
74
81
  };
75
82
 
76
- if (!docked) {
77
- style.paddingTop = 0;
78
- style.paddingHorizontal = 15;
79
- }
80
-
81
- return { ...combinedStyle, ...style };
82
- },
83
- playerContainer: (docked: boolean, style: ViewStyle) => {
84
- const combinedStyle: ViewStyle = {
85
- flex: 1,
83
+ return {
84
+ ...combinedStyle,
85
+ ...style,
86
86
  };
87
-
88
- if (docked) {
89
- combinedStyle.height = style.height;
90
- }
91
-
92
- return combinedStyle;
93
87
  },
88
+ playerContainer: {
89
+ flex: 1,
90
+ },
91
+ paddingHorizontal: { paddingTop: 0, paddingHorizontal: PADDING_HORIZONTAL },
94
92
 
95
93
  controlsMobile: {
96
94
  height: 50,
@@ -144,9 +142,9 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
144
142
  const isTablet = useIsTablet();
145
143
 
146
144
  const isTabletLandscape = !isTV() && isTablet && !isTabletPortrait;
147
-
145
+
148
146
  // TODO: Have generic place for live url from configuration. Currently its hardcoded for client.
149
-
147
+
150
148
  const feedUrl = getLiveUrl(entry?.extensions?.live?.channel_src ?? "");
151
149
 
152
150
  const { title, summary } = useTitleSummaryOverlay(
@@ -168,6 +166,9 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
168
166
 
169
167
  const [sleepTimerDate, setSleepTimerDate] = useState(0);
170
168
 
169
+ const [defaultDimensions, setDefaultDimensions] =
170
+ React.useState<Dimensions>(undefined);
171
+
171
172
  const [dimensions, setDimensions] = React.useState<Dimensions>({
172
173
  width: 0,
173
174
  height: 0,
@@ -181,9 +182,11 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
181
182
  const { width, height } = event.nativeEvent.layout;
182
183
 
183
184
  setDimensions({
184
- width: docked ? defaultAspectRatioWidth(height) : width,
185
+ width,
185
186
  height,
186
187
  });
188
+
189
+ if (!defaultDimensions) setDefaultDimensions({ width, height });
187
190
  };
188
191
 
189
192
  const cancelSleepTimer = async () => {
@@ -195,7 +198,6 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
195
198
  });
196
199
 
197
200
  setSleepTimerDate(0);
198
- player?.pause();
199
201
 
200
202
  await localStorage.removeItem("sleep", NAMESPACE);
201
203
  };
@@ -293,7 +295,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
293
295
  playerState.isPaused ? player?.play() : player.pause();
294
296
  }, [playerState, player]);
295
297
 
296
- const seekDuration = Number(value("seek_duration"));
298
+ const seekDuration = toNumberWithDefault(10, value("seek_duration"));
297
299
 
298
300
  const onRewindButtonPress = React.useCallback(() => {
299
301
  player?.rewind(seekDuration);
@@ -376,58 +378,64 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
376
378
  player?.seekTo(0);
377
379
  }, [player]);
378
380
 
379
- const edges = React.useMemo<Edge[]>(
380
- () => (docked ? [] : ["right", "left", "top"]),
381
- [docked]
382
- );
381
+ const edges = React.useMemo<Edge[]>(() => ["right", "left", "top"], [docked]);
383
382
 
384
- const ContainerView = docked ? View : SafeAreaView;
383
+ const ContainerView = SafeAreaView;
385
384
 
386
385
  const MainContent = React.useMemo(() => {
387
386
  return (
388
- <ContainerView style={Styles.mainContainer(docked, style)} edges={edges}>
389
- <ScrollView
390
- style={Styles.playerContainer(docked, style)}
391
- onLayout={onLayout}
387
+ <ContainerView style={Styles.mainContainer(style)} edges={edges}>
388
+ <AnimationComponent
389
+ animationType={ComponentAnimationType.moveUpComponent}
390
+ additionalData={{ saveArea: true }}
392
391
  >
393
- <Layout
394
- entry={entry}
395
- playerState={playerState}
396
- layoutState={layoutState}
397
- value={value}
398
- onPlaybackButtonPress={onPlaybackButtonPress}
399
- onRewindButtonPress={onRewindButtonPress}
400
- onForwardButtonPress={onForwardButtonPress}
401
- onPlayerSeek={onPlayerSeek}
402
- onSkipStart={onSkipStart}
403
- onSpeedButtonPress={onSpeedButtonPress}
404
- onSleepButtonPress={onSleepButtonPress}
405
- playbackSpeedName={formatSpeed(playbackSpeed.value)}
406
- playbackSleepName={
407
- sleepTimer.value === 0 ? "sleep_timer" : "sleep_timer_active"
408
- }
409
- sleepTimerDate={sleepTimerDate}
410
- cancelSleepTimer={cancelSleepTimer}
411
- onSkipLive={onSkipLive}
412
- onCloseVideoModal={onCloseVideoModal}
413
- maximiseVideoModal={maximiseVideoModal}
414
- configuration={configuration}
415
- dimensions={dimensions}
416
- playNextData={playNextData}
417
- title={title}
418
- summary={summary}
419
- />
420
- {children}
421
- {!docked && (
422
- <PlayerDetails
423
- configuration={configuration}
424
- style={Styles.playerDetails}
425
- entry={entry}
426
- isTabletLandscape={isTabletLandscape}
427
- isAudioPlayer={true}
428
- />
429
- )}
430
- </ScrollView>
392
+ <AnimatedScrollModal>
393
+ <View style={Styles.playerContainer} onLayout={onLayout}>
394
+ <Layout
395
+ entry={entry}
396
+ playerState={playerState}
397
+ layoutState={layoutState}
398
+ value={value}
399
+ onPlaybackButtonPress={onPlaybackButtonPress}
400
+ onRewindButtonPress={onRewindButtonPress}
401
+ onForwardButtonPress={onForwardButtonPress}
402
+ onPlayerSeek={onPlayerSeek}
403
+ onSkipStart={onSkipStart}
404
+ onSpeedButtonPress={onSpeedButtonPress}
405
+ onSleepButtonPress={onSleepButtonPress}
406
+ playbackSpeedName={formatSpeed(playbackSpeed.value)}
407
+ playbackSleepName={
408
+ sleepTimer.value === 0 ? "sleep_timer" : "sleep_timer_active"
409
+ }
410
+ sleepTimerDate={sleepTimerDate}
411
+ cancelSleepTimer={cancelSleepTimer}
412
+ onSkipLive={onSkipLive}
413
+ onCloseVideoModal={onCloseVideoModal}
414
+ maximiseVideoModal={maximiseVideoModal}
415
+ configuration={configuration}
416
+ dimensions={dimensions}
417
+ playNextData={playNextData}
418
+ title={title}
419
+ summary={summary}
420
+ defaultDimensions={defaultDimensions}
421
+ />
422
+ <View style={Styles.paddingHorizontal}>
423
+ {children}
424
+ <AnimationComponent
425
+ animationType={ComponentAnimationType.componentFade}
426
+ >
427
+ <PlayerDetails
428
+ configuration={configuration}
429
+ style={Styles.playerDetails}
430
+ entry={entry}
431
+ isTabletLandscape={isTabletLandscape}
432
+ isAudioPlayer={true}
433
+ />
434
+ </AnimationComponent>
435
+ </View>
436
+ </View>
437
+ </AnimatedScrollModal>
438
+ </AnimationComponent>
431
439
  </ContainerView>
432
440
  );
433
441
  }, [
@@ -456,17 +464,20 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
456
464
  if (configuration.magic_background) {
457
465
  const baseUrl = entry?.extensions?.audio_player_background_image ?? "";
458
466
 
459
- // TODO: To be added when background is ready
467
+ const queryParamName =
468
+ configuration.audio_player_background_image_query || "width";
469
+
470
+ const queryParamValue = 15;
460
471
 
461
- // const queryParamName =
462
- // configuration.audio_player_background_image_query || "width";
463
- //
464
- // const queryParamValue = 15;
465
- //
466
- // const url = addQueryParam(baseUrl, queryParamName, queryParamValue);
472
+ const url = addQueryParam(baseUrl, queryParamName, queryParamValue);
467
473
 
468
474
  return (
469
- <MagicBG image={baseUrl} fallbackUrl={baseUrl} defaultColor="#000000">
475
+ <MagicBG
476
+ image={url}
477
+ fallbackUrl={baseUrl}
478
+ colors={entry?.extensions?.backgroundColors}
479
+ defaultColor="#000000"
480
+ >
470
481
  {MainContent}
471
482
  </MagicBG>
472
483
  );
@@ -1,6 +1,7 @@
1
1
  import * as React from "react";
2
2
  import * as R from "ramda";
3
3
  import { View } from "react-native";
4
+ import { dayjs } from "@applicaster/zapp-react-native-utils/dateUtils";
4
5
 
5
6
  import {
6
7
  ProgressBar,
@@ -18,13 +19,22 @@ import {
18
19
  rewindButton,
19
20
  skipToStartButton,
20
21
  skipToLiveButton,
22
+ PADDING_HORIZONTAL,
21
23
  speedButton,
22
24
  sleepButton,
23
25
  } from "./defaultLayoutsConts";
24
26
  import { AudioDescription } from "../AudioDescription";
25
27
  import { PlayerImageBackground } from "@applicaster/zapp-react-native-ui-components/Components/PlayerImageBackground";
26
28
  import { useLanguageData } from "@applicaster/zapp-react-native-utils/reactHooks/player";
29
+ import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
27
30
  import { useEffect, useMemo, useState } from "react";
31
+ import {
32
+ useModalAnimationContext,
33
+ AnimationComponent,
34
+ ComponentAnimationType,
35
+ } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
36
+ import DockedLayout from "./DockedLayout";
37
+ import { isValidDate } from "../../Utils";
28
38
 
29
39
  type Dimensions = {
30
40
  width: number;
@@ -60,22 +70,29 @@ type LayoutProps = {
60
70
  onPlayerSeek: (targetTime: number) => void;
61
71
  onSkipLive: () => void;
62
72
  onSkipStart: () => void;
73
+ onCloseVideoModal: () => void;
74
+ maximiseVideoModal: () => void;
63
75
  dimensions: Dimensions;
76
+ playNextData: PlayNextData;
64
77
  title: string | number;
65
78
  summary: string | number;
79
+ defaultDimensions: Dimensions;
66
80
  };
67
81
 
68
82
  const Styles = {
69
83
  container: { flex: 1 },
70
- tabletContainer: (isPortraitMode) => ({
84
+ tabletContainer: (isPortraitMode: boolean) => ({
71
85
  flex: 1,
72
86
  alignItems: "center",
73
87
  justifyContent: isPortraitMode ? "center" : "flex-start",
74
88
  }),
75
- tabletLayout: {
76
- width: 463,
89
+ playerImageWrapper: {
90
+ width: "100%",
77
91
  maxHeight: 750,
78
92
  marginTop: 80,
93
+ },
94
+ tabletLayout: {
95
+ width: 463,
79
96
  marginBottom: 80,
80
97
  },
81
98
  controls: (isTablet: boolean, isLiveShowFullControls: boolean) => ({
@@ -84,24 +101,31 @@ const Styles = {
84
101
  justifyContent: isLiveShowFullControls ? "space-between" : "space-evenly",
85
102
  }),
86
103
  backgroundImageContainer: (dimensions: Dimensions, isTablet: boolean) => {
104
+ const mobileValue = dimensions.width
105
+ ? dimensions.width - PADDING_HORIZONTAL * 2
106
+ : 330;
107
+
87
108
  return {
88
- width: isTablet ? 463 : dimensions.width || 330,
89
- height: isTablet ? 463 : dimensions.width || 330,
109
+ width: isTablet ? 463 : mobileValue,
110
+ height: isTablet ? 463 : mobileValue,
90
111
  };
91
112
  },
92
- backgroundImageContainerImageStyle: (isTablet) => ({
93
- borderRadius: isTablet ? 24 : 10,
113
+ backgroundImageContainerImageStyle: (
114
+ isTablet: boolean,
115
+ docked: boolean,
116
+ startComponentsAnimation: boolean,
117
+ isActiveGesture: boolean
118
+ ) => ({
119
+ borderRadius:
120
+ (startComponentsAnimation && isActiveGesture) || docked
121
+ ? 0
122
+ : isTablet
123
+ ? 24
124
+ : 10,
94
125
  }),
95
- playerContainer: (docked: boolean, style) => {
96
- const combinedStyle = {
97
- flex: 1,
98
- };
99
126
 
100
- if (docked) {
101
- combinedStyle["height"] = style.height;
102
- }
103
-
104
- return combinedStyle;
127
+ paddingHorizontal: {
128
+ paddingHorizontal: PADDING_HORIZONTAL,
105
129
  },
106
130
 
107
131
  controlsMobile: {
@@ -115,6 +139,12 @@ const Styles = {
115
139
  separator: {
116
140
  height: 20,
117
141
  },
142
+ flexDirectionRow: {
143
+ flexDirection: "row",
144
+ },
145
+ alignItemsCenter: {
146
+ alignItems: "center",
147
+ },
118
148
  };
119
149
 
120
150
  export default function DefaultLayout(props: LayoutProps) {
@@ -139,12 +169,14 @@ export default function DefaultLayout(props: LayoutProps) {
139
169
  sleepTimerDate,
140
170
  title,
141
171
  summary,
172
+ defaultDimensions,
142
173
  } = props;
143
174
 
144
175
  const isTablet = useIsTablet();
145
176
  const { width, height } = dimensions;
146
177
  const isPortraitMode = width < height;
147
178
  const isLiveContent = playerState.isLive;
179
+ const docked = layoutState.docked;
148
180
 
149
181
  const languageData = useLanguageData("audio-player");
150
182
 
@@ -160,8 +192,31 @@ export default function DefaultLayout(props: LayoutProps) {
160
192
 
161
193
  let showFullControls = !controller?.isAd();
162
194
 
195
+ const startTime = entry.extensions?.live?.start_time;
196
+ const endTime = entry.extensions?.live?.end_time;
197
+
198
+ const hasValidStartTime = isValidDate(startTime);
199
+ const hasValidEndTime = isValidDate(endTime);
200
+
201
+ const isDateBasedLiveContent =
202
+ isLiveContent && hasValidStartTime && hasValidEndTime;
203
+
204
+ const needsToShowProgressBar =
205
+ (isLiveContent &&
206
+ (Boolean(value("liveSeekingEnabled")) || isDateBasedLiveContent)) ||
207
+ !isLiveContent;
208
+
209
+ const startTimestamp = hasValidStartTime
210
+ ? dayjs.utc(startTime!).valueOf()
211
+ : undefined;
212
+
213
+ const endTimestamp = hasValidEndTime
214
+ ? dayjs.utc(endTime!).valueOf()
215
+ : undefined;
216
+
163
217
  if (isLiveContent) {
164
218
  const seekEnabled = Boolean(value("liveSeekingEnabled"));
219
+
165
220
  showFullControls = !!(controller?.hasSeekableDuration?.() && seekEnabled);
166
221
  }
167
222
 
@@ -191,12 +246,14 @@ export default function DefaultLayout(props: LayoutProps) {
191
246
 
192
247
  const rewind = rewindButton({
193
248
  isTablet,
194
- onPress: controller?.hasContentDuration?.() ? onRewindButtonPress : null,
249
+ onPress: controller?.hasSeekableDuration?.() ? onRewindButtonPress : null,
195
250
  });
196
251
 
197
252
  const forward = forwardButton({
198
253
  isTablet,
199
- onPress: controller?.hasContentDuration?.() ? onForwardButtonPress : null,
254
+ onPress: controller?.hasSeekableDuration?.()
255
+ ? onForwardButtonPress
256
+ : null,
200
257
  });
201
258
 
202
259
  const speed = speedButton({
@@ -225,7 +282,6 @@ export default function DefaultLayout(props: LayoutProps) {
225
282
  return [skipToStart, rewind, play, forward, skipToLive];
226
283
  }
227
284
 
228
- // Temporary empty button until we add sleep button. It will ensure the buttons will not break in their position
229
285
  return [speed, rewind, play, forward, sleep];
230
286
  }, [
231
287
  playerState,
@@ -246,15 +302,12 @@ export default function DefaultLayout(props: LayoutProps) {
246
302
 
247
303
  useEffect(() => {
248
304
  if (showCounter && sleepTimerDate !== 0) {
249
- // Setting the initial timeLeft based on sleepTimerDate
250
305
  setTimeLeft(sleepTimerDate - Date.now());
251
306
 
252
- // Setting up an interval to update the remaining time every second
253
307
  const intervalId = setInterval(() => {
254
308
  setTimeLeft(() => {
255
309
  const newTimeLeft = sleepTimerDate - Date.now();
256
310
 
257
- // If the new remaining time is less than or equal to 0, clear the interval and trigger the cancelSleepTimer function
258
311
  if (newTimeLeft <= 0) {
259
312
  clearInterval(intervalId);
260
313
 
@@ -262,26 +315,28 @@ export default function DefaultLayout(props: LayoutProps) {
262
315
 
263
316
  return 0;
264
317
  } else {
265
- // Otherwise, update the state with the new remaining time
266
318
  return newTimeLeft;
267
319
  }
268
320
  });
269
321
  }, 1000);
270
322
 
271
- // Clearing the interval when the component unmounts or dependencies change
272
323
  return () => clearInterval(intervalId);
273
324
  } else {
274
- // Ensure the timeLeft state is set correctly if showCounter is false
275
325
  setTimeLeft(0);
276
326
  }
277
327
  }, [sleepTimerDate, showCounter, cancelSleepTimer]);
278
328
 
279
329
  const Separator = () => <View style={Styles.separator} />;
280
330
 
281
- const liveSeekingEnabled = value("liveSeekingEnabled");
331
+ const defaultImageDimensions = React.useMemo(
332
+ () =>
333
+ defaultDimensions &&
334
+ Styles.backgroundImageContainer(defaultDimensions, isTablet),
335
+ [defaultDimensions, isTablet]
336
+ );
282
337
 
283
- const needsToShowProgressBar =
284
- (isLiveContent && liveSeekingEnabled) || !isLiveContent;
338
+ const { isActiveGesture, startComponentsAnimation } =
339
+ useModalAnimationContext();
285
340
 
286
341
  return (
287
342
  <View
@@ -289,65 +344,107 @@ export default function DefaultLayout(props: LayoutProps) {
289
344
  isTablet ? Styles.tabletContainer(isPortraitMode) : Styles.container
290
345
  }
291
346
  >
292
- <TransportInfo
293
- content={entry}
294
- value={value}
295
- visible={true}
296
- languageData={languageData}
297
- layoutState={layoutState}
298
- actionButtons={actionButtons}
299
- />
300
- <View
301
- style={
302
- isTablet ? Styles.tabletContainer(isPortraitMode) : Styles.container
303
- }
347
+ <AnimationComponent animationType={ComponentAnimationType.componentFade}>
348
+ <TransportInfo
349
+ content={entry}
350
+ value={value}
351
+ visible={true}
352
+ languageData={languageData}
353
+ layoutState={layoutState}
354
+ actionButtons={actionButtons}
355
+ />
356
+ </AnimationComponent>
357
+ <AnimationComponent
358
+ animationType={ComponentAnimationType.moveUpComponent}
359
+ style={isTablet ? Styles.playerImageWrapper : undefined}
304
360
  >
305
- <View style={isTablet ? Styles.tabletLayout : null}>
361
+ <AnimationComponent
362
+ animationType={ComponentAnimationType.moveComponentHorizontal}
363
+ additionalData={{
364
+ disableAnimatedComponent: !isTablet,
365
+ moveValue: (dimensions.width - 463) / 2,
366
+ extraAnimation: !isTablet
367
+ ? {
368
+ [ComponentAnimationType.audioPlayerPaddingHorizontal]: {
369
+ style: Styles.paddingHorizontal,
370
+ },
371
+ }
372
+ : null,
373
+ }}
374
+ style={isTablet ? Styles.alignItemsCenter : undefined}
375
+ >
306
376
  <PlayerImageBackground
307
377
  entry={entry}
308
378
  style={Styles.backgroundImageContainer(dimensions, isTablet)}
309
- imageStyle={Styles.backgroundImageContainerImageStyle(isTablet)}
310
- />
311
- <AudioDescription
312
- title={title}
313
- summary={summary}
314
- value={value}
315
- layoutState={layoutState}
379
+ imageStyle={Styles.backgroundImageContainerImageStyle(
380
+ isTablet,
381
+ docked,
382
+ startComponentsAnimation,
383
+ isActiveGesture
384
+ )}
385
+ defaultImageDimensions={defaultImageDimensions}
316
386
  />
317
- <Separator />
318
- {needsToShowProgressBar && (
319
- <View>
320
- <ProgressBar
321
- content={entry}
322
- value={value}
323
- visible={true}
324
- layoutState={layoutState}
325
- onPlayerSeek={onPlayerSeek}
326
- playerState={playerState}
327
- disableFullscreen={true}
328
- sliderStyle={2}
329
- />
330
-
331
- {showCounter && timeLeft >= 0 && (
332
- <CountDown
333
- timeLeft={timeLeft}
387
+ </AnimationComponent>
388
+
389
+ <DockedLayout {...props} />
390
+ </AnimationComponent>
391
+ <View
392
+ style={[
393
+ Styles.paddingHorizontal,
394
+ isTablet ? Styles.tabletLayout : undefined,
395
+ ]}
396
+ >
397
+ {!docked && (
398
+ <AnimationComponent
399
+ animationType={ComponentAnimationType.componentFade}
400
+ >
401
+ <AudioDescription
402
+ title={title}
403
+ summary={summary}
404
+ value={value}
405
+ layoutState={layoutState}
406
+ />
407
+ <Separator />
408
+ {needsToShowProgressBar && (
409
+ <View>
410
+ <ProgressBar
411
+ content={entry}
334
412
  value={value}
335
- title={sleepTitle}
413
+ visible={true}
414
+ layoutState={layoutState}
415
+ onPlayerSeek={onPlayerSeek}
416
+ playerState={playerState}
417
+ disableFullscreen={true}
418
+ sliderStyle={2}
419
+ startTimestamp={startTimestamp}
420
+ endTimestamp={endTimestamp}
421
+ isDateBasedLiveContent={isDateBasedLiveContent}
336
422
  />
337
- )}
338
423
 
339
- <Separator />
340
- </View>
341
- )}
342
- <Controls
343
- value={value}
344
- visible={true}
345
- keepAlive={null}
346
- buttons={controlButtons}
347
- style={Styles.controls(isTablet, isLiveContent && showFullControls)}
348
- playerState={playerState}
349
- />
350
- </View>
424
+ {showCounter && timeLeft >= 0 && (
425
+ <CountDown
426
+ timeLeft={timeLeft}
427
+ value={value}
428
+ title={sleepTitle}
429
+ />
430
+ )}
431
+
432
+ <Separator />
433
+ </View>
434
+ )}
435
+ <Controls
436
+ value={value}
437
+ visible={true}
438
+ keepAlive={null}
439
+ buttons={controlButtons}
440
+ style={Styles.controls(
441
+ isTablet,
442
+ isLiveContent && showFullControls
443
+ )}
444
+ playerState={playerState}
445
+ />
446
+ </AnimationComponent>
447
+ )}
351
448
  </View>
352
449
  </View>
353
450
  );
@@ -15,8 +15,13 @@ import {
15
15
  Button,
16
16
  } from "@applicaster/quick-brick-mobile-transport-controls";
17
17
 
18
- import { PlayerImageBackground } from "@applicaster/zapp-react-native-ui-components/Components/PlayerImageBackground";
19
18
  import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
19
+ import {
20
+ useModalAnimationContext,
21
+ AnimationComponent,
22
+ ComponentAnimationType,
23
+ PlayerAnimationStateEnum,
24
+ } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
20
25
 
21
26
  type Dimensions = {
22
27
  width: number;
@@ -104,14 +109,26 @@ const backgroundColorStyle = (value: GetValue): ViewStyle => ({
104
109
  backgroundColor: value("docked_player_background_color"),
105
110
  });
106
111
 
107
- const playerDimensionsStyle = ({
108
- height,
109
- }: PlayerDimensionsProp): ViewStyle => ({
110
- paddingLeft: height || 100,
112
+ const playerDimensionsStyle = (
113
+ minimisedHeight: number,
114
+ addPadding: boolean
115
+ ): ViewStyle => ({
116
+ paddingLeft: addPadding ? minimisedHeight || 100 : 0,
111
117
  });
112
118
 
113
- const backgroundImageStyle = (dimensions: Dimensions): ViewStyle => ({
114
- height: dimensions.height,
119
+ const animatedContainerStyle = (docked: boolean): ViewStyle => ({
120
+ top: docked ? 2 : null,
121
+ position: "absolute",
122
+ width: "100%",
123
+ zIndex: docked ? 1 : -1,
124
+ });
125
+
126
+ const backgroundImageStyle = (
127
+ dimensions: Dimensions,
128
+ minimisedHeight: number,
129
+ isActiveGesture: boolean
130
+ ): ViewStyle => ({
131
+ height: isActiveGesture ? minimisedHeight : dimensions.height,
115
132
  aspectRatio: 1,
116
133
  position: "absolute",
117
134
  });
@@ -193,7 +210,6 @@ export default function DockedLayout(props: LayoutProps) {
193
210
  dimensions,
194
211
  entry,
195
212
  onCloseVideoModal,
196
- maximiseVideoModal,
197
213
  onPlayerSeek,
198
214
  playerState,
199
215
  configuration,
@@ -207,9 +223,29 @@ export default function DockedLayout(props: LayoutProps) {
207
223
  const visible = true;
208
224
  const liveButton = Boolean(value("live_badge_enabled"));
209
225
 
226
+ const {
227
+ isActiveGesture,
228
+ setPlayerAnimationState,
229
+ startComponentsAnimation,
230
+ minimisedHeight,
231
+ } = useModalAnimationContext();
232
+
233
+ const maximazeVideoModal = React.useCallback(
234
+ () => setPlayerAnimationState(PlayerAnimationStateEnum.maximaze),
235
+ []
236
+ );
237
+
238
+ if (!layoutState.docked && !startComponentsAnimation) return null;
239
+
210
240
  return (
211
- <View style={styles.container}>
212
- {!playerState.isLive && (
241
+ <AnimationComponent
242
+ animationType={ComponentAnimationType.componentAppears}
243
+ style={[
244
+ styles.container,
245
+ animatedContainerStyle(isActiveGesture || layoutState.docked),
246
+ ]}
247
+ >
248
+ {!playerState.isLive && layoutState.docked && (
213
249
  <ProgressBar
214
250
  content={entry}
215
251
  value={value}
@@ -217,18 +253,27 @@ export default function DockedLayout(props: LayoutProps) {
217
253
  layoutState={layoutState}
218
254
  onPlayerSeek={onPlayerSeek}
219
255
  playerState={playerState}
256
+ docked
220
257
  />
221
258
  )}
222
259
 
223
260
  <View style={styles.content}>
224
- <PlayerImageBackground
225
- configuration={configuration}
226
- entry={entry}
227
- style={backgroundImageStyle(dimensions)}
261
+ <View
262
+ style={backgroundImageStyle(
263
+ dimensions,
264
+ minimisedHeight,
265
+ isActiveGesture
266
+ )}
228
267
  />
229
- <TouchableWithoutFeedback onPress={maximiseVideoModal}>
268
+ <TouchableWithoutFeedback onPress={maximazeVideoModal}>
230
269
  <View
231
- style={[styles.touchableArea, playerDimensionsStyle(dimensions)]}
270
+ style={[
271
+ styles.touchableArea,
272
+ playerDimensionsStyle(
273
+ minimisedHeight,
274
+ isActiveGesture || layoutState.docked
275
+ ),
276
+ ]}
232
277
  >
233
278
  <View
234
279
  style={[
@@ -272,6 +317,6 @@ export default function DockedLayout(props: LayoutProps) {
272
317
  />
273
318
  </View>
274
319
  </View>
275
- </View>
320
+ </AnimationComponent>
276
321
  );
277
322
  }
@@ -19,6 +19,8 @@ const playbackButtonMargins = (
19
19
  ): number =>
20
20
  isLiveShowFullControls ? (isTablet ? 65 : 10) : isTablet ? 95 : 40;
21
21
 
22
+ export const PADDING_HORIZONTAL = 15;
23
+
22
24
  export const playbackButton = ({
23
25
  playerState,
24
26
  liveButton,
@@ -1,6 +1,5 @@
1
1
  import React from "react";
2
2
  import DefaultLayout from "./DefaultLayout";
3
- import DockedLayout from "./DockedLayout";
4
3
  import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
5
4
 
6
5
  type Dimensions = {
@@ -40,6 +39,7 @@ type LayoutProps = {
40
39
  onSkipLive: () => void;
41
40
  maximiseVideoModal: () => void;
42
41
  dimensions: Dimensions;
42
+ defaultDimensions: Dimensions;
43
43
  playNextData: PlayNextData;
44
44
  title: string | number;
45
45
  summary: string | number;
@@ -48,11 +48,5 @@ type LayoutProps = {
48
48
  export default function Layout(
49
49
  props: LayoutProps
50
50
  ): React.ReactElement<LayoutProps> {
51
- const { layoutState } = props;
52
-
53
- if (layoutState.docked) {
54
- return <DockedLayout {...props} />;
55
- }
56
-
57
51
  return <DefaultLayout {...props} />;
58
52
  }
@@ -11,9 +11,10 @@ type MagicBGProps = {
11
11
  image: string;
12
12
  fallbackUrl?: string;
13
13
  defaultColor: string;
14
+ colors: string[]; // Updated to type string[] as it holds hex values
14
15
  };
15
16
 
16
- const colors = {
17
+ const defaultColors = {
17
18
  overlay: "rgba(0, 0, 0, 0.35)",
18
19
  defaultGradientStart: "rgba(0, 0, 0, 0.25)",
19
20
  defaultGradientEnd: "rgba(0, 0, 0, 0)",
@@ -25,7 +26,7 @@ const styles = StyleSheet.create({
25
26
  },
26
27
  fullScreenOverlay: {
27
28
  ...StyleSheet.absoluteFillObject,
28
- backgroundColor: colors.overlay,
29
+ backgroundColor: defaultColors.overlay,
29
30
  },
30
31
  gradientOverlay: {
31
32
  position: "absolute",
@@ -54,46 +55,63 @@ export const MagicBG: React.FC<MagicBGProps> = ({
54
55
  children,
55
56
  image,
56
57
  fallbackUrl = "",
58
+ colors = [],
57
59
  defaultColor,
58
60
  }) => {
59
61
  const [dominantColor, setDominantColor] =
60
62
  React.useState<string>(defaultColor);
61
63
 
62
64
  const [gradientColors, setGradientColors] = React.useState<string[]>([
63
- colors.defaultGradientStart,
64
- colors.defaultGradientEnd,
65
+ defaultColors.defaultGradientStart,
66
+ defaultColors.defaultGradientEnd,
65
67
  ]);
66
68
 
67
69
  useEffect(() => {
68
70
  const fetchColors = async () => {
69
- if (!image) return;
70
-
71
- try {
72
- const { gradientColors, dominantColor } =
73
- await fetchPaletteAndDominantColor(image);
74
-
75
- setGradientColors(gradientColors);
76
- setDominantColor(dominantColor);
77
- } catch (error) {
71
+ // Check if colors are provided and not empty
72
+ if (colors && colors.length > 0) {
73
+ // Use provided colors for gradient and dominant color
74
+ setGradientColors(colors.slice(0, 2)); // First 2 colors for gradient
75
+ setDominantColor(colors[0]); // First color as dominant
76
+ } else if (image) {
77
+ // If no colors, try fetching from image
78
78
  try {
79
79
  const { gradientColors, dominantColor } =
80
- await fetchPaletteAndDominantColor(fallbackUrl);
80
+ await fetchPaletteAndDominantColor(image);
81
81
 
82
82
  setGradientColors(gradientColors);
83
83
  setDominantColor(dominantColor);
84
- } catch {
85
- setGradientColors([
86
- colors.defaultGradientStart,
87
- colors.defaultGradientEnd,
88
- ]);
89
-
90
- setDominantColor(defaultColor);
84
+ } catch (error) {
85
+ // If image fetch fails, try fallback URL
86
+ try {
87
+ const { gradientColors, dominantColor } =
88
+ await fetchPaletteAndDominantColor(fallbackUrl);
89
+
90
+ setGradientColors(gradientColors);
91
+ setDominantColor(dominantColor);
92
+ } catch {
93
+ // If everything fails, use default color
94
+ setGradientColors([
95
+ defaultColors.defaultGradientStart,
96
+ defaultColors.defaultGradientEnd,
97
+ ]);
98
+
99
+ setDominantColor(defaultColor);
100
+ }
91
101
  }
102
+ } else {
103
+ // If no image or colors, use default color
104
+ setGradientColors([
105
+ defaultColors.defaultGradientStart,
106
+ defaultColors.defaultGradientEnd,
107
+ ]);
108
+
109
+ setDominantColor(defaultColor);
92
110
  }
93
111
  };
94
112
 
95
113
  fetchColors();
96
- }, [image, fallbackUrl, colors, defaultColor]);
114
+ }, []);
97
115
 
98
116
  return (
99
117
  <View style={[styles.container, { backgroundColor: dominantColor }]}>
@@ -1,26 +1,5 @@
1
1
  import queryString from "query-string";
2
-
3
- export const toTypeString = (obj) => {
4
- switch (typeof obj) {
5
- case "object":
6
- return obj instanceof Date ? obj.toISOString() : JSON.stringify(obj); // object, null
7
- case "undefined":
8
- return "";
9
- default:
10
- // boolean, number, string
11
- return obj.toString();
12
- }
13
- };
14
-
15
- export const stringsOnlyObject = (obj) => {
16
- const strObj = {};
17
-
18
- Object.keys(obj).forEach((x) => {
19
- strObj[x] = toTypeString(obj[x]);
20
- });
21
-
22
- return strObj;
23
- };
2
+ import { dayjs } from "@applicaster/zapp-react-native-utils/dateUtils";
24
3
 
25
4
  export const getLiveUrl = (url: string) => {
26
5
  // Use the replace method with a regular expression to replace all instances of subClass with livePage
@@ -42,3 +21,7 @@ export const addQueryParam = (
42
21
 
43
22
  return `${urlWithoutQuery}?${updatedQueryString}`;
44
23
  };
24
+
25
+ export const isValidDate = (dateString: string): boolean => {
26
+ return dateString.trim() !== "" && dayjs.utc(dateString).isValid();
27
+ };
@@ -36,6 +36,12 @@ import { AudioPlayerWrapper } from "./AudioLayer/AudioPlayerWrapper";
36
36
  import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
37
37
  import { getAllAccessibilityProps } from "@applicaster/zapp-react-native-utils/configurationUtils";
38
38
  import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
39
+ import { getTargetScreenDataFromEntry } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useTargetScreenData";
40
+ import { isAppleTV } from "@applicaster/zapp-react-native-ui-components/Helpers/Platform";
41
+ import {
42
+ AnimationComponent,
43
+ ComponentAnimationType,
44
+ } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
39
45
 
40
46
  const RNPlayerManager = {
41
47
  QuickBrickPlayerPlugin: isApplePlatform()
@@ -55,6 +61,7 @@ const styles = StyleSheet.create({
55
61
  position: "absolute",
56
62
  zIndex: 1,
57
63
  },
64
+ playerSize: { width: "100%", height: "100%" },
58
65
  });
59
66
 
60
67
  const logger = createLogger({
@@ -555,6 +562,26 @@ export default class VideoPlayer extends React.Component<
555
562
  this.props.listener?.onPlayerDetached?.(nativeEvent);
556
563
  };
557
564
 
565
+ onVideoFullscreenPlayerDidDismiss = () => {
566
+ this.props.listener?.onVideoFullscreenPlayerDidDismiss?.();
567
+ };
568
+
569
+ onVideoFullscreenPlayerDidPresent = () => {
570
+ this.props.listener?.onVideoFullscreenPlayerDidPresent?.();
571
+ };
572
+
573
+ onVideoFullscreenPlayerWillDismiss = () => {
574
+ this.props.listener?.onVideoFullscreenPlayerWillDismiss?.();
575
+ };
576
+
577
+ onVideoFullscreenPlayerWillPresent = () => {
578
+ this.props.listener?.onVideoFullscreenPlayerWillPresent?.();
579
+ };
580
+
581
+ onPlayerClose = () => {
582
+ this.props.listener?.onPlayerClose?.();
583
+ };
584
+
558
585
  onPiPEnter = () => {
559
586
  this.setState({ piped: true });
560
587
  this.props.openPiP();
@@ -758,8 +785,6 @@ export default class VideoPlayer extends React.Component<
758
785
 
759
786
  render() {
760
787
  const {
761
- castAction,
762
- controls,
763
788
  docked,
764
789
  entry,
765
790
  fullscreen,
@@ -769,8 +794,13 @@ export default class VideoPlayer extends React.Component<
769
794
  isTabletPortrait,
770
795
  muted,
771
796
  style,
797
+ castAction,
798
+ controller,
799
+ startComponentsAnimation,
772
800
  } = this.props;
773
801
 
802
+ const supportNativeCast = controller.supportNativeCast();
803
+
774
804
  const { audioTrackId, keyEvent, paused, seek, textTrackId, rate } =
775
805
  this.state;
776
806
 
@@ -817,17 +847,35 @@ export default class VideoPlayer extends React.Component<
817
847
  const liveCatchUpEnabled =
818
848
  this.props.pluginConfiguration?.liveCatchUpEnabled;
819
849
 
820
- const hideNativeControls = isTV()
821
- ? { controls: !this.getPlayNextData() }
822
- : {};
850
+ // TODO: Get screen data more reliable way useCurrentScreenData
851
+ const screenData = getTargetScreenDataFromEntry(this.props.playableItem);
823
852
 
824
- const platformSpecificProps = isApplePlatform()
853
+ const isInlineTV = screenData?.ui_components?.length > 0 && isTV();
854
+
855
+ let platformSpecificProps: any = isApplePlatform()
825
856
  ? {
826
- ...hideNativeControls,
827
857
  resizeMode: nativeResizeMode,
828
858
  }
829
859
  : {};
830
860
 
861
+ const supportsNativeControls =
862
+ !!this.props.controller?.supportsNativeControls?.();
863
+
864
+ const controls = isAppleTV()
865
+ ? supportsNativeControls && !isInlineTV && !this.getPlayNextData()
866
+ : supportsNativeControls && !this.getPlayNextData();
867
+
868
+ const shouldUseNativeControls =
869
+ controls &&
870
+ !startComponentsAnimation &&
871
+ !docked &&
872
+ !castAction?.state?.connected;
873
+
874
+ platformSpecificProps = {
875
+ ...platformSpecificProps,
876
+ controls: shouldUseNativeControls,
877
+ };
878
+
831
879
  const pictureInPictureEnabled =
832
880
  this.props.pluginConfiguration?.pictureInPictureEnabled;
833
881
 
@@ -835,7 +883,6 @@ export default class VideoPlayer extends React.Component<
835
883
  entry, // Must be passed first in list
836
884
  ...platformSpecificProps,
837
885
  audioTrackId,
838
- controls,
839
886
  docked,
840
887
  enableAutoAudioTrackSelection,
841
888
  fullscreen, // TODO: Check fullscreen params not crash
@@ -890,22 +937,17 @@ export default class VideoPlayer extends React.Component<
890
937
  onVideoEnd: this.onVideoEnd, // complete
891
938
  onVideoError: this.onVideoError, // error
892
939
  onVideoProgress: this.onVideoProgress,
893
- onVideoFullscreenPlayerDidDismiss: this.unHandledEvent(
894
- "onVideoFullscreenPlayerDidPresent"
895
- ),
896
- onVideoFullscreenPlayerDidPresent: this.unHandledEvent(
897
- "onVideoFullscreenPlayerDidPresent"
898
- ),
899
- onVideoFullscreenPlayerWillDismiss: this.unHandledEvent(
900
- "onVideoFullscreenPlayerWillDismiss"
901
- ),
902
- onVideoFullscreenPlayerWillPresent: this.unHandledEvent(
903
- "onVideoFullscreenPlayerWillPresent"
904
- ),
940
+ onVideoFullscreenPlayerDidDismiss: this.onVideoFullscreenPlayerDidDismiss,
941
+ onVideoFullscreenPlayerDidPresent: this.onVideoFullscreenPlayerDidPresent,
942
+ onVideoFullscreenPlayerWillDismiss:
943
+ this.onVideoFullscreenPlayerWillDismiss,
944
+ onVideoFullscreenPlayerWillPresent:
945
+ this.onVideoFullscreenPlayerWillPresent,
905
946
  onVideoLoad: this.onVideoLoad,
906
947
  onVideoLoadStart: this.unHandledEvent("onVideoLoadStart"),
907
948
  onVideoBuffer: this.onVideoBuffer,
908
949
  onPlaybackStalled: this.onPlaybackStalled,
950
+ onPlayerClose: this.onPlayerClose,
909
951
  onPlayerAttached: this.onPlayerAttached,
910
952
  onPlayerDetached: this.onPlayerDetached,
911
953
  };
@@ -979,7 +1021,7 @@ export default class VideoPlayer extends React.Component<
979
1021
  !needToShowPlayNextOverlay &&
980
1022
  this.props.mode !== "PIP";
981
1023
 
982
- if (controls === true) {
1024
+ if (shouldUseNativeControls) {
983
1025
  return null;
984
1026
  }
985
1027
 
@@ -998,6 +1040,7 @@ export default class VideoPlayer extends React.Component<
998
1040
  extraInfoText={castAction?.state?.friendlyStatus}
999
1041
  controlsAlwaysVisible={castAction?.state?.connected}
1000
1042
  playNextData={this.getPlayNextData()}
1043
+ nativeControls={!!controls}
1001
1044
  />
1002
1045
  ) : null;
1003
1046
  };
@@ -1032,29 +1075,14 @@ export default class VideoPlayer extends React.Component<
1032
1075
  const renderMobilePlayer = () => {
1033
1076
  return isFullScreenAudioPlayer && isAudioItem ? (
1034
1077
  <View style={containerStyle}>
1035
- {!castAction?.state?.connected && (
1078
+ {(!castAction?.state?.connected || supportNativeCast) && (
1036
1079
  <this.props.PlayerComponent
1037
1080
  ref={this._assignRoot}
1038
1081
  {...nativeEvents}
1039
1082
  {...nativeProps}
1040
1083
  />
1041
1084
  )}
1042
- <AudioPlayerWrapper {...sharedWrapperViewProps}>
1043
- <View>
1044
- {
1045
- <PlayNextOverlay
1046
- item={entry}
1047
- playerIsDocked={docked}
1048
- pluginConfiguration={this.getPluginConfiguration()}
1049
- playerId={this.props.playerId}
1050
- playNextData={this.getPlayNextData()}
1051
- setNextVideoPreloadThresholdPercentage={
1052
- this.props.setNextVideoPreloadThresholdPercentage
1053
- }
1054
- />
1055
- }
1056
- </View>
1057
- </AudioPlayerWrapper>
1085
+ <AudioPlayerWrapper {...sharedWrapperViewProps} />
1058
1086
  </View>
1059
1087
  ) : (
1060
1088
  <PlayerWrapper {...sharedWrapperViewProps}>
@@ -1069,11 +1097,20 @@ export default class VideoPlayer extends React.Component<
1069
1097
  <View style={styles.container}>
1070
1098
  <View style={[playerContainerStyles, playerDimensions]}>
1071
1099
  {isAudioItem && (
1072
- <AudioPlayer
1073
- style={playerDimensions}
1074
- audio_item={entry}
1075
- plugin_configuration={this.getPluginConfiguration()}
1076
- />
1100
+ <AnimationComponent
1101
+ animationType={ComponentAnimationType.player}
1102
+ additionalData={{
1103
+ ...playerDimensions,
1104
+ inlineAudioPlayer: true,
1105
+ }}
1106
+ style={getStyle(playerDimensions)}
1107
+ >
1108
+ <AudioPlayer
1109
+ style={styles.playerSize}
1110
+ audio_item={entry}
1111
+ plugin_configuration={this.getPluginConfiguration()}
1112
+ />
1113
+ </AnimationComponent>
1077
1114
  )}
1078
1115
 
1079
1116
  {shouldRenderBackground && (
@@ -1085,18 +1122,24 @@ export default class VideoPlayer extends React.Component<
1085
1122
  />
1086
1123
  )}
1087
1124
 
1088
- {!castAction?.state?.connected && (
1089
- <this.props.PlayerComponent
1090
- ref={this._assignRoot}
1091
- {...nativeEvents}
1092
- {...nativeProps}
1093
- listener={this.props.listener}
1125
+ {(!castAction?.state?.connected || supportNativeCast) && (
1126
+ <AnimationComponent
1127
+ animationType={ComponentAnimationType.player}
1128
+ additionalData={playerDimensions}
1094
1129
  style={getStyle(playerDimensions)}
1095
- pluginConfiguration={this.getPluginConfiguration()}
1096
- controller={this.props.controller}
1097
1130
  >
1098
- {this.childrenWithPlayNext()}
1099
- </this.props.PlayerComponent>
1131
+ <this.props.PlayerComponent
1132
+ ref={this._assignRoot}
1133
+ {...nativeEvents}
1134
+ {...nativeProps}
1135
+ listener={this.props.listener}
1136
+ style={styles.playerSize}
1137
+ pluginConfiguration={this.getPluginConfiguration()}
1138
+ controller={this.props.controller}
1139
+ >
1140
+ {this.childrenWithPlayNext()}
1141
+ </this.props.PlayerComponent>
1142
+ </AnimationComponent>
1100
1143
  )}
1101
1144
  </View>
1102
1145