@applicaster/quick-brick-player 13.0.0-rc.12 → 13.0.0-rc.121

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 (44) hide show
  1. package/package.json +27 -14
  2. package/src/CellPlayer/Assets/AssetsComponent.tsx +17 -3
  3. package/src/Player/AudioLayer/AudioDescription.tsx +107 -68
  4. package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +205 -281
  5. package/src/Player/AudioLayer/Layout/Controls/VerticalGutter.tsx +45 -0
  6. package/src/Player/AudioLayer/Layout/Controls/index.tsx +320 -0
  7. package/src/Player/AudioLayer/Layout/{defaultLayoutsConts.ts → Controls/utils.ts} +7 -25
  8. package/src/Player/AudioLayer/Layout/Debug/index.tsx +55 -0
  9. package/src/Player/AudioLayer/Layout/{DockedLayout.tsx → DockedControls/index.tsx} +77 -81
  10. package/src/Player/AudioLayer/Layout/MobileLayout.tsx +230 -0
  11. package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +70 -0
  12. package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +20 -0
  13. package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +108 -0
  14. package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +36 -0
  15. package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +220 -0
  16. package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +223 -0
  17. package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +128 -0
  18. package/src/Player/AudioLayer/Layout/VerticalGutter/index.tsx +8 -0
  19. package/src/Player/AudioLayer/Layout/const.ts +26 -0
  20. package/src/Player/AudioLayer/Layout/debug.ts +6 -0
  21. package/src/Player/AudioLayer/Layout/hooks/index.ts +5 -0
  22. package/src/Player/AudioLayer/Layout/hooks/useMobileLayoutImageSize.ts +14 -0
  23. package/src/Player/AudioLayer/Layout/hooks/useTabletLayoutImageSize.ts +105 -0
  24. package/src/Player/AudioLayer/Layout/hooks/useTransportInfoHeight.ts +54 -0
  25. package/src/Player/AudioLayer/Layout/index.tsx +21 -48
  26. package/src/Player/AudioLayer/Layout/types.ts +7 -0
  27. package/src/Player/AudioLayer/Layout/utils.ts +7 -0
  28. package/src/Player/AudioLayer/SleepTimerManager.ts +119 -0
  29. package/src/Player/AudioLayer/SpeedManager.ts +52 -0
  30. package/src/Player/AudioLayer/utils.ts +27 -0
  31. package/src/Player/Const/sleepTimerOptions.ts +39 -0
  32. package/src/Player/Const/speedOptions.ts +4 -0
  33. package/src/Player/Utils/Utils.ts +0 -5
  34. package/src/Player/Utils/index.tsx +117 -0
  35. package/src/Player/hooks/useIsCasting.tsx +57 -0
  36. package/src/Player/index.tsx +39 -22
  37. package/src/QuickBrickPlayer.tsx +3 -0
  38. package/src/Player/AudioLayer/Layout/DefaultLayout.tsx +0 -452
  39. package/src/Player/AudioLayer/LinearGradient/LinearGradientProxy.ts +0 -3
  40. package/src/Player/AudioLayer/LinearGradient/LinearGradientProxy.web.ts +0 -3
  41. package/src/Player/AudioLayer/LinearGradient/index.ts +0 -1
  42. package/src/Player/AudioLayer/MagicBG/index.tsx +0 -155
  43. package/src/Player/Helpers/VideoResizeMode.ts +0 -7
  44. package/src/utils/utils.ts +0 -25
@@ -0,0 +1,108 @@
1
+ import * as React from "react";
2
+
3
+ import {
4
+ AnimationComponent,
5
+ ComponentAnimationType,
6
+ useModalAnimationContext,
7
+ } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
8
+
9
+ import { AnimatedImage } from "./AnimatedImage";
10
+ import { FlexImage } from "./FlexImage";
11
+
12
+ import { styles } from "./styles";
13
+ import { calculateBorderRadius } from "../../utils";
14
+ import { PlayNextData } from "../types";
15
+ import { LayoutChangeEvent, View } from "react-native";
16
+
17
+ type Props = {
18
+ entry: ZappEntry;
19
+ layoutState: QuickBrickPlayer.LayoutState;
20
+ playerState: QuickBrickPlayer.PlayerState;
21
+ value: GetValue;
22
+ configuration: QuickBrickPlayer.AudioPlayerProps["configuration"];
23
+ dimensions: QuickBrickPlayer.AudioPlayerProps["dimensions"];
24
+ onCloseVideoModal: Callback;
25
+ onPlayerSeek: (targetTime: number) => void;
26
+ playNextData: PlayNextData;
27
+ title: string | number;
28
+ summary: string | number;
29
+ docked: boolean;
30
+ imageWidth?: Option<number>;
31
+ verticalOffset: number;
32
+ onLayoutImage: (event: LayoutChangeEvent) => void;
33
+ };
34
+
35
+ export const PlayerImage = (props: Props) => {
36
+ const {
37
+ entry,
38
+ dimensions,
39
+ docked,
40
+ verticalOffset,
41
+ imageWidth,
42
+ configuration,
43
+ onLayoutImage,
44
+ } = props;
45
+
46
+ const {
47
+ isActiveGesture,
48
+ startComponentsAnimation,
49
+ playerAnimationState,
50
+ minimisedHeight,
51
+ } = useModalAnimationContext();
52
+
53
+ const isShadowEnabled =
54
+ configuration?.audio_player_artwork_shadow_enabled ?? true;
55
+
56
+ const shouldShowShadow = !docked && isShadowEnabled;
57
+
58
+ const borderRadius = calculateBorderRadius(
59
+ docked,
60
+ startComponentsAnimation,
61
+ isActiveGesture,
62
+ playerAnimationState,
63
+ configuration
64
+ );
65
+
66
+ return (
67
+ <AnimationComponent
68
+ animationType={ComponentAnimationType.moveUpComponent}
69
+ additionalData={{
70
+ marginTop: verticalOffset,
71
+ }}
72
+ style={styles.flex}
73
+ >
74
+ <AnimationComponent
75
+ animationType={ComponentAnimationType.moveComponentHorizontal}
76
+ additionalData={{
77
+ // we move image horiontally to this value due artwork is centered
78
+ moveValue: (dimensions.width - minimisedHeight) / 2,
79
+ }}
80
+ style={styles.alignItemsCenter}
81
+ >
82
+ <View
83
+ onLayout={onLayoutImage}
84
+ style={[
85
+ shouldShowShadow ? styles.shadow : undefined,
86
+ { borderRadius },
87
+ ]}
88
+ >
89
+ {!imageWidth ? (
90
+ <View style={[styles.defaultImageWrapperView, { borderRadius }]}>
91
+ <FlexImage
92
+ entry={entry}
93
+ style={styles.backgroundImageContainer}
94
+ />
95
+ </View>
96
+ ) : (
97
+ // we have imageSize here and now we could animate resizing of this image
98
+ <AnimatedImage
99
+ entry={entry}
100
+ style={[styles.backgroundImageContainer, { borderRadius }]}
101
+ imageWidth={imageWidth}
102
+ />
103
+ )}
104
+ </View>
105
+ </AnimationComponent>
106
+ </AnimationComponent>
107
+ );
108
+ };
@@ -0,0 +1,36 @@
1
+ /* eslint-disable react-native/no-color-literals */
2
+ import { StyleSheet } from "react-native";
3
+ import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
4
+
5
+ const SHADOW_COLOR = "rgba(0, 0, 0, 1)";
6
+
7
+ export const styles = StyleSheet.create({
8
+ backgroundImageContainer: {
9
+ flex: 1,
10
+ aspectRatio: 1,
11
+ overflow: "hidden",
12
+ },
13
+
14
+ alignItemsCenter: {
15
+ flex: 1,
16
+ alignItems: "center",
17
+ },
18
+
19
+ flex: {
20
+ flex: 1,
21
+ },
22
+ defaultImageWrapperView: {
23
+ overflow: "hidden",
24
+ },
25
+ shadow: {
26
+ borderColor: "transparent",
27
+ shadowColor: SHADOW_COLOR,
28
+ shadowOffset: { width: 0, height: 24 },
29
+ shadowOpacity: platformSelect({
30
+ ios: 0.35,
31
+ default: 0.2,
32
+ }),
33
+ shadowRadius: 32,
34
+ elevation: 12,
35
+ },
36
+ });
@@ -0,0 +1,220 @@
1
+ import * as React from "react";
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";
9
+
10
+ import { TransportInfo } from "./TransportInfo";
11
+ import { PlayerImage } from "./PlayerImage";
12
+ import { Controls } from "./Controls";
13
+
14
+ import { DockedControls } from "./DockedControls";
15
+ import { withDebug } from "./debug";
16
+
17
+ import { Props } from "./types";
18
+ import { isSmallTabletHeight as getIsSmallTabletHeight } from "./utils";
19
+ import { NAVBAR_HEIGHT, TABLET_LANDSCAPE } from "./const";
20
+ import { FlexImage } from "./PlayerImage/FlexImage";
21
+
22
+ const isIOS = isApplePlatform();
23
+
24
+ const MIN_WIDTH = TABLET_LANDSCAPE.MIN_WIDTH; // Minimum width for the audio player container
25
+ const MAX_SPACING = TABLET_LANDSCAPE.MARGIN_VERTICAL; // Maximum spacing for the audio player container
26
+ const MIN_SPACING = TABLET_LANDSCAPE.MARGIN_VERTICAL_S; // Minimum spacing for the audio player container
27
+ const transportInfoHeight = NAVBAR_HEIGHT;
28
+
29
+ const styles = StyleSheet.create({
30
+ container: {
31
+ flex: 1,
32
+ alignItems: "center",
33
+ height: "100%",
34
+ ...withDebug({
35
+ borderWidth: 2,
36
+ borderColor: "magenta",
37
+ }),
38
+ },
39
+ flex: {
40
+ flex: 1,
41
+ },
42
+ audioPlayerContainer: {
43
+ flexDirection: "column",
44
+ alignItems: "center",
45
+ justifyContent: "center",
46
+ minWidth: MIN_WIDTH,
47
+
48
+ ...withDebug({
49
+ borderWidth: 2,
50
+ borderColor: "blue",
51
+ }),
52
+ },
53
+ audioPlayerContainerHeightLimit: {
54
+ maxHeight: 750,
55
+ },
56
+ audioPlayerContainerPaddings: {
57
+ paddingBottom: MAX_SPACING,
58
+ paddingTop: MAX_SPACING,
59
+ },
60
+ // For small screens, we reduce the padding to fit better
61
+ audioPlayerContainerPaddingsSmall: {
62
+ paddingBottom: MIN_SPACING,
63
+ paddingTop: MIN_SPACING,
64
+ },
65
+ controlsContainer: { flexGrow: 0, alignSelf: "stretch" },
66
+ // eslint-disable-next-line react-native/no-color-literals
67
+ debugYellow: {
68
+ borderWidth: 2,
69
+ borderColor: "yellow",
70
+ },
71
+ });
72
+
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
+ export function TabletLandscapeLayout({
90
+ entry,
91
+ layoutState,
92
+ playerState,
93
+ value,
94
+ onPlaybackButtonPress,
95
+ onRewindButtonPress,
96
+ onForwardButtonPress,
97
+ onPlayerSeek,
98
+ onSkipStart,
99
+ onSkipLive,
100
+ onSpeedButtonPress,
101
+ onSleepButtonPress,
102
+ onCloseVideoModal,
103
+ playbackSpeedName,
104
+ playbackSleepName,
105
+ configuration,
106
+ dimensions,
107
+ playNextData,
108
+ cancelSleepTimer,
109
+ sleepTimerDate,
110
+ title,
111
+ summary,
112
+ }: Props) {
113
+ const [imageWidth, setImageWidth] = React.useState(0);
114
+ const { docked } = layoutState;
115
+
116
+ const { bottom: bottomInset } = useSafeAreaInsets();
117
+ const { height: screenHeight } = useSafeAreaFrame();
118
+ const isSmallScreen = getIsSmallTabletHeight(screenHeight);
119
+ const { progressBarHeight } = useModalAnimationContext();
120
+
121
+ const onLayoutImage = React.useCallback((e) => {
122
+ setImageWidth(e.nativeEvent.layout.width);
123
+ }, []);
124
+
125
+ return (
126
+ <View style={styles.container}>
127
+ {/* TransportInfo */}
128
+ <TransportInfo
129
+ entry={entry}
130
+ layoutState={layoutState}
131
+ value={value}
132
+ configuration={configuration}
133
+ />
134
+
135
+ {/* TransportInfo */}
136
+
137
+ <View
138
+ style={[
139
+ styles.audioPlayerContainer,
140
+ {
141
+ marginTop: isSmallScreen
142
+ ? -TABLET_LANDSCAPE.MARGIN_VERTICAL_S
143
+ : -TABLET_LANDSCAPE.MARGIN_VERTICAL,
144
+ height: screenHeight - transportInfoHeight,
145
+ },
146
+ isSmallScreen
147
+ ? styles.audioPlayerContainerPaddingsSmall
148
+ : styles.audioPlayerContainerPaddings,
149
+ ]}
150
+ >
151
+ <View style={[styles.flex, styles.audioPlayerContainerHeightLimit]}>
152
+ {/* PlayerImage non-docked */}
153
+ <View style={[styles.flex, withDebug(styles.debugYellow)]}>
154
+ {!docked ? (
155
+ <PlayerImage
156
+ docked={false}
157
+ entry={entry}
158
+ layoutState={layoutState}
159
+ playerState={playerState}
160
+ value={value}
161
+ configuration={configuration}
162
+ onPlayerSeek={onPlayerSeek}
163
+ onCloseVideoModal={onCloseVideoModal}
164
+ dimensions={dimensions}
165
+ playNextData={playNextData}
166
+ title={title}
167
+ summary={summary}
168
+ verticalOffset={withAdditionalOffset({
169
+ progressBarHeight,
170
+ bottomInset,
171
+ })}
172
+ onLayoutImage={onLayoutImage}
173
+ />
174
+ ) : null}
175
+ </View>
176
+ {/* PlayerImage */}
177
+
178
+ <View style={styles.controlsContainer}>
179
+ <Controls
180
+ maxWidth={imageWidth}
181
+ entry={entry}
182
+ layoutState={layoutState}
183
+ playerState={playerState}
184
+ value={value}
185
+ title={title}
186
+ summary={summary}
187
+ sleepTimerDate={sleepTimerDate}
188
+ cancelSleepTimer={cancelSleepTimer}
189
+ playbackSpeedName={playbackSpeedName}
190
+ playbackSleepName={playbackSleepName}
191
+ onPlaybackButtonPress={onPlaybackButtonPress}
192
+ onRewindButtonPress={onRewindButtonPress}
193
+ onForwardButtonPress={onForwardButtonPress}
194
+ onPlayerSeek={onPlayerSeek}
195
+ onSkipStart={onSkipStart}
196
+ onSkipLive={onSkipLive}
197
+ onSpeedButtonPress={onSpeedButtonPress}
198
+ onSleepButtonPress={onSleepButtonPress}
199
+ docked={docked}
200
+ />
201
+ </View>
202
+ </View>
203
+ </View>
204
+
205
+ <DockedControls
206
+ ImageComponent={<FlexImage entry={entry} style={styles.flex} />}
207
+ entry={entry}
208
+ layoutState={layoutState}
209
+ playerState={playerState}
210
+ value={value}
211
+ dimensions={dimensions}
212
+ onCloseVideoModal={onCloseVideoModal}
213
+ onPlayerSeek={onPlayerSeek}
214
+ playNextData={playNextData}
215
+ title={title}
216
+ summary={summary}
217
+ />
218
+ </View>
219
+ );
220
+ }
@@ -0,0 +1,223 @@
1
+ import * as React from "react";
2
+ import { StyleSheet, View, ViewStyle } 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 { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
9
+
10
+ import { withDebug } from "./debug";
11
+ import { TABLET_PORTRAIT } from "./const";
12
+
13
+ import { TransportInfo } from "./TransportInfo";
14
+ import { PlayerImage } from "./PlayerImage";
15
+ import { Controls } from "./Controls";
16
+
17
+ import { useTabletLayoutImageSize } from "./hooks";
18
+ import { DockedControls } from "./DockedControls";
19
+ import { VerticalGutter } from "./VerticalGutter";
20
+
21
+ import { Props } from "./types";
22
+
23
+ const styles = StyleSheet.create({
24
+ container: {
25
+ flex: 1,
26
+
27
+ ...withDebug({
28
+ borderWidth: 2,
29
+ borderColor: "magenta",
30
+ }),
31
+ },
32
+
33
+ flex: {
34
+ flex: 1,
35
+ },
36
+
37
+ fillContainer: {
38
+ ...StyleSheet.absoluteFillObject,
39
+ alignItems: "center",
40
+ ...withDebug({
41
+ borderWidth: 2,
42
+ borderColor: "red",
43
+ }),
44
+ },
45
+
46
+ audioPlayerContainer: {
47
+ flex: 1,
48
+ maxWidth: TABLET_PORTRAIT.MAX_WIDTH,
49
+ marginLeft: TABLET_PORTRAIT.MARGIN_HORIZONTAL,
50
+ marginRight: TABLET_PORTRAIT.MARGIN_HORIZONTAL,
51
+
52
+ ...withDebug({
53
+ borderWidth: 2,
54
+ borderColor: "blue",
55
+ }),
56
+ },
57
+ });
58
+
59
+ const tabletStyles = ({
60
+ screenHeight,
61
+ topInset,
62
+ bottomInset,
63
+ topOffset,
64
+ }): ViewStyle => ({
65
+ alignItems: "center",
66
+ height: screenHeight - topInset - bottomInset,
67
+ opacity: topOffset ? 1 : 0, // hide content until topOffset is calculated
68
+ });
69
+
70
+ const justifyContent = (topOffset: Option<number>) =>
71
+ topOffset ? "flex-start" : "center";
72
+
73
+ export function TabletPortraitLayout({
74
+ entry,
75
+ layoutState,
76
+ playerState,
77
+ value,
78
+ onPlaybackButtonPress,
79
+ onRewindButtonPress,
80
+ onForwardButtonPress,
81
+ onPlayerSeek,
82
+ onSkipStart,
83
+ onSkipLive,
84
+ onSpeedButtonPress,
85
+ onSleepButtonPress,
86
+ onCloseVideoModal,
87
+ playbackSpeedName,
88
+ playbackSleepName,
89
+ configuration,
90
+ dimensions,
91
+ playNextData,
92
+ cancelSleepTimer,
93
+ sleepTimerDate,
94
+ title,
95
+ summary,
96
+ }: Props) {
97
+ const { docked } = layoutState;
98
+
99
+ const { bottom: bottomInset, top: topInset } = useSafeAreaInsets();
100
+ const { height: screenHeight } = useSafeAreaFrame();
101
+ const { progressBarHeight } = useModalAnimationContext();
102
+
103
+ const {
104
+ imageSize,
105
+ offsetY: topOffset,
106
+ onLayout,
107
+ } = useTabletLayoutImageSize({ isPortraitMode: true });
108
+
109
+ return (
110
+ <View
111
+ style={[
112
+ styles.container,
113
+ tabletStyles({
114
+ screenHeight,
115
+ topInset,
116
+ bottomInset,
117
+ topOffset,
118
+ }),
119
+ ]}
120
+ >
121
+ {/* TransportInfo */}
122
+ <TransportInfo
123
+ entry={entry}
124
+ layoutState={layoutState}
125
+ value={value}
126
+ configuration={configuration}
127
+ />
128
+
129
+ {/* TransportInfo */}
130
+
131
+ {/* PlayerImage */}
132
+ <View style={styles.fillContainer} pointerEvents="box-none">
133
+ <View
134
+ style={[
135
+ styles.audioPlayerContainer,
136
+ {
137
+ justifyContent: justifyContent(topOffset),
138
+ width: imageSize,
139
+ },
140
+ ]}
141
+ >
142
+ {topOffset ? <VerticalGutter height={topOffset} /> : null}
143
+
144
+ <View
145
+ style={[
146
+ styles.flex,
147
+ {
148
+ maxHeight: imageSize,
149
+
150
+ ...withDebug({
151
+ borderWidth: 2,
152
+ borderColor: "yellow",
153
+ }),
154
+ },
155
+ ]}
156
+ onLayout={onLayout}
157
+ >
158
+ <PlayerImage
159
+ entry={entry}
160
+ layoutState={layoutState}
161
+ playerState={playerState}
162
+ value={value}
163
+ configuration={configuration}
164
+ onPlayerSeek={onPlayerSeek}
165
+ onCloseVideoModal={onCloseVideoModal}
166
+ dimensions={dimensions}
167
+ playNextData={playNextData}
168
+ title={title}
169
+ summary={summary}
170
+ docked={docked}
171
+ imageWidth={imageSize}
172
+ verticalOffset={
173
+ toNumberWithDefaultZero(topOffset) - progressBarHeight
174
+ }
175
+ />
176
+ </View>
177
+
178
+ <View
179
+ style={{
180
+ maxWidth: imageSize,
181
+ }}
182
+ >
183
+ <Controls
184
+ entry={entry}
185
+ layoutState={layoutState}
186
+ playerState={playerState}
187
+ value={value}
188
+ title={title}
189
+ summary={summary}
190
+ sleepTimerDate={sleepTimerDate}
191
+ cancelSleepTimer={cancelSleepTimer}
192
+ playbackSpeedName={playbackSpeedName}
193
+ playbackSleepName={playbackSleepName}
194
+ onPlaybackButtonPress={onPlaybackButtonPress}
195
+ onRewindButtonPress={onRewindButtonPress}
196
+ onForwardButtonPress={onForwardButtonPress}
197
+ onPlayerSeek={onPlayerSeek}
198
+ onSkipStart={onSkipStart}
199
+ onSkipLive={onSkipLive}
200
+ onSpeedButtonPress={onSpeedButtonPress}
201
+ onSleepButtonPress={onSleepButtonPress}
202
+ docked={docked}
203
+ />
204
+ </View>
205
+ </View>
206
+ </View>
207
+ {/* PlayerImage */}
208
+
209
+ <DockedControls
210
+ entry={entry}
211
+ layoutState={layoutState}
212
+ playerState={playerState}
213
+ value={value}
214
+ dimensions={dimensions}
215
+ onCloseVideoModal={onCloseVideoModal}
216
+ onPlayerSeek={onPlayerSeek}
217
+ playNextData={playNextData}
218
+ title={title}
219
+ summary={summary}
220
+ />
221
+ </View>
222
+ );
223
+ }
@@ -0,0 +1,128 @@
1
+ import * as React from "react";
2
+ import { compose, map, propOr, split, take, trim } from "ramda";
3
+ import { LayoutChangeEvent, StyleSheet, View } from "react-native";
4
+
5
+ import { TransportInfo as MobileTransportInfo } from "@applicaster/quick-brick-mobile-transport-controls";
6
+ import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
7
+ 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";
12
+ import { toPositiveNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
13
+ import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
14
+
15
+ import { NAVBAR_HEIGHT, TABLET_LANDSCAPE } from "../const";
16
+ import { withDebug } from "../debug";
17
+ import { useSafeAreaFrame } from "react-native-safe-area-context";
18
+ import { isSmallTabletHeight } from "../utils";
19
+
20
+ const styles = StyleSheet.create({
21
+ container: {
22
+ height: NAVBAR_HEIGHT,
23
+ justifyContent: "center",
24
+ marginHorizontal: 10,
25
+ },
26
+ animatedContainer: {
27
+ width: "100%",
28
+ alignItems: "center",
29
+ justifyContent: "space-between",
30
+
31
+ ...withDebug({
32
+ borderWidth: 2,
33
+ borderColor: "yellow",
34
+ }),
35
+ },
36
+ });
37
+
38
+ const applyMarginBottom = ({ isTablet, marginBottom }) =>
39
+ isTablet ? marginBottom : 0;
40
+
41
+ type Props = {
42
+ entry: ZappEntry;
43
+ layoutState: QuickBrickPlayer.LayoutState;
44
+ value: GetValue;
45
+ configuration: QuickBrickPlayer.AudioPlayerProps["configuration"];
46
+ onLayout?: (event: LayoutChangeEvent) => void;
47
+ };
48
+
49
+ export const TransportInfo = ({
50
+ entry,
51
+ layoutState,
52
+ value,
53
+ configuration,
54
+ onLayout = noop,
55
+ }: Props) => {
56
+ const isTablet = useIsTablet();
57
+ const safeAreaFrame = useSafeAreaFrame();
58
+ const languageData = useLanguageData("audio-player");
59
+
60
+ const [marginBottom, setMarginBottom] = React.useState(0);
61
+
62
+ const handleLayout = React.useCallback(
63
+ (event: LayoutChangeEvent) => {
64
+ const height = toPositiveNumberWithDefaultZero(
65
+ event?.nativeEvent?.layout?.height
66
+ );
67
+
68
+ const minHeight = Math.min(
69
+ height,
70
+ isTablet && isSmallTabletHeight(safeAreaFrame.height)
71
+ ? TABLET_LANDSCAPE.MARGIN_VERTICAL_S
72
+ : TABLET_LANDSCAPE.MARGIN_VERTICAL
73
+ );
74
+
75
+ setMarginBottom(
76
+ (isTablet && isSmallTabletHeight(safeAreaFrame.height)
77
+ ? TABLET_LANDSCAPE.MARGIN_VERTICAL_S
78
+ : TABLET_LANDSCAPE.MARGIN_VERTICAL) - minHeight
79
+ );
80
+
81
+ // pass layoutChangeEvent to upper level
82
+ onLayout(event);
83
+ },
84
+ [onLayout]
85
+ );
86
+
87
+ 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]
96
+ );
97
+
98
+ return (
99
+ <View
100
+ style={[
101
+ styles.container,
102
+ {
103
+ marginBottom: applyMarginBottom({ isTablet, marginBottom }),
104
+
105
+ ...withDebug({
106
+ borderWidth: 2,
107
+ borderColor: "red",
108
+ }),
109
+ },
110
+ ]}
111
+ onLayout={handleLayout}
112
+ >
113
+ <AnimationComponent
114
+ animationType={ComponentAnimationType.componentFade}
115
+ style={styles.animatedContainer}
116
+ >
117
+ <MobileTransportInfo
118
+ content={entry}
119
+ value={value}
120
+ visible
121
+ languageData={languageData}
122
+ layoutState={layoutState}
123
+ actionButtons={actionButtons}
124
+ />
125
+ </AnimationComponent>
126
+ </View>
127
+ );
128
+ };