@applicaster/quick-brick-player 12.0.0-rc.8 → 12.0.0-rc.80
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 +276 -58
- package/src/Player/AudioLayer/Layout/DefaultLayout.tsx +261 -72
- package/src/Player/AudioLayer/Layout/DockedLayout.tsx +74 -23
- 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 +123 -67
|
@@ -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
|
/**
|
|
@@ -337,7 +339,7 @@ export default class VideoPlayer extends React.Component<
|
|
|
337
339
|
* Sets either subtitle language, or audio language if we have a selected a new locale.
|
|
338
340
|
* If no locale is set it defaults to system language for audio, and leaves subtitles unaltered.
|
|
339
341
|
*/
|
|
340
|
-
|
|
342
|
+
selectTrack = (selected = null) => {
|
|
341
343
|
const { trackType, id, language } = selected || {};
|
|
342
344
|
|
|
343
345
|
const isOff = language === "Off";
|
|
@@ -368,6 +370,10 @@ export default class VideoPlayer extends React.Component<
|
|
|
368
370
|
}
|
|
369
371
|
};
|
|
370
372
|
|
|
373
|
+
setPlaybackRate = (rate = 1.0) => {
|
|
374
|
+
this.setState({ rate });
|
|
375
|
+
};
|
|
376
|
+
|
|
371
377
|
getCurrentTime = () => {
|
|
372
378
|
return this.state.currentTime;
|
|
373
379
|
};
|
|
@@ -551,6 +557,26 @@ export default class VideoPlayer extends React.Component<
|
|
|
551
557
|
this.props.listener?.onPlayerDetached?.(nativeEvent);
|
|
552
558
|
};
|
|
553
559
|
|
|
560
|
+
onVideoFullscreenPlayerDidDismiss = () => {
|
|
561
|
+
this.props.listener?.onVideoFullscreenPlayerDidDismiss?.();
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
onVideoFullscreenPlayerDidPresent = () => {
|
|
565
|
+
this.props.listener?.onVideoFullscreenPlayerDidPresent?.();
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
onVideoFullscreenPlayerWillDismiss = () => {
|
|
569
|
+
this.props.listener?.onVideoFullscreenPlayerWillDismiss?.();
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
onVideoFullscreenPlayerWillPresent = () => {
|
|
573
|
+
this.props.listener?.onVideoFullscreenPlayerWillPresent?.();
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
onPlayerClose = () => {
|
|
577
|
+
this.props.listener?.onPlayerClose?.();
|
|
578
|
+
};
|
|
579
|
+
|
|
554
580
|
onPiPEnter = () => {
|
|
555
581
|
this.setState({ piped: true });
|
|
556
582
|
this.props.openPiP();
|
|
@@ -754,8 +780,6 @@ export default class VideoPlayer extends React.Component<
|
|
|
754
780
|
|
|
755
781
|
render() {
|
|
756
782
|
const {
|
|
757
|
-
castAction,
|
|
758
|
-
controls,
|
|
759
783
|
docked,
|
|
760
784
|
entry,
|
|
761
785
|
fullscreen,
|
|
@@ -765,9 +789,15 @@ export default class VideoPlayer extends React.Component<
|
|
|
765
789
|
isTabletPortrait,
|
|
766
790
|
muted,
|
|
767
791
|
style,
|
|
792
|
+
castAction,
|
|
793
|
+
controller,
|
|
794
|
+
startComponentsAnimation,
|
|
768
795
|
} = this.props;
|
|
769
796
|
|
|
770
|
-
const
|
|
797
|
+
const supportNativeCast = controller.supportNativeCast();
|
|
798
|
+
|
|
799
|
+
const { audioTrackId, keyEvent, paused, seek, textTrackId, rate } =
|
|
800
|
+
this.state;
|
|
771
801
|
|
|
772
802
|
const isAudioItem =
|
|
773
803
|
entry?.content?.type?.includes?.("audio") ||
|
|
@@ -812,17 +842,35 @@ export default class VideoPlayer extends React.Component<
|
|
|
812
842
|
const liveCatchUpEnabled =
|
|
813
843
|
this.props.pluginConfiguration?.liveCatchUpEnabled;
|
|
814
844
|
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
845
|
+
// TODO: Get screen data more reliable way useCurrentScreenData
|
|
846
|
+
const screenData = getTargetScreenDataFromEntry(this.props.playableItem);
|
|
847
|
+
|
|
848
|
+
const isInlineTV = screenData?.ui_components?.length > 0 && isTV();
|
|
818
849
|
|
|
819
|
-
|
|
850
|
+
let platformSpecificProps: any = isApplePlatform()
|
|
820
851
|
? {
|
|
821
|
-
...hideNativeControls,
|
|
822
852
|
resizeMode: nativeResizeMode,
|
|
823
853
|
}
|
|
824
854
|
: {};
|
|
825
855
|
|
|
856
|
+
const supportsNativeControls =
|
|
857
|
+
!!this.props.controller?.supportsNativeControls?.();
|
|
858
|
+
|
|
859
|
+
const controls = isAppleTV()
|
|
860
|
+
? supportsNativeControls && !isInlineTV && !this.getPlayNextData()
|
|
861
|
+
: supportsNativeControls && !this.getPlayNextData();
|
|
862
|
+
|
|
863
|
+
const shouldUseNativeControls =
|
|
864
|
+
controls &&
|
|
865
|
+
!startComponentsAnimation &&
|
|
866
|
+
!docked &&
|
|
867
|
+
!castAction?.state?.connected;
|
|
868
|
+
|
|
869
|
+
platformSpecificProps = {
|
|
870
|
+
...platformSpecificProps,
|
|
871
|
+
controls: shouldUseNativeControls,
|
|
872
|
+
};
|
|
873
|
+
|
|
826
874
|
const pictureInPictureEnabled =
|
|
827
875
|
this.props.pluginConfiguration?.pictureInPictureEnabled;
|
|
828
876
|
|
|
@@ -830,7 +878,6 @@ export default class VideoPlayer extends React.Component<
|
|
|
830
878
|
entry, // Must be passed first in list
|
|
831
879
|
...platformSpecificProps,
|
|
832
880
|
audioTrackId,
|
|
833
|
-
controls,
|
|
834
881
|
docked,
|
|
835
882
|
enableAutoAudioTrackSelection,
|
|
836
883
|
fullscreen, // TODO: Check fullscreen params not crash
|
|
@@ -839,6 +886,7 @@ export default class VideoPlayer extends React.Component<
|
|
|
839
886
|
nowPlayingEnabled,
|
|
840
887
|
paused,
|
|
841
888
|
seek,
|
|
889
|
+
rate,
|
|
842
890
|
textTrackId,
|
|
843
891
|
liveSeekingEnabled,
|
|
844
892
|
liveCatchUpEnabled,
|
|
@@ -884,22 +932,17 @@ export default class VideoPlayer extends React.Component<
|
|
|
884
932
|
onVideoEnd: this.onVideoEnd, // complete
|
|
885
933
|
onVideoError: this.onVideoError, // error
|
|
886
934
|
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
|
-
),
|
|
935
|
+
onVideoFullscreenPlayerDidDismiss: this.onVideoFullscreenPlayerDidDismiss,
|
|
936
|
+
onVideoFullscreenPlayerDidPresent: this.onVideoFullscreenPlayerDidPresent,
|
|
937
|
+
onVideoFullscreenPlayerWillDismiss:
|
|
938
|
+
this.onVideoFullscreenPlayerWillDismiss,
|
|
939
|
+
onVideoFullscreenPlayerWillPresent:
|
|
940
|
+
this.onVideoFullscreenPlayerWillPresent,
|
|
899
941
|
onVideoLoad: this.onVideoLoad,
|
|
900
942
|
onVideoLoadStart: this.unHandledEvent("onVideoLoadStart"),
|
|
901
943
|
onVideoBuffer: this.onVideoBuffer,
|
|
902
944
|
onPlaybackStalled: this.onPlaybackStalled,
|
|
945
|
+
onPlayerClose: this.onPlayerClose,
|
|
903
946
|
onPlayerAttached: this.onPlayerAttached,
|
|
904
947
|
onPlayerDetached: this.onPlayerDetached,
|
|
905
948
|
};
|
|
@@ -973,7 +1016,7 @@ export default class VideoPlayer extends React.Component<
|
|
|
973
1016
|
!needToShowPlayNextOverlay &&
|
|
974
1017
|
this.props.mode !== "PIP";
|
|
975
1018
|
|
|
976
|
-
if (
|
|
1019
|
+
if (shouldUseNativeControls) {
|
|
977
1020
|
return null;
|
|
978
1021
|
}
|
|
979
1022
|
|
|
@@ -992,6 +1035,7 @@ export default class VideoPlayer extends React.Component<
|
|
|
992
1035
|
extraInfoText={castAction?.state?.friendlyStatus}
|
|
993
1036
|
controlsAlwaysVisible={castAction?.state?.connected}
|
|
994
1037
|
playNextData={this.getPlayNextData()}
|
|
1038
|
+
nativeControls={!!controls}
|
|
995
1039
|
/>
|
|
996
1040
|
) : null;
|
|
997
1041
|
};
|
|
@@ -1005,10 +1049,12 @@ export default class VideoPlayer extends React.Component<
|
|
|
1005
1049
|
inline,
|
|
1006
1050
|
docked,
|
|
1007
1051
|
isModal,
|
|
1052
|
+
pip: this.state.piped,
|
|
1008
1053
|
layoutState: {
|
|
1009
1054
|
inline,
|
|
1010
1055
|
docked,
|
|
1011
1056
|
isModal,
|
|
1057
|
+
pip: this.state.piped,
|
|
1012
1058
|
},
|
|
1013
1059
|
configuration: this.getPluginConfiguration(),
|
|
1014
1060
|
fullscreen: fullscreen,
|
|
@@ -1024,29 +1070,14 @@ export default class VideoPlayer extends React.Component<
|
|
|
1024
1070
|
const renderMobilePlayer = () => {
|
|
1025
1071
|
return isFullScreenAudioPlayer && isAudioItem ? (
|
|
1026
1072
|
<View style={containerStyle}>
|
|
1027
|
-
{!castAction?.state?.connected && (
|
|
1073
|
+
{(!castAction?.state?.connected || supportNativeCast) && (
|
|
1028
1074
|
<this.props.PlayerComponent
|
|
1029
1075
|
ref={this._assignRoot}
|
|
1030
1076
|
{...nativeEvents}
|
|
1031
1077
|
{...nativeProps}
|
|
1032
1078
|
/>
|
|
1033
1079
|
)}
|
|
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>
|
|
1080
|
+
<AudioPlayerWrapper {...sharedWrapperViewProps} />
|
|
1050
1081
|
</View>
|
|
1051
1082
|
) : (
|
|
1052
1083
|
<PlayerWrapper {...sharedWrapperViewProps}>
|
|
@@ -1061,11 +1092,24 @@ export default class VideoPlayer extends React.Component<
|
|
|
1061
1092
|
<View style={styles.container}>
|
|
1062
1093
|
<View style={[playerContainerStyles, playerDimensions]}>
|
|
1063
1094
|
{isAudioItem && (
|
|
1064
|
-
<
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1095
|
+
<AnimationComponent
|
|
1096
|
+
animationType={ComponentAnimationType.player}
|
|
1097
|
+
additionalData={{
|
|
1098
|
+
...playerDimensions,
|
|
1099
|
+
inlineAudioPlayer: true,
|
|
1100
|
+
}}
|
|
1101
|
+
style={getStyle(playerDimensions)}
|
|
1102
|
+
>
|
|
1103
|
+
<AudioPlayer
|
|
1104
|
+
style={
|
|
1105
|
+
isTV()
|
|
1106
|
+
? getStyle(playerDimensions)
|
|
1107
|
+
: styles.playerSize
|
|
1108
|
+
}
|
|
1109
|
+
audio_item={entry}
|
|
1110
|
+
plugin_configuration={this.getPluginConfiguration()}
|
|
1111
|
+
/>
|
|
1112
|
+
</AnimationComponent>
|
|
1069
1113
|
)}
|
|
1070
1114
|
|
|
1071
1115
|
{shouldRenderBackground && (
|
|
@@ -1077,17 +1121,28 @@ export default class VideoPlayer extends React.Component<
|
|
|
1077
1121
|
/>
|
|
1078
1122
|
)}
|
|
1079
1123
|
|
|
1080
|
-
{!castAction?.state?.connected && (
|
|
1081
|
-
<
|
|
1082
|
-
|
|
1083
|
-
{
|
|
1084
|
-
{...nativeProps}
|
|
1085
|
-
listener={this.props.listener}
|
|
1124
|
+
{(!castAction?.state?.connected || supportNativeCast) && (
|
|
1125
|
+
<AnimationComponent
|
|
1126
|
+
animationType={ComponentAnimationType.player}
|
|
1127
|
+
additionalData={playerDimensions}
|
|
1086
1128
|
style={getStyle(playerDimensions)}
|
|
1087
|
-
pluginConfiguration={this.getPluginConfiguration()}
|
|
1088
1129
|
>
|
|
1089
|
-
|
|
1090
|
-
|
|
1130
|
+
<this.props.PlayerComponent
|
|
1131
|
+
ref={this._assignRoot}
|
|
1132
|
+
{...nativeEvents}
|
|
1133
|
+
{...nativeProps}
|
|
1134
|
+
listener={this.props.listener}
|
|
1135
|
+
style={
|
|
1136
|
+
isTV()
|
|
1137
|
+
? getStyle(playerDimensions)
|
|
1138
|
+
: styles.playerSize
|
|
1139
|
+
}
|
|
1140
|
+
pluginConfiguration={this.getPluginConfiguration()}
|
|
1141
|
+
controller={this.props.controller}
|
|
1142
|
+
>
|
|
1143
|
+
{this.childrenWithPlayNext()}
|
|
1144
|
+
</this.props.PlayerComponent>
|
|
1145
|
+
</AnimationComponent>
|
|
1091
1146
|
)}
|
|
1092
1147
|
</View>
|
|
1093
1148
|
|
|
@@ -1121,6 +1176,7 @@ export default class VideoPlayer extends React.Component<
|
|
|
1121
1176
|
listener={this.props.listener}
|
|
1122
1177
|
style={this.takeParentStyle}
|
|
1123
1178
|
pluginConfiguration={this.getPluginConfiguration()}
|
|
1179
|
+
controller={this.props.controller}
|
|
1124
1180
|
>
|
|
1125
1181
|
{this.childrenWithPlayNext()}
|
|
1126
1182
|
</this.props.PlayerComponent>
|