@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,12 +1,10 @@
1
1
  import * as React from "react";
2
+ import { StyleSheet, View } from "react-native";
2
3
  import {
3
- StyleSheet,
4
- TouchableWithoutFeedback,
5
- View,
6
- ViewStyle,
7
- } from "react-native";
8
- import * as R from "ramda";
9
- import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
4
+ useIsTablet,
5
+ useZStore,
6
+ } from "@applicaster/zapp-react-native-utils/reactHooks";
7
+ import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
10
8
 
11
9
  import {
12
10
  Button,
@@ -17,30 +15,28 @@ import {
17
15
 
18
16
  import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
19
17
 
20
- import {
21
- AnimationComponent,
22
- ComponentAnimationType,
23
- PlayerAnimationStateEnum,
24
- useModalAnimationContext,
25
- } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
26
- import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
27
18
  import { useSafeAreaInsets } from "react-native-safe-area-context";
19
+ import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
28
20
  import { getTabBarHeight } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/getTabBarHeight";
21
+ import { useTitleSummaryOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerTitleSummaryOverlay";
22
+ import { usePlayerState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerState";
23
+ import { useConfiguration } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/utils";
24
+ import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
25
+ import { PROGRESS_BAR_HEIGHT } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/utils";
26
+ import { isMenuVisible } from "@applicaster/zapp-react-native-ui-components/Components/Screen/navigationHandler";
27
+ import { usePlugins } from "@applicaster/zapp-react-native-redux";
28
+ import { partial } from "@applicaster/zapp-react-native-utils/utils";
29
29
 
30
30
  const bottomTabBarHeight = getTabBarHeight();
31
31
 
32
32
  type Props = {
33
33
  entry: ZappEntry;
34
34
  layoutState: QuickBrickPlayer.LayoutState;
35
- playerState: QuickBrickPlayer.PlayerState;
36
- value: GetValue;
37
- dimensions: QuickBrickPlayer.AudioPlayerProps["dimensions"];
38
- onCloseVideoModal: () => void;
39
- onPlayerSeek: (targetTime: number) => void;
35
+ onPlayerSeek?: (targetTime: number) => void;
40
36
  playNextData: PlayNextData;
41
- title: string | number;
42
- summary: string | number;
43
37
  ImageComponent?: React.ReactNode;
38
+ isActiveGesture?: boolean;
39
+ aspectRatio?: number;
44
40
  };
45
41
 
46
42
  const styles = StyleSheet.create({
@@ -90,34 +86,12 @@ const styles = StyleSheet.create({
90
86
  buttons: {
91
87
  marginVertical: 10,
92
88
  },
89
+ liveMarginTop: { marginTop: 0 },
90
+ marginTop: { marginTop: PROGRESS_BAR_HEIGHT },
93
91
  });
94
92
 
95
- const playerDimensionsStyle = (
96
- minimisedHeight: number,
97
- addPadding: boolean
98
- ): ViewStyle => ({
99
- width: addPadding ? toNumberWithDefault(100, minimisedHeight) : 0,
100
- });
101
-
102
- const animatedContainerStyle = (
103
- docked: boolean,
104
- progressBarHeight: number
105
- ): ViewStyle => ({
106
- top: progressBarHeight,
107
- position: "absolute",
108
- width: "100%",
109
- zIndex: docked ? 1 : -1,
110
- });
111
-
112
- const backgroundImageStyle = (
113
- dimensions: QuickBrickPlayer.AudioPlayerProps["dimensions"],
114
- minimisedHeight: number,
115
- isActiveGesture: boolean
116
- ): ViewStyle => ({
117
- height: isActiveGesture ? minimisedHeight : dimensions.height,
118
- aspectRatio: 1,
119
- position: "absolute",
120
- });
93
+ const getValue = (key: string, stylesObj: Record<string, any>) =>
94
+ stylesObj?.[key] ?? null;
121
95
 
122
96
  const controlButtons = (
123
97
  live: boolean,
@@ -180,140 +154,174 @@ export const DockedControls = (props: Props) => {
180
154
  const {
181
155
  entry,
182
156
  layoutState,
183
- playerState,
184
- value,
185
- dimensions,
186
- onCloseVideoModal,
187
- onPlayerSeek,
157
+ onPlayerSeek = noop,
188
158
  playNextData,
189
- title,
190
- summary,
191
159
  ImageComponent,
160
+ aspectRatio,
192
161
  } = props;
193
162
 
194
- const isTablet = useIsTablet();
163
+ const onCloseVideoModal = React.useCallback(() => {
164
+ playerManager.close();
165
+ }, []);
195
166
 
196
- const liveButton = Boolean(value("live_badge_enabled"));
167
+ const { currentRoute, screenData } = useNavigation();
197
168
 
198
- const {
199
- isActiveGesture,
200
- setPlayerAnimationState,
201
- startComponentsAnimation,
202
- minimisedHeight,
203
- progressBarHeight,
204
- } = useModalAnimationContext();
205
-
206
- const maximazeVideoModal = React.useCallback(
207
- () => setPlayerAnimationState(PlayerAnimationStateEnum.maximize),
208
- []
169
+ const plugins = usePlugins();
170
+ const menuVisible = isMenuVisible(currentRoute, screenData, plugins);
171
+
172
+ const { minimised_height: minimisedHeight } = useConfiguration();
173
+
174
+ const configuration = useZStore("playerConfiguration")();
175
+ const playerState = usePlayerState("shared-player-wrapper-docked");
176
+
177
+ const value = React.useCallback(
178
+ (key: string) => {
179
+ const retVal = getValue(key, configuration);
180
+
181
+ const minimumAllowedSeekableDurationInSeconds = getValue(
182
+ "minimumAllowedSeekableDurationInSeconds",
183
+ configuration
184
+ );
185
+
186
+ if (key === "liveSeekingEnabled") {
187
+ return playerState.seekableDuration <
188
+ minimumAllowedSeekableDurationInSeconds || playerManager.isCasting()
189
+ ? false
190
+ : retVal;
191
+ }
192
+
193
+ return retVal;
194
+ },
195
+ [...Object.values(configuration), playerState.seekableDuration]
209
196
  );
210
197
 
198
+ const { title, summary } = useTitleSummaryOverlay(
199
+ entry,
200
+ playerState?.isLive,
201
+ configuration?.audio_live_player_update_interval
202
+ );
203
+
204
+ const isTablet = useIsTablet();
205
+
206
+ const liveButton = Boolean(value("live_badge_enabled"));
207
+
211
208
  const dockedBackgroundColor = value("docked_player_background_color");
212
209
 
213
210
  const insets = useSafeAreaInsets();
214
211
 
215
- if (!layoutState.docked && !startComponentsAnimation) return null;
212
+ const progressBarLayoutState = React.useMemo(
213
+ () => ({
214
+ inline: layoutState.inline,
215
+ docked: true,
216
+ isModal: layoutState.isModal,
217
+ pip: layoutState.pip,
218
+ }),
219
+ [layoutState.inline, layoutState.isModal, layoutState.pip]
220
+ );
221
+
222
+ const _controlButtons = React.useMemo(
223
+ () => partial(controlButtons, playerState.isLive && liveButton),
224
+ [playerState.isLive, liveButton]
225
+ );
226
+
227
+ const containerStyles = React.useMemo(
228
+ () => ({
229
+ height: minimisedHeight,
230
+ maxHeight: minimisedHeight,
231
+ }),
232
+ [minimisedHeight]
233
+ );
234
+
235
+ const imageComponentWrapperStyles = React.useMemo(
236
+ () => ({
237
+ aspectRatio: aspectRatio,
238
+ height: minimisedHeight,
239
+ }),
240
+ [aspectRatio, minimisedHeight]
241
+ );
242
+
243
+ const backgroundColorStyle = React.useMemo(
244
+ () => ({
245
+ backgroundColor: dockedBackgroundColor,
246
+ }),
247
+ [dockedBackgroundColor]
248
+ );
249
+
250
+ const bottomSpacerStyle = React.useMemo(() => {
251
+ const tabBarHeight = menuVisible ? bottomTabBarHeight : 0;
252
+ const safeAreaBottomInset = insets.bottom || 0;
253
+
254
+ return {
255
+ height: safeAreaBottomInset + tabBarHeight,
256
+ };
257
+ }, [menuVisible, insets.bottom]);
258
+
259
+ const contentInfoContent = React.useMemo(
260
+ () => ({ ...entry, title, summary }),
261
+ [title, summary, entry]
262
+ );
216
263
 
217
264
  return (
218
- <AnimationComponent
219
- animationType={ComponentAnimationType.componentAppears}
220
- style={[
221
- styles.container,
222
- animatedContainerStyle(
223
- isActiveGesture || layoutState.docked,
224
- progressBarHeight
225
- ),
226
- {
227
- height: minimisedHeight + bottomTabBarHeight + insets.bottom,
228
- },
229
- ]}
230
- >
231
- {!playerState.isLive &&
232
- (layoutState.docked || startComponentsAnimation) ? (
233
- <ProgressBar
234
- name={"audio-docked-layout"}
235
- content={entry}
236
- value={value}
237
- visible
238
- layoutState={layoutState}
239
- onPlayerSeek={onPlayerSeek}
240
- playerState={playerState}
241
- startComponentsAnimation={startComponentsAnimation}
242
- docked
243
- />
244
- ) : null}
245
-
246
- <View style={styles.content}>
247
- <View
248
- style={backgroundImageStyle(
249
- dimensions,
250
- minimisedHeight,
251
- isActiveGesture
252
- )}
253
- />
254
- <TouchableWithoutFeedback onPress={maximazeVideoModal}>
265
+ <>
266
+ <View
267
+ style={[
268
+ styles.container,
269
+ containerStyles,
270
+ playerState.isLive ? styles.liveMarginTop : styles.marginTop,
271
+ ]}
272
+ >
273
+ {!playerState.isLive ? (
274
+ <ProgressBar
275
+ name={"shared-docked-layout"}
276
+ content={entry}
277
+ value={value}
278
+ visible
279
+ layoutState={progressBarLayoutState}
280
+ onPlayerSeek={onPlayerSeek}
281
+ playerState={playerState}
282
+ docked
283
+ />
284
+ ) : null}
285
+
286
+ <View style={styles.content}>
255
287
  <View style={styles.touchableArea}>
256
- {isActiveGesture || layoutState.docked ? (
257
- <View
258
- style={{ width: toNumberWithDefault(100, minimisedHeight) }}
259
- >
260
- {ImageComponent || null}
261
- </View>
262
- ) : (
263
- <View
264
- style={playerDimensionsStyle(
265
- minimisedHeight,
266
- isActiveGesture || layoutState.docked
267
- )}
268
- />
269
- )}
288
+ <View style={imageComponentWrapperStyles}>
289
+ {ImageComponent || null}
290
+ </View>
270
291
  <View
271
- style={[
272
- styles.contentInfo,
273
- { backgroundColor: dockedBackgroundColor },
274
- ]}
292
+ testID="content-info"
293
+ style={[styles.contentInfo, backgroundColorStyle]}
275
294
  >
276
- <ContentInfo
277
- content={{ ...entry, title, summary }}
278
- value={value}
279
- docked
280
- />
295
+ <ContentInfo content={contentInfoContent} value={value} docked />
281
296
  </View>
282
297
  </View>
283
- </TouchableWithoutFeedback>
284
- <View
285
- style={[
286
- isTablet
287
- ? styles.controlsContainerForTablet
288
- : styles.controlsContainerForMobile,
289
- { backgroundColor: dockedBackgroundColor },
290
- ]}
291
- >
292
- <Controls
293
- value={value}
294
- visible
295
- buttons={R.partial(controlButtons, [
296
- playerState.isLive && liveButton,
297
- ])}
298
- style={styles.playPauseButton}
299
- playNextData={playNextData}
300
- playerState={playerState}
301
- />
302
- <Button
303
- icon={"close_mini"}
304
- size={"medium"}
305
- value={value}
306
- onPress={onCloseVideoModal}
307
- style={styles.buttons}
308
- />
298
+ <View
299
+ style={[
300
+ isTablet
301
+ ? styles.controlsContainerForTablet
302
+ : styles.controlsContainerForMobile,
303
+ backgroundColorStyle,
304
+ ]}
305
+ >
306
+ <Controls
307
+ value={value}
308
+ visible
309
+ buttons={_controlButtons}
310
+ style={styles.playPauseButton}
311
+ playNextData={playNextData}
312
+ playerState={playerState}
313
+ />
314
+ <Button
315
+ icon={"close_mini"}
316
+ size={"medium"}
317
+ value={value}
318
+ onPress={onCloseVideoModal}
319
+ style={styles.buttons}
320
+ />
321
+ </View>
309
322
  </View>
310
323
  </View>
311
- <View
312
- style={{
313
- height: insets.bottom + bottomTabBarHeight,
314
- backgroundColor: dockedBackgroundColor,
315
- }}
316
- />
317
- </AnimationComponent>
324
+ <View style={[bottomSpacerStyle, backgroundColorStyle]} />
325
+ </>
318
326
  );
319
327
  };
@@ -4,7 +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
7
 
9
8
  import { MOBILE, NAVBAR_HEIGHT } from "./const";
10
9
  import { TransportInfo } from "./TransportInfo";
@@ -12,13 +11,12 @@ import { PlayerImage } from "./PlayerImage";
12
11
  import { Controls } from "./Controls";
13
12
 
14
13
  import { useMobileLayoutImageSize, useTransportInfoHeight } from "./hooks";
15
- import { DockedControls } from "./DockedControls";
16
14
  import { DEBUG, withDebug } from "./debug";
17
15
  import {
18
16
  BottomDebugSquare,
19
17
  LeftDebugSquare,
20
18
  RightDebugSquare,
21
- } from "./Debug/index";
19
+ } from "./DebugComponent";
22
20
 
23
21
  import { Props } from "./types";
24
22
 
@@ -56,6 +54,7 @@ const mobileStyles = ({
56
54
  imageSize,
57
55
  }): ViewStyle => ({
58
56
  height: screenHeight - topInset - bottomInset,
57
+ width: "100%",
59
58
 
60
59
  opacity: imageSize ? 1 : 0, // hide content until imageSize is calculated
61
60
 
@@ -77,11 +76,8 @@ export function MobileLayout({
77
76
  onSkipStart,
78
77
  onSkipLive,
79
78
  onSpeedButtonPress,
80
- onCloseVideoModal,
81
79
  playbackSpeedName,
82
80
  configuration,
83
- dimensions,
84
- playNextData,
85
81
  title,
86
82
  summary,
87
83
  }: Props) {
@@ -89,12 +85,10 @@ export function MobileLayout({
89
85
 
90
86
  const { bottom: bottomInset, top: topInset } = useSafeAreaInsets();
91
87
  const { height: screenHeight } = useSafeAreaFrame();
92
- const { progressBarHeight } = useModalAnimationContext();
93
88
 
94
89
  const { imageSize } = useMobileLayoutImageSize();
95
90
 
96
- const { height: transportInfoHeight, onLayout: onTransportInfoLayout } =
97
- useTransportInfoHeight();
91
+ const { onLayout: onTransportInfoLayout } = useTransportInfoHeight();
98
92
 
99
93
  const controlsContainerHeight = React.useMemo(() => {
100
94
  return (
@@ -108,10 +102,6 @@ export function MobileLayout({
108
102
  );
109
103
  }, [screenHeight, topInset, imageSize, bottomInset]);
110
104
 
111
- const verticalOffsetForImage = React.useMemo(() => {
112
- return transportInfoHeight + MOBILE.MARGIN_TOP - progressBarHeight;
113
- }, [transportInfoHeight, progressBarHeight]);
114
-
115
105
  return (
116
106
  <View
117
107
  style={[
@@ -161,22 +151,7 @@ export function MobileLayout({
161
151
  },
162
152
  ]}
163
153
  >
164
- <PlayerImage
165
- entry={entry}
166
- layoutState={layoutState}
167
- playerState={playerState}
168
- value={value}
169
- configuration={configuration}
170
- onPlayerSeek={onPlayerSeek}
171
- onCloseVideoModal={onCloseVideoModal}
172
- dimensions={dimensions}
173
- playNextData={playNextData}
174
- title={title}
175
- summary={summary}
176
- docked={docked}
177
- imageWidth={imageSize}
178
- verticalOffset={verticalOffsetForImage}
179
- />
154
+ <PlayerImage entry={entry} configuration={configuration} />
180
155
  </View>
181
156
  {/* PlayerImage */}
182
157
 
@@ -204,19 +179,6 @@ export function MobileLayout({
204
179
  />
205
180
  </View>
206
181
  </View>
207
-
208
- <DockedControls
209
- entry={entry}
210
- layoutState={layoutState}
211
- playerState={playerState}
212
- value={value}
213
- dimensions={dimensions}
214
- onCloseVideoModal={onCloseVideoModal}
215
- onPlayerSeek={onPlayerSeek}
216
- playNextData={playNextData}
217
- title={title}
218
- summary={summary}
219
- />
220
182
  </View>
221
183
  );
222
184
  }
@@ -1,7 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { Image, ImageStyle } from "react-native";
3
-
4
- import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
3
+ import { useBackgroundImage } from "@applicaster/zapp-react-native-utils/audioPlayerUtils";
5
4
 
6
5
  type Props = {
7
6
  entry: ZappEntry;
@@ -9,12 +8,9 @@ type Props = {
9
8
  };
10
9
 
11
10
  export const FlexImage = ({ entry, style }: Props) => {
12
- const source = React.useMemo(
13
- () => ({ uri: imageSrcFromMediaItem(entry, undefined) }),
14
- [entry]
15
- );
11
+ const backgroundImageSource = useBackgroundImage(entry);
16
12
 
17
- if (!source) return null;
18
-
19
- return <Image resizeMode="cover" style={style} source={source} />;
13
+ return (
14
+ <Image resizeMode="cover" style={style} source={backgroundImageSource} />
15
+ );
20
16
  };
@@ -1,56 +1,24 @@
1
1
  import * as React from "react";
2
- import { LayoutChangeEvent, View } from "react-native";
2
+ import { Animated, LayoutChangeEvent, View } from "react-native";
3
3
 
4
- import {
5
- AnimationComponent,
6
- ComponentAnimationType,
7
- useModalAnimationContext,
8
- } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
9
4
  import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
10
5
  import { toBooleanWithDefaultTrue } from "@applicaster/zapp-react-native-utils/booleanUtils";
11
6
 
12
- import { AnimatedImage } from "./AnimatedImage";
13
7
  import { FlexImage } from "./FlexImage";
14
8
 
15
9
  import { styles } from "./styles";
16
- import { calculateBorderRadius } from "../../utils";
17
- import { PlayNextData } from "../types";
10
+ import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
11
+ import { useModalAnimationContext } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
18
12
 
19
13
  type Props = {
20
14
  entry: ZappEntry;
21
- layoutState: QuickBrickPlayer.LayoutState;
22
- playerState: QuickBrickPlayer.PlayerState;
23
- value: GetValue;
24
15
  configuration: QuickBrickPlayer.AudioPlayerProps["configuration"];
25
- dimensions: QuickBrickPlayer.AudioPlayerProps["dimensions"];
26
- onCloseVideoModal: Callback;
27
- onPlayerSeek: (targetTime: number) => void;
28
- playNextData: PlayNextData;
29
- title: string | number;
30
- summary: string | number;
31
- docked: boolean;
32
- imageWidth?: Option<number>;
33
- verticalOffset: number;
16
+ docked?: boolean;
34
17
  onLayoutImage?: (event: LayoutChangeEvent) => void;
35
18
  };
36
19
 
37
20
  export const PlayerImage = (props: Props) => {
38
- const {
39
- entry,
40
- dimensions,
41
- docked,
42
- verticalOffset,
43
- imageWidth,
44
- configuration,
45
- onLayoutImage = noop,
46
- } = props;
47
-
48
- const {
49
- isActiveGesture,
50
- startComponentsAnimation,
51
- playerAnimationState,
52
- minimisedHeight,
53
- } = useModalAnimationContext();
21
+ const { entry, docked = false, configuration, onLayoutImage = noop } = props;
54
22
 
55
23
  const isShadowEnabled = toBooleanWithDefaultTrue(
56
24
  configuration?.audio_player_artwork_shadow_enabled
@@ -58,55 +26,39 @@ export const PlayerImage = (props: Props) => {
58
26
 
59
27
  const shouldShowShadow = !docked && isShadowEnabled;
60
28
 
61
- const borderRadius = calculateBorderRadius(
62
- docked,
63
- startComponentsAnimation,
64
- isActiveGesture,
65
- playerAnimationState,
66
- configuration
29
+ const borderRadius = toNumberWithDefaultZero(
30
+ configuration.audio_player_artwork_border_radius
67
31
  );
68
32
 
33
+ const { yTranslate } = useModalAnimationContext();
34
+
35
+ const isModalExpanded = yTranslate.current.interpolate({
36
+ inputRange: [0, 1], // this should be end with `1` only when it's in initial state ( 0pos), otherwise `0`
37
+ outputRange: [1, 0],
38
+ });
39
+
40
+ // do not use styles.shadow when isModalExpanded is 0
41
+
42
+ const animatedStyle = {
43
+ opacity: isModalExpanded,
44
+ };
45
+
69
46
  return (
70
- <AnimationComponent
71
- animationType={ComponentAnimationType.moveUpComponent}
72
- additionalData={{
73
- marginTop: verticalOffset,
74
- }}
75
- style={styles.flex}
76
- >
77
- <AnimationComponent
78
- animationType={ComponentAnimationType.moveComponentHorizontal}
79
- additionalData={{
80
- // we move image horiontally to this value due artwork is centered
81
- moveValue: (dimensions.width - minimisedHeight) / 2,
82
- }}
83
- style={styles.alignItemsCenter}
47
+ <View style={styles.alignItemsCenter}>
48
+ {/* Using an Animated.View to apply shadow to the image */}
49
+ <Animated.View
50
+ style={[
51
+ animatedStyle,
52
+ shouldShowShadow ? styles.shadow : undefined,
53
+ { borderRadius },
54
+ ]}
55
+ />
56
+ <View
57
+ onLayout={onLayoutImage}
58
+ style={[styles.defaultImageWrapperView, { borderRadius }]}
84
59
  >
85
- <View
86
- onLayout={onLayoutImage}
87
- style={[
88
- shouldShowShadow ? styles.shadow : undefined,
89
- { borderRadius },
90
- ]}
91
- >
92
- {!imageWidth ? (
93
- <View style={[styles.defaultImageWrapperView, { borderRadius }]}>
94
- <FlexImage
95
- entry={entry}
96
- style={styles.backgroundImageContainer}
97
- />
98
- </View>
99
- ) : (
100
- // we have imageSize here and now we could animate resizing of this image
101
- <AnimatedImage
102
- entry={entry}
103
- style={[styles.backgroundImageContainer, { borderRadius }]}
104
- imageWidth={imageWidth}
105
- docked={docked}
106
- />
107
- )}
108
- </View>
109
- </AnimationComponent>
110
- </AnimationComponent>
60
+ <FlexImage entry={entry} style={styles.backgroundImageContainer} />
61
+ </View>
62
+ </View>
111
63
  );
112
64
  };
@@ -23,7 +23,12 @@ export const styles = StyleSheet.create({
23
23
  overflow: "hidden",
24
24
  },
25
25
  shadow: {
26
- borderColor: "transparent",
26
+ zIndex: 0,
27
+ position: "absolute",
28
+ top: 0,
29
+ left: 0,
30
+ right: 0,
31
+ bottom: 0,
27
32
  shadowColor: SHADOW_COLOR,
28
33
  shadowOffset: { width: 0, height: 24 },
29
34
  shadowOpacity: platformSelect({