@applicaster/quick-brick-player 14.0.0-alpha.3552323332 → 14.0.0-alpha.4009339136

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/quick-brick-player",
3
- "version": "14.0.0-alpha.3552323332",
3
+ "version": "14.0.0-alpha.4009339136",
4
4
  "description": "Quick Brick Player",
5
5
  "main": "./src/index.ts",
6
6
  "types": "index.d.ts",
@@ -35,11 +35,11 @@
35
35
  },
36
36
  "homepage": "https://github.com/applicaster/quickbrick#readme",
37
37
  "dependencies": {
38
- "@applicaster/quick-brick-mobile-transport-controls": "14.0.0-alpha.3552323332",
39
- "@applicaster/quick-brick-tv-transport-controls": "14.0.0-rc.7",
40
- "@applicaster/zapp-react-native-tvos-app": "14.0.0-alpha.3552323332",
41
- "@applicaster/zapp-react-native-ui-components": "14.0.0-alpha.3552323332",
42
- "@applicaster/zapp-react-native-utils": "14.0.0-alpha.3552323332",
38
+ "@applicaster/quick-brick-mobile-transport-controls": "14.0.0-rc.25",
39
+ "@applicaster/quick-brick-tv-transport-controls": "14.0.0-rc.13",
40
+ "@applicaster/zapp-react-native-tvos-app": "14.0.0-alpha.4009339136",
41
+ "@applicaster/zapp-react-native-ui-components": "14.0.0-alpha.4009339136",
42
+ "@applicaster/zapp-react-native-utils": "14.0.0-alpha.4009339136",
43
43
  "query-string": "7.1.3",
44
44
  "react-native-web-linear-gradient": "1.1.2",
45
45
  "shaka-player": "4.3.5",
@@ -1,6 +1,11 @@
1
1
  import * as React from "react";
2
2
  import { useEffect, useState } from "react";
3
- import { StyleSheet, View, ViewStyle } from "react-native";
3
+ import {
4
+ Dimensions as ScreenDimensions,
5
+ StyleSheet,
6
+ View,
7
+ ViewStyle,
8
+ } from "react-native";
4
9
 
5
10
  import { Edge, SafeAreaView } from "react-native-safe-area-context";
6
11
  import { usePlayerState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerState";
@@ -8,9 +13,14 @@ import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerM
8
13
  import * as R from "ramda";
9
14
  import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
10
15
  import Layout from "./Layout";
11
- import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
16
+ import {
17
+ useIsTablet,
18
+ useNavigation,
19
+ } from "@applicaster/zapp-react-native-utils/reactHooks";
12
20
  import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
13
21
  import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
22
+ import { PlayerDetails } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/PlayerDetails";
23
+ import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
14
24
  import { formatSpeed } from "./utils";
15
25
  import {
16
26
  getBottomSheetModalDefaultItemIcon,
@@ -20,7 +30,12 @@ import {
20
30
  getBottomSheetModalSelectedItemIcon,
21
31
  } from "../Utils";
22
32
  import { useTitleSummaryOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerTitleSummaryOverlay";
23
-
33
+ import {
34
+ AnimatedScrollModal,
35
+ AnimationComponent,
36
+ ComponentAnimationType,
37
+ } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
38
+ import { PADDING_HORIZONTAL } from "./Layout/const";
24
39
  import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
25
40
 
26
41
  import { DEFAULT_SPEED, PlaybackSpeed, SpeedController } from "./SpeedManager";
@@ -66,10 +81,18 @@ type Props = {
66
81
  isTabletPortrait?: boolean;
67
82
  };
68
83
 
84
+ const { width: SCREEN_WIDTH } = ScreenDimensions.get("screen");
85
+
69
86
  const Styles = StyleSheet.create({
70
87
  playerContainer: {
71
88
  flex: 1,
72
89
  },
90
+ paddingHorizontal: { paddingTop: 0, paddingHorizontal: PADDING_HORIZONTAL },
91
+ playerDetails: {
92
+ marginTop: 60,
93
+ alignSelf: "center",
94
+ width: SCREEN_WIDTH - PADDING_HORIZONTAL * 2,
95
+ },
73
96
  });
74
97
 
75
98
  const edges: Edge[] = ["right", "left", "top"];
@@ -84,10 +107,16 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
84
107
  configuration,
85
108
  style,
86
109
  entry,
110
+ children,
87
111
  layoutState,
88
112
  playNextData = null,
113
+ isTabletPortrait,
89
114
  } = props;
90
115
 
116
+ const isTablet = useIsTablet();
117
+
118
+ const isTabletLandscape = !isTV() && isTablet && !isTabletPortrait;
119
+
91
120
  const { title, summary } = useTitleSummaryOverlay(
92
121
  entry,
93
122
  playerState?.isLive,
@@ -235,6 +264,10 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
235
264
  });
236
265
  }, [playbackSpeed, onSpeedSelect, configuration["playback_speed_title"]]);
237
266
 
267
+ const onCloseVideoModal = React.useCallback(() => {
268
+ playerManager.close();
269
+ }, [playerManager]);
270
+
238
271
  const onPlayerSeek = React.useCallback(
239
272
  (targetTime: number) => {
240
273
  player?.seekTo(targetTime);
@@ -252,28 +285,51 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
252
285
 
253
286
  return (
254
287
  <SafeAreaView style={[style, Styles.playerContainer]} edges={edges}>
255
- <View style={Styles.playerContainer} onLayout={onLayout}>
256
- <Layout
257
- entry={entry}
258
- playerState={playerState}
259
- layoutState={layoutState}
260
- value={value}
261
- onPlaybackButtonPress={onPlaybackButtonPress}
262
- onRewindButtonPress={onRewindButtonPress}
263
- onForwardButtonPress={onForwardButtonPress}
264
- onPlayerSeek={onPlayerSeek}
265
- onSkipStart={onSkipStart}
266
- onSpeedButtonPress={onSpeedButtonPress}
267
- playbackSpeedName={formatSpeed(playbackSpeed.value)}
268
- onSkipLive={onSkipLive}
269
- maximiseVideoModal={maximiseVideoModal}
270
- configuration={configuration}
271
- dimensions={dimensions}
272
- playNextData={playNextData}
273
- title={title}
274
- summary={summary}
275
- />
276
- </View>
288
+ <AnimationComponent
289
+ animationType={ComponentAnimationType.moveUpComponent}
290
+ additionalData={{ saveArea: true }}
291
+ style={Styles.playerContainer}
292
+ >
293
+ <AnimatedScrollModal>
294
+ <View style={Styles.playerContainer} onLayout={onLayout}>
295
+ <Layout
296
+ entry={entry}
297
+ playerState={playerState}
298
+ layoutState={layoutState}
299
+ value={value}
300
+ onPlaybackButtonPress={onPlaybackButtonPress}
301
+ onRewindButtonPress={onRewindButtonPress}
302
+ onForwardButtonPress={onForwardButtonPress}
303
+ onPlayerSeek={onPlayerSeek}
304
+ onSkipStart={onSkipStart}
305
+ onSpeedButtonPress={onSpeedButtonPress}
306
+ playbackSpeedName={formatSpeed(playbackSpeed.value)}
307
+ onSkipLive={onSkipLive}
308
+ onCloseVideoModal={onCloseVideoModal}
309
+ maximiseVideoModal={maximiseVideoModal}
310
+ configuration={configuration}
311
+ dimensions={dimensions}
312
+ playNextData={playNextData}
313
+ title={title}
314
+ summary={summary}
315
+ />
316
+ <View style={Styles.paddingHorizontal}>
317
+ {children}
318
+ <AnimationComponent
319
+ animationType={ComponentAnimationType.componentFade}
320
+ >
321
+ <PlayerDetails
322
+ isAudioPlayer
323
+ configuration={configuration}
324
+ style={Styles.playerDetails}
325
+ entry={entry}
326
+ isTabletLandscape={isTabletLandscape}
327
+ />
328
+ </AnimationComponent>
329
+ </View>
330
+ </View>
331
+ </AnimatedScrollModal>
332
+ </AnimationComponent>
277
333
  </SafeAreaView>
278
334
  );
279
335
  };
@@ -1,11 +1,12 @@
1
1
  import * as React from "react";
2
- import { StyleSheet, View, ViewStyle } from "react-native";
3
- import * as R from "ramda";
4
2
  import {
5
- useIsTablet,
6
- useZStore,
7
- } from "@applicaster/zapp-react-native-utils/reactHooks";
8
- import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
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";
9
10
 
10
11
  import {
11
12
  Button,
@@ -16,12 +17,15 @@ import {
16
17
 
17
18
  import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
18
19
 
20
+ import {
21
+ AnimationComponent,
22
+ ComponentAnimationType,
23
+ PlayerAnimationStateEnum,
24
+ useModalAnimationContext,
25
+ } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
19
26
  import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
20
27
  import { useSafeAreaInsets } from "react-native-safe-area-context";
21
28
  import { getTabBarHeight } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/getTabBarHeight";
22
- import { useTitleSummaryOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerTitleSummaryOverlay";
23
- import { usePlayerState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerState";
24
- import { useConfiguration } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/utils";
25
29
 
26
30
  const bottomTabBarHeight = getTabBarHeight();
27
31
 
@@ -30,16 +34,13 @@ type Props = {
30
34
  layoutState: QuickBrickPlayer.LayoutState;
31
35
  playerState: QuickBrickPlayer.PlayerState;
32
36
  value: GetValue;
37
+ dimensions: QuickBrickPlayer.AudioPlayerProps["dimensions"];
33
38
  onCloseVideoModal: () => void;
34
39
  onPlayerSeek: (targetTime: number) => void;
35
40
  playNextData: PlayNextData;
36
41
  title: string | number;
37
42
  summary: string | number;
38
43
  ImageComponent?: React.ReactNode;
39
- isActiveGesture?: boolean;
40
- minimisedHeight: number;
41
- progressBarHeight: number;
42
- aspectRatio?: number;
43
44
  };
44
45
 
45
46
  const styles = StyleSheet.create({
@@ -47,7 +48,6 @@ const styles = StyleSheet.create({
47
48
  flex: 1,
48
49
  flexDirection: "column",
49
50
  alignItems: "stretch",
50
- marginTop: 3, // from plugins/mobile-transport-controls/src/ProgressBar/layouts/DockedLayout.tsx
51
51
  },
52
52
  content: {
53
53
  flex: 1,
@@ -99,6 +99,26 @@ const playerDimensionsStyle = (
99
99
  width: addPadding ? toNumberWithDefault(100, minimisedHeight) : 0,
100
100
  });
101
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
+ });
121
+
102
122
  const controlButtons = (
103
123
  live: boolean,
104
124
  paused: boolean,
@@ -160,74 +180,58 @@ export const DockedControls = (props: Props) => {
160
180
  const {
161
181
  entry,
162
182
  layoutState,
183
+ playerState,
184
+ value,
185
+ dimensions,
186
+ onCloseVideoModal,
163
187
  onPlayerSeek,
164
188
  playNextData,
189
+ title,
190
+ summary,
165
191
  ImageComponent,
166
- isActiveGesture = true,
167
- aspectRatio,
168
192
  } = props;
169
193
 
170
- const onCloseVideoModal = React.useCallback(() => {
171
- playerManager.close();
172
- }, []);
173
-
174
- const { minimised_height: minimisedHeight } = useConfiguration();
175
-
176
- const configuration = useZStore("playerConfiguration")();
177
- const playerState = usePlayerState("shared-player-wrapper-docked");
178
-
179
- const getValue = (key: string, stylesObj: {}) =>
180
- R.propOr(null, key, stylesObj);
181
-
182
- const value = React.useCallback(
183
- (key: string) => {
184
- const retVal = getValue(key, configuration);
185
-
186
- const minimumAllowedSeekableDurationInSeconds = getValue(
187
- "minimumAllowedSeekableDurationInSeconds",
188
- configuration
189
- );
190
-
191
- if (key === "liveSeekingEnabled") {
192
- return playerState.seekableDuration <
193
- minimumAllowedSeekableDurationInSeconds || playerManager.isCasting()
194
- ? false
195
- : retVal;
196
- }
197
-
198
- return retVal;
199
- },
200
- [...Object.values(configuration), playerState]
201
- );
202
-
203
- const { title, summary } = useTitleSummaryOverlay(
204
- entry,
205
- playerState?.isLive,
206
- configuration?.audio_live_player_update_interval
207
- );
208
-
209
194
  const isTablet = useIsTablet();
210
195
 
211
196
  const liveButton = Boolean(value("live_badge_enabled"));
212
197
 
213
- const startComponentsAnimation = () => {};
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
+ []
209
+ );
214
210
 
215
211
  const dockedBackgroundColor = value("docked_player_background_color");
216
212
 
217
213
  const insets = useSafeAreaInsets();
218
214
 
215
+ if (!layoutState.docked && !startComponentsAnimation) return null;
216
+
219
217
  return (
220
- <View
218
+ <AnimationComponent
219
+ animationType={ComponentAnimationType.componentAppears}
221
220
  style={[
222
221
  styles.container,
222
+ animatedContainerStyle(
223
+ isActiveGesture || layoutState.docked,
224
+ progressBarHeight
225
+ ),
223
226
  {
224
227
  height: minimisedHeight + bottomTabBarHeight + insets.bottom,
225
228
  },
226
229
  ]}
227
230
  >
228
- {!playerState.isLive ? (
231
+ {!playerState.isLive &&
232
+ (layoutState.docked || startComponentsAnimation) ? (
229
233
  <ProgressBar
230
- name={"shared-docked-layout"}
234
+ name={"audio-docked-layout"}
231
235
  content={entry}
232
236
  value={value}
233
237
  visible
@@ -240,33 +244,43 @@ export const DockedControls = (props: Props) => {
240
244
  ) : null}
241
245
 
242
246
  <View style={styles.content}>
243
- <View style={styles.touchableArea}>
244
- {isActiveGesture || layoutState.docked ? (
245
- <View style={{ aspectRatio: aspectRatio, height: minimisedHeight }}>
246
- {ImageComponent || null}
247
- </View>
248
- ) : (
249
- <View
250
- style={playerDimensionsStyle(
251
- minimisedHeight,
252
- isActiveGesture || layoutState.docked
253
- )}
254
- />
247
+ <View
248
+ style={backgroundImageStyle(
249
+ dimensions,
250
+ minimisedHeight,
251
+ isActiveGesture
255
252
  )}
256
- <View
257
- testID="content-info"
258
- style={[
259
- styles.contentInfo,
260
- { backgroundColor: dockedBackgroundColor },
261
- ]}
262
- >
263
- <ContentInfo
264
- content={{ ...entry, title, summary }}
265
- value={value}
266
- docked
267
- />
253
+ />
254
+ <TouchableWithoutFeedback onPress={maximazeVideoModal}>
255
+ <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
+ )}
270
+ <View
271
+ style={[
272
+ styles.contentInfo,
273
+ { backgroundColor: dockedBackgroundColor },
274
+ ]}
275
+ >
276
+ <ContentInfo
277
+ content={{ ...entry, title, summary }}
278
+ value={value}
279
+ docked
280
+ />
281
+ </View>
268
282
  </View>
269
- </View>
283
+ </TouchableWithoutFeedback>
270
284
  <View
271
285
  style={[
272
286
  isTablet
@@ -300,6 +314,6 @@ export const DockedControls = (props: Props) => {
300
314
  backgroundColor: dockedBackgroundColor,
301
315
  }}
302
316
  />
303
- </View>
317
+ </AnimationComponent>
304
318
  );
305
319
  };
@@ -12,6 +12,7 @@ import { PlayerImage } from "./PlayerImage";
12
12
  import { Controls } from "./Controls";
13
13
 
14
14
  import { useMobileLayoutImageSize, useTransportInfoHeight } from "./hooks";
15
+ import { DockedControls } from "./DockedControls";
15
16
  import { DEBUG, withDebug } from "./debug";
16
17
  import {
17
18
  BottomDebugSquare,
@@ -55,7 +56,6 @@ const mobileStyles = ({
55
56
  imageSize,
56
57
  }): ViewStyle => ({
57
58
  height: screenHeight - topInset - bottomInset,
58
- width: "100%",
59
59
 
60
60
  opacity: imageSize ? 1 : 0, // hide content until imageSize is calculated
61
61
 
@@ -77,6 +77,7 @@ export function MobileLayout({
77
77
  onSkipStart,
78
78
  onSkipLive,
79
79
  onSpeedButtonPress,
80
+ onCloseVideoModal,
80
81
  playbackSpeedName,
81
82
  configuration,
82
83
  dimensions,
@@ -167,6 +168,7 @@ export function MobileLayout({
167
168
  value={value}
168
169
  configuration={configuration}
169
170
  onPlayerSeek={onPlayerSeek}
171
+ onCloseVideoModal={onCloseVideoModal}
170
172
  dimensions={dimensions}
171
173
  playNextData={playNextData}
172
174
  title={title}
@@ -202,6 +204,19 @@ export function MobileLayout({
202
204
  />
203
205
  </View>
204
206
  </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
+ />
205
220
  </View>
206
221
  );
207
222
  }
@@ -1,7 +1,16 @@
1
1
  import React, { PropsWithChildren } from "react";
2
2
  import { Image, Animated, StyleSheet, ImageStyle } from "react-native";
3
3
 
4
- import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
4
+ import {
5
+ useModalAnimationContext,
6
+ PlayerAnimationStateEnum,
7
+ DURATION_TO_MINIMIZE,
8
+ DURATION_TO_MAXIMIZE,
9
+ } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
10
+ import { PlayerAnimationStateT } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/ModalAnimationContext";
11
+ import { useBackgroundImage } from "@applicaster/zapp-react-native-utils/audioPlayerUtils";
12
+
13
+ import { useChangePlayerState } from "./hooks";
5
14
 
6
15
  const styles = StyleSheet.create({
7
16
  container: {
@@ -15,17 +24,48 @@ type Props = PropsWithChildren<{
15
24
  entry: ZappEntry;
16
25
  style?: ImageStyle | ImageStyle[];
17
26
  imageWidth: number;
27
+ docked: boolean;
18
28
  }>;
19
29
 
20
- export const AnimatedImage = ({ entry, style, imageWidth }: Props) => {
30
+ export const AnimatedImage = ({ entry, style, imageWidth, docked }: Props) => {
21
31
  const heightAnim = React.useRef(new Animated.Value(imageWidth)).current;
22
32
 
23
- const source = React.useMemo(
24
- () => ({ uri: imageSrcFromMediaItem(entry, undefined) }),
25
- [entry]
26
- );
33
+ const backgroundImageSource = useBackgroundImage(entry);
34
+
35
+ const { minimisedHeight } = useModalAnimationContext();
36
+
37
+ const changePlayerState$ = useChangePlayerState({ docked });
38
+
39
+ React.useEffect(() => {
40
+ const subscription = changePlayerState$.subscribe({
41
+ next: (nextPlayerState: PlayerAnimationStateT) => {
42
+ if (nextPlayerState === PlayerAnimationStateEnum.minimize) {
43
+ Animated.timing(heightAnim, {
44
+ toValue: minimisedHeight,
45
+ duration: DURATION_TO_MINIMIZE,
46
+ useNativeDriver: false, // width/height can't use native driver
47
+ }).start();
48
+ }
49
+
50
+ if (nextPlayerState === PlayerAnimationStateEnum.maximize) {
51
+ Animated.timing(heightAnim, {
52
+ toValue: imageWidth,
53
+ duration: DURATION_TO_MAXIMIZE,
54
+ useNativeDriver: false, // width/height can't use native driver
55
+ }).start();
56
+ }
57
+
58
+ if (nextPlayerState === PlayerAnimationStateEnum.appear_as_docked) {
59
+ // minimize image immediatly
60
+ heightAnim.setValue(minimisedHeight);
61
+ }
62
+ },
63
+ });
27
64
 
28
- if (!source) return null;
65
+ return () => {
66
+ subscription.unsubscribe();
67
+ };
68
+ }, [changePlayerState$, minimisedHeight, imageWidth]);
29
69
 
30
70
  return (
31
71
  <Animated.View
@@ -36,7 +76,7 @@ export const AnimatedImage = ({ entry, style, imageWidth }: Props) => {
36
76
  },
37
77
  ]}
38
78
  >
39
- <Image resizeMode="cover" style={style} source={source} />
79
+ <Image resizeMode="cover" style={style} source={backgroundImageSource} />
40
80
  </Animated.View>
41
81
  );
42
82
  };
@@ -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
  };