@applicaster/quick-brick-player 14.0.0-rc.9 → 14.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 +6 -11
- package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +44 -88
- package/src/Player/AudioLayer/Layout/Controls/index.tsx +8 -18
- package/src/Player/AudioLayer/Layout/DockedControls/index.tsx +169 -161
- package/src/Player/AudioLayer/Layout/MobileLayout.tsx +4 -42
- package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +5 -9
- package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +35 -83
- package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +6 -1
- package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +6 -66
- package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +1 -39
- package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +6 -18
- package/src/Player/AudioLayer/components/SleepTimerModalHeader/SleepTimerModalHeader.tsx +1 -1
- package/src/Player/AudioLayer/utils.ts +1 -27
- package/src/Player/PlayerModal/GestureAnimatedScrollView.ts +7 -0
- package/src/Player/PlayerModal/PlayerModal.tsx +110 -0
- package/src/Player/PlayerModal/VideoPlayerModal.tsx +289 -0
- package/src/Player/PlayerModal/consts/index.ts +17 -0
- package/src/Player/PlayerModal/context/index.ts +6 -0
- package/src/Player/PlayerModal/hooks/index.ts +169 -0
- package/src/Player/PlayerModal/index.ts +3 -0
- package/src/Player/PlayerModal/index.web.ts +5 -0
- package/src/Player/PlayerModal/styles.ts +109 -0
- package/src/Player/PlayerModal/utils/index.ts +111 -0
- package/src/Player/PlayerView/GenericTVPlayerView.tsx +42 -0
- package/src/Player/PlayerView/TVPlayerView.tsx +26 -0
- package/src/Player/PlayerView/TvOSPlayerView.tsx +51 -0
- package/src/Player/PlayerView/types.ts +41 -0
- package/src/Player/index.tsx +575 -380
- package/src/QuickBrickPlayer.tsx +16 -10
- package/src/utils/dimensions.ts +29 -0
- package/src/utils/index.ts +12 -0
- package/src/utils/logger.ts +6 -0
- package/src/utils/playerHelpers.ts +11 -0
- package/src/utils/playerStyles.ts +50 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +0 -87
- package/src/Player/AudioLayer/Layout/PlayerImage/hooks/index.ts +0 -1
- package/src/Player/AudioLayer/Layout/PlayerImage/hooks/useChangePlayerState.ts +0 -99
- /package/src/Player/AudioLayer/Layout/{Debug → DebugComponent}/index.tsx +0 -0
package/src/Player/index.tsx
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
+
/* eslint-disable react-native/no-inline-styles */
|
|
1
2
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
2
3
|
/* eslint-disable react-native/no-color-literals */
|
|
3
4
|
|
|
4
5
|
import React from "react";
|
|
5
6
|
import * as R from "ramda";
|
|
6
7
|
|
|
7
|
-
import {
|
|
8
|
+
import { findNodeHandle, StyleSheet, View, ViewStyle } from "react-native";
|
|
8
9
|
|
|
9
|
-
import { findNodeHandle, StyleSheet, View } from "react-native";
|
|
10
10
|
import TransportControlsMobile from "@applicaster/quick-brick-mobile-transport-controls";
|
|
11
11
|
import TransportControlsTV from "@applicaster/quick-brick-tv-transport-controls";
|
|
12
12
|
|
|
@@ -19,33 +19,41 @@ import {
|
|
|
19
19
|
isWeb,
|
|
20
20
|
} from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
21
21
|
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
PlayerDetails,
|
|
24
|
+
PlayerWrapper,
|
|
25
|
+
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal";
|
|
23
26
|
|
|
24
27
|
import { PlayNextOverlay } from "./PlayNextOverlay";
|
|
25
28
|
import { PlayerImageBackground } from "@applicaster/zapp-react-native-ui-components/Components/PlayerImageBackground";
|
|
26
29
|
|
|
27
30
|
import { GENERAL_EVENT } from "@applicaster/zapp-react-native-utils/analyticsUtils/events";
|
|
28
|
-
import { Categories, createLogger, Subsystem } from "../logger";
|
|
29
31
|
import { parseLanguageTracks } from "@applicaster/zapp-react-native-utils/playerUtils/configurationUtils";
|
|
30
32
|
import { DEFAULT_COLORS, SEEK_TIME } from "../utils/const";
|
|
33
|
+
import { logger, getScreenAspectRatio } from "../utils";
|
|
31
34
|
import { AudioPlayerWrapper } from "./AudioLayer/AudioPlayerWrapper";
|
|
32
35
|
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
|
|
33
36
|
import { getAllAccessibilityProps } from "@applicaster/zapp-react-native-utils/configurationUtils";
|
|
34
37
|
import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
|
|
35
38
|
import { getTargetScreenDataFromEntry } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useTargetScreenData";
|
|
36
|
-
import {
|
|
37
|
-
AnimationComponent,
|
|
38
|
-
ComponentAnimationType,
|
|
39
|
-
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
40
39
|
import { PlayerAnalyticsManager } from "@applicaster/zapp-react-native-utils/analyticsUtils/PlayerAnalyticsManager";
|
|
41
40
|
import { PlayerAnalyticsTrackerI } from "@applicaster/zapp-react-native-utils/analyticsUtils/playerAnalyticsTracker";
|
|
42
41
|
|
|
43
42
|
import { RNPlayerManager } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/nativePlayerManager";
|
|
44
43
|
import {
|
|
44
|
+
getTabletWidth,
|
|
45
45
|
isAudioItem as isAudioItemUtil,
|
|
46
46
|
isInlineTV as isInlineTVUtil,
|
|
47
47
|
} from "@applicaster/zapp-react-native-utils/playerUtils";
|
|
48
48
|
|
|
49
|
+
import { TVPlayerView } from "./PlayerView/TVPlayerView";
|
|
50
|
+
import PlayerModal, { VideoPlayerModal } from "./PlayerModal";
|
|
51
|
+
import { DockedControls } from "./AudioLayer/Layout/DockedControls";
|
|
52
|
+
import { FlexImage } from "./AudioLayer/Layout/PlayerImage/FlexImage";
|
|
53
|
+
import { PlayerError } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/conts";
|
|
54
|
+
|
|
55
|
+
const isTvOS = isTvOSPlatform();
|
|
56
|
+
|
|
49
57
|
const styles = StyleSheet.create({
|
|
50
58
|
container: { flex: 1 },
|
|
51
59
|
playerContainerBlack: { backgroundColor: DEFAULT_COLORS.black },
|
|
@@ -55,22 +63,46 @@ const styles = StyleSheet.create({
|
|
|
55
63
|
position: "absolute",
|
|
56
64
|
zIndex: 1,
|
|
57
65
|
},
|
|
58
|
-
audioPlayerSize: { width: "100%", height: "100%" },
|
|
59
66
|
playerSize: { width: "100%", height: "100%" },
|
|
67
|
+
flexImage: { height: "100%", aspectRatio: 1, flex: -1 },
|
|
60
68
|
});
|
|
61
69
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
type VideoPlayerProps = QuickBrickPlayer.PlayerProps & {
|
|
71
|
+
isCasting?: boolean;
|
|
72
|
+
playNextData?: PlayNextData;
|
|
73
|
+
castAction?: {
|
|
74
|
+
state?: {
|
|
75
|
+
connected?: boolean;
|
|
76
|
+
friendlyStatus?: string;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
openPiP?: () => void;
|
|
80
|
+
closePiP?: () => void;
|
|
81
|
+
playerEvent?: (eventName: string, eventData?: any) => void;
|
|
82
|
+
mode?: string;
|
|
83
|
+
updatePlayerState?: (state: string) => void;
|
|
84
|
+
setNextVideoPreloadThresholdPercentage?: (percentage: number) => void;
|
|
85
|
+
hideTransportControls?: boolean;
|
|
86
|
+
playableItem?: any;
|
|
87
|
+
playerPluginIdentifier?: string;
|
|
88
|
+
controller?: {
|
|
89
|
+
supportNativeCast?: () => boolean;
|
|
90
|
+
supportsNativeControls?: () => boolean;
|
|
91
|
+
};
|
|
92
|
+
children?: React.ReactNode;
|
|
93
|
+
};
|
|
70
94
|
|
|
71
95
|
export default class VideoPlayer extends React.Component<
|
|
72
|
-
|
|
73
|
-
QuickBrickPlayer.NativePlayerState
|
|
96
|
+
VideoPlayerProps,
|
|
97
|
+
QuickBrickPlayer.NativePlayerState & {
|
|
98
|
+
isCastConnected?: boolean;
|
|
99
|
+
audioTrackId: string | null;
|
|
100
|
+
textTrackId: string | null;
|
|
101
|
+
keyEvent?: any;
|
|
102
|
+
isLive?: boolean;
|
|
103
|
+
seekableDuration?: number;
|
|
104
|
+
displayOverlay?: boolean;
|
|
105
|
+
}
|
|
74
106
|
> {
|
|
75
107
|
public static propTypes = {};
|
|
76
108
|
_root: any;
|
|
@@ -81,7 +113,26 @@ export default class VideoPlayer extends React.Component<
|
|
|
81
113
|
private onVideoLoadCalled: boolean;
|
|
82
114
|
playNextData: PlayNextData;
|
|
83
115
|
|
|
84
|
-
state: QuickBrickPlayer.NativePlayerState
|
|
116
|
+
state: QuickBrickPlayer.NativePlayerState & {
|
|
117
|
+
isCastConnected?: boolean;
|
|
118
|
+
audioTrackId: string | null;
|
|
119
|
+
textTrackId: string | null;
|
|
120
|
+
keyEvent?: any;
|
|
121
|
+
isLive?: boolean;
|
|
122
|
+
seekableDuration?: number;
|
|
123
|
+
displayOverlay?: boolean;
|
|
124
|
+
} = {
|
|
125
|
+
// Base required properties from NativePlayerState
|
|
126
|
+
buffering: false,
|
|
127
|
+
docked: false,
|
|
128
|
+
fullscreen: false,
|
|
129
|
+
inline: false,
|
|
130
|
+
isModal: false,
|
|
131
|
+
isTabletPortrait: false,
|
|
132
|
+
muted: false,
|
|
133
|
+
showPoster: false,
|
|
134
|
+
|
|
135
|
+
// Extended properties
|
|
85
136
|
audioTrackId: null,
|
|
86
137
|
textTrackId: null,
|
|
87
138
|
isCasting: this.props.isCasting,
|
|
@@ -127,6 +178,8 @@ export default class VideoPlayer extends React.Component<
|
|
|
127
178
|
: { flexBasis: "auto", flexGrow: 1, flexShrink: 1 };
|
|
128
179
|
|
|
129
180
|
this.playerPluginId = this.props?.playerPluginIdentifier;
|
|
181
|
+
|
|
182
|
+
this.renderPlayerContent = this.renderPlayerContent.bind(this);
|
|
130
183
|
}
|
|
131
184
|
|
|
132
185
|
componentWillUnmount() {
|
|
@@ -404,9 +457,12 @@ export default class VideoPlayer extends React.Component<
|
|
|
404
457
|
|
|
405
458
|
// TODO: Should be unified on both platform
|
|
406
459
|
onVideoError = ({ nativeEvent }) => {
|
|
407
|
-
const
|
|
460
|
+
const description = nativeEvent.message;
|
|
461
|
+
const error = nativeEvent.error || nativeEvent.exception || "Unknown error"; // Android only fallback
|
|
462
|
+
|
|
463
|
+
const newError = new PlayerError(error, description);
|
|
408
464
|
|
|
409
|
-
return this.props?.listener?.onError(
|
|
465
|
+
return this.props?.listener?.onError(newError);
|
|
410
466
|
};
|
|
411
467
|
|
|
412
468
|
onPlayerPause = ({ nativeEvent = null }) => {
|
|
@@ -688,214 +744,223 @@ export default class VideoPlayer extends React.Component<
|
|
|
688
744
|
}
|
|
689
745
|
};
|
|
690
746
|
|
|
691
|
-
childrenWithExtensions = () => {
|
|
692
|
-
const { docked, entry, children } = this.props;
|
|
693
|
-
|
|
694
|
-
if (!isTvOS) {
|
|
695
|
-
return children;
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
const output = [];
|
|
699
|
-
|
|
700
|
-
// audio-player
|
|
701
|
-
if (isAudioItemUtil(entry)) {
|
|
702
|
-
const { nativePlayerIsReady } = this.state;
|
|
703
|
-
|
|
704
|
-
// we have to wait ready status of native player view, before showing audio_player
|
|
705
|
-
if (nativePlayerIsReady) {
|
|
706
|
-
output.push(
|
|
707
|
-
<View nativeID={AUDIO_PLAYER_NATIVE_ID} key={AUDIO_PLAYER_NATIVE_ID}>
|
|
708
|
-
{children}
|
|
709
|
-
</View>
|
|
710
|
-
);
|
|
711
|
-
}
|
|
712
|
-
} else {
|
|
713
|
-
output.push(children);
|
|
714
|
-
}
|
|
715
|
-
// audio-player
|
|
716
|
-
|
|
717
|
-
// play-next
|
|
718
|
-
if (this.getPlayNextData()) {
|
|
719
|
-
output.push(
|
|
720
|
-
<PlayNextOverlay
|
|
721
|
-
key="play-next-overlay"
|
|
722
|
-
item={entry}
|
|
723
|
-
playerIsDocked={docked}
|
|
724
|
-
pluginConfiguration={this.getPluginConfiguration()}
|
|
725
|
-
playerId={this.props.playerId}
|
|
726
|
-
playNextData={this.getPlayNextData()}
|
|
727
|
-
setNextVideoPreloadThresholdPercentage={
|
|
728
|
-
this.props.setNextVideoPreloadThresholdPercentage
|
|
729
|
-
}
|
|
730
|
-
/>
|
|
731
|
-
);
|
|
732
|
-
}
|
|
733
|
-
// play-next
|
|
734
|
-
|
|
735
|
-
return flatten(output); // prevent possible case with nested array
|
|
736
|
-
};
|
|
737
|
-
|
|
738
747
|
get supportNativeCast() {
|
|
739
748
|
return this.props.controller.supportNativeCast();
|
|
740
749
|
}
|
|
741
750
|
|
|
742
|
-
|
|
743
|
-
const {
|
|
744
|
-
|
|
745
|
-
entry,
|
|
746
|
-
fullscreen,
|
|
747
|
-
hideTransportControls,
|
|
748
|
-
inline,
|
|
749
|
-
isModal,
|
|
750
|
-
isTabletPortrait,
|
|
751
|
-
muted,
|
|
752
|
-
style,
|
|
753
|
-
castAction,
|
|
754
|
-
startComponentsAnimation,
|
|
755
|
-
} = this.props;
|
|
756
|
-
|
|
757
|
-
const { audioTrackId, keyEvent, paused, seek, textTrackId, rate } =
|
|
758
|
-
this.state;
|
|
751
|
+
renderPlayerContent(playerDimensions: ViewStyle) {
|
|
752
|
+
const { entry, docked } = this.props;
|
|
753
|
+
const { isAd, piped } = this.state;
|
|
759
754
|
|
|
755
|
+
const pluginConfiguration = this.getPluginConfiguration();
|
|
760
756
|
const isAudioItem = isAudioItemUtil(entry);
|
|
761
757
|
|
|
762
|
-
const
|
|
763
|
-
const generalStyles = isAudioItem ? styles.audio : styles.video;
|
|
758
|
+
const backgroundImageKey = pluginConfiguration?.player_preview_image_key;
|
|
764
759
|
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
760
|
+
const shouldRenderBackground =
|
|
761
|
+
!R.isNil(backgroundImageKey) &&
|
|
762
|
+
backgroundImageKey.length > 0 &&
|
|
763
|
+
!this.onVideoLoadCalled &&
|
|
764
|
+
!isAd;
|
|
768
765
|
|
|
769
|
-
|
|
770
|
-
|
|
766
|
+
const shouldRenderNativePlayer =
|
|
767
|
+
!this.props.isCasting || this.supportNativeCast;
|
|
771
768
|
|
|
772
|
-
const
|
|
773
|
-
Object.assign(
|
|
774
|
-
{},
|
|
775
|
-
isAudioItem ? styles.audio : { position: "absolute" },
|
|
776
|
-
dimensions
|
|
777
|
-
);
|
|
769
|
+
const playerContainerStyles = this.getPlayerContainerStyles(isAudioItem);
|
|
778
770
|
|
|
779
|
-
const
|
|
771
|
+
const backgroundImageStyle = this.getBackgroundImageStyle(
|
|
772
|
+
playerDimensions,
|
|
773
|
+
isAudioItem
|
|
774
|
+
);
|
|
780
775
|
|
|
781
|
-
const
|
|
782
|
-
|
|
776
|
+
const playerViewStyle = this.getPlayerViewStyle(
|
|
777
|
+
playerDimensions,
|
|
778
|
+
isAudioItem
|
|
779
|
+
);
|
|
783
780
|
|
|
784
|
-
const
|
|
785
|
-
|
|
781
|
+
const nativeEvents = this.getNativeEvents();
|
|
782
|
+
const nativeProps = this.getNativeProps();
|
|
786
783
|
|
|
787
|
-
const
|
|
788
|
-
|
|
789
|
-
|
|
784
|
+
const renderedNativePlayer = this.renderNativePlayer(
|
|
785
|
+
shouldRenderNativePlayer,
|
|
786
|
+
playerViewStyle,
|
|
787
|
+
nativeEvents,
|
|
788
|
+
nativeProps,
|
|
789
|
+
pluginConfiguration
|
|
790
|
+
);
|
|
790
791
|
|
|
791
|
-
const
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
792
|
+
const renderedBackgroundImage = this.renderBackgroundImage(
|
|
793
|
+
shouldRenderBackground,
|
|
794
|
+
backgroundImageKey,
|
|
795
|
+
entry,
|
|
796
|
+
backgroundImageStyle
|
|
797
|
+
);
|
|
796
798
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
799
|
+
const renderedAudioPlayer = this.renderAudioPlayer(
|
|
800
|
+
isAudioItem,
|
|
801
|
+
entry,
|
|
802
|
+
pluginConfiguration
|
|
803
|
+
);
|
|
800
804
|
|
|
801
|
-
|
|
802
|
-
|
|
805
|
+
const renderedTransportControls =
|
|
806
|
+
this.renderTransportControls(playerDimensions);
|
|
803
807
|
|
|
804
|
-
const
|
|
808
|
+
const renderedPlayNextOverlay = this.renderPlayNextOverlay(
|
|
809
|
+
piped,
|
|
810
|
+
entry,
|
|
811
|
+
docked,
|
|
812
|
+
pluginConfiguration
|
|
813
|
+
);
|
|
805
814
|
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
815
|
+
return (
|
|
816
|
+
<View style={styles.container}>
|
|
817
|
+
<View style={[playerContainerStyles, playerDimensions]}>
|
|
818
|
+
{renderedAudioPlayer}
|
|
819
|
+
{renderedBackgroundImage}
|
|
820
|
+
{renderedNativePlayer}
|
|
821
|
+
</View>
|
|
811
822
|
|
|
812
|
-
|
|
813
|
-
|
|
823
|
+
{renderedTransportControls}
|
|
824
|
+
{renderedPlayNextOverlay}
|
|
825
|
+
</View>
|
|
826
|
+
);
|
|
827
|
+
}
|
|
814
828
|
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
829
|
+
/* Returns player container style based on platform and content type (audio/video) */
|
|
830
|
+
private getPlayerContainerStyles = (isAudioItem: boolean) =>
|
|
831
|
+
isApplePlatform()
|
|
832
|
+
? styles.playerContainerBlack
|
|
833
|
+
: isTV() && isAudioItem
|
|
834
|
+
? styles.playerContainerTransparent
|
|
835
|
+
: styles.playerContainerBlack;
|
|
818
836
|
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
837
|
+
private getBackgroundImageStyle = (
|
|
838
|
+
dimensions: ViewStyle,
|
|
839
|
+
isAudioItem: boolean
|
|
840
|
+
): ViewStyle[] => [
|
|
841
|
+
isAudioItem ? styles.audio : { position: "absolute" },
|
|
842
|
+
dimensions,
|
|
843
|
+
];
|
|
844
|
+
|
|
845
|
+
/* Returns player view style based on platform and content type (audio/video) */
|
|
846
|
+
private getPlayerViewStyle = (
|
|
847
|
+
dimensions: ViewStyle,
|
|
848
|
+
isAudioItem: boolean
|
|
849
|
+
): ViewStyle | ViewStyle[] => {
|
|
850
|
+
const generalStyles = isAudioItem ? styles.audio : undefined;
|
|
851
|
+
|
|
852
|
+
if (isAndroidPlatform() && isAudioItem) {
|
|
853
|
+
return generalStyles;
|
|
854
|
+
}
|
|
824
855
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
controls: shouldUseNativeControls,
|
|
828
|
-
};
|
|
856
|
+
return [generalStyles, dimensions];
|
|
857
|
+
};
|
|
829
858
|
|
|
830
|
-
|
|
831
|
-
|
|
859
|
+
private renderAudioPlayer = (
|
|
860
|
+
isAudioItem: boolean,
|
|
861
|
+
entry: ZappEntry,
|
|
862
|
+
pluginConfiguration: Record<string, any>
|
|
863
|
+
) => {
|
|
864
|
+
if (!isAudioItem) return null;
|
|
865
|
+
|
|
866
|
+
return (
|
|
867
|
+
<AudioPlayer
|
|
868
|
+
style={styles.playerSize}
|
|
869
|
+
audio_item={entry}
|
|
870
|
+
plugin_configuration={pluginConfiguration}
|
|
871
|
+
/>
|
|
872
|
+
);
|
|
873
|
+
};
|
|
832
874
|
|
|
833
|
-
|
|
875
|
+
private renderBackgroundImage = (
|
|
876
|
+
shouldRender: boolean,
|
|
877
|
+
imageKey: string,
|
|
878
|
+
entry: ZappEntry,
|
|
879
|
+
style: ViewStyle | ViewStyle[]
|
|
880
|
+
) => {
|
|
881
|
+
if (!shouldRender) return null;
|
|
834
882
|
|
|
835
|
-
|
|
836
|
-
|
|
883
|
+
return (
|
|
884
|
+
<PlayerImageBackground imageKey={imageKey} entry={entry} style={style} />
|
|
885
|
+
);
|
|
886
|
+
};
|
|
837
887
|
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
888
|
+
private renderNativePlayer = (
|
|
889
|
+
shouldRender: boolean,
|
|
890
|
+
style: ViewStyle | ViewStyle[],
|
|
891
|
+
nativeEvents: ReturnType<typeof this.getNativeEvents>,
|
|
892
|
+
nativeProps: ReturnType<typeof this.getNativeProps>,
|
|
893
|
+
pluginConfiguration: Record<string, any>
|
|
894
|
+
) => {
|
|
895
|
+
if (!shouldRender) return null;
|
|
896
|
+
const PlayerComponent = this.props.PlayerComponent;
|
|
897
|
+
|
|
898
|
+
return (
|
|
899
|
+
<View style={style}>
|
|
900
|
+
<PlayerComponent
|
|
901
|
+
ref={this._assignRoot}
|
|
902
|
+
{...nativeEvents}
|
|
903
|
+
{...nativeProps}
|
|
904
|
+
listener={this.props.listener}
|
|
905
|
+
style={styles.playerSize}
|
|
906
|
+
pluginConfiguration={pluginConfiguration}
|
|
907
|
+
controller={this.props.controller}
|
|
908
|
+
>
|
|
909
|
+
{this.props.children}
|
|
910
|
+
</PlayerComponent>
|
|
911
|
+
</View>
|
|
912
|
+
);
|
|
913
|
+
};
|
|
861
914
|
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
915
|
+
private renderPlayNextOverlay = (
|
|
916
|
+
piped: boolean,
|
|
917
|
+
entry: ZappEntry,
|
|
918
|
+
docked: boolean,
|
|
919
|
+
pluginConfiguration: Record<string, any>
|
|
920
|
+
) => {
|
|
921
|
+
if (piped) return null;
|
|
922
|
+
|
|
923
|
+
return (
|
|
924
|
+
<PlayNextOverlay
|
|
925
|
+
item={entry}
|
|
926
|
+
playerIsDocked={docked}
|
|
927
|
+
pluginConfiguration={pluginConfiguration}
|
|
928
|
+
playerId={this.props.playerId}
|
|
929
|
+
playNextData={this.getPlayNextData()}
|
|
930
|
+
setNextVideoPreloadThresholdPercentage={
|
|
931
|
+
this.props.setNextVideoPreloadThresholdPercentage
|
|
932
|
+
}
|
|
933
|
+
/>
|
|
934
|
+
);
|
|
935
|
+
};
|
|
868
936
|
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
) {
|
|
873
|
-
delete nativeProps["paused"];
|
|
874
|
-
}
|
|
937
|
+
// Extract native events to a separate method for reusability
|
|
938
|
+
getNativeEvents = () => {
|
|
939
|
+
const { keyEvent } = this.state;
|
|
875
940
|
|
|
876
941
|
const adEvents = {
|
|
877
|
-
onAdBegin: this.onAdBegin,
|
|
878
|
-
onAdBreakBegin: this.onAdBreakBegin,
|
|
879
|
-
onAdBreakEnd: this.onAdBreakEnd,
|
|
880
|
-
onAdEnd: this.onAdEnd,
|
|
881
|
-
onAdError: this.onAdError,
|
|
882
|
-
onAdRequest: this.onAdRequest,
|
|
883
|
-
onAdClicked: this.onAdClicked,
|
|
884
|
-
onAdTapped: this.onAdTapped,
|
|
942
|
+
onAdBegin: this.onAdBegin,
|
|
943
|
+
onAdBreakBegin: this.onAdBreakBegin,
|
|
944
|
+
onAdBreakEnd: this.onAdBreakEnd,
|
|
945
|
+
onAdEnd: this.onAdEnd,
|
|
946
|
+
onAdError: this.onAdError,
|
|
947
|
+
onAdRequest: this.onAdRequest,
|
|
948
|
+
onAdClicked: this.onAdClicked,
|
|
949
|
+
onAdTapped: this.onAdTapped,
|
|
885
950
|
};
|
|
886
951
|
|
|
887
952
|
const playbackEvents = {
|
|
888
953
|
onPlaybackRateChange: this.onPlaybackRateChange,
|
|
889
|
-
onPlayerPause: this.onPlayerPause,
|
|
890
|
-
onPlayerResume: this.onPlayerResume,
|
|
891
|
-
onPlayerSeekComplete: this.onPlayerSeekComplete,
|
|
892
|
-
onPlayerSeekStart: this.onPlayerSeekStart,
|
|
954
|
+
onPlayerPause: this.onPlayerPause,
|
|
955
|
+
onPlayerResume: this.onPlayerResume,
|
|
956
|
+
onPlayerSeekComplete: this.onPlayerSeekComplete,
|
|
957
|
+
onPlayerSeekStart: this.onPlayerSeekStart,
|
|
893
958
|
};
|
|
894
959
|
|
|
895
960
|
const lifecycleEvents = {
|
|
896
961
|
onReadyForDisplay: this.unHandledEvent("onReadyForDisplay"),
|
|
897
|
-
onVideoEnd: this.onVideoEnd,
|
|
898
|
-
onVideoError: this.onVideoError,
|
|
962
|
+
onVideoEnd: this.onVideoEnd,
|
|
963
|
+
onVideoError: this.onVideoError,
|
|
899
964
|
onVideoProgress: this.onVideoProgress,
|
|
900
965
|
onVideoFullscreenPlayerDidDismiss: this.onVideoFullscreenPlayerDidDismiss,
|
|
901
966
|
onVideoFullscreenPlayerDidPresent: this.onVideoFullscreenPlayerDidPresent,
|
|
@@ -939,11 +1004,11 @@ export default class VideoPlayer extends React.Component<
|
|
|
939
1004
|
};
|
|
940
1005
|
|
|
941
1006
|
const unsupportedEvents = {
|
|
942
|
-
onBufferComplete: this.onBufferComplete,
|
|
943
|
-
onBufferStart: this.onBufferStart,
|
|
1007
|
+
onBufferComplete: this.onBufferComplete,
|
|
1008
|
+
onBufferStart: this.onBufferStart,
|
|
944
1009
|
};
|
|
945
1010
|
|
|
946
|
-
|
|
1011
|
+
return {
|
|
947
1012
|
...adEvents,
|
|
948
1013
|
...androidPlayerEvents,
|
|
949
1014
|
...lifecycleEvents,
|
|
@@ -952,60 +1017,199 @@ export default class VideoPlayer extends React.Component<
|
|
|
952
1017
|
...unsupportedEvents,
|
|
953
1018
|
...playbackEvents,
|
|
954
1019
|
...androidLifecyclePiPEvents,
|
|
1020
|
+
} as const;
|
|
1021
|
+
};
|
|
1022
|
+
|
|
1023
|
+
// Extract native props to a separate method for reusability
|
|
1024
|
+
getNativeProps = () => {
|
|
1025
|
+
const { entry, docked, fullscreen, inline, muted, castAction } = this.props;
|
|
1026
|
+
const { audioTrackId, textTrackId, paused, seek, rate } = this.state;
|
|
1027
|
+
|
|
1028
|
+
const nativeResizeMode = "ScaleAspectFit";
|
|
1029
|
+
|
|
1030
|
+
const isFullScreenAudioPlayer =
|
|
1031
|
+
this.getPluginConfiguration()?.full_screen_audio_player || false;
|
|
1032
|
+
|
|
1033
|
+
const isAudioItem = isAudioItemUtil(entry);
|
|
1034
|
+
const isAudioPlayer = isFullScreenAudioPlayer && isAudioItem;
|
|
1035
|
+
|
|
1036
|
+
let platformSpecificProps: Record<string, any> = isApplePlatform()
|
|
1037
|
+
? { resizeMode: nativeResizeMode }
|
|
1038
|
+
: {};
|
|
1039
|
+
|
|
1040
|
+
const supportsNativeControls =
|
|
1041
|
+
!!this.props.controller?.supportsNativeControls?.();
|
|
1042
|
+
|
|
1043
|
+
const controls = isTvOS
|
|
1044
|
+
? (supportsNativeControls && !this.isInlineTV()) ||
|
|
1045
|
+
!!this.getPlayNextData()
|
|
1046
|
+
: supportsNativeControls && !this.getPlayNextData();
|
|
1047
|
+
|
|
1048
|
+
const shouldUseNativeControls =
|
|
1049
|
+
controls && !docked && !castAction?.state?.connected;
|
|
1050
|
+
|
|
1051
|
+
platformSpecificProps = {
|
|
1052
|
+
...platformSpecificProps,
|
|
1053
|
+
controls: shouldUseNativeControls,
|
|
1054
|
+
};
|
|
1055
|
+
|
|
1056
|
+
const pictureInPictureEnabled =
|
|
1057
|
+
this.props.pluginConfiguration?.pictureInPictureEnabled && !isAudioPlayer;
|
|
1058
|
+
|
|
1059
|
+
const nowPlayingEnabled =
|
|
1060
|
+
this.props?.pluginConfiguration?.nowPlayingEnabled;
|
|
1061
|
+
|
|
1062
|
+
const enableAutoAudioTrackSelection =
|
|
1063
|
+
this.props.pluginConfiguration?.enable_auto_audio_track_selection;
|
|
1064
|
+
|
|
1065
|
+
const minimumAllowedSeekableDurationInSeconds =
|
|
1066
|
+
this.props?.pluginConfiguration?.minimumAllowedSeekableDurationInSeconds;
|
|
1067
|
+
|
|
1068
|
+
const liveSeekingEnabled =
|
|
1069
|
+
(this.props.pluginConfiguration?.liveSeekingEnabled &&
|
|
1070
|
+
this.state?.seekableDuration >
|
|
1071
|
+
minimumAllowedSeekableDurationInSeconds) ||
|
|
1072
|
+
false;
|
|
1073
|
+
|
|
1074
|
+
const liveCatchUpEnabled =
|
|
1075
|
+
this.props.pluginConfiguration?.liveCatchUpEnabled;
|
|
1076
|
+
|
|
1077
|
+
const nativeProps = {
|
|
1078
|
+
rate: undefined,
|
|
1079
|
+
entry,
|
|
1080
|
+
...platformSpecificProps,
|
|
1081
|
+
audioTrackId,
|
|
1082
|
+
docked,
|
|
1083
|
+
enableAutoAudioTrackSelection,
|
|
1084
|
+
fullscreen,
|
|
1085
|
+
inline,
|
|
1086
|
+
muted,
|
|
1087
|
+
nowPlayingEnabled,
|
|
1088
|
+
paused,
|
|
1089
|
+
seek,
|
|
1090
|
+
textTrackId,
|
|
1091
|
+
liveSeekingEnabled,
|
|
1092
|
+
liveCatchUpEnabled,
|
|
1093
|
+
playerId: this.props.playerId,
|
|
1094
|
+
pictureInPictureEnabled,
|
|
1095
|
+
seekStep:
|
|
1096
|
+
(this.props.pluginConfiguration?.seek_duration || SEEK_TIME) * 1000,
|
|
1097
|
+
accessibilityProps: getAllAccessibilityProps(
|
|
1098
|
+
this.getPluginConfiguration()
|
|
1099
|
+
),
|
|
955
1100
|
};
|
|
956
1101
|
|
|
1102
|
+
if (!isTvOS) {
|
|
1103
|
+
nativeProps.rate = rate;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
if (
|
|
1107
|
+
this.isReactNativeMethodsSupported() &&
|
|
1108
|
+
RNPlayerManager?.[this.playerPluginId]?.play
|
|
1109
|
+
) {
|
|
1110
|
+
delete nativeProps.paused;
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
return nativeProps;
|
|
1114
|
+
};
|
|
1115
|
+
|
|
1116
|
+
// Extract transport controls rendering to a separate method
|
|
1117
|
+
renderTransportControls = (playerDimensions) => {
|
|
1118
|
+
const {
|
|
1119
|
+
hideTransportControls,
|
|
1120
|
+
castAction,
|
|
1121
|
+
docked,
|
|
1122
|
+
fullscreen,
|
|
1123
|
+
isModal,
|
|
1124
|
+
entry,
|
|
1125
|
+
} = this.props;
|
|
1126
|
+
|
|
957
1127
|
const needToShowPlayNextOverlay =
|
|
958
1128
|
isTV() && this.getPlayNextData() && !docked;
|
|
959
1129
|
|
|
1130
|
+
const needsToRender =
|
|
1131
|
+
!hideTransportControls &&
|
|
1132
|
+
!needToShowPlayNextOverlay &&
|
|
1133
|
+
this.props.mode !== "PIP" &&
|
|
1134
|
+
!docked;
|
|
1135
|
+
|
|
1136
|
+
const supportsNativeControls =
|
|
1137
|
+
!!this.props.controller?.supportsNativeControls?.();
|
|
1138
|
+
|
|
1139
|
+
const controls = isTvOS
|
|
1140
|
+
? (supportsNativeControls && !this.isInlineTV()) ||
|
|
1141
|
+
!!this.getPlayNextData()
|
|
1142
|
+
: supportsNativeControls && !this.getPlayNextData();
|
|
1143
|
+
|
|
1144
|
+
const shouldUseNativeControls =
|
|
1145
|
+
controls && !docked && !castAction?.state?.connected;
|
|
1146
|
+
|
|
1147
|
+
if (shouldUseNativeControls) {
|
|
1148
|
+
return null;
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
const TransportControls = isTV()
|
|
1152
|
+
? TransportControlsTV
|
|
1153
|
+
: TransportControlsMobile;
|
|
1154
|
+
|
|
960
1155
|
const needToShowDefaultControls = !(
|
|
961
1156
|
(controls && !castAction?.state?.connected) ||
|
|
962
1157
|
this.getPlayNextData()
|
|
963
1158
|
);
|
|
964
1159
|
|
|
965
|
-
const playerContainerStyles = isApplePlatform()
|
|
966
|
-
? styles.playerContainerBlack
|
|
967
|
-
: isTV() && isAudioItem
|
|
968
|
-
? styles.playerContainerTransparent
|
|
969
|
-
: styles.playerContainerBlack;
|
|
970
|
-
|
|
971
1160
|
const isInline = () => {
|
|
972
1161
|
if (isTV()) {
|
|
973
|
-
return inline;
|
|
1162
|
+
return this.props.inline;
|
|
974
1163
|
}
|
|
975
1164
|
|
|
976
|
-
|
|
977
|
-
return fullscreen ? false : inline;
|
|
1165
|
+
return fullscreen ? false : this.props.inline;
|
|
978
1166
|
};
|
|
979
1167
|
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
1168
|
+
return needsToRender ? (
|
|
1169
|
+
<TransportControls
|
|
1170
|
+
playerContent={entry}
|
|
1171
|
+
configuration={this.getPluginConfiguration()}
|
|
1172
|
+
playerDimensions={playerDimensions}
|
|
1173
|
+
inline={isInline()}
|
|
1174
|
+
docked={fullscreen ? false : docked}
|
|
1175
|
+
isModal={isModal}
|
|
1176
|
+
extraInfoText={castAction?.state?.friendlyStatus}
|
|
1177
|
+
controlsAlwaysVisible={castAction?.state?.connected}
|
|
1178
|
+
playNextData={this.getPlayNextData()}
|
|
1179
|
+
needToShowDefaultControls={needToShowDefaultControls}
|
|
1180
|
+
/>
|
|
1181
|
+
) : null;
|
|
1182
|
+
};
|
|
985
1183
|
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
1184
|
+
// Helper method for inline TV check
|
|
1185
|
+
isInlineTV = () => {
|
|
1186
|
+
const screenData = getTargetScreenDataFromEntry(this.props.playableItem);
|
|
989
1187
|
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1188
|
+
return isInlineTVUtil(screenData);
|
|
1189
|
+
};
|
|
1190
|
+
|
|
1191
|
+
renderMobile = () => {
|
|
1192
|
+
const {
|
|
1193
|
+
docked,
|
|
1194
|
+
entry,
|
|
1195
|
+
fullscreen,
|
|
1196
|
+
inline,
|
|
1197
|
+
isModal,
|
|
1198
|
+
isTabletPortrait,
|
|
1199
|
+
style,
|
|
1200
|
+
isCasting,
|
|
1201
|
+
PlayerComponent,
|
|
1202
|
+
listener,
|
|
1203
|
+
} = this.props;
|
|
1204
|
+
|
|
1205
|
+
const { piped } = this.state;
|
|
1206
|
+
|
|
1207
|
+
const pluginConfiguration = this.getPluginConfiguration();
|
|
1208
|
+
|
|
1209
|
+
const isAudioItem = isAudioItemUtil(entry);
|
|
1210
|
+
|
|
1211
|
+
const isFullScreenAudioPlayer =
|
|
1212
|
+
pluginConfiguration?.full_screen_audio_player || false;
|
|
1009
1213
|
|
|
1010
1214
|
const sharedWrapperViewProps = {
|
|
1011
1215
|
style,
|
|
@@ -1013,171 +1217,162 @@ export default class VideoPlayer extends React.Component<
|
|
|
1013
1217
|
inline,
|
|
1014
1218
|
docked,
|
|
1015
1219
|
isModal,
|
|
1016
|
-
pip:
|
|
1220
|
+
pip: piped,
|
|
1017
1221
|
layoutState: {
|
|
1018
1222
|
inline,
|
|
1019
1223
|
docked,
|
|
1020
1224
|
isModal,
|
|
1021
|
-
pip:
|
|
1225
|
+
pip: piped,
|
|
1022
1226
|
},
|
|
1023
|
-
configuration:
|
|
1024
|
-
|
|
1025
|
-
isTabletPortrait: isTabletPortrait,
|
|
1227
|
+
configuration: pluginConfiguration,
|
|
1228
|
+
isTabletPortrait,
|
|
1026
1229
|
playNextData: this.getPlayNextData(),
|
|
1027
1230
|
};
|
|
1028
1231
|
|
|
1029
|
-
const
|
|
1232
|
+
const shouldRenderNativePlayer = !isCasting || this.supportNativeCast;
|
|
1030
1233
|
|
|
1031
|
-
const
|
|
1032
|
-
|
|
1234
|
+
const aspectRatio =
|
|
1235
|
+
!inline && isModal && !piped ? getScreenAspectRatio() : 16 / 9;
|
|
1033
1236
|
|
|
1034
|
-
const
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
return isFullScreenAudioPlayer && isAudioItem ? (
|
|
1039
|
-
// Ensure the View remains in the native hierarchy for proper rendering and interaction
|
|
1040
|
-
<View collapsable={false} style={containerStyle}>
|
|
1041
|
-
{shouldRenderNativePlayer ? (
|
|
1042
|
-
<this.props.PlayerComponent
|
|
1043
|
-
ref={this._assignRoot}
|
|
1044
|
-
{...nativeEvents}
|
|
1045
|
-
{...nativeProps}
|
|
1046
|
-
listener={this.props.listener}
|
|
1047
|
-
/>
|
|
1048
|
-
) : null}
|
|
1049
|
-
<AudioPlayerWrapper {...sharedWrapperViewProps} />
|
|
1050
|
-
</View>
|
|
1051
|
-
) : (
|
|
1052
|
-
<PlayerWrapper {...sharedWrapperViewProps}>
|
|
1053
|
-
{(playerDimensions) => {
|
|
1054
|
-
const shouldRenderBackground =
|
|
1055
|
-
!R.isNil(backgroundImageKey) &&
|
|
1056
|
-
backgroundImageKey.length > 0 &&
|
|
1057
|
-
!this.onVideoLoadCalled &&
|
|
1058
|
-
!this.state.isAd;
|
|
1059
|
-
|
|
1060
|
-
return (
|
|
1061
|
-
<View style={styles.container}>
|
|
1062
|
-
<View style={[playerContainerStyles, playerDimensions]}>
|
|
1063
|
-
{isAudioItem ? (
|
|
1064
|
-
<AnimationComponent
|
|
1065
|
-
animationType={ComponentAnimationType.player}
|
|
1066
|
-
additionalData={{
|
|
1067
|
-
...playerDimensions,
|
|
1068
|
-
inlineAudioPlayer: true,
|
|
1069
|
-
}}
|
|
1070
|
-
style={getStyle(playerDimensions)}
|
|
1071
|
-
>
|
|
1072
|
-
<AudioPlayer
|
|
1073
|
-
style={
|
|
1074
|
-
isTV()
|
|
1075
|
-
? getStyle(playerDimensions)
|
|
1076
|
-
: styles.playerSize
|
|
1077
|
-
}
|
|
1078
|
-
audio_item={entry}
|
|
1079
|
-
plugin_configuration={this.getPluginConfiguration()}
|
|
1080
|
-
/>
|
|
1081
|
-
</AnimationComponent>
|
|
1082
|
-
) : null}
|
|
1083
|
-
|
|
1084
|
-
{shouldRenderBackground ? (
|
|
1085
|
-
<PlayerImageBackground
|
|
1086
|
-
imageKey={backgroundImageKey}
|
|
1087
|
-
configuration={this.getPluginConfiguration()}
|
|
1088
|
-
entry={entry}
|
|
1089
|
-
style={getBackgroundImageStyle(playerDimensions)}
|
|
1090
|
-
/>
|
|
1091
|
-
) : null}
|
|
1092
|
-
|
|
1093
|
-
{shouldRenderNativePlayer ? (
|
|
1094
|
-
<AnimationComponent
|
|
1095
|
-
animationType={ComponentAnimationType.player}
|
|
1096
|
-
additionalData={{
|
|
1097
|
-
...playerDimensions,
|
|
1098
|
-
disableAnimatedComponent: isAudioItem,
|
|
1099
|
-
}}
|
|
1100
|
-
style={getStyle(playerDimensions)}
|
|
1101
|
-
>
|
|
1102
|
-
<this.props.PlayerComponent
|
|
1103
|
-
ref={this._assignRoot}
|
|
1104
|
-
{...nativeEvents}
|
|
1105
|
-
{...nativeProps}
|
|
1106
|
-
listener={this.props.listener}
|
|
1107
|
-
style={
|
|
1108
|
-
isTV()
|
|
1109
|
-
? getStyle(playerDimensions)
|
|
1110
|
-
: styles.playerSize
|
|
1111
|
-
}
|
|
1112
|
-
pluginConfiguration={this.getPluginConfiguration()}
|
|
1113
|
-
controller={this.props.controller}
|
|
1114
|
-
>
|
|
1115
|
-
{this.props.children}
|
|
1116
|
-
</this.props.PlayerComponent>
|
|
1117
|
-
</AnimationComponent>
|
|
1118
|
-
) : null}
|
|
1119
|
-
</View>
|
|
1120
|
-
|
|
1121
|
-
{renderTransportControls(playerDimensions)}
|
|
1122
|
-
{!this.state.piped && (
|
|
1123
|
-
<PlayNextOverlay
|
|
1124
|
-
item={entry}
|
|
1125
|
-
playerIsDocked={docked}
|
|
1126
|
-
pluginConfiguration={this.getPluginConfiguration()}
|
|
1127
|
-
playerId={this.props.playerId}
|
|
1128
|
-
playNextData={this.getPlayNextData()}
|
|
1129
|
-
setNextVideoPreloadThresholdPercentage={
|
|
1130
|
-
this.props.setNextVideoPreloadThresholdPercentage
|
|
1131
|
-
}
|
|
1132
|
-
/>
|
|
1133
|
-
)}
|
|
1134
|
-
</View>
|
|
1135
|
-
);
|
|
1136
|
-
}}
|
|
1137
|
-
</PlayerWrapper>
|
|
1138
|
-
);
|
|
1237
|
+
const audioPlayerProps = {
|
|
1238
|
+
ref: this._assignRoot,
|
|
1239
|
+
...this.getNativeEvents(),
|
|
1240
|
+
...this.getNativeProps(),
|
|
1139
1241
|
};
|
|
1140
1242
|
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
/>
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
{!isInlineTV && this.childrenWithExtensions()}
|
|
1162
|
-
</this.props.PlayerComponent>
|
|
1163
|
-
|
|
1164
|
-
{renderTransportControls(this.takeParentStyle)}
|
|
1165
|
-
{!isTvOS && (
|
|
1166
|
-
<PlayNextOverlay
|
|
1167
|
-
item={entry}
|
|
1168
|
-
playerIsDocked={docked}
|
|
1169
|
-
pluginConfiguration={this.getPluginConfiguration()}
|
|
1170
|
-
playerId={this.props.playerId}
|
|
1171
|
-
playNextData={this.getPlayNextData()}
|
|
1172
|
-
setNextVideoPreloadThresholdPercentage={
|
|
1173
|
-
this.props.setNextVideoPreloadThresholdPercentage
|
|
1243
|
+
return isFullScreenAudioPlayer && isAudioItem ? (
|
|
1244
|
+
// Ensure the View remains in the native hierarchy for proper rendering and interaction
|
|
1245
|
+
<PlayerModal
|
|
1246
|
+
content={
|
|
1247
|
+
<View collapsable={false} style={styles.container}>
|
|
1248
|
+
{shouldRenderNativePlayer ? (
|
|
1249
|
+
<PlayerComponent {...audioPlayerProps} listener={listener} />
|
|
1250
|
+
) : null}
|
|
1251
|
+
<AudioPlayerWrapper {...sharedWrapperViewProps} />
|
|
1252
|
+
</View>
|
|
1253
|
+
}
|
|
1254
|
+
collapsedContent={
|
|
1255
|
+
<View style={styles.container}>
|
|
1256
|
+
<DockedControls
|
|
1257
|
+
entry={entry}
|
|
1258
|
+
aspectRatio={1}
|
|
1259
|
+
layoutState={sharedWrapperViewProps.layoutState}
|
|
1260
|
+
playNextData={sharedWrapperViewProps.playNextData}
|
|
1261
|
+
ImageComponent={
|
|
1262
|
+
<FlexImage entry={entry} style={styles.flexImage} />
|
|
1174
1263
|
}
|
|
1175
1264
|
/>
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1265
|
+
</View>
|
|
1266
|
+
}
|
|
1267
|
+
/>
|
|
1268
|
+
) : isModal ? (
|
|
1269
|
+
<VideoPlayerModal
|
|
1270
|
+
isTabletPortrait={isTabletPortrait}
|
|
1271
|
+
aspectRatio={aspectRatio}
|
|
1272
|
+
pip={piped}
|
|
1273
|
+
fullscreen={fullscreen}
|
|
1274
|
+
modal
|
|
1275
|
+
style={{
|
|
1276
|
+
tabletLandscapeWidth: getTabletWidth(
|
|
1277
|
+
this.getPluginConfiguration().tablet_landscape_sidebar_width,
|
|
1278
|
+
style
|
|
1279
|
+
),
|
|
1280
|
+
width: style.width,
|
|
1281
|
+
height: style.height,
|
|
1282
|
+
}}
|
|
1283
|
+
content={
|
|
1284
|
+
<PlayerWrapper
|
|
1285
|
+
{...sharedWrapperViewProps}
|
|
1286
|
+
playerContent={this.renderPlayerContent}
|
|
1287
|
+
/>
|
|
1288
|
+
}
|
|
1289
|
+
extraContent={
|
|
1290
|
+
<PlayerDetails
|
|
1291
|
+
configuration={this.getPluginConfiguration()}
|
|
1292
|
+
style={{ flex: 1 }}
|
|
1293
|
+
entry={entry}
|
|
1294
|
+
isTabletLandscape={!isTabletPortrait}
|
|
1295
|
+
inline={inline}
|
|
1296
|
+
docked={docked}
|
|
1297
|
+
isModal={isModal}
|
|
1298
|
+
pip={piped}
|
|
1299
|
+
/>
|
|
1300
|
+
}
|
|
1301
|
+
collapsedContent={
|
|
1302
|
+
<View style={styles.container}>
|
|
1303
|
+
<DockedControls
|
|
1304
|
+
entry={entry}
|
|
1305
|
+
aspectRatio={aspectRatio}
|
|
1306
|
+
layoutState={sharedWrapperViewProps.layoutState}
|
|
1307
|
+
playNextData={sharedWrapperViewProps.playNextData}
|
|
1308
|
+
/>
|
|
1309
|
+
</View>
|
|
1310
|
+
}
|
|
1311
|
+
/>
|
|
1312
|
+
) : (
|
|
1313
|
+
<View style={style} testID={"player-view"}>
|
|
1314
|
+
<PlayerWrapper
|
|
1315
|
+
{...sharedWrapperViewProps}
|
|
1316
|
+
playerContent={this.renderPlayerContent}
|
|
1317
|
+
/>
|
|
1318
|
+
</View>
|
|
1319
|
+
);
|
|
1320
|
+
};
|
|
1321
|
+
|
|
1322
|
+
renderTV = () => {
|
|
1323
|
+
const {
|
|
1324
|
+
docked,
|
|
1325
|
+
entry,
|
|
1326
|
+
listener,
|
|
1327
|
+
controller,
|
|
1328
|
+
PlayerComponent,
|
|
1329
|
+
playerId,
|
|
1330
|
+
setNextVideoPreloadThresholdPercentage,
|
|
1331
|
+
children,
|
|
1332
|
+
} = this.props;
|
|
1333
|
+
|
|
1334
|
+
const isAudioItem = isAudioItemUtil(entry);
|
|
1335
|
+
|
|
1336
|
+
const playerProps = {
|
|
1337
|
+
ref: this._assignRoot,
|
|
1338
|
+
...this.getNativeEvents(),
|
|
1339
|
+
...this.getNativeProps(),
|
|
1340
|
+
listener,
|
|
1341
|
+
style: this.takeParentStyle,
|
|
1342
|
+
controller,
|
|
1343
|
+
};
|
|
1344
|
+
|
|
1345
|
+
const audioPlayerProps = {
|
|
1346
|
+
style: { ...styles.audio, ...this.takeParentStyle },
|
|
1179
1347
|
};
|
|
1180
1348
|
|
|
1181
|
-
return
|
|
1349
|
+
return (
|
|
1350
|
+
<View style={this.takeParentStyle} testID={"player-view"}>
|
|
1351
|
+
<TVPlayerView
|
|
1352
|
+
type={isAudioItem ? "audio" : "video"}
|
|
1353
|
+
entry={entry}
|
|
1354
|
+
inline={this.isInlineTV()}
|
|
1355
|
+
transportControls={this.renderTransportControls(this.takeParentStyle)}
|
|
1356
|
+
PlayerComponent={PlayerComponent}
|
|
1357
|
+
nativePlayerIsReady={this.state.nativePlayerIsReady}
|
|
1358
|
+
pluginConfiguration={this.getPluginConfiguration()}
|
|
1359
|
+
playerProps={playerProps}
|
|
1360
|
+
audioPlayerProps={audioPlayerProps}
|
|
1361
|
+
playNextProps={{
|
|
1362
|
+
playerIsDocked: docked,
|
|
1363
|
+
playerId: playerId,
|
|
1364
|
+
playNextData: this.getPlayNextData(),
|
|
1365
|
+
setNextVideoPreloadThresholdPercentage:
|
|
1366
|
+
setNextVideoPreloadThresholdPercentage,
|
|
1367
|
+
}}
|
|
1368
|
+
>
|
|
1369
|
+
{children}
|
|
1370
|
+
</TVPlayerView>
|
|
1371
|
+
</View>
|
|
1372
|
+
);
|
|
1373
|
+
};
|
|
1374
|
+
|
|
1375
|
+
render() {
|
|
1376
|
+
return isTV() ? this.renderTV() : this.renderMobile();
|
|
1182
1377
|
}
|
|
1183
1378
|
}
|