@applicaster/zapp-react-native-ui-components 12.0.0-alpha.4195481103 → 12.0.0-alpha.4271512420

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.
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { join, path, merge } from "ramda";
2
+ import { join, merge, path } from "ramda";
3
3
  import { View } from "react-native";
4
4
 
5
5
  import { Focusable } from "@applicaster/zapp-react-native-ui-components/Components/Focusable";
@@ -67,6 +67,10 @@ type Props = {
67
67
  behavior: Behavior;
68
68
  };
69
69
 
70
+ type State = {
71
+ hasFocusableInside: boolean;
72
+ };
73
+
70
74
  const baseCellStyles = {
71
75
  height: "100%",
72
76
  display: "flex",
@@ -78,7 +82,7 @@ const touchableStyles = {
78
82
  height: "100%",
79
83
  } as const;
80
84
 
81
- export class CellComponent extends React.Component<Props> {
85
+ export class CellComponent extends React.Component<Props, State> {
82
86
  constructor(props) {
83
87
  super(props);
84
88
  this.onPress = this.onPress.bind(this);
@@ -88,6 +92,10 @@ export class CellComponent extends React.Component<Props> {
88
92
  this.hasReceivedFocus = this.hasReceivedFocus.bind(this);
89
93
  this.scrollVertically = this.scrollVertically.bind(this);
90
94
  this.scrollToIndex = this.scrollToIndex.bind(this);
95
+
96
+ this.state = {
97
+ hasFocusableInside: props.CellRenderer.hasFocusableInside?.(props.item),
98
+ };
91
99
  }
92
100
 
93
101
  setScreenLayout(componentAnchorPointY, screenLayout) {
@@ -192,6 +200,16 @@ export class CellComponent extends React.Component<Props> {
192
200
  return !isFocusable ? false : focused || focusableFocused;
193
201
  }
194
202
 
203
+ componentDidUpdate(prevProps: Readonly<Props>) {
204
+ if (prevProps.item !== this.props.item) {
205
+ this.setState({
206
+ hasFocusableInside: this.props.CellRenderer.hasFocusableInside?.(
207
+ this.props.item
208
+ ),
209
+ });
210
+ }
211
+ }
212
+
195
213
  render() {
196
214
  const {
197
215
  item,
@@ -220,9 +238,7 @@ export class CellComponent extends React.Component<Props> {
220
238
  this.onFocus(focusable, mouse);
221
239
  };
222
240
 
223
- const hasFocusableInside = CellRenderer.hasFocusableInside?.(item);
224
-
225
- if (hasFocusableInside) {
241
+ if (this.state.hasFocusableInside) {
226
242
  return (
227
243
  <CellWithFocusable
228
244
  CellRenderer={CellRenderer}
@@ -13,8 +13,8 @@ import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
13
13
 
14
14
  import { useScreenConfiguration } from "../../River/useScreenConfiguration";
15
15
  import {
16
+ findMenuPlugin,
16
17
  getNavigationProps,
17
- resolveNavigationPlugin,
18
18
  routeIsPlayerScreen,
19
19
  } from "@applicaster/zapp-react-native-utils/navigationUtils";
20
20
  import { isApplePlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
@@ -118,13 +118,8 @@ export const ScreenContainer = React.memo(function ScreenContainer({
118
118
  });
119
119
 
120
120
  const menuPlugin = React.useMemo(
121
- () =>
122
- resolveNavigationPlugin({
123
- category: "menu",
124
- navigations: activeRiver?.navigations,
125
- plugins,
126
- }) as QuickBrickPlugin,
127
- []
121
+ () => findMenuPlugin(activeRiver?.navigations, plugins),
122
+ [activeRiver?.navigations]
128
123
  );
129
124
 
130
125
  const NavBarComponent = React.useMemo(
@@ -19,7 +19,7 @@ jest.mock("@applicaster/zapp-react-native-utils/navigationUtils", () => ({
19
19
  ...jest.requireActual<any>(
20
20
  "@applicaster/zapp-react-native-utils/navigationUtils"
21
21
  ),
22
- resolveNavigationPlugin: () => ({}),
22
+ findMenuPlugin: () => ({}),
23
23
  }));
24
24
 
25
25
  jest.mock("@applicaster/quick-brick-core/App/ActionSetters", () => ({
@@ -108,6 +108,26 @@ const prepareEntry = (entry) => {
108
108
  };
109
109
  }
110
110
 
111
+ const previewPlayback =
112
+ entry.extensions?.["brightcove"]?.["preview_playback"];
113
+
114
+ if (previewPlayback) {
115
+ return {
116
+ ...entry,
117
+ extensions: {
118
+ ...entry.extensions,
119
+ brightcove: {
120
+ ...entry?.extensions?.["brightcove"],
121
+ video_id: previewPlayback,
122
+ },
123
+ },
124
+ };
125
+ }
126
+
127
+ if (entry.extensions?.["brightcove"]?.["video_id"]) {
128
+ return entry;
129
+ }
130
+
111
131
  const src = entry.content?.src;
112
132
 
113
133
  if (!src) {
@@ -37,14 +37,28 @@ function retrieveData(entry, func, args) {
37
37
  */
38
38
 
39
39
  export function configInflater(
40
- entry,
41
- { type, style, additionalProps = {}, data = [], elements }
40
+ entry: any,
41
+ {
42
+ type,
43
+ style,
44
+ additionalProps = {},
45
+ data = [],
46
+ elements,
47
+ }: {
48
+ type: any;
49
+ style: any;
50
+ additionalProps?: Record<string, any>;
51
+ data?: Array<{ propName: string; func: Function; args: any[] }>;
52
+ elements?: any[];
53
+ }
42
54
  ) {
43
- const props = R.reduce(
44
- (acc, curr) =>
45
- R.assoc(curr.propName, retrieveData(entry, curr.func, curr.args), acc),
46
- additionalProps,
47
- data
55
+ const props = data.reduce(
56
+ (acc, curr) => {
57
+ acc[curr.propName] = retrieveData(entry, curr.func, curr.args);
58
+
59
+ return acc;
60
+ },
61
+ { ...additionalProps }
48
62
  );
49
63
 
50
64
  let adjustedElements;
@@ -52,6 +52,8 @@ export function masterCellBuilder({
52
52
  const { View } = componentsMap;
53
53
  const elementsBuilder = dataAdapter(cellConfiguration);
54
54
 
55
+ // This is very expensive operation
56
+ // Keep calls to minimum
55
57
  const hasFocusableInside = hasFocusableInsideBuilder(elementsBuilder);
56
58
 
57
59
  /**
@@ -84,7 +86,7 @@ export function masterCellBuilder({
84
86
  entry: item,
85
87
  state: getEntryState(state, entryIsSelected),
86
88
  }),
87
- [state, item, entryIsSelected]
89
+ [state, item?.id, entryIsSelected] // Assuming that item won't mutate
88
90
  );
89
91
 
90
92
  const wrapperRef = React.useRef(null);
@@ -124,6 +124,7 @@ const nativeStyles = {
124
124
  playerScreen: {
125
125
  flex: 1,
126
126
  backgroundColor: "black",
127
+ overflow: "hidden",
127
128
  },
128
129
  playerWrapper: {
129
130
  flex: 1,
@@ -252,11 +253,7 @@ const PlayerContainerComponent = (props: Props) => {
252
253
  }
253
254
 
254
255
  showNavBar(true);
255
-
256
- // Hack to close player screen on mobile only (tv handles that in InteractionManager)
257
- if (!isTV()) {
258
- navigator.goBack();
259
- }
256
+ navigator.goBack();
260
257
  }, [isModal, navigator.goBack, showNavBar]);
261
258
 
262
259
  const playEntry = (entry) => navigator.replaceTop(entry, { mode });
@@ -2,9 +2,9 @@ import * as React from "react";
2
2
  import { last } from "ramda";
3
3
  import { View, StyleSheet } from "react-native";
4
4
  import {
5
+ findMenuPlugin,
5
6
  getNavigationProps,
6
7
  getPathAttributes,
7
- resolveNavigationPlugin,
8
8
  } from "@applicaster/zapp-react-native-utils/navigationUtils";
9
9
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
10
10
  import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
@@ -131,11 +131,7 @@ export const Screen = ({ route, Components }: Props) => {
131
131
  fallbackNavigations: navigator.activeRiver.navigations,
132
132
  });
133
133
 
134
- const menuPlugin = resolveNavigationPlugin({
135
- category: "menu",
136
- navigations,
137
- plugins,
138
- }) as QuickBrickPlugin;
134
+ const menuPlugin = findMenuPlugin(navigations, plugins);
139
135
 
140
136
  const NavBar = (Components.NavBar ||
141
137
  menuPlugin.module) as React.ComponentType<any>;
@@ -11,10 +11,10 @@ import {
11
11
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
12
12
  import { getComponentModule } from "@applicaster/zapp-react-native-utils/pluginUtils";
13
13
  import {
14
- getNavigationPropsV2,
15
- resolveNavigationPlugin,
14
+ shouldNavBarDisplayMenu,
15
+ getNavBarProps,
16
+ getScreenId,
16
17
  } from "@applicaster/zapp-react-native-utils/navigationUtils";
17
- import { useSafeAreaInsets } from "react-native-safe-area-context";
18
18
  import {
19
19
  useDimensions,
20
20
  useRoute,
@@ -25,20 +25,16 @@ import {
25
25
  } from "@applicaster/zapp-react-native-utils/reactHooks";
26
26
  import { getNavigationPluginModule } from "@applicaster/zapp-react-native-app/App/Layout/layoutHelpers";
27
27
 
28
- import { ScreenContextProvider } from "../../Contexts/ScreenContext";
29
28
  import { RouteManager } from "../RouteManager";
30
29
  import { useScreenConfiguration } from "../River/useScreenConfiguration";
31
30
  import { useScreenOrientationHandler } from "./orientationHandler";
32
31
 
33
- const getScreenId = (
34
- screenData: LegacyNavigationScreenData,
35
- fallbackRiver: ZappRiver
36
- ) => {
37
- return screenData?.targetScreen
38
- ? screenData?.targetScreen?.id ?? fallbackRiver.id
39
- : "screen_id" in screenData
40
- ? screenData.screen_id
41
- : fallbackRiver.id;
32
+ const screenStyles = {
33
+ flex: 1,
34
+ paddingTop: 0,
35
+ // paddingBottom: insets.bottom, // Should be applied directly by UI plugin
36
+ // paddingLeft: insets.left, // Should be applied directly by UI plugin
37
+ // paddingRight: insets.right, // Should be applied directly by UI plugin
42
38
  };
43
39
 
44
40
  function colorIsNotTransparent(color) {
@@ -49,9 +45,7 @@ function colorIsNotTransparent(color) {
49
45
  R.replace("rgba(", "")
50
46
  )(color);
51
47
 
52
- const alpha = Number(layers?.[3]);
53
-
54
- return alpha > 0;
48
+ return Number(layers?.[3]) > 0;
55
49
  }
56
50
 
57
51
  function isValidColor(string) {
@@ -71,7 +65,6 @@ export function Screen(_props: Props) {
71
65
  // Gets the data for the current screen configuration
72
66
  const currentScreenData = useCurrentScreenData();
73
67
  const { backgroundColor } = useScreenConfiguration(currentScreenData.id);
74
- const insets = useSafeAreaInsets();
75
68
 
76
69
  const {
77
70
  width: screenWidth,
@@ -96,30 +89,12 @@ export function Screen(_props: Props) {
96
89
 
97
90
  const layoutData = { isTablet, isTabletPortrait, width: screenWidth, height };
98
91
 
99
- const hasMenu =
100
- resolveNavigationPlugin({
101
- category: "menu",
102
- navigations: currentRiver.navigations,
103
- plugins,
104
- })?.identifier === "quick_brick_side_menu";
105
-
106
- const navBarProps = React.useMemo<MobileNavBarPluginProps | null>(() => {
107
- const props = getNavigationPropsV2({
108
- currentRiver,
109
- title,
110
- category: "nav_bar",
111
- });
112
-
113
- if (props) {
114
- return {
115
- ...props,
116
- id: pathname,
117
- pathname: pathname,
118
- };
119
- }
120
-
121
- return null;
122
- }, [currentRiver, pathname]);
92
+ const hasMenu = shouldNavBarDisplayMenu(currentRiver, plugins);
93
+
94
+ const navBarProps = React.useMemo<MobileNavBarPluginProps | null>(
95
+ getNavBarProps(currentRiver, pathname, title),
96
+ [currentRiver, pathname]
97
+ );
123
98
 
124
99
  const NavBar = React.useMemo(
125
100
  () =>
@@ -141,16 +116,12 @@ export function Screen(_props: Props) {
141
116
 
142
117
  const style = React.useMemo(
143
118
  () => ({
144
- flex: 1,
119
+ ...screenStyles,
145
120
  backgroundColor: isValidColor(backgroundColor)
146
121
  ? backgroundColor
147
122
  : theme.app_background_color,
148
- paddingTop: 0,
149
- // paddingBottom: insets.bottom, // Should be applied directly by UI plugin
150
- // paddingLeft: insets.left, // Should be applied directly by UI plugin
151
- // paddingRight: insets.right, // Should be applied directly by UI plugin
152
123
  }),
153
- [insets, screenWidth, theme.app_background_color, backgroundColor]
124
+ [theme.app_background_color, backgroundColor]
154
125
  );
155
126
 
156
127
  const targetScreenData =
@@ -172,15 +143,13 @@ export function Screen(_props: Props) {
172
143
  }
173
144
 
174
145
  return (
175
- <ScreenContextProvider pathname={pathname}>
176
- <View style={style}>
177
- {navBarProps && <NavBar {...navBarProps} hasMenu={hasMenu} />}
178
-
179
- <OfflineFallbackScreen screenData={targetScreenData}>
180
- {/* @TODO RouteManager doesn't use props, can they be removed ? */}
181
- <RouteManager pathname={pathname} screenData={screenData} />
182
- </OfflineFallbackScreen>
183
- </View>
184
- </ScreenContextProvider>
146
+ <View style={style}>
147
+ {navBarProps && <NavBar {...navBarProps} hasMenu={hasMenu} />}
148
+
149
+ <OfflineFallbackScreen screenData={targetScreenData}>
150
+ {/* @TODO RouteManager doesn't use props, can they be removed ? */}
151
+ <RouteManager pathname={pathname} screenData={screenData} />
152
+ </OfflineFallbackScreen>
153
+ </View>
185
154
  );
186
155
  }
@@ -5,6 +5,11 @@
5
5
  * is similar to the navbar, except that it covers scenarios where only the navbar (and not)
6
6
  * the menu, will be hidden
7
7
  *
8
+ * - playable screens
9
+ * - qb_search_screen
10
+ * - screen hooks that specify showNavBar or presentFullScreen
11
+ * - screens or nested screens that have allow_screen_plugin_presentation set to true
12
+ *
8
13
  * @param {String} route current route of the screen
9
14
  * @param {Object} screenData payload associated with the currently presented screen
10
15
  * @returns {Boolean}
@@ -1,13 +1,9 @@
1
1
  import React from "react";
2
- import {
3
- Animated,
4
- useWindowDimensions,
5
- ViewProps,
6
- ViewStyle,
7
- } from "react-native";
2
+ import { Animated, ViewProps, ViewStyle } from "react-native";
8
3
  import { useSafeAreaFrame } from "react-native-safe-area-context";
9
4
  import { PathnameContext } from "../../Contexts/PathnameContext";
10
5
  import { ScreenDataContext } from "../../Contexts/ScreenDataContext";
6
+ import { ScreenContextProvider } from "../../Contexts/ScreenContext";
11
7
 
12
8
  type Props = {
13
9
  children: any;
@@ -53,12 +49,15 @@ export function Scene({
53
49
  }, [screenData, isActive]);
54
50
 
55
51
  const frame = useSafeAreaFrame();
56
- const { height, width } = useWindowDimensions();
57
52
 
58
- // Safe frame takes too long to update,
59
- // so we can not rely on it there, and use height and width instead.
60
53
  const isAnimating = animating && overlayStyle;
61
- const dimensions = isAnimating ? { height, width } : frame;
54
+
55
+ const dimensions = isAnimating
56
+ ? {
57
+ height: "100%",
58
+ width: "100%",
59
+ }
60
+ : frame;
62
61
 
63
62
  return (
64
63
  <Animated.View
@@ -67,7 +66,9 @@ export function Scene({
67
66
  >
68
67
  <ScreenDataContext.Provider value={initialScreenData}>
69
68
  <PathnameContext.Provider value={pathname}>
70
- {children}
69
+ <ScreenContextProvider pathname={pathname}>
70
+ {children}
71
+ </ScreenContextProvider>
71
72
  </PathnameContext.Provider>
72
73
  </ScreenDataContext.Provider>
73
74
  {isAnimating && <Animated.View style={overlayStyle} />}
@@ -22,7 +22,9 @@ exports[`<Scene /> renders correctly 1`] = `
22
22
  }
23
23
  >
24
24
  <ContextProvider>
25
- <ContextProvider />
25
+ <ContextProvider>
26
+ <ScreenContextProvider />
27
+ </ContextProvider>
26
28
  </ContextProvider>
27
29
  </ForwardRef(AnimatedComponentWrapper)>
28
30
  `;
@@ -39,14 +41,16 @@ exports[`<Scene /> renders the overlay while animating 1`] = `
39
41
  "paddingBottom": 49,
40
42
  },
41
43
  Object {
42
- "height": 1334,
43
- "width": 750,
44
+ "height": "100%",
45
+ "width": "100%",
44
46
  },
45
47
  ]
46
48
  }
47
49
  >
48
50
  <ContextProvider>
49
- <ContextProvider />
51
+ <ContextProvider>
52
+ <ScreenContextProvider />
53
+ </ContextProvider>
50
54
  </ContextProvider>
51
55
  <ForwardRef(AnimatedComponentWrapper)
52
56
  style={
@@ -5,7 +5,6 @@ import {
5
5
  useModalAnimationContext,
6
6
  PlayerAnimationStateEnum,
7
7
  } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
8
- import { useDimensions } from "@applicaster/zapp-react-native-utils/reactHooks";
9
8
 
10
9
  type Props = {
11
10
  style: ViewStyle[];
@@ -18,13 +17,8 @@ export const AnimatedPlayerModalWrapper = (props: Props) => {
18
17
  animatedValues: { lastScrollY, dragScrollY, translateYOffset },
19
18
  modalSnapPoints,
20
19
  setStartComponentsAnimation,
21
- lastScrollYValue,
22
20
  } = useModalAnimationContext();
23
21
 
24
- const { height: screenHeight } = useDimensions("screen", {
25
- deviceInfo: true,
26
- });
27
-
28
22
  const interpolateConfig: Animated.InterpolationConfigType = React.useMemo(
29
23
  () => ({
30
24
  inputRange: modalSnapPoints,
@@ -51,16 +45,10 @@ export const AnimatedPlayerModalWrapper = (props: Props) => {
51
45
  }
52
46
 
53
47
  React.useEffect(() => {
54
- const translateYListener = translateY.addListener(({ value }) => {
55
- const preparedValue = Math.round(
56
- Math.abs(value) - lastScrollYValue.current
57
- );
58
-
48
+ const translateYListener = translateY.addListener(() => {
59
49
  (playerAnimationState === PlayerAnimationStateEnum.minimize ||
60
50
  playerAnimationState === PlayerAnimationStateEnum.maximaze) &&
61
- setStartComponentsAnimation(
62
- preparedValue >= Math.round((screenHeight * 10) / 100)
63
- );
51
+ setStartComponentsAnimation(true);
64
52
  });
65
53
 
66
54
  return () => {
@@ -58,6 +58,7 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
58
58
  modalSnapPoints,
59
59
  lastSnap,
60
60
  setLastSnap,
61
+ setStartComponentsAnimation,
61
62
  } = useModalAnimationContext();
62
63
 
63
64
  const { isLanguageOverlayVisible } = React.useContext(PlayerContainerContext);
@@ -204,7 +205,8 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
204
205
 
205
206
  if (
206
207
  (videoModalState.mode === "MAXIMIZED" &&
207
- videoModalState.previousMode === "MAXIMIZED") ||
208
+ videoModalState.previousMode === "MINIMIZED" &&
209
+ previousItemId === videoModalState.item?.id) ||
208
210
  previousItemId !== videoModalState.item?.id
209
211
  ) {
210
212
  setPlayerAnimationState(PlayerAnimationStateEnum.maximaze);
@@ -281,10 +283,11 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
281
283
  if (
282
284
  preparedValue > 0 &&
283
285
  scrollPosition.current === 0 &&
284
- playerAnimationState !== PlayerAnimationStateEnum.drag_player
286
+ playerAnimationState !== PlayerAnimationStateEnum.drag_player &&
287
+ playerAnimationState !== PlayerAnimationStateEnum.drag_scroll
285
288
  ) {
286
- playerAnimationState !== PlayerAnimationStateEnum.drag_scroll &&
287
- setPlayerAnimationState(PlayerAnimationStateEnum.drag_scroll);
289
+ isMinimizedModal && setStartComponentsAnimation(true);
290
+ setPlayerAnimationState(PlayerAnimationStateEnum.drag_scroll);
288
291
  }
289
292
  });
290
293
 
@@ -292,7 +295,7 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
292
295
  lastScrollY.removeListener(lastScrollYListenerId);
293
296
  dragScrollY.removeListener(dragListenerId);
294
297
  };
295
- }, [playerAnimationState, isAudioItem, modalSnapPoints]);
298
+ }, [playerAnimationState, isAudioItem, modalSnapPoints, isMinimizedModal]);
296
299
 
297
300
  const Wrapper = React.useMemo(
298
301
  () => (Platform.OS === "android" ? GestureHandlerRootView : View),
@@ -34,6 +34,7 @@ export const AnimatedVideoPlayer = ({ children }: Props) => {
34
34
  lastSnap,
35
35
  setLastSnap,
36
36
  resetPlayerAnimationState,
37
+ setStartComponentsAnimation,
37
38
  } = useModalAnimationContext();
38
39
 
39
40
  const { videoModalState } = useNavigation();
@@ -121,8 +122,10 @@ export const AnimatedVideoPlayer = ({ children }: Props) => {
121
122
  preparedValue > 0 &&
122
123
  playerAnimationState !== PlayerAnimationStateEnum.drag_scroll
123
124
  ) {
124
- playerAnimationState !== PlayerAnimationStateEnum.drag_player &&
125
+ if (playerAnimationState !== PlayerAnimationStateEnum.drag_player) {
126
+ isMinimizedModal && setStartComponentsAnimation(true);
125
127
  setPlayerAnimationState(PlayerAnimationStateEnum.drag_player);
128
+ }
126
129
 
127
130
  translateYOffset.setValue(
128
131
  isMaximazedModal
@@ -51,6 +51,7 @@ export const AnimationView = ({
51
51
  setTabletLandscapePlayerTopPosition,
52
52
  modalSnapPoints,
53
53
  startComponentsAnimationDistance,
54
+ progressBarHeight,
54
55
  } = useModalAnimationContext();
55
56
 
56
57
  const isRTL = useIsRTL();
@@ -62,9 +63,9 @@ export const AnimationView = ({
62
63
  } = useDimensions("window", { deviceInfo: true });
63
64
 
64
65
  const { videoModalState } = useNavigation();
65
- const bottomTabBarHeight = useGetBottomTabBarHeight();
66
- const minimisedWidth = defaultAspectRatioWidth(minimisedHeight);
67
66
  const insets = useSafeAreaInsets();
67
+ const bottomTabBarHeight = useGetBottomTabBarHeight() + (insets.bottom || 0);
68
+ const minimisedWidth = defaultAspectRatioWidth(minimisedHeight);
68
69
  const animationComponentRef = useRef(null);
69
70
 
70
71
  // retrieving top position of the player for tablet landscape mode
@@ -92,12 +93,12 @@ export const AnimationView = ({
92
93
  const inlineAudioPlayer = additionalData.inlineAudioPlayer;
93
94
 
94
95
  const moveUpValue = additionalData.saveArea
95
- ? -insets.top
96
+ ? -insets.top + (isAudioItem ? 0 : progressBarHeight)
96
97
  : isTablet
97
98
  ? isTabletLandscape && (!isAudioItem || (isAudioItem && inlineAudioPlayer))
98
- ? -tabletLandscapePlayerTopPosition
99
+ ? -tabletLandscapePlayerTopPosition + progressBarHeight
99
100
  : -130
100
- : -50;
101
+ : -50 + progressBarHeight;
101
102
 
102
103
  const moveComponentHorizontalValue = additionalData.moveValue
103
104
  ? isRTL
@@ -1,12 +1,17 @@
1
1
  import React, { useContext } from "react";
2
2
  import { Animated } from "react-native";
3
3
 
4
- import { useSafeAreaInsets } from "react-native-safe-area-context";
4
+ import {
5
+ useSafeAreaInsets,
6
+ useSafeAreaFrame,
7
+ } from "react-native-safe-area-context";
5
8
  import {
6
9
  useGetBottomTabBarHeight,
7
- useDimensions,
10
+ useNavigation,
8
11
  } from "@applicaster/zapp-react-native-utils/reactHooks";
12
+ import { isLive } from "@applicaster/zapp-react-native-utils/playerUtils";
9
13
 
14
+ import { PROGRESS_BAR_HEIGHT } from "./utils";
10
15
  import { useConfiguration } from "../utils";
11
16
 
12
17
  export enum PlayerAnimationStateEnum {
@@ -40,6 +45,7 @@ export type ModalAnimationContextT = {
40
45
  tabletLandscapePlayerTopPosition: number;
41
46
  setTabletLandscapePlayerTopPosition: (value: number) => void;
42
47
  startComponentsAnimationDistance: number;
48
+ progressBarHeight: number;
43
49
  };
44
50
 
45
51
  const ReactContext = React.createContext<ModalAnimationContextT>({
@@ -64,6 +70,7 @@ const ReactContext = React.createContext<ModalAnimationContextT>({
64
70
  tabletLandscapePlayerTopPosition: 0,
65
71
  setTabletLandscapePlayerTopPosition: () => null,
66
72
  startComponentsAnimationDistance: 0,
73
+ progressBarHeight: 0,
67
74
  });
68
75
 
69
76
  export function useModalAnimationContext() {
@@ -82,6 +89,11 @@ const Provider = ({ children }: { children: React.ReactNode }) => {
82
89
  const [startComponentsAnimation, setStartComponentsAnimation] =
83
90
  React.useState<boolean>(false);
84
91
 
92
+ const {
93
+ videoModalState: { mode, visible, item },
94
+ } = useNavigation();
95
+
96
+ const isLiveItem = isLive(item);
85
97
  const { minimised_height: minimisedHeight } = useConfiguration();
86
98
 
87
99
  const resetPlayerAnimationState = React.useCallback(() => {
@@ -95,21 +107,28 @@ const Provider = ({ children }: { children: React.ReactNode }) => {
95
107
  const translateYOffset = React.useRef(new Animated.Value(0)).current;
96
108
  const dragVideoPlayerY = React.useRef(new Animated.Value(0)).current;
97
109
 
98
- const { height } = useDimensions("window", { fullDimensions: true });
110
+ const { height: safeAreaFrameHeight } = useSafeAreaFrame();
111
+ const [height, setHeight] = React.useState<number>(safeAreaFrameHeight);
112
+ const progressBarHeight = isLiveItem ? 0 : PROGRESS_BAR_HEIGHT;
99
113
  const { bottom: bottomSafeArea } = useSafeAreaInsets();
100
114
  const bottomTabBarHeight = useGetBottomTabBarHeight();
115
+ const startComponentsAnimationDistance = Math.round((height * 60) / 100);
101
116
 
102
- const startComponentsAnimationDistance = React.useMemo(
103
- () => Math.round((height * 60) / 100),
104
- [height]
105
- );
117
+ React.useEffect(() => {
118
+ if (visible && mode === "MAXIMIZED" && height !== safeAreaFrameHeight) {
119
+ setHeight(safeAreaFrameHeight);
120
+ }
121
+ }, [height, safeAreaFrameHeight, mode, visible]);
106
122
 
107
123
  /*
108
124
  If bottomTabBarHeight is equal 0 it means an app does not use bottomTabBar.
109
125
  Because of this we need to minus bottom SafeArea offset.
110
126
  */
111
127
  const minValue =
112
- height - minimisedHeight - (bottomTabBarHeight || bottomSafeArea);
128
+ height -
129
+ minimisedHeight -
130
+ (bottomTabBarHeight || bottomSafeArea) -
131
+ progressBarHeight;
113
132
 
114
133
  const modalSnapPoints = React.useMemo(() => [0, minValue], [minValue]);
115
134
  // Last snap state which will helps us to make smooth responder to scrollview animation
@@ -142,6 +161,7 @@ const Provider = ({ children }: { children: React.ReactNode }) => {
142
161
  tabletLandscapePlayerTopPosition,
143
162
  setTabletLandscapePlayerTopPosition,
144
163
  startComponentsAnimationDistance,
164
+ progressBarHeight,
145
165
  }}
146
166
  >
147
167
  {children}
@@ -13,6 +13,7 @@ export enum ComponentAnimationType {
13
13
  }
14
14
 
15
15
  export const AUDIO_PLAYER_HORIZONTAL_PADDING = 15;
16
+ export const PROGRESS_BAR_HEIGHT = 3;
16
17
 
17
18
  export const defaultAspectRatioWidth = (height: number): number =>
18
19
  (height / 9) * 16;
@@ -225,7 +225,7 @@ export const PlayerWrapper = (props: Props) => {
225
225
  </AnimationComponent>
226
226
  </View>
227
227
  <AnimatedScrollModal>
228
- {isInlineModal ? (
228
+ {isInlineModal && !docked ? (
229
229
  <AnimationComponent
230
230
  animationType={ComponentAnimationType.componentFade}
231
231
  style={defaultStyles.flex}
@@ -1,5 +1,4 @@
1
1
  import * as React from "react";
2
- import { Dimensions } from "react-native";
3
2
  import { useIsTabletLandscape } from "@applicaster/zapp-react-native-utils/reactHooks/device/useMemoizedIsTablet";
4
3
  import {
5
4
  addOrientationChangeListener,
@@ -9,11 +8,10 @@ import {
9
8
  } from "@applicaster/zapp-react-native-utils/appUtils/orientationHelper";
10
9
 
11
10
  import { getXray } from "@applicaster/zapp-react-native-utils/logger";
11
+ import { useSafeAreaFrame } from "react-native-safe-area-context";
12
12
 
13
13
  const { Logger } = getXray();
14
14
 
15
- const { width: WIDTH, height: HEIGHT } = Dimensions.get("window");
16
-
17
15
  const logger = new Logger(
18
16
  "hooks",
19
17
  "zapp-react-native-ui-components/Components/VideoModal"
@@ -24,20 +22,18 @@ type Size = {
24
22
  height: number | string;
25
23
  };
26
24
 
27
- const MODAL_SIZE_FOR_PORTRAIT: Size = {
28
- width: WIDTH,
29
- height: HEIGHT,
30
- };
31
-
32
25
  const MODAL_SIZE_FOR_LANDSCAPE: Size = {
33
26
  width: "100%",
34
27
  height: "100%",
35
28
  };
36
29
 
37
30
  export const useModalSize = (): Size => {
38
- const [modalSize, setModalSize] = React.useState<Size>(
39
- MODAL_SIZE_FOR_PORTRAIT
40
- );
31
+ const frame = useSafeAreaFrame();
32
+
33
+ const [modalSize, setModalSize] = React.useState<Size>({
34
+ width: frame.width,
35
+ height: frame.height,
36
+ });
41
37
 
42
38
  const setNewModalSize = React.useCallback((newSize, log) => {
43
39
  setModalSize((oldSize) => {
@@ -90,7 +86,9 @@ export const useModalSize = (): Size => {
90
86
  toOrientation === ORIENTATIONS.landscapeSensor;
91
87
 
92
88
  setNewModalSize(
93
- isLandscape ? MODAL_SIZE_FOR_LANDSCAPE : MODAL_SIZE_FOR_PORTRAIT,
89
+ isLandscape
90
+ ? MODAL_SIZE_FOR_LANDSCAPE
91
+ : { width: frame.width, height: frame.height },
94
92
  `useModalSize: set modal size ${
95
93
  isLandscape ? "landscape" : "portrait"
96
94
  } for orientation: ${to}`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-ui-components",
3
- "version": "12.0.0-alpha.4195481103",
3
+ "version": "12.0.0-alpha.4271512420",
4
4
  "description": "Applicaster Zapp React Native ui components for the Quick Brick App",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -34,10 +34,10 @@
34
34
  "redux-mock-store": "^1.5.3"
35
35
  },
36
36
  "dependencies": {
37
- "@applicaster/applicaster-types": "12.0.0-alpha.4195481103",
38
- "@applicaster/zapp-react-native-bridge": "12.0.0-alpha.4195481103",
39
- "@applicaster/zapp-react-native-redux": "12.0.0-alpha.4195481103",
40
- "@applicaster/zapp-react-native-utils": "12.0.0-alpha.4195481103",
37
+ "@applicaster/applicaster-types": "12.0.0-alpha.4271512420",
38
+ "@applicaster/zapp-react-native-bridge": "12.0.0-alpha.4271512420",
39
+ "@applicaster/zapp-react-native-redux": "12.0.0-alpha.4271512420",
40
+ "@applicaster/zapp-react-native-utils": "12.0.0-alpha.4271512420",
41
41
  "promise": "^8.3.0",
42
42
  "react-router-native": "^5.1.2",
43
43
  "url": "^0.11.0",