@applicaster/quick-brick-player 14.0.0-rc.9 → 14.0.0-rc.90

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.
Files changed (38) hide show
  1. package/package.json +6 -11
  2. package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +44 -88
  3. package/src/Player/AudioLayer/Layout/Controls/index.tsx +8 -18
  4. package/src/Player/AudioLayer/Layout/DockedControls/index.tsx +169 -161
  5. package/src/Player/AudioLayer/Layout/MobileLayout.tsx +4 -42
  6. package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +5 -9
  7. package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +35 -83
  8. package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +6 -1
  9. package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +6 -66
  10. package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +1 -39
  11. package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +6 -18
  12. package/src/Player/AudioLayer/components/SleepTimerModalHeader/SleepTimerModalHeader.tsx +1 -1
  13. package/src/Player/AudioLayer/utils.ts +1 -27
  14. package/src/Player/PlayerModal/GestureAnimatedScrollView.ts +7 -0
  15. package/src/Player/PlayerModal/PlayerModal.tsx +110 -0
  16. package/src/Player/PlayerModal/VideoPlayerModal.tsx +289 -0
  17. package/src/Player/PlayerModal/consts/index.ts +17 -0
  18. package/src/Player/PlayerModal/context/index.ts +6 -0
  19. package/src/Player/PlayerModal/hooks/index.ts +169 -0
  20. package/src/Player/PlayerModal/index.ts +3 -0
  21. package/src/Player/PlayerModal/index.web.ts +5 -0
  22. package/src/Player/PlayerModal/styles.ts +109 -0
  23. package/src/Player/PlayerModal/utils/index.ts +111 -0
  24. package/src/Player/PlayerView/GenericTVPlayerView.tsx +42 -0
  25. package/src/Player/PlayerView/TVPlayerView.tsx +26 -0
  26. package/src/Player/PlayerView/TvOSPlayerView.tsx +51 -0
  27. package/src/Player/PlayerView/types.ts +41 -0
  28. package/src/Player/index.tsx +575 -380
  29. package/src/QuickBrickPlayer.tsx +16 -10
  30. package/src/utils/dimensions.ts +29 -0
  31. package/src/utils/index.ts +12 -0
  32. package/src/utils/logger.ts +6 -0
  33. package/src/utils/playerHelpers.ts +11 -0
  34. package/src/utils/playerStyles.ts +50 -0
  35. package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +0 -87
  36. package/src/Player/AudioLayer/Layout/PlayerImage/hooks/index.ts +0 -1
  37. package/src/Player/AudioLayer/Layout/PlayerImage/hooks/useChangePlayerState.ts +0 -99
  38. /package/src/Player/AudioLayer/Layout/{Debug → DebugComponent}/index.tsx +0 -0
@@ -1,25 +1,16 @@
1
1
  import * as React from "react";
2
2
  import { StyleSheet, View } from "react-native";
3
- import {
4
- useSafeAreaFrame,
5
- useSafeAreaInsets,
6
- } from "react-native-safe-area-context";
7
- import { useModalAnimationContext } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
8
- import { isApplePlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
3
+ import { useSafeAreaFrame } from "react-native-safe-area-context";
9
4
 
10
5
  import { TransportInfo } from "./TransportInfo";
11
6
  import { PlayerImage } from "./PlayerImage";
12
7
  import { Controls } from "./Controls";
13
8
 
14
- import { DockedControls } from "./DockedControls";
15
9
  import { withDebug } from "./debug";
16
10
 
17
11
  import { Props } from "./types";
18
12
  import { isSmallTabletHeight as getIsSmallTabletHeight } from "./utils";
19
13
  import { NAVBAR_HEIGHT, TABLET_LANDSCAPE } from "./const";
20
- import { FlexImage } from "./PlayerImage/FlexImage";
21
-
22
- const isIOS = isApplePlatform();
23
14
 
24
15
  const MIN_WIDTH = TABLET_LANDSCAPE.MIN_WIDTH; // Minimum width for the audio player container
25
16
  const MAX_SPACING = TABLET_LANDSCAPE.MARGIN_VERTICAL; // Maximum spacing for the audio player container
@@ -70,22 +61,6 @@ const styles = StyleSheet.create({
70
61
  },
71
62
  });
72
63
 
73
- const isTabletWithHomeButton = (bottomInset: number): boolean =>
74
- bottomInset === 0;
75
-
76
- const withAdditionalOffset = ({ progressBarHeight, bottomInset }) => {
77
- if (isIOS && isTabletWithHomeButton(bottomInset)) {
78
- return progressBarHeight === 0 ? 8 : progressBarHeight + 2;
79
- }
80
-
81
- if (isIOS && !isTabletWithHomeButton(bottomInset)) {
82
- return progressBarHeight === 0 ? 4 : 1;
83
- }
84
-
85
- // android
86
- return progressBarHeight === 0 ? 4 : 0.5;
87
- };
88
-
89
64
  export function TabletLandscapeLayout({
90
65
  entry,
91
66
  layoutState,
@@ -98,21 +73,16 @@ export function TabletLandscapeLayout({
98
73
  onSkipStart,
99
74
  onSkipLive,
100
75
  onSpeedButtonPress,
101
- onCloseVideoModal,
102
76
  playbackSpeedName,
103
77
  configuration,
104
- dimensions,
105
- playNextData,
106
78
  title,
107
79
  summary,
108
80
  }: Props) {
109
81
  const [imageWidth, setImageWidth] = React.useState(0);
110
82
  const { docked } = layoutState;
111
83
 
112
- const { bottom: bottomInset } = useSafeAreaInsets();
113
84
  const { height: screenHeight } = useSafeAreaFrame();
114
85
  const isSmallScreen = getIsSmallTabletHeight(screenHeight);
115
- const { progressBarHeight } = useModalAnimationContext();
116
86
 
117
87
  const onLayoutImage = React.useCallback((e) => {
118
88
  setImageWidth(e.nativeEvent.layout.width);
@@ -147,27 +117,11 @@ export function TabletLandscapeLayout({
147
117
  <View style={[styles.flex, styles.audioPlayerContainerHeightLimit]}>
148
118
  {/* PlayerImage non-docked */}
149
119
  <View style={[styles.flex, withDebug(styles.debugYellow)]}>
150
- {!docked ? (
151
- <PlayerImage
152
- docked={false}
153
- entry={entry}
154
- layoutState={layoutState}
155
- playerState={playerState}
156
- value={value}
157
- configuration={configuration}
158
- onPlayerSeek={onPlayerSeek}
159
- onCloseVideoModal={onCloseVideoModal}
160
- dimensions={dimensions}
161
- playNextData={playNextData}
162
- title={title}
163
- summary={summary}
164
- verticalOffset={withAdditionalOffset({
165
- progressBarHeight,
166
- bottomInset,
167
- })}
168
- onLayoutImage={onLayoutImage}
169
- />
170
- ) : null}
120
+ <PlayerImage
121
+ entry={entry}
122
+ configuration={configuration}
123
+ onLayoutImage={onLayoutImage}
124
+ />
171
125
  </View>
172
126
  {/* PlayerImage */}
173
127
 
@@ -193,20 +147,6 @@ export function TabletLandscapeLayout({
193
147
  </View>
194
148
  </View>
195
149
  </View>
196
-
197
- <DockedControls
198
- ImageComponent={<FlexImage entry={entry} style={styles.flex} />}
199
- entry={entry}
200
- layoutState={layoutState}
201
- playerState={playerState}
202
- value={value}
203
- dimensions={dimensions}
204
- onCloseVideoModal={onCloseVideoModal}
205
- onPlayerSeek={onPlayerSeek}
206
- playNextData={playNextData}
207
- title={title}
208
- summary={summary}
209
- />
210
150
  </View>
211
151
  );
212
152
  }
@@ -4,8 +4,6 @@ import {
4
4
  useSafeAreaFrame,
5
5
  useSafeAreaInsets,
6
6
  } from "react-native-safe-area-context";
7
- import { useModalAnimationContext } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
8
- import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
9
7
 
10
8
  import { withDebug } from "./debug";
11
9
  import { TABLET_PORTRAIT } from "./const";
@@ -15,7 +13,6 @@ import { PlayerImage } from "./PlayerImage";
15
13
  import { Controls } from "./Controls";
16
14
 
17
15
  import { useTabletLayoutImageSize } from "./hooks";
18
- import { DockedControls } from "./DockedControls";
19
16
  import { VerticalGutter } from "./VerticalGutter";
20
17
 
21
18
  import { Props } from "./types";
@@ -82,11 +79,8 @@ export function TabletPortraitLayout({
82
79
  onSkipStart,
83
80
  onSkipLive,
84
81
  onSpeedButtonPress,
85
- onCloseVideoModal,
86
82
  playbackSpeedName,
87
83
  configuration,
88
- dimensions,
89
- playNextData,
90
84
  title,
91
85
  summary,
92
86
  }: Props) {
@@ -94,7 +88,6 @@ export function TabletPortraitLayout({
94
88
 
95
89
  const { bottom: bottomInset, top: topInset } = useSafeAreaInsets();
96
90
  const { height: screenHeight } = useSafeAreaFrame();
97
- const { progressBarHeight } = useModalAnimationContext();
98
91
 
99
92
  const {
100
93
  imageSize,
@@ -151,24 +144,7 @@ export function TabletPortraitLayout({
151
144
  ]}
152
145
  onLayout={onLayout}
153
146
  >
154
- <PlayerImage
155
- entry={entry}
156
- layoutState={layoutState}
157
- playerState={playerState}
158
- value={value}
159
- configuration={configuration}
160
- onPlayerSeek={onPlayerSeek}
161
- onCloseVideoModal={onCloseVideoModal}
162
- dimensions={dimensions}
163
- playNextData={playNextData}
164
- title={title}
165
- summary={summary}
166
- docked={docked}
167
- imageWidth={imageSize}
168
- verticalOffset={
169
- toNumberWithDefaultZero(topOffset) - progressBarHeight
170
- }
171
- />
147
+ <PlayerImage entry={entry} configuration={configuration} />
172
148
  </View>
173
149
 
174
150
  <View
@@ -196,20 +172,6 @@ export function TabletPortraitLayout({
196
172
  </View>
197
173
  </View>
198
174
  </View>
199
- {/* PlayerImage */}
200
-
201
- <DockedControls
202
- entry={entry}
203
- layoutState={layoutState}
204
- playerState={playerState}
205
- value={value}
206
- dimensions={dimensions}
207
- onCloseVideoModal={onCloseVideoModal}
208
- onPlayerSeek={onPlayerSeek}
209
- playNextData={playNextData}
210
- title={title}
211
- summary={summary}
212
- />
213
175
  </View>
214
176
  );
215
177
  }
@@ -1,14 +1,10 @@
1
1
  import * as React from "react";
2
- import { compose, map, propOr, split, take, trim } from "ramda";
3
2
  import { LayoutChangeEvent, StyleSheet, View } from "react-native";
4
3
 
5
4
  import { TransportInfo as MobileTransportInfo } from "@applicaster/quick-brick-mobile-transport-controls";
6
5
  import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
7
6
  import { useLanguageData } from "@applicaster/zapp-react-native-utils/reactHooks/player";
8
- import {
9
- AnimationComponent,
10
- ComponentAnimationType,
11
- } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
7
+
12
8
  import { toPositiveNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
13
9
  import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
14
10
 
@@ -16,6 +12,7 @@ import { NAVBAR_HEIGHT, TABLET_LANDSCAPE } from "../const";
16
12
  import { withDebug } from "../debug";
17
13
  import { useSafeAreaFrame } from "react-native-safe-area-context";
18
14
  import { isSmallTabletHeight } from "../utils";
15
+ import { getPlayerActionButtons } from "@applicaster/zapp-react-native-utils/playerUtils";
19
16
 
20
17
  const styles = StyleSheet.create({
21
18
  container: {
@@ -85,14 +82,8 @@ export const TransportInfo = ({
85
82
  );
86
83
 
87
84
  const actionButtons = React.useMemo(
88
- () =>
89
- compose(
90
- take(2),
91
- map(trim),
92
- split(","),
93
- propOr("", "player_action_buttons")
94
- )(configuration),
95
- [configuration.player_action_buttons]
85
+ () => getPlayerActionButtons(configuration),
86
+ [configuration]
96
87
  );
97
88
 
98
89
  return (
@@ -110,10 +101,7 @@ export const TransportInfo = ({
110
101
  ]}
111
102
  onLayout={handleLayout}
112
103
  >
113
- <AnimationComponent
114
- animationType={ComponentAnimationType.componentFade}
115
- style={styles.animatedContainer}
116
- >
104
+ <View style={styles.animatedContainer}>
117
105
  <MobileTransportInfo
118
106
  content={entry}
119
107
  value={value}
@@ -122,7 +110,7 @@ export const TransportInfo = ({
122
110
  layoutState={layoutState}
123
111
  actionButtons={actionButtons}
124
112
  />
125
- </AnimationComponent>
113
+ </View>
126
114
  </View>
127
115
  );
128
116
  };
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
  import { ModalHeader } from "@applicaster/zapp-react-native-ui-components/Components/ModalComponent/Header";
3
- import { isNil } from "lodash";
3
+ import { isNil } from "@applicaster/zapp-react-native-utils/utils";
4
4
 
5
5
  const formatTime = (milliseconds: number) => {
6
6
  const totalSeconds = Math.floor(milliseconds / 1000);
@@ -1,10 +1,6 @@
1
1
  import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
2
- import {
3
- PlayerAnimationStateEnum,
4
- PlayerAnimationStateT,
5
- } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/ModalAnimationContext";
2
+
6
3
  import { parseJsonIfNeeded } from "@applicaster/zapp-react-native-utils/functionUtils";
7
- import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
8
4
 
9
5
  export const NAMESPACE = "audio-player";
10
6
 
@@ -36,25 +32,3 @@ export const formatSpeed = (value: number) => {
36
32
  // Return the formatted string with "speed_" prefix
37
33
  return `speed_${formattedValue}`;
38
34
  };
39
-
40
- export const calculateBorderRadius = (
41
- docked: boolean,
42
- startComponentsAnimation: boolean,
43
- isActiveGesture: boolean,
44
- playerAnimationState: PlayerAnimationStateT,
45
- configuration: Record<string, any>
46
- ): number => {
47
- const shouldRemoveBorderRadius =
48
- (startComponentsAnimation &&
49
- isActiveGesture &&
50
- playerAnimationState !== PlayerAnimationStateEnum.maximize) ||
51
- docked;
52
-
53
- if (shouldRemoveBorderRadius) {
54
- return 0;
55
- }
56
-
57
- return toNumberWithDefaultZero(
58
- configuration.audio_player_artwork_border_radius
59
- );
60
- };
@@ -0,0 +1,7 @@
1
+ import { Animated } from "react-native";
2
+ import { createNativeWrapper } from "react-native-gesture-handler";
3
+
4
+ export const GestureAnimatedScrollView = createNativeWrapper(
5
+ Animated.ScrollView,
6
+ {}
7
+ );
@@ -0,0 +1,110 @@
1
+ import React, { ReactElement } from "react";
2
+
3
+ import { Animated, Pressable } from "react-native";
4
+ import { PanGestureHandler } from "react-native-gesture-handler";
5
+ import { useStyles } from "./styles";
6
+ import { useVideoModalState } from "./hooks";
7
+ import { MODAL_COLLAPSE_RATIO, MODAL_RADIUS } from "./consts";
8
+ import { getWindowHeight } from "./utils";
9
+ import { useSafeAreaFrame } from "react-native-safe-area-context";
10
+
11
+ type AnimatedModalProps = {
12
+ content?: ReactElement;
13
+ collapsedContent?: ReactElement;
14
+ };
15
+
16
+ export function AnimatedModal({
17
+ content,
18
+ collapsedContent,
19
+ }: AnimatedModalProps) {
20
+ const { translateY, collapsed, gestureHandlerProps, expand, offset } =
21
+ useVideoModalState();
22
+
23
+ const frame = useSafeAreaFrame();
24
+ const collapsedHeight = frame.height - offset.current;
25
+
26
+ const height = getWindowHeight();
27
+ const heightAboveMinimised = height - collapsedHeight;
28
+
29
+ const styles = useStyles({ height: collapsedHeight, type: "audio" });
30
+
31
+ const MODAL_COLLAPSE_START = height * MODAL_COLLAPSE_RATIO;
32
+
33
+ // Interpolated opacities for smooth cross-fade
34
+ const collapsedOpacity = translateY.interpolate({
35
+ inputRange: [MODAL_COLLAPSE_START, heightAboveMinimised],
36
+ outputRange: [0, 1],
37
+ extrapolate: "clamp",
38
+ });
39
+
40
+ const expandedOpacity = translateY.interpolate({
41
+ inputRange: [0, heightAboveMinimised],
42
+ outputRange: [1, 0],
43
+ extrapolate: "clamp",
44
+ });
45
+
46
+ const borderTopRadiusAnimated = translateY.interpolate({
47
+ inputRange: [0, heightAboveMinimised],
48
+ outputRange: [MODAL_RADIUS, 0],
49
+ extrapolate: "clamp",
50
+ });
51
+
52
+ return (
53
+ <PanGestureHandler {...gestureHandlerProps}>
54
+ <Animated.View
55
+ pointerEvents={"auto"}
56
+ style={[
57
+ styles.modalWrapper,
58
+ {
59
+ borderTopLeftRadius: borderTopRadiusAnimated,
60
+ borderTopRightRadius: borderTopRadiusAnimated,
61
+ transform: [{ translateY }],
62
+ height: height,
63
+ },
64
+ ]}
65
+ >
66
+ <Animated.View
67
+ style={[
68
+ styles.modal,
69
+ {
70
+ borderTopLeftRadius: borderTopRadiusAnimated,
71
+ borderTopRightRadius: borderTopRadiusAnimated,
72
+ },
73
+ ]}
74
+ >
75
+ {/* Expanded Content (fades in) */}
76
+ <Animated.View
77
+ pointerEvents={!collapsed ? "auto" : "none"}
78
+ style={styles.modalContent}
79
+ >
80
+ <Animated.View
81
+ pointerEvents={!collapsed ? "auto" : "none"}
82
+ style={[
83
+ styles.expandedContentContainer,
84
+ { opacity: expandedOpacity },
85
+ ]}
86
+ >
87
+ {content}
88
+ </Animated.View>
89
+ </Animated.View>
90
+ {/* Collapsed Bar (fades out) */}
91
+ <Animated.View
92
+ pointerEvents={collapsed ? "box-none" : "none"}
93
+ style={[
94
+ styles.collapsedBarContainer,
95
+ { opacity: collapsedOpacity },
96
+ ]}
97
+ >
98
+ <Pressable
99
+ testID="collapsedBarWrapper"
100
+ onPress={expand}
101
+ style={styles.collapsedBarWrapper}
102
+ >
103
+ {collapsedContent}
104
+ </Pressable>
105
+ </Animated.View>
106
+ </Animated.View>
107
+ </Animated.View>
108
+ </PanGestureHandler>
109
+ );
110
+ }