@applicaster/quick-brick-player 13.0.0-rc.13 → 13.0.0-rc.131
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 +27 -14
- package/src/CellPlayer/Assets/AssetsComponent.tsx +17 -3
- package/src/Player/AudioLayer/AudioDescription.tsx +107 -68
- package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +142 -295
- package/src/Player/AudioLayer/Layout/Controls/VerticalGutter.tsx +45 -0
- package/src/Player/AudioLayer/Layout/Controls/index.tsx +291 -0
- package/src/Player/AudioLayer/Layout/{defaultLayoutsConts.ts → Controls/utils.ts} +9 -27
- package/src/Player/AudioLayer/Layout/Debug/index.tsx +55 -0
- package/src/Player/AudioLayer/Layout/{DockedLayout.tsx → DockedControls/index.tsx} +77 -81
- package/src/Player/AudioLayer/Layout/MobileLayout.tsx +222 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +87 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +20 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/hooks/index.ts +1 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/hooks/useChangePlayerState.ts +99 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +112 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +36 -0
- package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +212 -0
- package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +215 -0
- package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +128 -0
- package/src/Player/AudioLayer/Layout/VerticalGutter/index.tsx +8 -0
- package/src/Player/AudioLayer/Layout/const.ts +26 -0
- package/src/Player/AudioLayer/Layout/debug.ts +6 -0
- package/src/Player/AudioLayer/Layout/hooks/index.ts +5 -0
- package/src/Player/AudioLayer/Layout/hooks/useMobileLayoutImageSize.ts +14 -0
- package/src/Player/AudioLayer/Layout/hooks/useTabletLayoutImageSize.ts +105 -0
- package/src/Player/AudioLayer/Layout/hooks/useTransportInfoHeight.ts +54 -0
- package/src/Player/AudioLayer/Layout/index.tsx +21 -48
- package/src/Player/AudioLayer/Layout/types.ts +7 -0
- package/src/Player/AudioLayer/Layout/utils.ts +7 -0
- package/src/Player/AudioLayer/SleepTimerManager.ts +130 -0
- package/src/Player/AudioLayer/SpeedManager.ts +52 -0
- package/src/Player/AudioLayer/components/SleepTimerModalHeader/SleepTimerModalHeader.tsx +66 -0
- package/src/Player/AudioLayer/components/SleepTimerModalHeader/index.ts +1 -0
- package/src/Player/AudioLayer/useSleepTimerModal.ts +109 -0
- package/src/Player/AudioLayer/utils.ts +27 -0
- package/src/Player/Const/sleepTimerOptions.ts +41 -0
- package/src/Player/Const/speedOptions.ts +4 -0
- package/src/Player/Utils/Utils.ts +0 -5
- package/src/Player/Utils/index.tsx +123 -0
- package/src/Player/hooks/useIsCasting.tsx +57 -0
- package/src/Player/index.tsx +106 -49
- package/src/QuickBrickPlayer.tsx +3 -0
- package/src/Player/AudioLayer/Layout/DefaultLayout.tsx +0 -452
- package/src/Player/AudioLayer/LinearGradient/LinearGradientProxy.ts +0 -3
- package/src/Player/AudioLayer/LinearGradient/LinearGradientProxy.web.ts +0 -3
- package/src/Player/AudioLayer/LinearGradient/index.ts +0 -1
- package/src/Player/AudioLayer/MagicBG/index.tsx +0 -155
- package/src/Player/Helpers/VideoResizeMode.ts +0 -7
- package/src/utils/utils.ts +0 -25
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import queryString from "query-string";
|
|
2
2
|
import { dayjs } from "@applicaster/zapp-react-native-utils/dateUtils";
|
|
3
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");
|
|
7
|
-
};
|
|
8
|
-
|
|
9
4
|
export const addQueryParam = (
|
|
10
5
|
baseUrl: string,
|
|
11
6
|
paramName: string,
|
|
@@ -1 +1,124 @@
|
|
|
1
|
+
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
2
|
+
|
|
1
3
|
export * from "./Utils";
|
|
4
|
+
|
|
5
|
+
export const getBottomSheetModalIconProps = (theme) => ({
|
|
6
|
+
height: theme["audio_modal_bottom_sheet_item_icon_height"],
|
|
7
|
+
width: theme["audio_modal_bottom_sheet_item_icon_width"],
|
|
8
|
+
marginBottom: theme["audio_modal_bottom_sheet_item_icon_margin_bottom"],
|
|
9
|
+
marginLeft: theme["audio_modal_bottom_sheet_item_icon_margin_left"],
|
|
10
|
+
marginRight: theme["audio_modal_bottom_sheet_item_icon_margin_right"],
|
|
11
|
+
marginTop: theme["audio_modal_bottom_sheet_item_icon_margin_top"],
|
|
12
|
+
flavour: theme["modal_bottom_sheet_item_icon_flavour"],
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export const getBottomSheetModalLabelProps = (theme, width: number) => {
|
|
16
|
+
const {
|
|
17
|
+
audio_modal_bottom_sheet_item_label_android_letter_spacing,
|
|
18
|
+
audio_modal_bottom_sheet_item_label_ios_letter_spacing,
|
|
19
|
+
audio_modal_bottom_sheet_item_label_family_ios_font_selector,
|
|
20
|
+
audio_modal_bottom_sheet_item_label_family_android_font_selector,
|
|
21
|
+
audio_modal_bottom_sheet_item_label_focus_font_color,
|
|
22
|
+
audio_modal_bottom_sheet_item_label_font_color,
|
|
23
|
+
audio_modal_bottom_sheet_item_label_selected_font_color,
|
|
24
|
+
audio_modal_bottom_sheet_item_label_hover_selected_font_color,
|
|
25
|
+
audio_modal_bottom_sheet_item_label_font_size,
|
|
26
|
+
audio_modal_bottom_sheet_item_label_line_height,
|
|
27
|
+
audio_modal_bottom_sheet_item_label_margin_bottom,
|
|
28
|
+
audio_modal_bottom_sheet_item_label_margin_top,
|
|
29
|
+
audio_modal_bottom_sheet_item_label_margin_left,
|
|
30
|
+
audio_modal_bottom_sheet_item_label_margin_right,
|
|
31
|
+
audio_modal_bottom_sheet_item_label_transform,
|
|
32
|
+
audio_modal_bottom_sheet_item_icon_width,
|
|
33
|
+
audio_modal_bottom_sheet_item_icon_margin_left,
|
|
34
|
+
audio_modal_bottom_sheet_item_icon_margin_right,
|
|
35
|
+
audio_modal_bottom_sheet_item_margin_left,
|
|
36
|
+
audio_modal_bottom_sheet_item_margin_right,
|
|
37
|
+
audio_modal_bottom_sheet_item_padding_left,
|
|
38
|
+
audio_modal_bottom_sheet_item_padding_right,
|
|
39
|
+
} = theme;
|
|
40
|
+
|
|
41
|
+
const maxWidth =
|
|
42
|
+
width -
|
|
43
|
+
(audio_modal_bottom_sheet_item_icon_width +
|
|
44
|
+
audio_modal_bottom_sheet_item_icon_margin_left +
|
|
45
|
+
audio_modal_bottom_sheet_item_icon_margin_right +
|
|
46
|
+
audio_modal_bottom_sheet_item_margin_left +
|
|
47
|
+
audio_modal_bottom_sheet_item_margin_right +
|
|
48
|
+
audio_modal_bottom_sheet_item_padding_left +
|
|
49
|
+
audio_modal_bottom_sheet_item_padding_right);
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
fontFamily: platformSelect({
|
|
53
|
+
ios: audio_modal_bottom_sheet_item_label_family_ios_font_selector,
|
|
54
|
+
android: audio_modal_bottom_sheet_item_label_family_android_font_selector,
|
|
55
|
+
}),
|
|
56
|
+
letterSpacing: platformSelect({
|
|
57
|
+
ios: audio_modal_bottom_sheet_item_label_ios_letter_spacing,
|
|
58
|
+
android: audio_modal_bottom_sheet_item_label_android_letter_spacing,
|
|
59
|
+
}),
|
|
60
|
+
fontSize: audio_modal_bottom_sheet_item_label_font_size,
|
|
61
|
+
color: audio_modal_bottom_sheet_item_label_font_color,
|
|
62
|
+
focusColor: audio_modal_bottom_sheet_item_label_focus_font_color,
|
|
63
|
+
hoverSelectedColor:
|
|
64
|
+
audio_modal_bottom_sheet_item_label_hover_selected_font_color,
|
|
65
|
+
selectedColor: audio_modal_bottom_sheet_item_label_selected_font_color,
|
|
66
|
+
lineHeight: audio_modal_bottom_sheet_item_label_line_height,
|
|
67
|
+
marginBottom: audio_modal_bottom_sheet_item_label_margin_bottom,
|
|
68
|
+
marginTop: audio_modal_bottom_sheet_item_label_margin_top,
|
|
69
|
+
marginLeft: audio_modal_bottom_sheet_item_label_margin_left,
|
|
70
|
+
marginRight: audio_modal_bottom_sheet_item_label_margin_right,
|
|
71
|
+
transform: audio_modal_bottom_sheet_item_label_transform,
|
|
72
|
+
maxWidth,
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const getBottomSheetModalItemProps = (theme, width: number) => {
|
|
77
|
+
const {
|
|
78
|
+
audio_modal_bottom_sheet_item_background_color,
|
|
79
|
+
audio_modal_bottom_sheet_item_focus_background_color,
|
|
80
|
+
audio_modal_bottom_sheet_item_selected_background_color,
|
|
81
|
+
audio_modal_bottom_sheet_item_focused_selected_background_color,
|
|
82
|
+
audio_modal_bottom_sheet_item_corner_radius,
|
|
83
|
+
audio_modal_bottom_sheet_item_margin_bottom,
|
|
84
|
+
audio_modal_bottom_sheet_item_margin_left,
|
|
85
|
+
audio_modal_bottom_sheet_item_margin_right,
|
|
86
|
+
audio_modal_bottom_sheet_item_margin_top,
|
|
87
|
+
audio_modal_bottom_sheet_item_padding_bottom,
|
|
88
|
+
audio_modal_bottom_sheet_item_padding_left,
|
|
89
|
+
audio_modal_bottom_sheet_item_padding_right,
|
|
90
|
+
audio_modal_bottom_sheet_item_padding_top,
|
|
91
|
+
} = theme;
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
backgroundColor: audio_modal_bottom_sheet_item_background_color,
|
|
95
|
+
focusedBackgroundColor:
|
|
96
|
+
audio_modal_bottom_sheet_item_focus_background_color,
|
|
97
|
+
selectedBackgroundColor:
|
|
98
|
+
audio_modal_bottom_sheet_item_selected_background_color,
|
|
99
|
+
focusedSelectedBackgroundColor:
|
|
100
|
+
audio_modal_bottom_sheet_item_focused_selected_background_color,
|
|
101
|
+
borderRadius: audio_modal_bottom_sheet_item_corner_radius,
|
|
102
|
+
marginBottom: audio_modal_bottom_sheet_item_margin_bottom,
|
|
103
|
+
marginTop: audio_modal_bottom_sheet_item_margin_top,
|
|
104
|
+
marginLeft: audio_modal_bottom_sheet_item_margin_left,
|
|
105
|
+
marginRight: audio_modal_bottom_sheet_item_margin_right,
|
|
106
|
+
paddingTop: audio_modal_bottom_sheet_item_padding_top,
|
|
107
|
+
paddingBottom: audio_modal_bottom_sheet_item_padding_bottom,
|
|
108
|
+
paddingRight: audio_modal_bottom_sheet_item_padding_right,
|
|
109
|
+
paddingLeft: audio_modal_bottom_sheet_item_padding_left,
|
|
110
|
+
maxWidth: width,
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export const getBottomSheetModalSelectedItemIcon = (theme) =>
|
|
115
|
+
theme["audio_modal_bottom_sheet_item_selected_icon"] || null;
|
|
116
|
+
|
|
117
|
+
export const getBottomSheetModalDefaultItemIcon = (theme) =>
|
|
118
|
+
theme["audio_modal_bottom_sheet_item_default_icon"] || null;
|
|
119
|
+
|
|
120
|
+
export const selectSleepTitle = (configuration) =>
|
|
121
|
+
configuration.playback_sleep_title;
|
|
122
|
+
|
|
123
|
+
export const selectSleepOffLabel = (configuration) =>
|
|
124
|
+
configuration.playback_sleep_off_label;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
|
|
3
|
+
import { useAppState } from "@applicaster/zapp-react-native-utils/reactHooks/app";
|
|
4
|
+
import { isApplePlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
5
|
+
|
|
6
|
+
const CHROMECAST_IDENTIFIER = "quick-brick-chromecast-action";
|
|
7
|
+
|
|
8
|
+
const fakeEntry: any = {
|
|
9
|
+
title: "Chromecast use is casting fake entry",
|
|
10
|
+
id: "quick-brick-use-is-casting-fake-entry",
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Returns the cast action state connection status, does not update when app is in background on Apple platforms
|
|
15
|
+
* On other platforms, it continues to check the cast action state even when the app is in background
|
|
16
|
+
*/
|
|
17
|
+
export const useIsCasting = () => {
|
|
18
|
+
const actionContext = useActions(CHROMECAST_IDENTIFIER);
|
|
19
|
+
const appState = useAppState();
|
|
20
|
+
const isAppInForeground = appState === "active";
|
|
21
|
+
const shouldOnlyUpdateInForeground = isApplePlatform();
|
|
22
|
+
|
|
23
|
+
const [castActionState, setCastActionState] = React.useState(
|
|
24
|
+
!actionContext ? null : actionContext.initialEntryState(fakeEntry)
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
React.useEffect(() => {
|
|
28
|
+
if (!shouldOnlyUpdateInForeground || isAppInForeground) {
|
|
29
|
+
if (actionContext && castActionState === null) {
|
|
30
|
+
setCastActionState(actionContext.initialEntryState(fakeEntry));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}, [
|
|
34
|
+
actionContext,
|
|
35
|
+
setCastActionState,
|
|
36
|
+
isAppInForeground,
|
|
37
|
+
shouldOnlyUpdateInForeground,
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
React.useEffect(() => {
|
|
41
|
+
if (typeof actionContext?.addListener === "function") {
|
|
42
|
+
return actionContext?.addListener(String(fakeEntry.id), (state) => {
|
|
43
|
+
// Only check foreground state on Apple platforms
|
|
44
|
+
if (!shouldOnlyUpdateInForeground || isAppInForeground) {
|
|
45
|
+
setCastActionState(state);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}, [
|
|
50
|
+
setCastActionState,
|
|
51
|
+
actionContext,
|
|
52
|
+
isAppInForeground,
|
|
53
|
+
shouldOnlyUpdateInForeground,
|
|
54
|
+
]);
|
|
55
|
+
|
|
56
|
+
return !!castActionState?.connected;
|
|
57
|
+
};
|
package/src/Player/index.tsx
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
import React from "react";
|
|
5
5
|
import * as R from "ramda";
|
|
6
6
|
|
|
7
|
+
import { flatten } from "@applicaster/zapp-react-native-utils/utils";
|
|
8
|
+
|
|
7
9
|
import { findNodeHandle, StyleSheet, View } from "react-native";
|
|
8
10
|
import TransportControlsMobile from "@applicaster/quick-brick-mobile-transport-controls";
|
|
9
11
|
import TransportControlsTV from "@applicaster/quick-brick-tv-transport-controls";
|
|
@@ -40,6 +42,7 @@ import { PlayerAnalyticsManager } from "@applicaster/zapp-react-native-utils/ana
|
|
|
40
42
|
import { PlayerAnalyticsTrackerI } from "@applicaster/zapp-react-native-utils/analyticsUtils/playerAnalyticsTracker";
|
|
41
43
|
|
|
42
44
|
import { RNPlayerManager } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/nativePlayerManager";
|
|
45
|
+
import { isAudioItem as isAudioItemUtil } from "@applicaster/zapp-react-native-utils/playerUtils";
|
|
43
46
|
|
|
44
47
|
const styles = StyleSheet.create({
|
|
45
48
|
container: { flex: 1 },
|
|
@@ -50,6 +53,7 @@ const styles = StyleSheet.create({
|
|
|
50
53
|
position: "absolute",
|
|
51
54
|
zIndex: 1,
|
|
52
55
|
},
|
|
56
|
+
audioPlayerSize: { width: "100%", height: "100%" },
|
|
53
57
|
playerSize: { width: "100%", height: "100%" },
|
|
54
58
|
});
|
|
55
59
|
|
|
@@ -58,6 +62,10 @@ const logger = createLogger({
|
|
|
58
62
|
subsystem: Subsystem,
|
|
59
63
|
});
|
|
60
64
|
|
|
65
|
+
const isTvOS = isTvOSPlatform();
|
|
66
|
+
|
|
67
|
+
const AUDIO_PLAYER_NATIVE_ID = "audio-player-view";
|
|
68
|
+
|
|
61
69
|
export default class VideoPlayer extends React.Component<
|
|
62
70
|
QuickBrickPlayer.PlayerProps,
|
|
63
71
|
QuickBrickPlayer.NativePlayerState
|
|
@@ -74,6 +82,7 @@ export default class VideoPlayer extends React.Component<
|
|
|
74
82
|
state: QuickBrickPlayer.NativePlayerState = {
|
|
75
83
|
audioTrackId: null,
|
|
76
84
|
textTrackId: null,
|
|
85
|
+
isCasting: this.props.isCasting,
|
|
77
86
|
|
|
78
87
|
// TODO: Can be deleted, on controller logic
|
|
79
88
|
isAd: false,
|
|
@@ -92,6 +101,8 @@ export default class VideoPlayer extends React.Component<
|
|
|
92
101
|
// Player state
|
|
93
102
|
currentTime: 0,
|
|
94
103
|
duration: 0,
|
|
104
|
+
|
|
105
|
+
nativePlayerIsReady: false,
|
|
95
106
|
};
|
|
96
107
|
|
|
97
108
|
private _tracker: PlayerAnalyticsTrackerI;
|
|
@@ -487,6 +498,9 @@ export default class VideoPlayer extends React.Component<
|
|
|
487
498
|
|
|
488
499
|
onVideoFullscreenPlayerDidPresent = () => {
|
|
489
500
|
this.props.listener?.onVideoFullscreenPlayerDidPresent?.();
|
|
501
|
+
|
|
502
|
+
// we have to have a signal that player is ready, in order to show audio_player(for example)
|
|
503
|
+
this.setState({ nativePlayerIsReady: true });
|
|
490
504
|
};
|
|
491
505
|
|
|
492
506
|
onVideoFullscreenPlayerWillDismiss = () => {
|
|
@@ -672,32 +686,57 @@ export default class VideoPlayer extends React.Component<
|
|
|
672
686
|
}
|
|
673
687
|
};
|
|
674
688
|
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
689
|
+
childrenWithExtensions = () => {
|
|
690
|
+
const { docked, entry, children } = this.props;
|
|
691
|
+
|
|
692
|
+
if (!isTvOS) {
|
|
693
|
+
return children;
|
|
678
694
|
}
|
|
679
695
|
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
696
|
+
const output = [];
|
|
697
|
+
|
|
698
|
+
// audio-player
|
|
699
|
+
if (isAudioItemUtil(entry)) {
|
|
700
|
+
const { nativePlayerIsReady } = this.state;
|
|
701
|
+
|
|
702
|
+
// we have to wait ready status of native player view, before showing audio_player
|
|
703
|
+
if (nativePlayerIsReady) {
|
|
704
|
+
output.push(
|
|
705
|
+
<View nativeID={AUDIO_PLAYER_NATIVE_ID} key={AUDIO_PLAYER_NATIVE_ID}>
|
|
706
|
+
{children}
|
|
707
|
+
</View>
|
|
708
|
+
);
|
|
709
|
+
}
|
|
710
|
+
} else {
|
|
711
|
+
output.push(children);
|
|
712
|
+
}
|
|
713
|
+
// audio-player
|
|
714
|
+
|
|
715
|
+
// play-next
|
|
716
|
+
if (this.getPlayNextData()) {
|
|
717
|
+
output.push(
|
|
718
|
+
<PlayNextOverlay
|
|
719
|
+
key="play-next-overlay"
|
|
720
|
+
item={entry}
|
|
721
|
+
playerIsDocked={docked}
|
|
722
|
+
pluginConfiguration={this.getPluginConfiguration()}
|
|
723
|
+
playerId={this.props.playerId}
|
|
724
|
+
playNextData={this.getPlayNextData()}
|
|
725
|
+
setNextVideoPreloadThresholdPercentage={
|
|
726
|
+
this.props.setNextVideoPreloadThresholdPercentage
|
|
727
|
+
}
|
|
728
|
+
/>
|
|
729
|
+
);
|
|
730
|
+
}
|
|
731
|
+
// play-next
|
|
732
|
+
|
|
733
|
+
return flatten(output); // prevent possible case with nested array
|
|
699
734
|
};
|
|
700
735
|
|
|
736
|
+
get supportNativeCast() {
|
|
737
|
+
return this.props.controller.supportNativeCast();
|
|
738
|
+
}
|
|
739
|
+
|
|
701
740
|
render() {
|
|
702
741
|
const {
|
|
703
742
|
docked,
|
|
@@ -710,18 +749,13 @@ export default class VideoPlayer extends React.Component<
|
|
|
710
749
|
muted,
|
|
711
750
|
style,
|
|
712
751
|
castAction,
|
|
713
|
-
controller,
|
|
714
752
|
startComponentsAnimation,
|
|
715
753
|
} = this.props;
|
|
716
754
|
|
|
717
|
-
const supportNativeCast = controller.supportNativeCast();
|
|
718
|
-
|
|
719
755
|
const { audioTrackId, keyEvent, paused, seek, textTrackId, rate } =
|
|
720
756
|
this.state;
|
|
721
757
|
|
|
722
|
-
const isAudioItem =
|
|
723
|
-
entry?.content?.type?.includes?.("audio") ||
|
|
724
|
-
entry?.type?.value === "audio";
|
|
758
|
+
const isAudioItem = isAudioItemUtil(entry);
|
|
725
759
|
|
|
726
760
|
const getStyle = (dimensions) => {
|
|
727
761
|
const generalStyles = isAudioItem ? styles.audio : styles.video;
|
|
@@ -791,8 +825,13 @@ export default class VideoPlayer extends React.Component<
|
|
|
791
825
|
controls: shouldUseNativeControls,
|
|
792
826
|
};
|
|
793
827
|
|
|
828
|
+
const isFullScreenAudioPlayer =
|
|
829
|
+
this.getPluginConfiguration()?.["full_screen_audio_player"] || false;
|
|
830
|
+
|
|
831
|
+
const isAudioPlayer = isFullScreenAudioPlayer && isAudioItem;
|
|
832
|
+
|
|
794
833
|
const pictureInPictureEnabled =
|
|
795
|
-
this.props.pluginConfiguration?.pictureInPictureEnabled;
|
|
834
|
+
this.props.pluginConfiguration?.pictureInPictureEnabled && !isAudioPlayer;
|
|
796
835
|
|
|
797
836
|
const nativeProps = {
|
|
798
837
|
entry, // Must be passed first in list
|
|
@@ -806,7 +845,6 @@ export default class VideoPlayer extends React.Component<
|
|
|
806
845
|
nowPlayingEnabled,
|
|
807
846
|
paused,
|
|
808
847
|
seek,
|
|
809
|
-
rate,
|
|
810
848
|
textTrackId,
|
|
811
849
|
liveSeekingEnabled,
|
|
812
850
|
liveCatchUpEnabled,
|
|
@@ -817,7 +855,14 @@ export default class VideoPlayer extends React.Component<
|
|
|
817
855
|
accessibilityProps: getAllAccessibilityProps(
|
|
818
856
|
this.getPluginConfiguration()
|
|
819
857
|
),
|
|
820
|
-
};
|
|
858
|
+
};
|
|
859
|
+
|
|
860
|
+
if (!isAppleTV()) {
|
|
861
|
+
// TODO: Move to RN method and remove from props.
|
|
862
|
+
// Causes tvOS bug: native player passes rate on fast seek,
|
|
863
|
+
// RN returns it and it breaks playback.
|
|
864
|
+
nativeProps.rate = rate;
|
|
865
|
+
}
|
|
821
866
|
|
|
822
867
|
if (
|
|
823
868
|
this.isReactNativeMethodsSupported() &&
|
|
@@ -918,8 +963,8 @@ export default class VideoPlayer extends React.Component<
|
|
|
918
963
|
const playerContainerStyles = isApplePlatform()
|
|
919
964
|
? styles.playerContainerBlack
|
|
920
965
|
: isTV() && isAudioItem
|
|
921
|
-
|
|
922
|
-
|
|
966
|
+
? styles.playerContainerTransparent
|
|
967
|
+
: styles.playerContainerBlack;
|
|
923
968
|
|
|
924
969
|
const isInline = () => {
|
|
925
970
|
if (isTV()) {
|
|
@@ -960,9 +1005,6 @@ export default class VideoPlayer extends React.Component<
|
|
|
960
1005
|
) : null;
|
|
961
1006
|
};
|
|
962
1007
|
|
|
963
|
-
const isFullScreenAudioPlayer =
|
|
964
|
-
this.getPluginConfiguration()?.["full_screen_audio_player"] || false;
|
|
965
|
-
|
|
966
1008
|
const sharedWrapperViewProps = {
|
|
967
1009
|
style,
|
|
968
1010
|
entry,
|
|
@@ -987,17 +1029,21 @@ export default class VideoPlayer extends React.Component<
|
|
|
987
1029
|
const backgroundImageKey =
|
|
988
1030
|
this.getPluginConfiguration()?.player_preview_image_key;
|
|
989
1031
|
|
|
1032
|
+
const shouldRenderNativePlayer =
|
|
1033
|
+
!this.props.isCasting || this.supportNativeCast;
|
|
1034
|
+
|
|
990
1035
|
const renderMobilePlayer = () => {
|
|
991
1036
|
return isFullScreenAudioPlayer && isAudioItem ? (
|
|
992
|
-
|
|
993
|
-
|
|
1037
|
+
// Ensure the View remains in the native hierarchy for proper rendering and interaction
|
|
1038
|
+
<View collapsable={false} style={containerStyle}>
|
|
1039
|
+
{shouldRenderNativePlayer ? (
|
|
994
1040
|
<this.props.PlayerComponent
|
|
995
1041
|
ref={this._assignRoot}
|
|
996
1042
|
{...nativeEvents}
|
|
997
1043
|
{...nativeProps}
|
|
998
1044
|
listener={this.props.listener}
|
|
999
1045
|
/>
|
|
1000
|
-
)}
|
|
1046
|
+
) : null}
|
|
1001
1047
|
<AudioPlayerWrapper {...sharedWrapperViewProps} />
|
|
1002
1048
|
</View>
|
|
1003
1049
|
) : (
|
|
@@ -1012,7 +1058,7 @@ export default class VideoPlayer extends React.Component<
|
|
|
1012
1058
|
return (
|
|
1013
1059
|
<View style={styles.container}>
|
|
1014
1060
|
<View style={[playerContainerStyles, playerDimensions]}>
|
|
1015
|
-
{isAudioItem
|
|
1061
|
+
{isAudioItem ? (
|
|
1016
1062
|
<AnimationComponent
|
|
1017
1063
|
animationType={ComponentAnimationType.player}
|
|
1018
1064
|
additionalData={{
|
|
@@ -1031,21 +1077,24 @@ export default class VideoPlayer extends React.Component<
|
|
|
1031
1077
|
plugin_configuration={this.getPluginConfiguration()}
|
|
1032
1078
|
/>
|
|
1033
1079
|
</AnimationComponent>
|
|
1034
|
-
)}
|
|
1080
|
+
) : null}
|
|
1035
1081
|
|
|
1036
|
-
{shouldRenderBackground
|
|
1082
|
+
{shouldRenderBackground ? (
|
|
1037
1083
|
<PlayerImageBackground
|
|
1038
1084
|
imageKey={backgroundImageKey}
|
|
1039
1085
|
configuration={this.getPluginConfiguration()}
|
|
1040
1086
|
entry={entry}
|
|
1041
1087
|
style={getBackgroundImageStyle(playerDimensions)}
|
|
1042
1088
|
/>
|
|
1043
|
-
)}
|
|
1089
|
+
) : null}
|
|
1044
1090
|
|
|
1045
|
-
{
|
|
1091
|
+
{shouldRenderNativePlayer ? (
|
|
1046
1092
|
<AnimationComponent
|
|
1047
1093
|
animationType={ComponentAnimationType.player}
|
|
1048
|
-
additionalData={
|
|
1094
|
+
additionalData={{
|
|
1095
|
+
...playerDimensions,
|
|
1096
|
+
disableAnimatedComponent: isAudioItem,
|
|
1097
|
+
}}
|
|
1049
1098
|
style={getStyle(playerDimensions)}
|
|
1050
1099
|
>
|
|
1051
1100
|
<this.props.PlayerComponent
|
|
@@ -1061,10 +1110,10 @@ export default class VideoPlayer extends React.Component<
|
|
|
1061
1110
|
pluginConfiguration={this.getPluginConfiguration()}
|
|
1062
1111
|
controller={this.props.controller}
|
|
1063
1112
|
>
|
|
1064
|
-
{this.
|
|
1113
|
+
{this.props.children}
|
|
1065
1114
|
</this.props.PlayerComponent>
|
|
1066
1115
|
</AnimationComponent>
|
|
1067
|
-
)}
|
|
1116
|
+
) : null}
|
|
1068
1117
|
</View>
|
|
1069
1118
|
|
|
1070
1119
|
{renderTransportControls(playerDimensions)}
|
|
@@ -1090,6 +1139,14 @@ export default class VideoPlayer extends React.Component<
|
|
|
1090
1139
|
const renderTVPlayer = () => {
|
|
1091
1140
|
return (
|
|
1092
1141
|
<View style={this.takeParentStyle} testID={"player-view"}>
|
|
1142
|
+
{!isTvOS && isAudioItem ? (
|
|
1143
|
+
<AudioPlayer
|
|
1144
|
+
style={getStyle(styles.audioPlayerSize)}
|
|
1145
|
+
audio_item={entry}
|
|
1146
|
+
plugin_configuration={this.getPluginConfiguration()}
|
|
1147
|
+
/>
|
|
1148
|
+
) : null}
|
|
1149
|
+
|
|
1093
1150
|
<this.props.PlayerComponent
|
|
1094
1151
|
ref={this._assignRoot}
|
|
1095
1152
|
{...nativeEvents}
|
|
@@ -1099,11 +1156,11 @@ export default class VideoPlayer extends React.Component<
|
|
|
1099
1156
|
pluginConfiguration={this.getPluginConfiguration()}
|
|
1100
1157
|
controller={this.props.controller}
|
|
1101
1158
|
>
|
|
1102
|
-
{this.
|
|
1159
|
+
{this.childrenWithExtensions()}
|
|
1103
1160
|
</this.props.PlayerComponent>
|
|
1104
1161
|
|
|
1105
1162
|
{renderTransportControls(this.takeParentStyle)}
|
|
1106
|
-
{!
|
|
1163
|
+
{!isTvOS && (
|
|
1107
1164
|
<PlayNextOverlay
|
|
1108
1165
|
item={entry}
|
|
1109
1166
|
playerIsDocked={docked}
|
package/src/QuickBrickPlayer.tsx
CHANGED
|
@@ -5,6 +5,7 @@ import Player from "./Player";
|
|
|
5
5
|
import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
|
|
6
6
|
import { isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
7
7
|
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
8
|
+
import { useIsCasting } from "./Player/hooks/useIsCasting";
|
|
8
9
|
|
|
9
10
|
const CHROMECAST_IDENTIFIER = "quick-brick-chromecast-action";
|
|
10
11
|
|
|
@@ -24,6 +25,7 @@ const QuickBrickPlayerComponent = (
|
|
|
24
25
|
}, [props.PlayerComponent]);
|
|
25
26
|
|
|
26
27
|
const castAction = useActions(CHROMECAST_IDENTIFIER);
|
|
28
|
+
const isCasting = useIsCasting();
|
|
27
29
|
|
|
28
30
|
const isModal = Boolean(props?.isModal);
|
|
29
31
|
const isScreenDisabled = !controller?.isFullScreenSupported() || !isModal;
|
|
@@ -48,6 +50,7 @@ const QuickBrickPlayerComponent = (
|
|
|
48
50
|
{...props}
|
|
49
51
|
ref={ref}
|
|
50
52
|
castAction={!props?.disableCastAction && castAction}
|
|
53
|
+
isCasting={isCasting}
|
|
51
54
|
PlayerComponent={props.PlayerComponent}
|
|
52
55
|
openPiP={openPiP}
|
|
53
56
|
closePiP={closePiP}
|