@applicaster/quick-brick-player 14.0.0-alpha.5431459455 → 14.0.0-alpha.5533663133

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.5431459455",
3
+ "version": "14.0.0-alpha.5533663133",
4
4
  "description": "Quick Brick Player",
5
5
  "main": "./src/index.ts",
6
6
  "types": "index.d.ts",
@@ -35,13 +35,12 @@
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.5431459455",
39
- "@applicaster/quick-brick-tv-transport-controls": "14.0.0-rc.7",
40
- "@applicaster/zapp-react-native-tvos-app": "14.0.0-alpha.5431459455",
41
- "@applicaster/zapp-react-native-ui-components": "14.0.0-alpha.5431459455",
42
- "@applicaster/zapp-react-native-utils": "14.0.0-alpha.5431459455",
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.5533663133",
41
+ "@applicaster/zapp-react-native-ui-components": "14.0.0-alpha.5533663133",
42
+ "@applicaster/zapp-react-native-utils": "14.0.0-alpha.5533663133",
43
43
  "query-string": "7.1.3",
44
- "react-native-web-linear-gradient": "1.1.2",
45
44
  "shaka-player": "4.3.5",
46
45
  "typeface-montserrat": "^0.0.54",
47
46
  "video.js": "7.14.3",
@@ -62,11 +61,9 @@
62
61
  "react": "*",
63
62
  "react-native": "*",
64
63
  "react-native-fs": "*",
65
- "react-native-gesture-handler": "*",
66
64
  "react-native-linear-gradient": "*",
67
65
  "react-native-safe-area-context": "*",
68
66
  "react-native-svg": "*",
69
- "react-native-web": "*",
70
67
  "react-native-webview": "*",
71
68
  "uglify-js": "*",
72
69
  "validate-color": "*",
@@ -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,13 +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
- import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
26
29
 
27
30
  const bottomTabBarHeight = getTabBarHeight();
28
31
 
@@ -31,15 +34,13 @@ type Props = {
31
34
  layoutState: QuickBrickPlayer.LayoutState;
32
35
  playerState: QuickBrickPlayer.PlayerState;
33
36
  value: GetValue;
37
+ dimensions: QuickBrickPlayer.AudioPlayerProps["dimensions"];
34
38
  onCloseVideoModal: () => void;
35
39
  onPlayerSeek: (targetTime: number) => void;
36
40
  playNextData: PlayNextData;
37
41
  title: string | number;
38
42
  summary: string | number;
39
43
  ImageComponent?: React.ReactNode;
40
- isActiveGesture?: boolean;
41
- minimisedHeight: 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,111 +180,107 @@ export const DockedControls = (props: Props) => {
160
180
  const {
161
181
  entry,
162
182
  layoutState,
163
- onPlayerSeek = noop,
183
+ playerState,
184
+ value,
185
+ dimensions,
186
+ onCloseVideoModal,
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
- );
194
+ const isTablet = useIsTablet();
190
195
 
191
- if (key === "liveSeekingEnabled") {
192
- return playerState.seekableDuration <
193
- minimumAllowedSeekableDurationInSeconds || playerManager.isCasting()
194
- ? false
195
- : retVal;
196
- }
196
+ const liveButton = Boolean(value("live_badge_enabled"));
197
197
 
198
- return retVal;
199
- },
200
- [...Object.values(configuration), playerState]
201
- );
198
+ const {
199
+ isActiveGesture,
200
+ setPlayerAnimationState,
201
+ startComponentsAnimation,
202
+ minimisedHeight,
203
+ progressBarHeight,
204
+ } = useModalAnimationContext();
202
205
 
203
- const { title, summary } = useTitleSummaryOverlay(
204
- entry,
205
- playerState?.isLive,
206
- configuration?.audio_live_player_update_interval
206
+ const maximazeVideoModal = React.useCallback(
207
+ () => setPlayerAnimationState(PlayerAnimationStateEnum.maximize),
208
+ []
207
209
  );
208
210
 
209
- const isTablet = useIsTablet();
210
-
211
- const liveButton = Boolean(value("live_badge_enabled"));
212
-
213
211
  const dockedBackgroundColor = value("docked_player_background_color");
214
212
 
215
213
  const insets = useSafeAreaInsets();
216
214
 
215
+ if (!layoutState.docked && !startComponentsAnimation) return null;
216
+
217
217
  return (
218
- <View
218
+ <AnimationComponent
219
+ animationType={ComponentAnimationType.componentAppears}
219
220
  style={[
220
221
  styles.container,
222
+ animatedContainerStyle(
223
+ isActiveGesture || layoutState.docked,
224
+ progressBarHeight
225
+ ),
221
226
  {
222
227
  height: minimisedHeight + bottomTabBarHeight + insets.bottom,
223
228
  },
224
229
  ]}
225
230
  >
226
- {!playerState.isLive ? (
231
+ {!playerState.isLive &&
232
+ (layoutState.docked || startComponentsAnimation) ? (
227
233
  <ProgressBar
228
- name={"shared-docked-layout"}
234
+ name={"audio-docked-layout"}
229
235
  content={entry}
230
236
  value={value}
231
237
  visible
232
238
  layoutState={layoutState}
233
239
  onPlayerSeek={onPlayerSeek}
234
240
  playerState={playerState}
235
- startComponentsAnimation={noop}
241
+ startComponentsAnimation={startComponentsAnimation}
236
242
  docked
237
243
  />
238
244
  ) : null}
239
245
 
240
246
  <View style={styles.content}>
241
- <View style={styles.touchableArea}>
242
- {isActiveGesture || layoutState.docked ? (
243
- <View style={{ aspectRatio: aspectRatio, height: minimisedHeight }}>
244
- {ImageComponent || null}
245
- </View>
246
- ) : (
247
- <View
248
- style={playerDimensionsStyle(
249
- minimisedHeight,
250
- isActiveGesture || layoutState.docked
251
- )}
252
- />
247
+ <View
248
+ style={backgroundImageStyle(
249
+ dimensions,
250
+ minimisedHeight,
251
+ isActiveGesture
253
252
  )}
254
- <View
255
- testID="content-info"
256
- style={[
257
- styles.contentInfo,
258
- { backgroundColor: dockedBackgroundColor },
259
- ]}
260
- >
261
- <ContentInfo
262
- content={{ ...entry, title, summary }}
263
- value={value}
264
- docked
265
- />
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>
266
282
  </View>
267
- </View>
283
+ </TouchableWithoutFeedback>
268
284
  <View
269
285
  style={[
270
286
  isTablet
@@ -298,6 +314,6 @@ export const DockedControls = (props: Props) => {
298
314
  backgroundColor: dockedBackgroundColor,
299
315
  }}
300
316
  />
301
- </View>
317
+ </AnimationComponent>
302
318
  );
303
319
  };
@@ -12,12 +12,13 @@ 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,
18
19
  LeftDebugSquare,
19
20
  RightDebugSquare,
20
- } from "./Debug/index";
21
+ } from "./DebugComponent";
21
22
 
22
23
  import { Props } from "./types";
23
24
 
@@ -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
  };