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