@applicaster/quick-brick-player 14.0.0-rc.4 → 14.0.0-rc.40

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.
@@ -0,0 +1,42 @@
1
+ import { ReactNode, ComponentType } from "react";
2
+ import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
3
+ import { ViewStyle } from "react-native";
4
+
5
+ export interface PlayNextOverlayProps {
6
+ playerIsDocked: boolean;
7
+ playerId?: string;
8
+ playNextData: PlayNextData;
9
+ setNextVideoPreloadThresholdPercentage: (percentage: number) => void;
10
+ }
11
+
12
+ export interface PlayerComponentProps {
13
+ ref: React.RefObject<any>;
14
+ listener: Record<string, any>;
15
+ configuration: Record<string, any>;
16
+ style: ViewStyle;
17
+ }
18
+
19
+ export interface AudioPlayerProps {
20
+ style: ViewStyle;
21
+ }
22
+
23
+ export interface PlayerViewBaseProps {
24
+ children?: ReactNode;
25
+ type: "audio" | "video";
26
+ entry: ZappEntry;
27
+ pluginConfiguration: Record<string, any>;
28
+ PlayerComponent: ComponentType<any>;
29
+ playerProps: PlayerComponentProps;
30
+ playNextProps: PlayNextOverlayProps;
31
+ audioPlayerProps: AudioPlayerProps;
32
+ transportControls?: ReactNode;
33
+ inline?: boolean;
34
+ }
35
+
36
+ export interface TvOSPlayerViewProps extends PlayerViewBaseProps {
37
+ nativePlayerIsReady: boolean;
38
+ }
39
+
40
+ export type GenericTVPlayerViewProps = PlayerViewBaseProps;
41
+
42
+ export type TVPlayerViewProps = TvOSPlayerViewProps | GenericTVPlayerViewProps;
@@ -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 { flatten } from "@applicaster/zapp-react-native-utils/utils";
8
+ import { findNodeHandle, StyleSheet, View, Dimensions } 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,7 +19,10 @@ import {
19
19
  isWeb,
20
20
  } from "@applicaster/zapp-react-native-utils/reactUtils";
21
21
 
22
- import { PlayerWrapper } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal";
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";
@@ -33,19 +36,21 @@ 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
+
49
54
  const styles = StyleSheet.create({
50
55
  container: { flex: 1 },
51
56
  playerContainerBlack: { backgroundColor: DEFAULT_COLORS.black },
@@ -55,8 +60,8 @@ const styles = StyleSheet.create({
55
60
  position: "absolute",
56
61
  zIndex: 1,
57
62
  },
58
- audioPlayerSize: { width: "100%", height: "100%" },
59
63
  playerSize: { width: "100%", height: "100%" },
64
+ flexImage: { height: "100%", aspectRatio: 1, flex: -1 },
60
65
  });
61
66
 
62
67
  const logger = createLogger({
@@ -66,7 +71,14 @@ const logger = createLogger({
66
71
 
67
72
  const isTvOS = isTvOSPlatform();
68
73
 
69
- const AUDIO_PLAYER_NATIVE_ID = "audio-player-view";
74
+ const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get("screen");
75
+
76
+ const getScreenAspectRatio = () => {
77
+ const longEdge = Math.max(SCREEN_WIDTH, SCREEN_HEIGHT);
78
+ const shortEdge = Math.min(SCREEN_WIDTH, SCREEN_HEIGHT);
79
+
80
+ return longEdge / shortEdge;
81
+ };
70
82
 
71
83
  export default class VideoPlayer extends React.Component<
72
84
  QuickBrickPlayer.PlayerProps,
@@ -688,53 +700,6 @@ export default class VideoPlayer extends React.Component<
688
700
  }
689
701
  };
690
702
 
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
703
  get supportNativeCast() {
739
704
  return this.props.controller.supportNativeCast();
740
705
  }
@@ -1021,159 +986,196 @@ export default class VideoPlayer extends React.Component<
1021
986
  pip: this.state.piped,
1022
987
  },
1023
988
  configuration: this.getPluginConfiguration(),
1024
- fullscreen: fullscreen,
1025
- isTabletPortrait: isTabletPortrait,
989
+ isTabletPortrait,
1026
990
  playNextData: this.getPlayNextData(),
1027
991
  };
1028
992
 
1029
- const containerStyle = { flex: 1 };
1030
-
1031
993
  const backgroundImageKey =
1032
994
  this.getPluginConfiguration()?.player_preview_image_key;
1033
995
 
1034
996
  const shouldRenderNativePlayer =
1035
997
  !this.props.isCasting || this.supportNativeCast;
1036
998
 
999
+ const aspectRatio =
1000
+ !inline && isModal && !this.state.piped ? getScreenAspectRatio() : 16 / 9;
1001
+
1037
1002
  const renderMobilePlayer = () => {
1038
1003
  return isFullScreenAudioPlayer && isAudioItem ? (
1039
1004
  // 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>
1005
+ <PlayerModal
1006
+ content={
1007
+ <View collapsable={false} style={styles.container}>
1008
+ {shouldRenderNativePlayer ? (
1009
+ <this.props.PlayerComponent
1010
+ ref={this._assignRoot}
1011
+ {...nativeEvents}
1012
+ {...nativeProps}
1013
+ listener={this.props.listener}
1014
+ />
1015
+ ) : null}
1016
+ <AudioPlayerWrapper {...sharedWrapperViewProps} />
1017
+ </View>
1018
+ }
1019
+ collapsedContent={
1020
+ <View style={styles.container}>
1021
+ <DockedControls
1022
+ entry={entry}
1023
+ aspectRatio={1}
1024
+ layoutState={sharedWrapperViewProps.layoutState}
1025
+ playNextData={sharedWrapperViewProps.playNextData}
1026
+ ImageComponent={
1027
+ <FlexImage entry={entry} style={styles.flexImage} />
1028
+ }
1029
+ />
1030
+ </View>
1031
+ }
1032
+ />
1051
1033
  ) : (
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
1034
+ <VideoPlayerModal
1035
+ enabled={!!isModal && !fullscreen}
1036
+ isTabletPortrait={isTabletPortrait}
1037
+ aspectRatio={aspectRatio}
1038
+ pip={this.state.piped}
1039
+ fullscreen={fullscreen}
1040
+ style={{
1041
+ tabletLandscapeWidth: getTabletWidth(
1042
+ this.getPluginConfiguration().tablet_landscape_sidebar_width,
1043
+ style
1044
+ ),
1045
+ width: style.width,
1046
+ height: style.height,
1047
+ }}
1048
+ content={(_opacityAnim) => (
1049
+ <PlayerWrapper
1050
+ {...sharedWrapperViewProps}
1051
+ playerContent={(playerDimensions) => {
1052
+ const shouldRenderBackground =
1053
+ !R.isNil(backgroundImageKey) &&
1054
+ backgroundImageKey.length > 0 &&
1055
+ !this.onVideoLoadCalled &&
1056
+ !this.state.isAd;
1057
+
1058
+ return (
1059
+ <View style={styles.container}>
1060
+ <View style={[playerContainerStyles, playerDimensions]}>
1061
+ {isAudioItem ? (
1062
+ <AudioPlayer
1063
+ style={
1064
+ isTV()
1065
+ ? getStyle(playerDimensions)
1066
+ : styles.playerSize
1067
+ }
1068
+ audio_item={entry}
1069
+ plugin_configuration={this.getPluginConfiguration()}
1070
+ />
1071
+ ) : null}
1072
+
1073
+ {shouldRenderBackground ? (
1074
+ <PlayerImageBackground
1075
+ imageKey={backgroundImageKey}
1076
+ configuration={this.getPluginConfiguration()}
1077
+ entry={entry}
1078
+ style={getBackgroundImageStyle(playerDimensions)}
1079
+ />
1080
+ ) : null}
1081
+
1082
+ {shouldRenderNativePlayer ? (
1083
+ <View style={getStyle(playerDimensions)}>
1084
+ <this.props.PlayerComponent
1085
+ ref={this._assignRoot}
1086
+ {...nativeEvents}
1087
+ {...nativeProps}
1088
+ listener={this.props.listener}
1089
+ style={
1090
+ isTV()
1091
+ ? getStyle(playerDimensions)
1092
+ : styles.playerSize
1093
+ }
1094
+ pluginConfiguration={this.getPluginConfiguration()}
1095
+ controller={this.props.controller}
1096
+ >
1097
+ {this.props.children}
1098
+ </this.props.PlayerComponent>
1099
+ </View>
1100
+ ) : null}
1101
+ </View>
1102
+
1103
+ {renderTransportControls(playerDimensions)}
1104
+ {!this.state.piped && (
1105
+ <PlayNextOverlay
1106
+ item={entry}
1107
+ playerIsDocked={docked}
1108
+ pluginConfiguration={this.getPluginConfiguration()}
1109
+ playerId={this.props.playerId}
1110
+ playNextData={this.getPlayNextData()}
1111
+ setNextVideoPreloadThresholdPercentage={
1112
+ this.props.setNextVideoPreloadThresholdPercentage
1077
1113
  }
1078
- audio_item={entry}
1079
- plugin_configuration={this.getPluginConfiguration()}
1080
1114
  />
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
- )}
1115
+ )}
1116
+ </View>
1117
+ );
1118
+ }}
1119
+ />
1120
+ )}
1121
+ extraContent={(_opacityAnim) => (
1122
+ <PlayerDetails
1123
+ configuration={this.getPluginConfiguration()}
1124
+ style={{ flex: 1 }}
1125
+ entry={entry}
1126
+ isTabletLandscape={!isTabletPortrait}
1127
+ inline={inline}
1128
+ docked={docked}
1129
+ isModal={isModal}
1130
+ pip={this.state.piped}
1131
+ />
1132
+ )}
1133
+ collapsedContent={(_opacityAnim) =>
1134
+ this.state.piped ? null : (
1135
+ <View style={styles.container}>
1136
+ <DockedControls
1137
+ entry={entry}
1138
+ aspectRatio={aspectRatio}
1139
+ layoutState={sharedWrapperViewProps.layoutState}
1140
+ playNextData={sharedWrapperViewProps.playNextData}
1141
+ />
1134
1142
  </View>
1135
- );
1136
- }}
1137
- </PlayerWrapper>
1143
+ )
1144
+ }
1145
+ />
1138
1146
  );
1139
1147
  };
1140
1148
 
1141
1149
  const renderTVPlayer = () => {
1142
1150
  return (
1143
1151
  <View style={this.takeParentStyle} testID={"player-view"}>
1144
- {isAudioItem && (isInlineTV || !isTvOS) ? (
1145
- <AudioPlayer
1146
- style={getStyle(styles.audioPlayerSize)}
1147
- audio_item={entry}
1148
- plugin_configuration={this.getPluginConfiguration()}
1149
- />
1150
- ) : null}
1151
-
1152
- <this.props.PlayerComponent
1153
- ref={this._assignRoot}
1154
- {...nativeEvents}
1155
- {...nativeProps}
1156
- listener={this.props.listener}
1157
- style={this.takeParentStyle}
1152
+ <TVPlayerView
1153
+ type={isAudioItem ? "audio" : "video"}
1154
+ entry={entry}
1155
+ inline={isInlineTV}
1156
+ transportControls={renderTransportControls(this.takeParentStyle)}
1157
+ PlayerComponent={this.props.PlayerComponent}
1158
+ nativePlayerIsReady={this.state.nativePlayerIsReady}
1158
1159
  pluginConfiguration={this.getPluginConfiguration()}
1159
- controller={this.props.controller}
1160
+ playerProps={{
1161
+ ref: this._assignRoot,
1162
+ ...nativeEvents,
1163
+ ...nativeProps,
1164
+ listener: this.props.listener,
1165
+ style: this.takeParentStyle,
1166
+ controller: this.props.controller,
1167
+ }}
1168
+ audioPlayerProps={{ style: getStyle(styles.playerSize) }}
1169
+ playNextProps={{
1170
+ playerIsDocked: docked,
1171
+ playerId: this.props.playerId,
1172
+ playNextData: this.getPlayNextData(),
1173
+ setNextVideoPreloadThresholdPercentage:
1174
+ this.props.setNextVideoPreloadThresholdPercentage,
1175
+ }}
1160
1176
  >
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
1174
- }
1175
- />
1176
- )}
1177
+ {this.props.children}
1178
+ </TVPlayerView>
1177
1179
  </View>
1178
1180
  );
1179
1181
  };