@applicaster/quick-brick-player 15.0.0-alpha.5740530237 → 15.0.0-alpha.5830601313

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": "15.0.0-alpha.5740530237",
3
+ "version": "15.0.0-alpha.5830601313",
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-rc.56",
39
- "@applicaster/quick-brick-tv-transport-controls": "14.0.0-rc.60",
40
- "@applicaster/zapp-react-native-tvos-app": "15.0.0-alpha.5740530237",
41
- "@applicaster/zapp-react-native-ui-components": "15.0.0-alpha.5740530237",
42
- "@applicaster/zapp-react-native-utils": "15.0.0-alpha.5740530237",
38
+ "@applicaster/quick-brick-mobile-transport-controls": "15.0.0-alpha.5830601313",
39
+ "@applicaster/quick-brick-tv-transport-controls": "15.0.0-rc.15",
40
+ "@applicaster/zapp-react-native-tvos-app": "15.0.0-alpha.5830601313",
41
+ "@applicaster/zapp-react-native-ui-components": "15.0.0-alpha.5830601313",
42
+ "@applicaster/zapp-react-native-utils": "15.0.0-alpha.5830601313",
43
43
  "query-string": "7.1.3",
44
44
  "shaka-player": "4.3.5",
45
45
  "typeface-montserrat": "^0.0.54",
@@ -61,6 +61,7 @@ type Props = {
61
61
  inline: boolean;
62
62
  docked: boolean;
63
63
  isModal: boolean;
64
+ pip: boolean;
64
65
  };
65
66
  playNextData: PlayNextData;
66
67
  isTabletPortrait?: boolean;
@@ -99,11 +100,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
99
100
  );
100
101
 
101
102
  useEffect(() => {
102
- if (player) {
103
- setSpeedManager(new SpeedController(player));
104
- } else {
105
- setSpeedManager(null);
106
- }
103
+ setSpeedManager(player ? new SpeedController(player) : null);
107
104
  }, [player]);
108
105
 
109
106
  useEffect(() => {
@@ -217,7 +214,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
217
214
  items: speedOptions,
218
215
  current_selection: playbackSpeed,
219
216
  onPress: onSpeedSelect,
220
- title: configuration["playback_speed_title"],
217
+ title: configuration.playback_speed_title,
221
218
  itemProps: getBottomSheetModalItemProps,
222
219
  iconProps: getBottomSheetModalIconProps,
223
220
  labelProps: getBottomSheetModalLabelProps,
@@ -233,7 +230,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
233
230
  ],
234
231
  },
235
232
  });
236
- }, [playbackSpeed, onSpeedSelect, configuration["playback_speed_title"]]);
233
+ }, [playbackSpeed, onSpeedSelect, configuration.playback_speed_title]);
237
234
 
238
235
  const onPlayerSeek = React.useCallback(
239
236
  (targetTime: number) => {
@@ -250,13 +247,28 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
250
247
  player?.seekTo(0);
251
248
  }, [player]);
252
249
 
250
+ const layoutStateMemo = React.useMemo(
251
+ () => ({
252
+ inline: layoutState.inline,
253
+ docked: layoutState.docked,
254
+ isModal: layoutState.isModal,
255
+ pip: layoutState.pip,
256
+ }),
257
+ [
258
+ layoutState.inline,
259
+ layoutState.docked,
260
+ layoutState.isModal,
261
+ layoutState.pip,
262
+ ]
263
+ );
264
+
253
265
  return (
254
266
  <SafeAreaView style={[style, Styles.playerContainer]} edges={edges}>
255
267
  <View style={Styles.playerContainer} onLayout={onLayout}>
256
268
  <Layout
257
269
  entry={entry}
258
270
  playerState={playerState}
259
- layoutState={layoutState}
271
+ layoutState={layoutStateMemo}
260
272
  value={value}
261
273
  onPlaybackButtonPress={onPlaybackButtonPress}
262
274
  onRewindButtonPress={onRewindButtonPress}
@@ -1,6 +1,5 @@
1
1
  import * as React from "react";
2
- import { StyleSheet, View, ViewStyle } from "react-native";
3
- import * as R from "ramda";
2
+ import { StyleSheet, View } from "react-native";
4
3
  import {
5
4
  useIsTablet,
6
5
  useZStore,
@@ -16,7 +15,6 @@ import {
16
15
 
17
16
  import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
18
17
 
19
- import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
20
18
  import { useSafeAreaInsets } from "react-native-safe-area-context";
21
19
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
22
20
  import { getTabBarHeight } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/getTabBarHeight";
@@ -27,22 +25,17 @@ import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
27
25
  import { PROGRESS_BAR_HEIGHT } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/utils";
28
26
  import { isMenuVisible } from "@applicaster/zapp-react-native-ui-components/Components/Screen/navigationHandler";
29
27
  import { usePlugins } from "@applicaster/zapp-react-native-redux";
28
+ import { partial } from "@applicaster/zapp-react-native-utils/utils";
30
29
 
31
30
  const bottomTabBarHeight = getTabBarHeight();
32
31
 
33
32
  type Props = {
34
33
  entry: ZappEntry;
35
34
  layoutState: QuickBrickPlayer.LayoutState;
36
- playerState: QuickBrickPlayer.PlayerState;
37
- value: GetValue;
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;
44
38
  isActiveGesture?: boolean;
45
- minimisedHeight: number;
46
39
  aspectRatio?: number;
47
40
  };
48
41
 
@@ -51,7 +44,6 @@ const styles = StyleSheet.create({
51
44
  flex: 1,
52
45
  flexDirection: "column",
53
46
  alignItems: "stretch",
54
- marginTop: PROGRESS_BAR_HEIGHT,
55
47
  },
56
48
  content: {
57
49
  flex: 1,
@@ -94,14 +86,12 @@ const styles = StyleSheet.create({
94
86
  buttons: {
95
87
  marginVertical: 10,
96
88
  },
89
+ liveMarginTop: { marginTop: 0 },
90
+ marginTop: { marginTop: PROGRESS_BAR_HEIGHT },
97
91
  });
98
92
 
99
- const playerDimensionsStyle = (
100
- minimisedHeight: number,
101
- addPadding: boolean
102
- ): ViewStyle => ({
103
- width: addPadding ? toNumberWithDefault(100, minimisedHeight) : 0,
104
- });
93
+ const getValue = (key: string, stylesObj: Record<string, any>) =>
94
+ stylesObj?.[key] ?? null;
105
95
 
106
96
  const controlButtons = (
107
97
  live: boolean,
@@ -167,7 +157,6 @@ export const DockedControls = (props: Props) => {
167
157
  onPlayerSeek = noop,
168
158
  playNextData,
169
159
  ImageComponent,
170
- isActiveGesture = true,
171
160
  aspectRatio,
172
161
  } = props;
173
162
 
@@ -185,11 +174,6 @@ export const DockedControls = (props: Props) => {
185
174
  const configuration = useZStore("playerConfiguration")();
186
175
  const playerState = usePlayerState("shared-player-wrapper-docked");
187
176
 
188
- const getValue = React.useCallback(
189
- (key: string, stylesObj: {}) => R.propOr(null, key, stylesObj),
190
- []
191
- );
192
-
193
177
  const value = React.useCallback(
194
178
  (key: string) => {
195
179
  const retVal = getValue(key, configuration);
@@ -208,7 +192,7 @@ export const DockedControls = (props: Props) => {
208
192
 
209
193
  return retVal;
210
194
  },
211
- [...Object.values(configuration), playerState.seekableDuration, getValue]
195
+ [...Object.values(configuration), playerState.seekableDuration]
212
196
  );
213
197
 
214
198
  const { title, summary } = useTitleSummaryOverlay(
@@ -225,15 +209,65 @@ export const DockedControls = (props: Props) => {
225
209
 
226
210
  const insets = useSafeAreaInsets();
227
211
 
212
+ const progresBarLayoutState = 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
+ );
263
+
228
264
  return (
229
265
  <>
230
266
  <View
231
267
  style={[
232
268
  styles.container,
233
- {
234
- height: minimisedHeight,
235
- maxHeight: minimisedHeight,
236
- },
269
+ containerStyles,
270
+ playerState.isLive ? styles.liveMarginTop : styles.marginTop,
237
271
  ]}
238
272
  >
239
273
  {!playerState.isLive ? (
@@ -242,42 +276,23 @@ export const DockedControls = (props: Props) => {
242
276
  content={entry}
243
277
  value={value}
244
278
  visible
245
- layoutState={layoutState}
279
+ layoutState={progresBarLayoutState}
246
280
  onPlayerSeek={onPlayerSeek}
247
281
  playerState={playerState}
248
- startComponentsAnimation={noop}
249
282
  docked
250
283
  />
251
284
  ) : null}
252
285
 
253
286
  <View style={styles.content}>
254
287
  <View style={styles.touchableArea}>
255
- {isActiveGesture || layoutState.docked ? (
256
- <View
257
- style={{ aspectRatio: aspectRatio, height: minimisedHeight }}
258
- >
259
- {ImageComponent || null}
260
- </View>
261
- ) : (
262
- <View
263
- style={playerDimensionsStyle(
264
- minimisedHeight,
265
- isActiveGesture || layoutState.docked
266
- )}
267
- />
268
- )}
288
+ <View style={imageComponentWrapperStyles}>
289
+ {ImageComponent || null}
290
+ </View>
269
291
  <View
270
292
  testID="content-info"
271
- style={[
272
- styles.contentInfo,
273
- { backgroundColor: dockedBackgroundColor },
274
- ]}
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
298
  <View
@@ -285,15 +300,13 @@ export const DockedControls = (props: Props) => {
285
300
  isTablet
286
301
  ? styles.controlsContainerForTablet
287
302
  : styles.controlsContainerForMobile,
288
- { backgroundColor: dockedBackgroundColor },
303
+ backgroundColorStyle,
289
304
  ]}
290
305
  >
291
306
  <Controls
292
307
  value={value}
293
308
  visible
294
- buttons={R.partial(controlButtons, [
295
- playerState.isLive && liveButton,
296
- ])}
309
+ buttons={_controlButtons}
297
310
  style={styles.playPauseButton}
298
311
  playNextData={playNextData}
299
312
  playerState={playerState}
@@ -308,12 +321,7 @@ export const DockedControls = (props: Props) => {
308
321
  </View>
309
322
  </View>
310
323
  </View>
311
- <View
312
- style={{
313
- height: insets.bottom + (menuVisible ? bottomTabBarHeight : 0),
314
- backgroundColor: dockedBackgroundColor,
315
- }}
316
- />
324
+ <View style={[bottomSpacerStyle, backgroundColorStyle]} />
317
325
  </>
318
326
  );
319
327
  };
@@ -151,12 +151,7 @@ export function MobileLayout({
151
151
  },
152
152
  ]}
153
153
  >
154
- <PlayerImage
155
- entry={entry}
156
- docked={false}
157
- imageWidth={imageSize}
158
- configuration={configuration}
159
- />
154
+ <PlayerImage entry={entry} configuration={configuration} />
160
155
  </View>
161
156
  {/* PlayerImage */}
162
157
 
@@ -4,7 +4,6 @@ import { LayoutChangeEvent, View } from "react-native";
4
4
  import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
5
5
  import { toBooleanWithDefaultTrue } from "@applicaster/zapp-react-native-utils/booleanUtils";
6
6
 
7
- import { AnimatedImage } from "./AnimatedImage";
8
7
  import { FlexImage } from "./FlexImage";
9
8
 
10
9
  import { styles } from "./styles";
@@ -13,19 +12,12 @@ import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/nu
13
12
  type Props = {
14
13
  entry: ZappEntry;
15
14
  configuration: QuickBrickPlayer.AudioPlayerProps["configuration"];
16
- docked: boolean;
17
- imageWidth?: Option<number>;
15
+ docked?: boolean;
18
16
  onLayoutImage?: (event: LayoutChangeEvent) => void;
19
17
  };
20
18
 
21
19
  export const PlayerImage = (props: Props) => {
22
- const {
23
- entry,
24
- docked,
25
- imageWidth,
26
- configuration,
27
- onLayoutImage = noop,
28
- } = props;
20
+ const { entry, docked = false, configuration, onLayoutImage = noop } = props;
29
21
 
30
22
  const isShadowEnabled = toBooleanWithDefaultTrue(
31
23
  configuration?.audio_player_artwork_shadow_enabled
@@ -43,19 +35,9 @@ export const PlayerImage = (props: Props) => {
43
35
  onLayout={onLayoutImage}
44
36
  style={[shouldShowShadow ? styles.shadow : undefined, { borderRadius }]}
45
37
  >
46
- {!imageWidth ? (
47
- <View style={[styles.defaultImageWrapperView, { borderRadius }]}>
48
- <FlexImage entry={entry} style={styles.backgroundImageContainer} />
49
- </View>
50
- ) : (
51
- // we have imageSize here and now we could animate resizing of this image
52
- <AnimatedImage
53
- entry={entry}
54
- style={[styles.backgroundImageContainer, { borderRadius }]}
55
- imageWidth={imageWidth}
56
- docked={docked}
57
- />
58
- )}
38
+ <View style={[styles.defaultImageWrapperView, { borderRadius }]}>
39
+ <FlexImage entry={entry} style={styles.backgroundImageContainer} />
40
+ </View>
59
41
  </View>
60
42
  </View>
61
43
  );
@@ -117,14 +117,11 @@ export function TabletLandscapeLayout({
117
117
  <View style={[styles.flex, styles.audioPlayerContainerHeightLimit]}>
118
118
  {/* PlayerImage non-docked */}
119
119
  <View style={[styles.flex, withDebug(styles.debugYellow)]}>
120
- {!docked ? (
121
- <PlayerImage
122
- docked={false}
123
- entry={entry}
124
- configuration={configuration}
125
- onLayoutImage={onLayoutImage}
126
- />
127
- ) : null}
120
+ <PlayerImage
121
+ entry={entry}
122
+ configuration={configuration}
123
+ onLayoutImage={onLayoutImage}
124
+ />
128
125
  </View>
129
126
  {/* PlayerImage */}
130
127
 
@@ -144,12 +144,7 @@ export function TabletPortraitLayout({
144
144
  ]}
145
145
  onLayout={onLayout}
146
146
  >
147
- <PlayerImage
148
- entry={entry}
149
- configuration={configuration}
150
- docked={docked}
151
- imageWidth={imageSize}
152
- />
147
+ <PlayerImage entry={entry} configuration={configuration} />
153
148
  </View>
154
149
 
155
150
  <View
@@ -1,10 +1,6 @@
1
1
  import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
2
- import {
3
- PlayerAnimationStateEnum,
4
- PlayerAnimationStateT,
5
- } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/ModalAnimationContext";
2
+
6
3
  import { parseJsonIfNeeded } from "@applicaster/zapp-react-native-utils/functionUtils";
7
- import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
8
4
 
9
5
  export const NAMESPACE = "audio-player";
10
6
 
@@ -36,25 +32,3 @@ export const formatSpeed = (value: number) => {
36
32
  // Return the formatted string with "speed_" prefix
37
33
  return `speed_${formattedValue}`;
38
34
  };
39
-
40
- export const calculateBorderRadius = (
41
- docked: boolean,
42
- startComponentsAnimation: boolean,
43
- isActiveGesture: boolean,
44
- playerAnimationState: PlayerAnimationStateT,
45
- configuration: Record<string, any>
46
- ): number => {
47
- const shouldRemoveBorderRadius =
48
- (startComponentsAnimation &&
49
- isActiveGesture &&
50
- playerAnimationState !== PlayerAnimationStateEnum.maximize) ||
51
- docked;
52
-
53
- if (shouldRemoveBorderRadius) {
54
- return 0;
55
- }
56
-
57
- return toNumberWithDefaultZero(
58
- configuration.audio_player_artwork_border_radius
59
- );
60
- };
@@ -4,8 +4,9 @@ import { Animated, Pressable } from "react-native";
4
4
  import { PanGestureHandler } from "react-native-gesture-handler";
5
5
  import { useStyles } from "./styles";
6
6
  import { useVideoModalState } from "./hooks";
7
- import { MODAL_COLLAPSE_START, MODAL_RADIUS, SCREEN_HEIGHT } from "./consts";
7
+ import { MODAL_COLLAPSE_RATIO, MODAL_RADIUS } from "./consts";
8
8
  import { useModalAnimationContext } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
9
+ import { getScreenHeight, getWindowHeight } from "./utils";
9
10
 
10
11
  type AnimatedModalProps = {
11
12
  content?: ReactElement;
@@ -28,21 +29,27 @@ export function AnimatedModal({
28
29
 
29
30
  const styles = useStyles({ height: collapsedHeight, type: "audio" });
30
31
 
32
+ const WINDOW_HEIGHT = getWindowHeight();
33
+ const heightAboveMinimised = WINDOW_HEIGHT - collapsedHeight;
34
+ const screenHeight = getScreenHeight();
35
+
36
+ const MODAL_COLLAPSE_START = WINDOW_HEIGHT * MODAL_COLLAPSE_RATIO;
37
+
31
38
  // Interpolated opacities for smooth cross-fade
32
39
  const collapsedOpacity = translateY.interpolate({
33
- inputRange: [MODAL_COLLAPSE_START, SCREEN_HEIGHT - collapsedHeight],
40
+ inputRange: [MODAL_COLLAPSE_START, heightAboveMinimised],
34
41
  outputRange: [0, 1],
35
42
  extrapolate: "clamp",
36
43
  });
37
44
 
38
45
  const expandedOpacity = translateY.interpolate({
39
- inputRange: [0, SCREEN_HEIGHT - collapsedHeight],
46
+ inputRange: [0, heightAboveMinimised],
40
47
  outputRange: [1, 0],
41
48
  extrapolate: "clamp",
42
49
  });
43
50
 
44
51
  const borderTopRadiusAnimated = translateY.interpolate({
45
- inputRange: [0, SCREEN_HEIGHT - collapsedHeight],
52
+ inputRange: [0, heightAboveMinimised],
46
53
  outputRange: [MODAL_RADIUS, 0],
47
54
  extrapolate: "clamp",
48
55
  });
@@ -57,7 +64,7 @@ export function AnimatedModal({
57
64
  borderTopLeftRadius: borderTopRadiusAnimated,
58
65
  borderTopRightRadius: borderTopRadiusAnimated,
59
66
  transform: [{ translateY }],
60
- height: SCREEN_HEIGHT,
67
+ height: screenHeight,
61
68
  },
62
69
  ]}
63
70
  >
@@ -67,7 +74,7 @@ export function AnimatedModal({
67
74
  {
68
75
  borderTopLeftRadius: borderTopRadiusAnimated,
69
76
  borderTopRightRadius: borderTopRadiusAnimated,
70
- height: SCREEN_HEIGHT,
77
+ height: screenHeight,
71
78
  },
72
79
  ]}
73
80
  >
@@ -1,4 +1,4 @@
1
- import React, { ReactElement, useRef } from "react";
1
+ import React, { ReactElement, useMemo, useRef } from "react";
2
2
 
3
3
  import { Animated, Pressable, StyleSheet, ViewStyle } from "react-native";
4
4
  import { PanGestureHandler } from "react-native-gesture-handler";
@@ -7,10 +7,8 @@ import { useConfiguration } from "@applicaster/zapp-react-native-ui-components/C
7
7
  import { useVideoModalState } from "./hooks";
8
8
  import {
9
9
  DEFAULT_IMAGE_RATIO_VIDEO,
10
- MODAL_COLLAPSE_START,
10
+ MODAL_COLLAPSE_RATIO,
11
11
  MODAL_RADIUS,
12
- SCREEN_HEIGHT,
13
- SCREEN_WIDTH,
14
12
  VIDEO_TRANSITION_THRESHOLD,
15
13
  } from "./consts";
16
14
  import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
@@ -20,6 +18,7 @@ import { PROGRESS_BAR_HEIGHT } from "@applicaster/zapp-react-native-ui-component
20
18
  import { useSafeAreaInsets } from "react-native-safe-area-context";
21
19
  import { GestureAnimatedScrollView } from "./GestureAnimatedScrollView";
22
20
  import { PlayerDetailsWrapperHeightContext } from "./context";
21
+ import { getScreenHeight, getWindowHeight, getWindowWidth } from "./utils";
23
22
 
24
23
  const orientationStyles = StyleSheet.create({
25
24
  landscape: { flexDirection: "row" },
@@ -46,8 +45,6 @@ type AnimatedModalProps = {
46
45
  };
47
46
  };
48
47
 
49
- const height = SCREEN_HEIGHT;
50
-
51
48
  export function VideoPlayerModal({
52
49
  aspectRatio = DEFAULT_IMAGE_RATIO_VIDEO,
53
50
  content,
@@ -62,7 +59,12 @@ export function VideoPlayerModal({
62
59
  const enabled = !!modal && !fullscreen;
63
60
  const isTablet = useIsTablet();
64
61
 
65
- let width = SCREEN_WIDTH;
62
+ const WINDOW_WIDTH = useMemo(() => getWindowWidth(), []); // remember initial width, ignore rotation changes
63
+ const height = useMemo(() => getWindowHeight(), []); // remember initial height, ignore rotation changes
64
+ const screenHeight = useMemo(() => getScreenHeight(), []); // remember initial height, ignore rotation changes
65
+ const MODAL_COLLAPSE_START = height * MODAL_COLLAPSE_RATIO;
66
+
67
+ let width = WINDOW_WIDTH;
66
68
 
67
69
  if (isTablet && !isTabletPortrait) {
68
70
  width = style?.tabletLandscapeWidth || width;
@@ -83,6 +85,8 @@ export function VideoPlayerModal({
83
85
  expand,
84
86
  } = useVideoModalState(modal ? translateYRef : dummyRef);
85
87
 
88
+ const heightAboveMinimised = height - collapsedHeight;
89
+
86
90
  const isTabletLandscape = !isTV() && isTablet && !isTabletPortrait;
87
91
 
88
92
  const styles = useStyles({ height: collapsedHeight });
@@ -96,7 +100,7 @@ export function VideoPlayerModal({
96
100
  // Interpolated opacities for smooth cross-fade
97
101
  const collapsedOpacity = !isFullScreenOrPIP
98
102
  ? translateY.interpolate({
99
- inputRange: [MODAL_COLLAPSE_START, height - collapsedHeight],
103
+ inputRange: [MODAL_COLLAPSE_START, heightAboveMinimised],
100
104
  outputRange: [0, 1],
101
105
  extrapolate: "clamp",
102
106
  })
@@ -104,7 +108,7 @@ export function VideoPlayerModal({
104
108
 
105
109
  const expandedOpacity = !isFullScreenOrPIP
106
110
  ? translateY.interpolate({
107
- inputRange: [0, height - collapsedHeight],
111
+ inputRange: [0, heightAboveMinimised],
108
112
  outputRange: [1, 0],
109
113
  extrapolate: "clamp",
110
114
  })
@@ -112,10 +116,7 @@ export function VideoPlayerModal({
112
116
 
113
117
  const xPosition = !isFullScreenOrPIP
114
118
  ? translateY.interpolate({
115
- inputRange: [
116
- height * VIDEO_TRANSITION_THRESHOLD,
117
- height - collapsedHeight,
118
- ],
119
+ inputRange: [height * VIDEO_TRANSITION_THRESHOLD, MODAL_COLLAPSE_START],
119
120
  outputRange: [0, -(width - width * SCALE_FACTOR) / 2],
120
121
  extrapolate: "clamp",
121
122
  })
@@ -125,10 +126,7 @@ export function VideoPlayerModal({
125
126
 
126
127
  const yPosition = !isFullScreenOrPIP
127
128
  ? translateY.interpolate({
128
- inputRange: [
129
- height * VIDEO_TRANSITION_THRESHOLD,
130
- height - collapsedHeight,
131
- ],
129
+ inputRange: [height * VIDEO_TRANSITION_THRESHOLD, MODAL_COLLAPSE_START],
132
130
  outputRange: [
133
131
  0,
134
132
  isTablet && isTabletLandscape
@@ -136,8 +134,8 @@ export function VideoPlayerModal({
136
134
  : -(
137
135
  PROGRESS_BAR_HEIGHT +
138
136
  insets.top / 2 +
139
- (SCREEN_WIDTH / aspectRatio -
140
- (SCREEN_WIDTH / aspectRatio) * SCALE_FACTOR) /
137
+ (WINDOW_WIDTH / aspectRatio -
138
+ (WINDOW_WIDTH / aspectRatio) * SCALE_FACTOR) /
141
139
  2
142
140
  ),
143
141
  ],
@@ -147,10 +145,7 @@ export function VideoPlayerModal({
147
145
 
148
146
  const scalePosition = !isFullScreenOrPIP
149
147
  ? translateY.interpolate({
150
- inputRange: [
151
- height * VIDEO_TRANSITION_THRESHOLD,
152
- height - collapsedHeight,
153
- ],
148
+ inputRange: [height * VIDEO_TRANSITION_THRESHOLD, MODAL_COLLAPSE_START],
154
149
  outputRange: [1, SCALE_FACTOR],
155
150
  extrapolate: "clamp",
156
151
  })
@@ -192,7 +187,7 @@ export function VideoPlayerModal({
192
187
  borderTopLeftRadius: borderTopRadiusAnimated,
193
188
  borderTopRightRadius: borderTopRadiusAnimated,
194
189
  transform: [{ translateY: isFullScreenOrPIP ? 0 : translateY }],
195
- height: height,
190
+ height: screenHeight,
196
191
  },
197
192
  ]}
198
193
  >
@@ -204,13 +199,16 @@ export function VideoPlayerModal({
204
199
  {
205
200
  borderTopLeftRadius: borderTopRadiusAnimated,
206
201
  borderTopRightRadius: borderTopRadiusAnimated,
207
- height: height,
202
+ height: screenHeight,
208
203
  },
209
204
  ]}
210
205
  >
211
206
  <Animated.View
212
207
  pointerEvents={!collapsed ? "auto" : "none"}
213
- style={[styles.modalContent, directionStyles(isTabletLandscape)]}
208
+ style={[
209
+ pip ? styles.modalContentPiP : styles.modalContent,
210
+ directionStyles(isTabletLandscape),
211
+ ]}
214
212
  >
215
213
  <Animated.View
216
214
  style={[