@applicaster/quick-brick-player 12.0.0-rc.9 → 12.0.0-rc.91
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 +7 -6
- package/src/CellPlayer/Assets/AssetsComponent.tsx +2 -1
- package/src/Player/AudioLayer/AudioDescription.tsx +3 -3
- package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +277 -58
- package/src/Player/AudioLayer/Layout/DefaultLayout.tsx +260 -71
- package/src/Player/AudioLayer/Layout/DockedLayout.tsx +71 -18
- package/src/Player/AudioLayer/Layout/defaultLayoutsConts.ts +32 -1
- package/src/Player/AudioLayer/Layout/index.tsx +9 -7
- package/src/Player/AudioLayer/MagicBG/index.tsx +96 -27
- package/src/Player/AudioLayer/utils.ts +33 -0
- package/src/Player/Utils/Utils.ts +26 -16
- package/src/Player/Utils/index.tsx +0 -2
- package/src/Player/index.tsx +130 -72
|
@@ -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
|
|
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:
|
|
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
|
-
|
|
47
|
-
|
|
64
|
+
defaultColors.defaultGradientStart,
|
|
65
|
+
defaultColors.defaultGradientEnd,
|
|
48
66
|
]);
|
|
49
67
|
|
|
50
|
-
React.
|
|
51
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
const animateColors = () => {
|
|
73
|
+
Animated.timing(backgroundColorAnim, {
|
|
74
|
+
toValue: 1,
|
|
75
|
+
duration: 500,
|
|
76
|
+
useNativeDriver: false,
|
|
77
|
+
}).start();
|
|
60
78
|
|
|
61
|
-
|
|
79
|
+
Animated.timing(gradientOpacityAnim, {
|
|
80
|
+
toValue: 1,
|
|
81
|
+
duration: 500,
|
|
82
|
+
useNativeDriver: false,
|
|
83
|
+
}).start();
|
|
84
|
+
};
|
|
62
85
|
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
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
|
-
}, [
|
|
127
|
+
}, []);
|
|
128
|
+
|
|
129
|
+
const interpolatedBackgroundColor = backgroundColorAnim.interpolate({
|
|
130
|
+
inputRange: [0, 1],
|
|
131
|
+
outputRange: ["black", dominantColor],
|
|
132
|
+
});
|
|
78
133
|
|
|
79
134
|
return (
|
|
80
|
-
<View
|
|
135
|
+
<Animated.View
|
|
136
|
+
style={[
|
|
137
|
+
styles.container,
|
|
138
|
+
{ backgroundColor: interpolatedBackgroundColor },
|
|
139
|
+
]}
|
|
140
|
+
>
|
|
81
141
|
<View style={styles.fullScreenOverlay} />
|
|
82
|
-
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
|
14
|
-
|
|
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
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
20
|
+
const updatedQueryString = queryString.stringify(parsedQuery);
|
|
21
|
+
|
|
22
|
+
return `${urlWithoutQuery}?${updatedQueryString}`;
|
|
23
|
+
};
|
|
19
24
|
|
|
20
|
-
|
|
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
|
};
|
package/src/Player/index.tsx
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import React from "react";
|
|
5
5
|
import * as R from "ramda";
|
|
6
6
|
|
|
7
|
-
import { findNodeHandle,
|
|
7
|
+
import { findNodeHandle, StyleSheet, View } from "react-native";
|
|
8
8
|
import TransportControlsMobile from "@applicaster/quick-brick-mobile-transport-controls";
|
|
9
9
|
import TransportControlsTV from "@applicaster/quick-brick-tv-transport-controls";
|
|
10
10
|
|
|
@@ -36,15 +36,13 @@ 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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
: NativeModules.QBKalturaPlayerModule,
|
|
47
|
-
};
|
|
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";
|
|
45
|
+
import { RNPlayerManager } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/nativePlayerManager";
|
|
48
46
|
|
|
49
47
|
const styles = StyleSheet.create({
|
|
50
48
|
container: { flex: 1 },
|
|
@@ -55,6 +53,7 @@ const styles = StyleSheet.create({
|
|
|
55
53
|
position: "absolute",
|
|
56
54
|
zIndex: 1,
|
|
57
55
|
},
|
|
56
|
+
playerSize: { width: "100%", height: "100%" },
|
|
58
57
|
});
|
|
59
58
|
|
|
60
59
|
const logger = createLogger({
|
|
@@ -87,7 +86,7 @@ export default class VideoPlayer extends React.Component<
|
|
|
87
86
|
// TODO: Can be deleted, on controller logic
|
|
88
87
|
paused: false,
|
|
89
88
|
piped: false,
|
|
90
|
-
rate: 1,
|
|
89
|
+
rate: 1.0,
|
|
91
90
|
// TODO: Hack for analytics, must br removed
|
|
92
91
|
resume: null,
|
|
93
92
|
|
|
@@ -113,8 +112,6 @@ export default class VideoPlayer extends React.Component<
|
|
|
113
112
|
}
|
|
114
113
|
|
|
115
114
|
componentWillUnmount() {
|
|
116
|
-
this.stopBackgroundPlayback();
|
|
117
|
-
|
|
118
115
|
this.playbackStarted = false;
|
|
119
116
|
this.handleAnalyticEvent(GENERAL_EVENT.session_end);
|
|
120
117
|
this.onPlayerClosed();
|
|
@@ -159,6 +156,11 @@ export default class VideoPlayer extends React.Component<
|
|
|
159
156
|
}
|
|
160
157
|
}
|
|
161
158
|
|
|
159
|
+
// For close button
|
|
160
|
+
public closeNativePlayer = () => {
|
|
161
|
+
this.stopBackgroundPlayback();
|
|
162
|
+
};
|
|
163
|
+
|
|
162
164
|
getPlayNextData = () => this.props.playNextData as PlayNextData;
|
|
163
165
|
|
|
164
166
|
/**
|
|
@@ -333,11 +335,7 @@ export default class VideoPlayer extends React.Component<
|
|
|
333
335
|
}
|
|
334
336
|
};
|
|
335
337
|
|
|
336
|
-
|
|
337
|
-
* Sets either subtitle language, or audio language if we have a selected a new locale.
|
|
338
|
-
* If no locale is set it defaults to system language for audio, and leaves subtitles unaltered.
|
|
339
|
-
*/
|
|
340
|
-
setLanguage = (selected = null) => {
|
|
338
|
+
selectTrack = (selected) => {
|
|
341
339
|
const { trackType, id, language } = selected || {};
|
|
342
340
|
|
|
343
341
|
const isOff = language === "Off";
|
|
@@ -368,6 +366,10 @@ export default class VideoPlayer extends React.Component<
|
|
|
368
366
|
}
|
|
369
367
|
};
|
|
370
368
|
|
|
369
|
+
setPlaybackRate = (rate = 1.0) => {
|
|
370
|
+
this.setState({ rate });
|
|
371
|
+
};
|
|
372
|
+
|
|
371
373
|
getCurrentTime = () => {
|
|
372
374
|
return this.state.currentTime;
|
|
373
375
|
};
|
|
@@ -551,6 +553,26 @@ export default class VideoPlayer extends React.Component<
|
|
|
551
553
|
this.props.listener?.onPlayerDetached?.(nativeEvent);
|
|
552
554
|
};
|
|
553
555
|
|
|
556
|
+
onVideoFullscreenPlayerDidDismiss = () => {
|
|
557
|
+
this.props.listener?.onVideoFullscreenPlayerDidDismiss?.();
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
onVideoFullscreenPlayerDidPresent = () => {
|
|
561
|
+
this.props.listener?.onVideoFullscreenPlayerDidPresent?.();
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
onVideoFullscreenPlayerWillDismiss = () => {
|
|
565
|
+
this.props.listener?.onVideoFullscreenPlayerWillDismiss?.();
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
onVideoFullscreenPlayerWillPresent = () => {
|
|
569
|
+
this.props.listener?.onVideoFullscreenPlayerWillPresent?.();
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
onPlayerClose = () => {
|
|
573
|
+
this.props.listener?.onPlayerClose?.();
|
|
574
|
+
};
|
|
575
|
+
|
|
554
576
|
onPiPEnter = () => {
|
|
555
577
|
this.setState({ piped: true });
|
|
556
578
|
this.props.openPiP();
|
|
@@ -754,8 +776,6 @@ export default class VideoPlayer extends React.Component<
|
|
|
754
776
|
|
|
755
777
|
render() {
|
|
756
778
|
const {
|
|
757
|
-
castAction,
|
|
758
|
-
controls,
|
|
759
779
|
docked,
|
|
760
780
|
entry,
|
|
761
781
|
fullscreen,
|
|
@@ -765,9 +785,15 @@ export default class VideoPlayer extends React.Component<
|
|
|
765
785
|
isTabletPortrait,
|
|
766
786
|
muted,
|
|
767
787
|
style,
|
|
788
|
+
castAction,
|
|
789
|
+
controller,
|
|
790
|
+
startComponentsAnimation,
|
|
768
791
|
} = this.props;
|
|
769
792
|
|
|
770
|
-
const
|
|
793
|
+
const supportNativeCast = controller.supportNativeCast();
|
|
794
|
+
|
|
795
|
+
const { audioTrackId, keyEvent, paused, seek, textTrackId, rate } =
|
|
796
|
+
this.state;
|
|
771
797
|
|
|
772
798
|
const isAudioItem =
|
|
773
799
|
entry?.content?.type?.includes?.("audio") ||
|
|
@@ -812,17 +838,35 @@ export default class VideoPlayer extends React.Component<
|
|
|
812
838
|
const liveCatchUpEnabled =
|
|
813
839
|
this.props.pluginConfiguration?.liveCatchUpEnabled;
|
|
814
840
|
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
841
|
+
// TODO: Get screen data more reliable way useCurrentScreenData
|
|
842
|
+
const screenData = getTargetScreenDataFromEntry(this.props.playableItem);
|
|
843
|
+
|
|
844
|
+
const isInlineTV = screenData?.ui_components?.length > 0 && isTV();
|
|
818
845
|
|
|
819
|
-
|
|
846
|
+
let platformSpecificProps: any = isApplePlatform()
|
|
820
847
|
? {
|
|
821
|
-
...hideNativeControls,
|
|
822
848
|
resizeMode: nativeResizeMode,
|
|
823
849
|
}
|
|
824
850
|
: {};
|
|
825
851
|
|
|
852
|
+
const supportsNativeControls =
|
|
853
|
+
!!this.props.controller?.supportsNativeControls?.();
|
|
854
|
+
|
|
855
|
+
const controls = isAppleTV()
|
|
856
|
+
? supportsNativeControls && !isInlineTV && !this.getPlayNextData()
|
|
857
|
+
: supportsNativeControls && !this.getPlayNextData();
|
|
858
|
+
|
|
859
|
+
const shouldUseNativeControls =
|
|
860
|
+
controls &&
|
|
861
|
+
!startComponentsAnimation &&
|
|
862
|
+
!docked &&
|
|
863
|
+
!castAction?.state?.connected;
|
|
864
|
+
|
|
865
|
+
platformSpecificProps = {
|
|
866
|
+
...platformSpecificProps,
|
|
867
|
+
controls: shouldUseNativeControls,
|
|
868
|
+
};
|
|
869
|
+
|
|
826
870
|
const pictureInPictureEnabled =
|
|
827
871
|
this.props.pluginConfiguration?.pictureInPictureEnabled;
|
|
828
872
|
|
|
@@ -830,7 +874,6 @@ export default class VideoPlayer extends React.Component<
|
|
|
830
874
|
entry, // Must be passed first in list
|
|
831
875
|
...platformSpecificProps,
|
|
832
876
|
audioTrackId,
|
|
833
|
-
controls,
|
|
834
877
|
docked,
|
|
835
878
|
enableAutoAudioTrackSelection,
|
|
836
879
|
fullscreen, // TODO: Check fullscreen params not crash
|
|
@@ -839,6 +882,7 @@ export default class VideoPlayer extends React.Component<
|
|
|
839
882
|
nowPlayingEnabled,
|
|
840
883
|
paused,
|
|
841
884
|
seek,
|
|
885
|
+
rate,
|
|
842
886
|
textTrackId,
|
|
843
887
|
liveSeekingEnabled,
|
|
844
888
|
liveCatchUpEnabled,
|
|
@@ -884,22 +928,17 @@ export default class VideoPlayer extends React.Component<
|
|
|
884
928
|
onVideoEnd: this.onVideoEnd, // complete
|
|
885
929
|
onVideoError: this.onVideoError, // error
|
|
886
930
|
onVideoProgress: this.onVideoProgress,
|
|
887
|
-
onVideoFullscreenPlayerDidDismiss: this.
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
onVideoFullscreenPlayerWillDismiss: this.unHandledEvent(
|
|
894
|
-
"onVideoFullscreenPlayerWillDismiss"
|
|
895
|
-
),
|
|
896
|
-
onVideoFullscreenPlayerWillPresent: this.unHandledEvent(
|
|
897
|
-
"onVideoFullscreenPlayerWillPresent"
|
|
898
|
-
),
|
|
931
|
+
onVideoFullscreenPlayerDidDismiss: this.onVideoFullscreenPlayerDidDismiss,
|
|
932
|
+
onVideoFullscreenPlayerDidPresent: this.onVideoFullscreenPlayerDidPresent,
|
|
933
|
+
onVideoFullscreenPlayerWillDismiss:
|
|
934
|
+
this.onVideoFullscreenPlayerWillDismiss,
|
|
935
|
+
onVideoFullscreenPlayerWillPresent:
|
|
936
|
+
this.onVideoFullscreenPlayerWillPresent,
|
|
899
937
|
onVideoLoad: this.onVideoLoad,
|
|
900
938
|
onVideoLoadStart: this.unHandledEvent("onVideoLoadStart"),
|
|
901
939
|
onVideoBuffer: this.onVideoBuffer,
|
|
902
940
|
onPlaybackStalled: this.onPlaybackStalled,
|
|
941
|
+
onPlayerClose: this.onPlayerClose,
|
|
903
942
|
onPlayerAttached: this.onPlayerAttached,
|
|
904
943
|
onPlayerDetached: this.onPlayerDetached,
|
|
905
944
|
};
|
|
@@ -950,7 +989,13 @@ export default class VideoPlayer extends React.Component<
|
|
|
950
989
|
...androidLifecyclePiPEvents,
|
|
951
990
|
};
|
|
952
991
|
|
|
953
|
-
const needToShowPlayNextOverlay =
|
|
992
|
+
const needToShowPlayNextOverlay =
|
|
993
|
+
isTV() && this.getPlayNextData() && !docked;
|
|
994
|
+
|
|
995
|
+
const needToShowDefaultControls = !(
|
|
996
|
+
(controls && !castAction?.state?.connected) ||
|
|
997
|
+
this.getPlayNextData()
|
|
998
|
+
);
|
|
954
999
|
|
|
955
1000
|
const playerContainerStyles = isApplePlatform()
|
|
956
1001
|
? styles.playerContainerBlack
|
|
@@ -973,7 +1018,7 @@ export default class VideoPlayer extends React.Component<
|
|
|
973
1018
|
!needToShowPlayNextOverlay &&
|
|
974
1019
|
this.props.mode !== "PIP";
|
|
975
1020
|
|
|
976
|
-
if (
|
|
1021
|
+
if (shouldUseNativeControls) {
|
|
977
1022
|
return null;
|
|
978
1023
|
}
|
|
979
1024
|
|
|
@@ -992,6 +1037,7 @@ export default class VideoPlayer extends React.Component<
|
|
|
992
1037
|
extraInfoText={castAction?.state?.friendlyStatus}
|
|
993
1038
|
controlsAlwaysVisible={castAction?.state?.connected}
|
|
994
1039
|
playNextData={this.getPlayNextData()}
|
|
1040
|
+
needToShowDefaultControls={needToShowDefaultControls}
|
|
995
1041
|
/>
|
|
996
1042
|
) : null;
|
|
997
1043
|
};
|
|
@@ -1005,10 +1051,12 @@ export default class VideoPlayer extends React.Component<
|
|
|
1005
1051
|
inline,
|
|
1006
1052
|
docked,
|
|
1007
1053
|
isModal,
|
|
1054
|
+
pip: this.state.piped,
|
|
1008
1055
|
layoutState: {
|
|
1009
1056
|
inline,
|
|
1010
1057
|
docked,
|
|
1011
1058
|
isModal,
|
|
1059
|
+
pip: this.state.piped,
|
|
1012
1060
|
},
|
|
1013
1061
|
configuration: this.getPluginConfiguration(),
|
|
1014
1062
|
fullscreen: fullscreen,
|
|
@@ -1024,29 +1072,14 @@ export default class VideoPlayer extends React.Component<
|
|
|
1024
1072
|
const renderMobilePlayer = () => {
|
|
1025
1073
|
return isFullScreenAudioPlayer && isAudioItem ? (
|
|
1026
1074
|
<View style={containerStyle}>
|
|
1027
|
-
{!castAction?.state?.connected && (
|
|
1075
|
+
{(!castAction?.state?.connected || supportNativeCast) && (
|
|
1028
1076
|
<this.props.PlayerComponent
|
|
1029
1077
|
ref={this._assignRoot}
|
|
1030
1078
|
{...nativeEvents}
|
|
1031
1079
|
{...nativeProps}
|
|
1032
1080
|
/>
|
|
1033
1081
|
)}
|
|
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>
|
|
1082
|
+
<AudioPlayerWrapper {...sharedWrapperViewProps} />
|
|
1050
1083
|
</View>
|
|
1051
1084
|
) : (
|
|
1052
1085
|
<PlayerWrapper {...sharedWrapperViewProps}>
|
|
@@ -1061,11 +1094,24 @@ export default class VideoPlayer extends React.Component<
|
|
|
1061
1094
|
<View style={styles.container}>
|
|
1062
1095
|
<View style={[playerContainerStyles, playerDimensions]}>
|
|
1063
1096
|
{isAudioItem && (
|
|
1064
|
-
<
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1097
|
+
<AnimationComponent
|
|
1098
|
+
animationType={ComponentAnimationType.player}
|
|
1099
|
+
additionalData={{
|
|
1100
|
+
...playerDimensions,
|
|
1101
|
+
inlineAudioPlayer: true,
|
|
1102
|
+
}}
|
|
1103
|
+
style={getStyle(playerDimensions)}
|
|
1104
|
+
>
|
|
1105
|
+
<AudioPlayer
|
|
1106
|
+
style={
|
|
1107
|
+
isTV()
|
|
1108
|
+
? getStyle(playerDimensions)
|
|
1109
|
+
: styles.playerSize
|
|
1110
|
+
}
|
|
1111
|
+
audio_item={entry}
|
|
1112
|
+
plugin_configuration={this.getPluginConfiguration()}
|
|
1113
|
+
/>
|
|
1114
|
+
</AnimationComponent>
|
|
1069
1115
|
)}
|
|
1070
1116
|
|
|
1071
1117
|
{shouldRenderBackground && (
|
|
@@ -1077,17 +1123,28 @@ export default class VideoPlayer extends React.Component<
|
|
|
1077
1123
|
/>
|
|
1078
1124
|
)}
|
|
1079
1125
|
|
|
1080
|
-
{!castAction?.state?.connected && (
|
|
1081
|
-
<
|
|
1082
|
-
|
|
1083
|
-
{
|
|
1084
|
-
{...nativeProps}
|
|
1085
|
-
listener={this.props.listener}
|
|
1126
|
+
{(!castAction?.state?.connected || supportNativeCast) && (
|
|
1127
|
+
<AnimationComponent
|
|
1128
|
+
animationType={ComponentAnimationType.player}
|
|
1129
|
+
additionalData={playerDimensions}
|
|
1086
1130
|
style={getStyle(playerDimensions)}
|
|
1087
|
-
pluginConfiguration={this.getPluginConfiguration()}
|
|
1088
1131
|
>
|
|
1089
|
-
|
|
1090
|
-
|
|
1132
|
+
<this.props.PlayerComponent
|
|
1133
|
+
ref={this._assignRoot}
|
|
1134
|
+
{...nativeEvents}
|
|
1135
|
+
{...nativeProps}
|
|
1136
|
+
listener={this.props.listener}
|
|
1137
|
+
style={
|
|
1138
|
+
isTV()
|
|
1139
|
+
? getStyle(playerDimensions)
|
|
1140
|
+
: styles.playerSize
|
|
1141
|
+
}
|
|
1142
|
+
pluginConfiguration={this.getPluginConfiguration()}
|
|
1143
|
+
controller={this.props.controller}
|
|
1144
|
+
>
|
|
1145
|
+
{this.childrenWithPlayNext()}
|
|
1146
|
+
</this.props.PlayerComponent>
|
|
1147
|
+
</AnimationComponent>
|
|
1091
1148
|
)}
|
|
1092
1149
|
</View>
|
|
1093
1150
|
|
|
@@ -1121,6 +1178,7 @@ export default class VideoPlayer extends React.Component<
|
|
|
1121
1178
|
listener={this.props.listener}
|
|
1122
1179
|
style={this.takeParentStyle}
|
|
1123
1180
|
pluginConfiguration={this.getPluginConfiguration()}
|
|
1181
|
+
controller={this.props.controller}
|
|
1124
1182
|
>
|
|
1125
1183
|
{this.childrenWithPlayNext()}
|
|
1126
1184
|
</this.props.PlayerComponent>
|