@applicaster/quick-brick-player 13.0.0-rc.99 → 13.0.0

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 (34) hide show
  1. package/package.json +6 -7
  2. package/src/Player/AudioLayer/AudioDescription.tsx +109 -68
  3. package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +81 -189
  4. package/src/Player/AudioLayer/Layout/Controls/VerticalGutter.tsx +23 -5
  5. package/src/Player/AudioLayer/Layout/Controls/index.tsx +24 -49
  6. package/src/Player/AudioLayer/Layout/Controls/utils.ts +2 -2
  7. package/src/Player/AudioLayer/Layout/DockedControls/index.tsx +38 -19
  8. package/src/Player/AudioLayer/Layout/MobileLayout.tsx +4 -13
  9. package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +39 -40
  10. package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +6 -22
  11. package/src/Player/AudioLayer/Layout/PlayerImage/hooks/index.ts +1 -0
  12. package/src/Player/AudioLayer/Layout/PlayerImage/hooks/useChangePlayerState.ts +99 -0
  13. package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +37 -20
  14. package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +19 -0
  15. package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +101 -105
  16. package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +2 -11
  17. package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +19 -5
  18. package/src/Player/AudioLayer/Layout/const.ts +4 -0
  19. package/src/Player/AudioLayer/Layout/hooks/useTransportInfoHeight.ts +1 -1
  20. package/src/Player/AudioLayer/Layout/utils.ts +7 -0
  21. package/src/Player/AudioLayer/SleepTimerManager.ts +22 -11
  22. package/src/Player/AudioLayer/components/SleepTimerModalHeader/SleepTimerModalHeader.tsx +66 -0
  23. package/src/Player/AudioLayer/components/SleepTimerModalHeader/index.ts +1 -0
  24. package/src/Player/AudioLayer/useSleepTimerModal.ts +109 -0
  25. package/src/Player/Const/sleepTimerOptions.ts +7 -5
  26. package/src/Player/Utils/index.tsx +6 -0
  27. package/src/Player/hooks/useIsCasting.tsx +57 -0
  28. package/src/Player/index.tsx +84 -37
  29. package/src/QuickBrickPlayer.tsx +3 -0
  30. package/src/Player/AudioLayer/LinearGradient/LinearGradientProxy.ts +0 -3
  31. package/src/Player/AudioLayer/LinearGradient/LinearGradientProxy.web.ts +0 -3
  32. package/src/Player/AudioLayer/LinearGradient/index.ts +0 -1
  33. package/src/Player/AudioLayer/MagicBG/index.tsx +0 -155
  34. package/src/utils/utils.ts +0 -25
@@ -2,7 +2,10 @@ import * as React from "react";
2
2
  import { StyleSheet } from "react-native";
3
3
 
4
4
  import { dayjs } from "@applicaster/zapp-react-native-utils/dateUtils";
5
- import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
5
+ import {
6
+ useIsTablet,
7
+ useZStore,
8
+ } from "@applicaster/zapp-react-native-utils/reactHooks";
6
9
  import {
7
10
  Controls as MobileTransportControls,
8
11
  ProgressBar,
@@ -27,6 +30,7 @@ import {
27
30
  sleepButton,
28
31
  speedButton,
29
32
  } from "./utils";
33
+ import { useSleepTimerModal } from "../../useSleepTimerModal";
30
34
 
31
35
  const styles = StyleSheet.create({
32
36
  flex: {
@@ -64,11 +68,8 @@ type Props = {
64
68
  value: GetValue;
65
69
  title: string | number;
66
70
  summary: string | number;
67
- sleepTimerDate: number;
68
- cancelSleepTimer: Callback;
69
71
 
70
72
  playbackSpeedName: string;
71
- playbackSleepName: string;
72
73
 
73
74
  onPlaybackButtonPress: Callback;
74
75
  onRewindButtonPress: Callback;
@@ -77,7 +78,8 @@ type Props = {
77
78
  onSkipStart: Callback;
78
79
  onSkipLive: Callback;
79
80
  onSpeedButtonPress: Callback;
80
- onSleepButtonPress: Callback;
81
+
82
+ maxWidth?: number;
81
83
 
82
84
  docked: boolean;
83
85
  };
@@ -90,11 +92,8 @@ export const Controls = (props: Props) => {
90
92
  value,
91
93
  title,
92
94
  summary,
93
- sleepTimerDate,
94
- cancelSleepTimer,
95
95
 
96
96
  playbackSpeedName,
97
- playbackSleepName,
98
97
 
99
98
  onPlaybackButtonPress,
100
99
  onRewindButtonPress,
@@ -103,11 +102,26 @@ export const Controls = (props: Props) => {
103
102
  onSkipStart,
104
103
  onSkipLive,
105
104
  onSpeedButtonPress,
106
- onSleepButtonPress,
105
+ maxWidth = 320,
107
106
 
108
107
  docked,
109
108
  } = props;
110
109
 
110
+ const configuration = useZStore("playerConfiguration");
111
+
112
+ const { sleepTimerState, onSleepButtonPress } = useSleepTimerModal(
113
+ playerManager.getActivePlayer(),
114
+ configuration
115
+ );
116
+
117
+ const timerRemaining =
118
+ sleepTimerState.timerDate !== 0 && +sleepTimerState.timerDate > Date.now()
119
+ ? sleepTimerState.timerDate
120
+ : null;
121
+
122
+ const playbackSleepName =
123
+ timerRemaining === null ? "sleep_timer" : "sleep_timer_active";
124
+
111
125
  const isTablet = useIsTablet();
112
126
  const controller = playerManager.getActivePlayer();
113
127
  let showFullControls = !controller?.isAd();
@@ -121,45 +135,6 @@ export const Controls = (props: Props) => {
121
135
  showFullControls = !!(controller?.hasSeekableDuration?.() && seekEnabled);
122
136
  }
123
137
 
124
- const [timeLeft, setTimeLeft] = React.useState(
125
- sleepTimerDate !== 0 ? sleepTimerDate - Date.now() : 0
126
- );
127
-
128
- const showCounter = React.useMemo(() => sleepTimerDate > 0, [sleepTimerDate]);
129
-
130
- const countDownOptions = React.useMemo(() => {
131
- return {
132
- showCounter: showCounter && timeLeft >= 0,
133
- timeLeft,
134
- };
135
- }, [showCounter, timeLeft]);
136
-
137
- React.useEffect(() => {
138
- if (showCounter && sleepTimerDate !== 0) {
139
- setTimeLeft(sleepTimerDate - Date.now());
140
-
141
- const intervalId = setInterval(() => {
142
- setTimeLeft(() => {
143
- const newTimeLeft = sleepTimerDate - Date.now();
144
-
145
- if (newTimeLeft <= 0) {
146
- clearInterval(intervalId);
147
-
148
- cancelSleepTimer();
149
-
150
- return 0;
151
- } else {
152
- return newTimeLeft;
153
- }
154
- });
155
- }, 1000);
156
-
157
- return () => clearInterval(intervalId);
158
- } else {
159
- setTimeLeft(0);
160
- }
161
- }, [sleepTimerDate, showCounter, cancelSleepTimer]);
162
-
163
138
  const startTime = entry.extensions?.live?.start_time;
164
139
  const endTime = entry.extensions?.live?.end_time;
165
140
 
@@ -270,6 +245,7 @@ export const Controls = (props: Props) => {
270
245
  summary={summary}
271
246
  value={value}
272
247
  layoutState={layoutState}
248
+ maxWidth={maxWidth}
273
249
  />
274
250
 
275
251
  <VerticalGutter />
@@ -291,7 +267,6 @@ export const Controls = (props: Props) => {
291
267
  isDateBasedLiveContent={isDateBasedLiveContent}
292
268
  onSkipLive={onSkipLive}
293
269
  progressBarStyles={styles.progressBar}
294
- countDownOptions={countDownOptions}
295
270
  thumbStyles={styles.progressBarThumbStyles}
296
271
  thumbStylesPressed={styles.progressBarThumbStyles_pressed}
297
272
  trackStyles={styles.progressBarTrackStyles}
@@ -99,7 +99,7 @@ export const skipToLiveButton = (props: ButtonsProps): ControlsButton =>
99
99
  skipButtonByName({ ...props, name: "skip_live" });
100
100
 
101
101
  export const speedButton = (props: ButtonsProps): ControlsButton =>
102
- speedButtonByName({ ...props });
102
+ speedButtonByName(props);
103
103
 
104
104
  export const sleepButton = (props: ButtonsProps): ControlsButton =>
105
- sleepButtonByName({ ...props });
105
+ sleepButtonByName(props);
@@ -24,19 +24,23 @@ import {
24
24
  useModalAnimationContext,
25
25
  } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
26
26
  import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
27
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
28
+ import { getTabBarHeight } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/getTabBarHeight";
29
+
30
+ const bottomTabBarHeight = getTabBarHeight();
27
31
 
28
32
  type Props = {
29
33
  entry: ZappEntry;
30
34
  layoutState: QuickBrickPlayer.LayoutState;
31
35
  playerState: QuickBrickPlayer.PlayerState;
32
36
  value: GetValue;
33
- configuration: QuickBrickPlayer.AudioPlayerProps["configuration"];
34
37
  dimensions: QuickBrickPlayer.AudioPlayerProps["dimensions"];
35
38
  onCloseVideoModal: () => void;
36
39
  onPlayerSeek: (targetTime: number) => void;
37
40
  playNextData: PlayNextData;
38
41
  title: string | number;
39
42
  summary: string | number;
43
+ ImageComponent?: React.ReactNode;
40
44
  };
41
45
 
42
46
  const styles = StyleSheet.create({
@@ -53,6 +57,7 @@ const styles = StyleSheet.create({
53
57
  touchableArea: {
54
58
  flexShrink: 1,
55
59
  flex: 1,
60
+ flexDirection: "row",
56
61
  alignSelf: "stretch",
57
62
  },
58
63
  contentInfo: {
@@ -87,15 +92,11 @@ const styles = StyleSheet.create({
87
92
  },
88
93
  });
89
94
 
90
- const backgroundColorStyle = (value: GetValue): ViewStyle => ({
91
- backgroundColor: value("docked_player_background_color"),
92
- });
93
-
94
95
  const playerDimensionsStyle = (
95
96
  minimisedHeight: number,
96
97
  addPadding: boolean
97
98
  ): ViewStyle => ({
98
- paddingLeft: addPadding ? toNumberWithDefault(100, minimisedHeight) : 0,
99
+ width: addPadding ? toNumberWithDefault(100, minimisedHeight) : 0,
99
100
  });
100
101
 
101
102
  const animatedContainerStyle = (
@@ -181,13 +182,13 @@ export const DockedControls = (props: Props) => {
181
182
  layoutState,
182
183
  playerState,
183
184
  value,
184
- configuration,
185
185
  dimensions,
186
186
  onCloseVideoModal,
187
187
  onPlayerSeek,
188
188
  playNextData,
189
189
  title,
190
190
  summary,
191
+ ImageComponent,
191
192
  } = props;
192
193
 
193
194
  const isTablet = useIsTablet();
@@ -207,6 +208,10 @@ export const DockedControls = (props: Props) => {
207
208
  []
208
209
  );
209
210
 
211
+ const dockedBackgroundColor = value("docked_player_background_color");
212
+
213
+ const insets = useSafeAreaInsets();
214
+
210
215
  if (!layoutState.docked && !startComponentsAnimation) return null;
211
216
 
212
217
  return (
@@ -218,7 +223,9 @@ export const DockedControls = (props: Props) => {
218
223
  isActiveGesture || layoutState.docked,
219
224
  progressBarHeight
220
225
  ),
221
- { height: minimisedHeight },
226
+ {
227
+ height: minimisedHeight + bottomTabBarHeight + insets.bottom,
228
+ },
222
229
  ]}
223
230
  >
224
231
  {!playerState.isLive &&
@@ -245,19 +252,25 @@ export const DockedControls = (props: Props) => {
245
252
  )}
246
253
  />
247
254
  <TouchableWithoutFeedback onPress={maximazeVideoModal}>
248
- <View
249
- style={[
250
- styles.touchableArea,
251
- playerDimensionsStyle(
252
- minimisedHeight,
253
- isActiveGesture || layoutState.docked
254
- ),
255
- ]}
256
- >
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
+ )}
257
270
  <View
258
271
  style={[
259
272
  styles.contentInfo,
260
- !configuration.magic_background && backgroundColorStyle(value),
273
+ { backgroundColor: dockedBackgroundColor },
261
274
  ]}
262
275
  >
263
276
  <ContentInfo
@@ -273,7 +286,7 @@ export const DockedControls = (props: Props) => {
273
286
  isTablet
274
287
  ? styles.controlsContainerForTablet
275
288
  : styles.controlsContainerForMobile,
276
- !configuration.magic_background && backgroundColorStyle(value),
289
+ { backgroundColor: dockedBackgroundColor },
277
290
  ]}
278
291
  >
279
292
  <Controls
@@ -295,6 +308,12 @@ export const DockedControls = (props: Props) => {
295
308
  />
296
309
  </View>
297
310
  </View>
311
+ <View
312
+ style={{
313
+ height: insets.bottom + bottomTabBarHeight,
314
+ backgroundColor: dockedBackgroundColor,
315
+ }}
316
+ />
298
317
  </AnimationComponent>
299
318
  );
300
319
  };
@@ -1,8 +1,8 @@
1
1
  import * as React from "react";
2
- import { View, ViewStyle, StyleSheet } from "react-native";
2
+ import { StyleSheet, View, ViewStyle } from "react-native";
3
3
  import {
4
- useSafeAreaInsets,
5
4
  useSafeAreaFrame,
5
+ useSafeAreaInsets,
6
6
  } from "react-native-safe-area-context";
7
7
  import { useModalAnimationContext } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
8
8
 
@@ -13,11 +13,11 @@ import { Controls } from "./Controls";
13
13
 
14
14
  import { useMobileLayoutImageSize, useTransportInfoHeight } from "./hooks";
15
15
  import { DockedControls } from "./DockedControls";
16
- import { withDebug, DEBUG } from "./debug";
16
+ import { DEBUG, withDebug } from "./debug";
17
17
  import {
18
+ BottomDebugSquare,
18
19
  LeftDebugSquare,
19
20
  RightDebugSquare,
20
- BottomDebugSquare,
21
21
  } from "./Debug/index";
22
22
 
23
23
  import { Props } from "./types";
@@ -77,15 +77,11 @@ export function MobileLayout({
77
77
  onSkipStart,
78
78
  onSkipLive,
79
79
  onSpeedButtonPress,
80
- onSleepButtonPress,
81
80
  onCloseVideoModal,
82
81
  playbackSpeedName,
83
- playbackSleepName,
84
82
  configuration,
85
83
  dimensions,
86
84
  playNextData,
87
- cancelSleepTimer,
88
- sleepTimerDate,
89
85
  title,
90
86
  summary,
91
87
  }: Props) {
@@ -196,10 +192,7 @@ export function MobileLayout({
196
192
  value={value}
197
193
  title={title}
198
194
  summary={summary}
199
- sleepTimerDate={sleepTimerDate}
200
- cancelSleepTimer={cancelSleepTimer}
201
195
  playbackSpeedName={playbackSpeedName}
202
- playbackSleepName={playbackSleepName}
203
196
  onPlaybackButtonPress={onPlaybackButtonPress}
204
197
  onRewindButtonPress={onRewindButtonPress}
205
198
  onForwardButtonPress={onForwardButtonPress}
@@ -207,7 +200,6 @@ export function MobileLayout({
207
200
  onSkipStart={onSkipStart}
208
201
  onSkipLive={onSkipLive}
209
202
  onSpeedButtonPress={onSpeedButtonPress}
210
- onSleepButtonPress={onSleepButtonPress}
211
203
  docked={docked}
212
204
  />
213
205
  </View>
@@ -218,7 +210,6 @@ export function MobileLayout({
218
210
  layoutState={layoutState}
219
211
  playerState={playerState}
220
212
  value={value}
221
- configuration={configuration}
222
213
  dimensions={dimensions}
223
214
  onCloseVideoModal={onCloseVideoModal}
224
215
  onPlayerSeek={onPlayerSeek}
@@ -1,13 +1,16 @@
1
1
  import React, { PropsWithChildren } from "react";
2
- import { ImageBackground, Animated, StyleSheet } from "react-native";
2
+ import { Image, Animated, StyleSheet, ImageStyle } from "react-native";
3
3
 
4
- import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
5
4
  import {
6
5
  useModalAnimationContext,
7
6
  PlayerAnimationStateEnum,
8
7
  DURATION_TO_MINIMIZE,
9
8
  DURATION_TO_MAXIMIZE,
10
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";
11
14
 
12
15
  const styles = StyleSheet.create({
13
16
  container: {
@@ -19,47 +22,50 @@ const styles = StyleSheet.create({
19
22
 
20
23
  type Props = PropsWithChildren<{
21
24
  entry: ZappEntry;
22
- style?: { [K: string]: any };
23
- imageStyle?: { [K: string]: any };
25
+ style?: ImageStyle | ImageStyle[];
24
26
  imageWidth: number;
27
+ docked: boolean;
25
28
  }>;
26
29
 
27
- export const AnimatedImage = ({
28
- entry,
29
- style,
30
- imageStyle,
31
- imageWidth,
32
- }: Props) => {
30
+ export const AnimatedImage = ({ entry, style, imageWidth, docked }: Props) => {
33
31
  const heightAnim = React.useRef(new Animated.Value(imageWidth)).current;
34
32
 
35
- const source = React.useMemo(
36
- () => ({ uri: imageSrcFromMediaItem(entry, undefined) }),
37
- [entry]
38
- );
33
+ const backgroundImageSource = useBackgroundImage(entry);
34
+
35
+ const { minimisedHeight } = useModalAnimationContext();
39
36
 
40
- const { playerAnimationState, minimisedHeight } = useModalAnimationContext();
37
+ const changePlayerState$ = useChangePlayerState({ docked });
41
38
 
42
39
  React.useEffect(() => {
43
- if (playerAnimationState === PlayerAnimationStateEnum.minimize) {
44
- Animated.timing(heightAnim, {
45
- toValue: minimisedHeight,
46
- duration: DURATION_TO_MINIMIZE,
47
- useNativeDriver: false, // width/height can't use native driver
48
- }).start();
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
49
 
50
- return;
51
- }
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
+ }
52
57
 
53
- if (playerAnimationState === PlayerAnimationStateEnum.maximize) {
54
- Animated.timing(heightAnim, {
55
- toValue: imageWidth,
56
- duration: DURATION_TO_MAXIMIZE,
57
- useNativeDriver: false, // width/height can't use native driver
58
- }).start();
59
- }
60
- }, [playerAnimationState, imageWidth]);
58
+ if (nextPlayerState === PlayerAnimationStateEnum.appear_as_docked) {
59
+ // minimize image immediatly
60
+ heightAnim.setValue(minimisedHeight);
61
+ }
62
+ },
63
+ });
61
64
 
62
- if (!source) return null;
65
+ return () => {
66
+ subscription.unsubscribe();
67
+ };
68
+ }, [changePlayerState$, minimisedHeight, imageWidth]);
63
69
 
64
70
  return (
65
71
  <Animated.View
@@ -70,14 +76,7 @@ export const AnimatedImage = ({
70
76
  },
71
77
  ]}
72
78
  >
73
- <ImageBackground
74
- resizeMode="cover"
75
- style={style}
76
- imageStyle={imageStyle}
77
- source={source}
78
- >
79
- {null}
80
- </ImageBackground>
79
+ <Image resizeMode="cover" style={style} source={backgroundImageSource} />
81
80
  </Animated.View>
82
81
  );
83
82
  };
@@ -1,32 +1,16 @@
1
1
  import * as React from "react";
2
- import { ImageBackground } from "react-native";
3
-
4
- import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
2
+ import { Image, ImageStyle } from "react-native";
3
+ import { useBackgroundImage } from "@applicaster/zapp-react-native-utils/audioPlayerUtils";
5
4
 
6
5
  type Props = {
7
6
  entry: ZappEntry;
8
- style?: { [K: string]: any };
9
- imageStyle?: { [K: string]: any };
7
+ style?: ImageStyle;
10
8
  };
11
9
 
12
- const style = { flex: 1, aspectRatio: 1 };
13
-
14
- export const FlexImage = ({ entry, imageStyle }: Props) => {
15
- const source = React.useMemo(
16
- () => ({ uri: imageSrcFromMediaItem(entry, undefined) }),
17
- [entry]
18
- );
19
-
20
- if (!source) return null;
10
+ export const FlexImage = ({ entry, style }: Props) => {
11
+ const backgroundImageSource = useBackgroundImage(entry);
21
12
 
22
13
  return (
23
- <ImageBackground
24
- resizeMode="cover"
25
- style={style}
26
- source={source}
27
- imageStyle={imageStyle}
28
- >
29
- {null}
30
- </ImageBackground>
14
+ <Image resizeMode="cover" style={style} source={backgroundImageSource} />
31
15
  );
32
16
  };
@@ -0,0 +1 @@
1
+ export { useChangePlayerState } from "./useChangePlayerState";
@@ -0,0 +1,99 @@
1
+ import * as React from "react";
2
+ import { Subject, Observable } from "rxjs";
3
+
4
+ import { distinctUntilChanged } from "rxjs/operators";
5
+ import { isNil } from "@applicaster/zapp-react-native-utils/utils";
6
+ import { useRefWithInitialValue } from "@applicaster/zapp-react-native-utils/reactHooks/state/useRefWithInitialValue";
7
+ import { usePrevious } from "@applicaster/zapp-react-native-utils/reactHooks/utils";
8
+ import {
9
+ useModalAnimationContext,
10
+ PlayerAnimationStateEnum,
11
+ } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
12
+ import { PlayerAnimationStateT } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/ModalAnimationContext";
13
+
14
+ const builder = () => {
15
+ const changePlayerState$ = new Subject<PlayerAnimationStateT>();
16
+
17
+ const emitMaximized = (): void => {
18
+ changePlayerState$.next(PlayerAnimationStateEnum.maximize);
19
+ };
20
+
21
+ const emitMinimized = (): void => {
22
+ changePlayerState$.next(PlayerAnimationStateEnum.minimize);
23
+ };
24
+
25
+ const emitAppearInDocked = (): void => {
26
+ // if audio_player was presented in docked mode
27
+ changePlayerState$.next(PlayerAnimationStateEnum.appear_as_docked);
28
+ };
29
+
30
+ return {
31
+ emitMaximized,
32
+ emitMinimized,
33
+ emitAppearInDocked,
34
+ changePlayerState$: changePlayerState$.pipe(distinctUntilChanged()),
35
+ };
36
+ };
37
+
38
+ export const useChangePlayerState = ({
39
+ docked,
40
+ }): Observable<PlayerAnimationStateT> => {
41
+ const changePlayerStateRef =
42
+ useRefWithInitialValue<ReturnType<typeof builder>>(builder);
43
+
44
+ const { playerAnimationState } = useModalAnimationContext();
45
+
46
+ const previousPlayerAnimationState = usePrevious(playerAnimationState);
47
+
48
+ React.useEffect(() => {
49
+ if (
50
+ !docked &&
51
+ isNil(previousPlayerAnimationState) &&
52
+ playerAnimationState === PlayerAnimationStateEnum.minimize
53
+ ) {
54
+ changePlayerStateRef.current.emitMinimized();
55
+
56
+ return;
57
+ }
58
+
59
+ if (
60
+ !docked &&
61
+ isNil(previousPlayerAnimationState) &&
62
+ playerAnimationState === PlayerAnimationStateEnum.maximize
63
+ ) {
64
+ changePlayerStateRef.current.emitMaximized();
65
+
66
+ return;
67
+ }
68
+
69
+ if (
70
+ !docked &&
71
+ previousPlayerAnimationState === PlayerAnimationStateEnum.drag_scroll &&
72
+ playerAnimationState === PlayerAnimationStateEnum.maximize
73
+ ) {
74
+ changePlayerStateRef.current.emitMaximized();
75
+
76
+ return;
77
+ }
78
+
79
+ if (
80
+ !docked &&
81
+ previousPlayerAnimationState === PlayerAnimationStateEnum.drag_scroll &&
82
+ playerAnimationState === PlayerAnimationStateEnum.minimize
83
+ ) {
84
+ changePlayerStateRef.current.emitMinimized();
85
+
86
+ return;
87
+ }
88
+
89
+ if (
90
+ docked &&
91
+ isNil(previousPlayerAnimationState) &&
92
+ isNil(playerAnimationState)
93
+ ) {
94
+ changePlayerStateRef.current.emitAppearInDocked();
95
+ }
96
+ }, [previousPlayerAnimationState, playerAnimationState, docked]);
97
+
98
+ return changePlayerStateRef.current.changePlayerState$;
99
+ };