@applicaster/quick-brick-player 12.0.0-rc.7 → 12.0.0-rc.71

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.
@@ -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 = {
@@ -24,27 +23,30 @@ type LayoutProps = {
24
23
  isBuffering: boolean;
25
24
  };
26
25
  value: GetValue;
26
+ sleepTimerDate: number;
27
+ playbackSpeedName: string;
28
+ playbackSleepName: string;
27
29
  configuration: { [key: string]: any };
28
30
  onPlaybackButtonPress: () => void;
29
31
  onRewindButtonPress: () => void;
30
32
  onForwardButtonPress: () => void;
33
+ onSpeedButtonPress: () => void;
34
+ onSleepButtonPress: () => void;
31
35
  onCloseVideoModal: () => void;
36
+ cancelSleepTimer: () => void;
32
37
  onPlayerSeek: (targetTime: number) => void;
33
38
  onSkipStart: () => void;
34
39
  onSkipLive: () => void;
35
40
  maximiseVideoModal: () => void;
36
41
  dimensions: Dimensions;
42
+ defaultDimensions: Dimensions;
37
43
  playNextData: PlayNextData;
44
+ title: string | number;
45
+ summary: string | number;
38
46
  };
39
47
 
40
48
  export default function Layout(
41
49
  props: LayoutProps
42
50
  ): React.ReactElement<LayoutProps> {
43
- const { layoutState } = props;
44
-
45
- if (layoutState.docked) {
46
- return <DockedLayout {...props} />;
47
- }
48
-
49
51
  return <DefaultLayout {...props} />;
50
52
  }
@@ -1,17 +1,19 @@
1
- // Disabling for now as lint can't recognise typescript definition here
2
1
  /* eslint-disable react/prop-types */
3
2
  import * as React from "react";
4
- import { StyleSheet, View } from "react-native";
3
+ import { Animated, StyleSheet, View } from "react-native";
5
4
  import LinearGradient from "../LinearGradient";
6
5
  import { getDominantColor, getPalettes } from "../../../utils/utils";
6
+ import { useEffect } from "react";
7
7
 
8
8
  type MagicBGProps = {
9
9
  children: React.ReactNode;
10
10
  image: string;
11
+ fallbackUrl?: string;
11
12
  defaultColor: string;
13
+ colors: string[];
12
14
  };
13
15
 
14
- const colors = {
16
+ const defaultColors = {
15
17
  overlay: "rgba(0, 0, 0, 0.35)",
16
18
  defaultGradientStart: "rgba(0, 0, 0, 0.25)",
17
19
  defaultGradientEnd: "rgba(0, 0, 0, 0)",
@@ -23,7 +25,7 @@ const styles = StyleSheet.create({
23
25
  },
24
26
  fullScreenOverlay: {
25
27
  ...StyleSheet.absoluteFillObject,
26
- backgroundColor: colors.overlay,
28
+ backgroundColor: defaultColors.overlay,
27
29
  },
28
30
  gradientOverlay: {
29
31
  position: "absolute",
@@ -34,53 +36,120 @@ const styles = StyleSheet.create({
34
36
  },
35
37
  });
36
38
 
39
+ const fetchPaletteAndDominantColor = async (imageUrl: string) => {
40
+ const palette = await getPalettes(imageUrl);
41
+
42
+ const colors = palette.map(
43
+ (color: { r: number; g: number; b: number }) =>
44
+ `rgb(${color.r}, ${color.g}, ${color.b})`
45
+ );
46
+
47
+ const dominant = await getDominantColor(imageUrl);
48
+ const dominantColor = `rgb(${dominant.r}, ${dominant.g}, ${dominant.b})`;
49
+
50
+ return { gradientColors: colors.slice(0, 2), dominantColor };
51
+ };
52
+
37
53
  export const MagicBG: React.FC<MagicBGProps> = ({
38
54
  children,
39
55
  image,
56
+ fallbackUrl = "",
57
+ colors = [],
40
58
  defaultColor,
41
59
  }) => {
42
60
  const [dominantColor, setDominantColor] =
43
61
  React.useState<string>(defaultColor);
44
62
 
45
63
  const [gradientColors, setGradientColors] = React.useState<string[]>([
46
- colors.defaultGradientStart,
47
- colors.defaultGradientEnd,
64
+ defaultColors.defaultGradientStart,
65
+ defaultColors.defaultGradientEnd,
48
66
  ]);
49
67
 
50
- React.useEffect(() => {
51
- const fetchColors = async () => {
52
- if (image) {
53
- try {
54
- const palette = await getPalettes(image);
68
+ const [backgroundColorAnim] = React.useState(new Animated.Value(0)); // from 0 to 1
69
+ const [gradientOpacityAnim] = React.useState(new Animated.Value(0)); // from 0 to 1
55
70
 
56
- const colors = palette.map(
57
- (color: { r: number; g: number; b: number }) =>
58
- `rgb(${color.r}, ${color.g}, ${color.b})`
59
- );
71
+ useEffect(() => {
72
+ const animateColors = () => {
73
+ Animated.timing(backgroundColorAnim, {
74
+ toValue: 1,
75
+ duration: 500,
76
+ useNativeDriver: false,
77
+ }).start();
60
78
 
61
- setGradientColors(colors.slice(0, 2));
79
+ Animated.timing(gradientOpacityAnim, {
80
+ toValue: 1,
81
+ duration: 500,
82
+ useNativeDriver: false,
83
+ }).start();
84
+ };
62
85
 
63
- const dominant = await getDominantColor(image);
64
- setDominantColor(`rgb(${dominant.r}, ${dominant.g}, ${dominant.b})`);
86
+ const fetchColors = async () => {
87
+ if (colors && colors.length > 0) {
88
+ setGradientColors(colors.slice(0, 2));
89
+ setDominantColor(colors[0]);
90
+ animateColors();
91
+ } else if (image) {
92
+ try {
93
+ const { gradientColors, dominantColor } =
94
+ await fetchPaletteAndDominantColor(image);
95
+
96
+ setGradientColors(gradientColors);
97
+ setDominantColor(dominantColor);
98
+ animateColors();
65
99
  } catch (error) {
66
- setGradientColors([
67
- colors.defaultGradientStart,
68
- colors.defaultGradientEnd,
69
- ]);
100
+ try {
101
+ const { gradientColors, dominantColor } =
102
+ await fetchPaletteAndDominantColor(fallbackUrl);
103
+
104
+ setGradientColors(gradientColors);
105
+ setDominantColor(dominantColor);
106
+ animateColors();
107
+ } catch {
108
+ setGradientColors([
109
+ defaultColors.defaultGradientStart,
110
+ defaultColors.defaultGradientEnd,
111
+ ]);
70
112
 
71
- setDominantColor(defaultColor);
113
+ setDominantColor(defaultColor);
114
+ }
72
115
  }
116
+ } else {
117
+ setGradientColors([
118
+ defaultColors.defaultGradientStart,
119
+ defaultColors.defaultGradientEnd,
120
+ ]);
121
+
122
+ setDominantColor(defaultColor);
73
123
  }
74
124
  };
75
125
 
76
126
  fetchColors();
77
- }, [image, defaultColor]);
127
+ }, []);
128
+
129
+ const interpolatedBackgroundColor = backgroundColorAnim.interpolate({
130
+ inputRange: [0, 1],
131
+ outputRange: ["black", dominantColor],
132
+ });
78
133
 
79
134
  return (
80
- <View style={[styles.container, { backgroundColor: dominantColor }]}>
135
+ <Animated.View
136
+ style={[
137
+ styles.container,
138
+ { backgroundColor: interpolatedBackgroundColor },
139
+ ]}
140
+ >
81
141
  <View style={styles.fullScreenOverlay} />
82
- <LinearGradient colors={gradientColors} style={styles.gradientOverlay} />
142
+
143
+ <Animated.View
144
+ style={[styles.gradientOverlay, { opacity: gradientOpacityAnim }]}
145
+ >
146
+ <LinearGradient
147
+ colors={gradientColors}
148
+ style={StyleSheet.absoluteFill}
149
+ />
150
+ </Animated.View>
151
+
83
152
  {children}
84
- </View>
153
+ </Animated.View>
85
154
  );
86
155
  };
@@ -0,0 +1,33 @@
1
+ import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
2
+ import { parseJsonIfNeeded } from "@applicaster/zapp-react-native-utils/functionUtils";
3
+
4
+ export const NAMESPACE = "audio-player";
5
+
6
+ export async function loadItemsFromStorage(key: string) {
7
+ const storedItems = await localStorage.getItem(key, NAMESPACE);
8
+
9
+ return parseJsonIfNeeded(storedItems) || null;
10
+ }
11
+
12
+ export const hasDatePassed = (timestamp: number) => {
13
+ // Get the current date and time
14
+ const currentDate = new Date();
15
+
16
+ // Compare the current date's timestamp with the given timestamp
17
+ return currentDate.getTime() > timestamp;
18
+ };
19
+
20
+ export const formatSpeed = (value: number) => {
21
+ let formattedValue = value.toString();
22
+
23
+ // If the value ends with ".0", remove it
24
+ if (formattedValue.endsWith(".0")) {
25
+ formattedValue = formattedValue.slice(0, -2);
26
+ }
27
+
28
+ // Replace "." with "_"
29
+ formattedValue = formattedValue.replace(".", "_");
30
+
31
+ // Return the formatted string with "speed_" prefix
32
+ return `speed_${formattedValue}`;
33
+ };
@@ -1,21 +1,31 @@
1
- export const toTypeString = (obj) => {
2
- switch (typeof obj) {
3
- case "object":
4
- return obj instanceof Date ? obj.toISOString() : JSON.stringify(obj); // object, null
5
- case "undefined":
6
- return "";
7
- default:
8
- // boolean, number, string
9
- return obj.toString();
10
- }
1
+ import queryString from "query-string";
2
+ import { dayjs } from "@applicaster/zapp-react-native-utils/dateUtils";
3
+
4
+ export const getLiveUrl = (url: string) => {
5
+ // Use the replace method with a regular expression to replace all instances of subClass with livePage
6
+ return url.replace(new RegExp("subClass", "g"), "livePage");
11
7
  };
12
8
 
13
- export const stringsOnlyObject = (obj) => {
14
- const strObj = {};
9
+ export const addQueryParam = (
10
+ baseUrl: string,
11
+ paramName: string,
12
+ paramValue: string | number
13
+ ) => {
14
+ const [urlWithoutQuery, query] = baseUrl.split("?");
15
+
16
+ const parsedQuery = queryString.parse(query);
17
+
18
+ parsedQuery[paramName] = paramValue.toString();
15
19
 
16
- Object.keys(obj).forEach((x) => {
17
- strObj[x] = toTypeString(obj[x]);
18
- });
20
+ const updatedQueryString = queryString.stringify(parsedQuery);
21
+
22
+ return `${urlWithoutQuery}?${updatedQueryString}`;
23
+ };
19
24
 
20
- return strObj;
25
+ export const isValidDate = (dateString: string | undefined): boolean => {
26
+ return (
27
+ typeof dateString === "string" &&
28
+ dateString.trim() !== "" &&
29
+ dayjs.utc(dateString).isValid()
30
+ );
21
31
  };
@@ -1,3 +1 @@
1
- export * from "./AssetsHelper";
2
-
3
1
  export * from "./Utils";
@@ -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({
@@ -87,7 +94,7 @@ export default class VideoPlayer extends React.Component<
87
94
  // TODO: Can be deleted, on controller logic
88
95
  paused: false,
89
96
  piped: false,
90
- rate: 1,
97
+ rate: 1.0,
91
98
  // TODO: Hack for analytics, must br removed
92
99
  resume: null,
93
100
 
@@ -368,6 +375,10 @@ export default class VideoPlayer extends React.Component<
368
375
  }
369
376
  };
370
377
 
378
+ setPlaybackRate = (rate = 1.0) => {
379
+ this.setState({ rate });
380
+ };
381
+
371
382
  getCurrentTime = () => {
372
383
  return this.state.currentTime;
373
384
  };
@@ -551,6 +562,26 @@ export default class VideoPlayer extends React.Component<
551
562
  this.props.listener?.onPlayerDetached?.(nativeEvent);
552
563
  };
553
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
+
554
585
  onPiPEnter = () => {
555
586
  this.setState({ piped: true });
556
587
  this.props.openPiP();
@@ -754,8 +785,6 @@ export default class VideoPlayer extends React.Component<
754
785
 
755
786
  render() {
756
787
  const {
757
- castAction,
758
- controls,
759
788
  docked,
760
789
  entry,
761
790
  fullscreen,
@@ -765,9 +794,15 @@ export default class VideoPlayer extends React.Component<
765
794
  isTabletPortrait,
766
795
  muted,
767
796
  style,
797
+ castAction,
798
+ controller,
799
+ startComponentsAnimation,
768
800
  } = this.props;
769
801
 
770
- const { audioTrackId, keyEvent, paused, seek, textTrackId } = this.state;
802
+ const supportNativeCast = controller.supportNativeCast();
803
+
804
+ const { audioTrackId, keyEvent, paused, seek, textTrackId, rate } =
805
+ this.state;
771
806
 
772
807
  const isAudioItem =
773
808
  entry?.content?.type?.includes?.("audio") ||
@@ -812,17 +847,35 @@ export default class VideoPlayer extends React.Component<
812
847
  const liveCatchUpEnabled =
813
848
  this.props.pluginConfiguration?.liveCatchUpEnabled;
814
849
 
815
- const hideNativeControls = isTV()
816
- ? { controls: !this.getPlayNextData() }
817
- : {};
850
+ // TODO: Get screen data more reliable way useCurrentScreenData
851
+ const screenData = getTargetScreenDataFromEntry(this.props.playableItem);
852
+
853
+ const isInlineTV = screenData?.ui_components?.length > 0 && isTV();
818
854
 
819
- const platformSpecificProps = isApplePlatform()
855
+ let platformSpecificProps: any = isApplePlatform()
820
856
  ? {
821
- ...hideNativeControls,
822
857
  resizeMode: nativeResizeMode,
823
858
  }
824
859
  : {};
825
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
+
826
879
  const pictureInPictureEnabled =
827
880
  this.props.pluginConfiguration?.pictureInPictureEnabled;
828
881
 
@@ -830,7 +883,6 @@ export default class VideoPlayer extends React.Component<
830
883
  entry, // Must be passed first in list
831
884
  ...platformSpecificProps,
832
885
  audioTrackId,
833
- controls,
834
886
  docked,
835
887
  enableAutoAudioTrackSelection,
836
888
  fullscreen, // TODO: Check fullscreen params not crash
@@ -839,6 +891,7 @@ export default class VideoPlayer extends React.Component<
839
891
  nowPlayingEnabled,
840
892
  paused,
841
893
  seek,
894
+ rate,
842
895
  textTrackId,
843
896
  liveSeekingEnabled,
844
897
  liveCatchUpEnabled,
@@ -884,22 +937,17 @@ export default class VideoPlayer extends React.Component<
884
937
  onVideoEnd: this.onVideoEnd, // complete
885
938
  onVideoError: this.onVideoError, // error
886
939
  onVideoProgress: this.onVideoProgress,
887
- onVideoFullscreenPlayerDidDismiss: this.unHandledEvent(
888
- "onVideoFullscreenPlayerDidPresent"
889
- ),
890
- onVideoFullscreenPlayerDidPresent: this.unHandledEvent(
891
- "onVideoFullscreenPlayerDidPresent"
892
- ),
893
- onVideoFullscreenPlayerWillDismiss: this.unHandledEvent(
894
- "onVideoFullscreenPlayerWillDismiss"
895
- ),
896
- onVideoFullscreenPlayerWillPresent: this.unHandledEvent(
897
- "onVideoFullscreenPlayerWillPresent"
898
- ),
940
+ onVideoFullscreenPlayerDidDismiss: this.onVideoFullscreenPlayerDidDismiss,
941
+ onVideoFullscreenPlayerDidPresent: this.onVideoFullscreenPlayerDidPresent,
942
+ onVideoFullscreenPlayerWillDismiss:
943
+ this.onVideoFullscreenPlayerWillDismiss,
944
+ onVideoFullscreenPlayerWillPresent:
945
+ this.onVideoFullscreenPlayerWillPresent,
899
946
  onVideoLoad: this.onVideoLoad,
900
947
  onVideoLoadStart: this.unHandledEvent("onVideoLoadStart"),
901
948
  onVideoBuffer: this.onVideoBuffer,
902
949
  onPlaybackStalled: this.onPlaybackStalled,
950
+ onPlayerClose: this.onPlayerClose,
903
951
  onPlayerAttached: this.onPlayerAttached,
904
952
  onPlayerDetached: this.onPlayerDetached,
905
953
  };
@@ -973,7 +1021,7 @@ export default class VideoPlayer extends React.Component<
973
1021
  !needToShowPlayNextOverlay &&
974
1022
  this.props.mode !== "PIP";
975
1023
 
976
- if (controls === true) {
1024
+ if (shouldUseNativeControls) {
977
1025
  return null;
978
1026
  }
979
1027
 
@@ -992,6 +1040,7 @@ export default class VideoPlayer extends React.Component<
992
1040
  extraInfoText={castAction?.state?.friendlyStatus}
993
1041
  controlsAlwaysVisible={castAction?.state?.connected}
994
1042
  playNextData={this.getPlayNextData()}
1043
+ nativeControls={!!controls}
995
1044
  />
996
1045
  ) : null;
997
1046
  };
@@ -1005,10 +1054,12 @@ export default class VideoPlayer extends React.Component<
1005
1054
  inline,
1006
1055
  docked,
1007
1056
  isModal,
1057
+ pip: this.state.piped,
1008
1058
  layoutState: {
1009
1059
  inline,
1010
1060
  docked,
1011
1061
  isModal,
1062
+ pip: this.state.piped,
1012
1063
  },
1013
1064
  configuration: this.getPluginConfiguration(),
1014
1065
  fullscreen: fullscreen,
@@ -1024,29 +1075,14 @@ export default class VideoPlayer extends React.Component<
1024
1075
  const renderMobilePlayer = () => {
1025
1076
  return isFullScreenAudioPlayer && isAudioItem ? (
1026
1077
  <View style={containerStyle}>
1027
- {!castAction?.state?.connected && (
1078
+ {(!castAction?.state?.connected || supportNativeCast) && (
1028
1079
  <this.props.PlayerComponent
1029
1080
  ref={this._assignRoot}
1030
1081
  {...nativeEvents}
1031
1082
  {...nativeProps}
1032
1083
  />
1033
1084
  )}
1034
- <AudioPlayerWrapper {...sharedWrapperViewProps}>
1035
- <View>
1036
- {
1037
- <PlayNextOverlay
1038
- item={entry}
1039
- playerIsDocked={docked}
1040
- pluginConfiguration={this.getPluginConfiguration()}
1041
- playerId={this.props.playerId}
1042
- playNextData={this.getPlayNextData()}
1043
- setNextVideoPreloadThresholdPercentage={
1044
- this.props.setNextVideoPreloadThresholdPercentage
1045
- }
1046
- />
1047
- }
1048
- </View>
1049
- </AudioPlayerWrapper>
1085
+ <AudioPlayerWrapper {...sharedWrapperViewProps} />
1050
1086
  </View>
1051
1087
  ) : (
1052
1088
  <PlayerWrapper {...sharedWrapperViewProps}>
@@ -1061,11 +1097,24 @@ export default class VideoPlayer extends React.Component<
1061
1097
  <View style={styles.container}>
1062
1098
  <View style={[playerContainerStyles, playerDimensions]}>
1063
1099
  {isAudioItem && (
1064
- <AudioPlayer
1065
- style={playerDimensions}
1066
- audio_item={entry}
1067
- plugin_configuration={this.getPluginConfiguration()}
1068
- />
1100
+ <AnimationComponent
1101
+ animationType={ComponentAnimationType.player}
1102
+ additionalData={{
1103
+ ...playerDimensions,
1104
+ inlineAudioPlayer: true,
1105
+ }}
1106
+ style={getStyle(playerDimensions)}
1107
+ >
1108
+ <AudioPlayer
1109
+ style={
1110
+ isTV()
1111
+ ? getStyle(playerDimensions)
1112
+ : styles.playerSize
1113
+ }
1114
+ audio_item={entry}
1115
+ plugin_configuration={this.getPluginConfiguration()}
1116
+ />
1117
+ </AnimationComponent>
1069
1118
  )}
1070
1119
 
1071
1120
  {shouldRenderBackground && (
@@ -1077,17 +1126,28 @@ export default class VideoPlayer extends React.Component<
1077
1126
  />
1078
1127
  )}
1079
1128
 
1080
- {!castAction?.state?.connected && (
1081
- <this.props.PlayerComponent
1082
- ref={this._assignRoot}
1083
- {...nativeEvents}
1084
- {...nativeProps}
1085
- listener={this.props.listener}
1129
+ {(!castAction?.state?.connected || supportNativeCast) && (
1130
+ <AnimationComponent
1131
+ animationType={ComponentAnimationType.player}
1132
+ additionalData={playerDimensions}
1086
1133
  style={getStyle(playerDimensions)}
1087
- pluginConfiguration={this.getPluginConfiguration()}
1088
1134
  >
1089
- {this.childrenWithPlayNext()}
1090
- </this.props.PlayerComponent>
1135
+ <this.props.PlayerComponent
1136
+ ref={this._assignRoot}
1137
+ {...nativeEvents}
1138
+ {...nativeProps}
1139
+ listener={this.props.listener}
1140
+ style={
1141
+ isTV()
1142
+ ? getStyle(playerDimensions)
1143
+ : styles.playerSize
1144
+ }
1145
+ pluginConfiguration={this.getPluginConfiguration()}
1146
+ controller={this.props.controller}
1147
+ >
1148
+ {this.childrenWithPlayNext()}
1149
+ </this.props.PlayerComponent>
1150
+ </AnimationComponent>
1091
1151
  )}
1092
1152
  </View>
1093
1153
 
@@ -1121,6 +1181,7 @@ export default class VideoPlayer extends React.Component<
1121
1181
  listener={this.props.listener}
1122
1182
  style={this.takeParentStyle}
1123
1183
  pluginConfiguration={this.getPluginConfiguration()}
1184
+ controller={this.props.controller}
1124
1185
  >
1125
1186
  {this.childrenWithPlayNext()}
1126
1187
  </this.props.PlayerComponent>