@applicaster/zapp-react-native-ui-components 12.0.0-alpha.4337072244 → 12.0.0-alpha.4354608902

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 (63) hide show
  1. package/Components/BaseFocusable/index.tsx +2 -2
  2. package/Components/Cell/Cell.tsx +9 -8
  3. package/Components/Cell/CellWithFocusable.tsx +7 -5
  4. package/Components/Cell/TvOSCellComponent.tsx +6 -11
  5. package/Components/Focusable/Focusable.tsx +6 -1
  6. package/Components/FocusableGroup/index.tsx +10 -2
  7. package/Components/Layout/TV/ScreenContainer.tsx +79 -5
  8. package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +38 -28
  9. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +25 -13
  10. package/Components/Layout/TV/__tests__/index.test.tsx +3 -2
  11. package/Components/Layout/TV/index.tsx +47 -41
  12. package/Components/Layout/TV/index.web.tsx +33 -0
  13. package/Components/Layout/index.tsx +15 -11
  14. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +88 -112
  15. package/Components/MasterCell/DefaultComponents/DynamicBadge.tsx +4 -2
  16. package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -1
  17. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +20 -0
  18. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.tsx +6 -1
  19. package/Components/MasterCell/utils/__tests__/insertBetween.test.js +9 -0
  20. package/Components/MasterCell/utils/index.ts +17 -30
  21. package/Components/NativeFocusables/{index.js → index.ts} +4 -2
  22. package/Components/Navigator/StackNavigator.tsx +57 -0
  23. package/Components/Navigator/index.ts +1 -0
  24. package/Components/PlayerContainer/PlayerContainer.tsx +2 -0
  25. package/Components/River/ComponentsMap/ComponentsMap.tsx +6 -0
  26. package/Components/River/RefreshControl.tsx +2 -2
  27. package/Components/RouteManager/index.tsx +2 -2
  28. package/Components/Screen/TV/hooks/useInitialFocus.ts +6 -3
  29. package/Components/Screen/TV/index.web.tsx +12 -21
  30. package/Components/Screen/__tests__/Screen.test.tsx +3 -0
  31. package/Components/Screen/index.tsx +55 -58
  32. package/Components/Screen/navigationHandler.ts +5 -0
  33. package/Components/Transitioner/Scene.tsx +32 -26
  34. package/Components/Transitioner/Transitioner.tsx +21 -28
  35. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +12 -4
  36. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +1 -0
  37. package/Components/VideoLive/LiveImageManager.ts +28 -1
  38. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +2 -14
  39. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +56 -43
  40. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +42 -32
  41. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +104 -86
  42. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +32 -4
  43. package/Components/VideoModal/ModalAnimation/utils.ts +7 -4
  44. package/Components/VideoModal/PlayerDetails.tsx +3 -3
  45. package/Components/VideoModal/PlayerWrapper.tsx +69 -62
  46. package/Components/VideoModal/VideoModal.tsx +4 -4
  47. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +7 -0
  48. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +32 -12
  49. package/Components/VideoModal/hooks/useModalSize.ts +10 -12
  50. package/Components/VideoModal/utils.ts +5 -2
  51. package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
  52. package/Contexts/FocusableGroupContext/FocusableGroupContext.ts +3 -0
  53. package/Contexts/FocusableGroupContext/FocusableGroupContextProvider.tsx +16 -0
  54. package/Contexts/FocusableGroupContext/__tests__/FocusableGroupContextProvider.test.tsx +22 -0
  55. package/Contexts/FocusableGroupContext/__tests__/withFocusableContext.test.tsx +26 -0
  56. package/Contexts/FocusableGroupContext/index.ts +7 -0
  57. package/Contexts/FocusableGroupContext/withFocusableContext.tsx +17 -0
  58. package/Contexts/ScreenDataContext/index.tsx +20 -0
  59. package/Decorators/Analytics/{index.js → index.tsx} +11 -11
  60. package/README.md +1 -13
  61. package/package.json +5 -5
  62. /package/Components/FocusableGroup/{index.android.js → index.android.ts} +0 -0
  63. /package/Components/FocusableGroup/{index.ios.js → index.ios.ts} +0 -0
@@ -1,20 +1,24 @@
1
1
  import * as React from "react";
2
- import { last, pathOr } from "ramda";
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";
11
11
  import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
12
- import { useScreenBackgroundColor } from "@applicaster/zapp-react-native-utils/reactHooks/screen";
12
+ import {
13
+ useNavbarState,
14
+ useScreenBackgroundColor,
15
+ } from "@applicaster/zapp-react-native-utils/reactHooks/screen";
13
16
  import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
14
17
 
15
18
  import { NavBarContainer } from "../../Layout/TV/NavBarContainer";
16
19
  import { ScreenResolver } from "../../ScreenResolver";
17
20
  import { useInitialFocus, useRestoreFocus } from "./hooks";
21
+ import { isPlayerPlugin } from "@applicaster/zapp-react-native-utils/pluginUtils";
18
22
 
19
23
  const styles = StyleSheet.create({
20
24
  container: {
@@ -36,16 +40,6 @@ type Props = {
36
40
  Components: Components;
37
41
  };
38
42
 
39
- const isPlayer = (routeState): boolean => {
40
- const pluginType = pathOr(
41
- "unknown_plugin_type",
42
- ["state", "screen", "plugin_type"],
43
- routeState
44
- );
45
-
46
- return pluginType === "player";
47
- };
48
-
49
43
  const getActiveRiver = ({
50
44
  screenId,
51
45
  screenType,
@@ -137,19 +131,17 @@ export const Screen = ({ route, Components }: Props) => {
137
131
  fallbackNavigations: navigator.activeRiver.navigations,
138
132
  });
139
133
 
140
- const menuPlugin = resolveNavigationPlugin({
141
- category: "menu",
142
- navigations,
143
- plugins,
144
- }) as QuickBrickPlugin;
134
+ const menuPlugin = findMenuPlugin(navigations, plugins);
145
135
 
146
136
  const NavBar = (Components.NavBar ||
147
137
  menuPlugin.module) as React.ComponentType<any>;
148
138
 
149
- const isNavBarVisible = !isPlayer(routeState);
139
+ const isPlayer = isPlayerPlugin(routeState);
140
+
141
+ const { visible: isNavBarVisible } = useNavbarState();
150
142
 
151
143
  const screenData =
152
- screenType === "hooks"
144
+ screenType === "hooks" || isPlayer
153
145
  ? routeState?.state?.entry
154
146
  : routeState?.state?.screen;
155
147
 
@@ -157,7 +149,6 @@ export const Screen = ({ route, Components }: Props) => {
157
149
  <View style={[styles.container, { backgroundColor }]}>
158
150
  <NavBarContainer isVisible={isNavBarVisible} onReady={noop}>
159
151
  <NavBar
160
- groupId={route}
161
152
  isVisible={isNavBarVisible}
162
153
  menuPlugin={menuPlugin}
163
154
  navigationProps={navigationProps}
@@ -10,6 +10,8 @@ const mock_navBarVisibleFlag = true;
10
10
 
11
11
  const mockIsNavBarVisible = jest.fn(() => mock_navBarVisibleFlag);
12
12
 
13
+ const mockIsOrientationCompatible = jest.fn(() => true);
14
+
13
15
  jest.mock("react-native-safe-area-context", () => ({
14
16
  useSafeAreaInsets: () => ({ top: 44 }),
15
17
  }));
@@ -21,6 +23,7 @@ jest.mock("../../RouteManager", () => ({
21
23
  jest.mock(
22
24
  "@applicaster/zapp-react-native-utils/appUtils/orientationHelper",
23
25
  () => ({
26
+ isOrientationCompatible: mockIsOrientationCompatible,
24
27
  allowedOrientationsForScreen: jest.fn(),
25
28
  getOrientation: jest.fn(),
26
29
  getScreenOrientation: jest.fn(),
@@ -3,14 +3,18 @@ import React from "react";
3
3
  import * as R from "ramda";
4
4
  import { View } from "react-native";
5
5
  import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
6
+ import {
7
+ isOrientationCompatible,
8
+ useGetScreenOrientation,
9
+ } from "@applicaster/zapp-react-native-utils/appUtils/orientationHelper";
6
10
 
7
11
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
8
12
  import { getComponentModule } from "@applicaster/zapp-react-native-utils/pluginUtils";
9
13
  import {
10
- getNavigationPropsV2,
11
- resolveNavigationPlugin,
14
+ shouldNavBarDisplayMenu,
15
+ getNavBarProps,
16
+ getScreenId,
12
17
  } from "@applicaster/zapp-react-native-utils/navigationUtils";
13
- import { useSafeAreaInsets } from "react-native-safe-area-context";
14
18
  import {
15
19
  useDimensions,
16
20
  useRoute,
@@ -21,20 +25,16 @@ import {
21
25
  } from "@applicaster/zapp-react-native-utils/reactHooks";
22
26
  import { getNavigationPluginModule } from "@applicaster/zapp-react-native-app/App/Layout/layoutHelpers";
23
27
 
24
- import { ScreenContextProvider } from "../../Contexts/ScreenContext";
25
28
  import { RouteManager } from "../RouteManager";
26
29
  import { useScreenConfiguration } from "../River/useScreenConfiguration";
27
30
  import { useScreenOrientationHandler } from "./orientationHandler";
28
31
 
29
- const getScreenId = (
30
- screenData: LegacyNavigationScreenData,
31
- fallbackRiver: ZappRiver
32
- ) => {
33
- return screenData?.targetScreen
34
- ? screenData?.targetScreen?.id ?? fallbackRiver.id
35
- : "screen_id" in screenData
36
- ? screenData.screen_id
37
- : 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
38
38
  };
39
39
 
40
40
  function colorIsNotTransparent(color) {
@@ -45,9 +45,7 @@ function colorIsNotTransparent(color) {
45
45
  R.replace("rgba(", "")
46
46
  )(color);
47
47
 
48
- const alpha = Number(layers?.[3]);
49
-
50
- return alpha > 0;
48
+ return Number(layers?.[3]) > 0;
51
49
  }
52
50
 
53
51
  function isValidColor(string) {
@@ -67,9 +65,12 @@ export function Screen(_props: Props) {
67
65
  // Gets the data for the current screen configuration
68
66
  const currentScreenData = useCurrentScreenData();
69
67
  const { backgroundColor } = useScreenConfiguration(currentScreenData.id);
70
- const insets = useSafeAreaInsets();
71
68
 
72
- const { width: screenWidth } = useDimensions("screen", {
69
+ const {
70
+ width: screenWidth,
71
+ height,
72
+ deviceInfo,
73
+ } = useDimensions("screen", {
73
74
  fullDimensions: true,
74
75
  });
75
76
 
@@ -81,30 +82,19 @@ export function Screen(_props: Props) {
81
82
 
82
83
  const { title } = useNavbarState();
83
84
 
84
- const hasMenu =
85
- resolveNavigationPlugin({
86
- category: "menu",
87
- navigations: currentRiver.navigations,
88
- plugins,
89
- })?.identifier === "quick_brick_side_menu";
90
-
91
- const navBarProps = React.useMemo<MobileNavBarPluginProps | null>(() => {
92
- const props = getNavigationPropsV2({
93
- currentRiver,
94
- title,
95
- category: "nav_bar",
96
- });
97
-
98
- if (props) {
99
- return {
100
- ...props,
101
- id: pathname,
102
- pathname: pathname,
103
- };
104
- }
105
-
106
- return null;
107
- }, [currentRiver, pathname]);
85
+ const isTablet = deviceInfo?.isTablet;
86
+
87
+ const { appData } = usePickFromState(["appData"]);
88
+ const isTabletPortrait = appData?.isTabletPortrait;
89
+
90
+ const layoutData = { isTablet, isTabletPortrait, width: screenWidth, height };
91
+
92
+ const hasMenu = shouldNavBarDisplayMenu(currentRiver, plugins);
93
+
94
+ const navBarProps = React.useMemo<MobileNavBarPluginProps | null>(
95
+ getNavBarProps(currentRiver, pathname, title),
96
+ [currentRiver, pathname]
97
+ );
108
98
 
109
99
  const NavBar = React.useMemo(
110
100
  () =>
@@ -126,16 +116,12 @@ export function Screen(_props: Props) {
126
116
 
127
117
  const style = React.useMemo(
128
118
  () => ({
129
- flex: 1,
119
+ ...screenStyles,
130
120
  backgroundColor: isValidColor(backgroundColor)
131
121
  ? backgroundColor
132
122
  : theme.app_background_color,
133
- paddingTop: 0,
134
- // paddingBottom: insets.bottom, // Should be applied directly by UI plugin
135
- // paddingLeft: insets.left, // Should be applied directly by UI plugin
136
- // paddingRight: insets.right, // Should be applied directly by UI plugin
137
123
  }),
138
- [insets, screenWidth, theme.app_background_color, backgroundColor]
124
+ [theme.app_background_color, backgroundColor]
139
125
  );
140
126
 
141
127
  const targetScreenData =
@@ -143,16 +129,27 @@ export function Screen(_props: Props) {
143
129
 
144
130
  useScreenOrientationHandler({ screenData: targetScreenData });
145
131
 
132
+ const orientation = useGetScreenOrientation(targetScreenData);
133
+
134
+ // We prevent rendering of the screen until UI is actually rotated to screen desired orientation.
135
+ // This saves unnecessary re-renders and user will not see distorted aspect screen.
136
+ if (
137
+ !isOrientationCompatible({
138
+ orientation,
139
+ layoutData,
140
+ })
141
+ ) {
142
+ return <View style={style} />;
143
+ }
144
+
146
145
  return (
147
- <ScreenContextProvider pathname={pathname}>
148
- <View style={style}>
149
- {navBarProps && <NavBar {...navBarProps} hasMenu={hasMenu} />}
150
-
151
- <OfflineFallbackScreen screenData={targetScreenData}>
152
- {/* @TODO RouteManager doesn't use props, can they be removed ? */}
153
- <RouteManager pathname={pathname} screenData={screenData} />
154
- </OfflineFallbackScreen>
155
- </View>
156
- </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>
157
154
  );
158
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,12 +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";
5
+ import { ScreenDataContext } from "../../Contexts/ScreenDataContext";
6
+ import { ScreenContextProvider } from "../../Contexts/ScreenContext";
10
7
 
11
8
  type Props = {
12
9
  children: any;
@@ -16,6 +13,8 @@ type Props = {
16
13
  animating: boolean;
17
14
  contentStyle: ViewStyle;
18
15
  pathname: string;
16
+ isActive: boolean;
17
+ screenData: NavigationScreenData;
19
18
  };
20
19
 
21
20
  /**
@@ -38,34 +37,41 @@ export function Scene({
38
37
  animating,
39
38
  contentStyle,
40
39
  pathname,
40
+ isActive = false,
41
+ screenData,
41
42
  }: Props) {
43
+ const [initialScreenData, setInitialScreenData] = React.useState(screenData);
44
+
45
+ React.useLayoutEffect(() => {
46
+ if (isActive) {
47
+ setInitialScreenData(screenData);
48
+ }
49
+ }, [screenData, isActive]);
50
+
42
51
  const frame = useSafeAreaFrame();
43
- const { height, width } = useWindowDimensions();
44
52
 
45
- if (overlayStyle && animating) {
46
- // Safe frame takes too long to update,
47
- // so we can not rely on it there, and use height and width instead.
48
- return (
49
- <Animated.View
50
- pointerEvents={pointerEvents}
51
- style={[style, contentStyle, { height, width }]}
52
- >
53
- <PathnameContext.Provider value={pathname}>
54
- {children}
55
- </PathnameContext.Provider>
56
- <Animated.View style={overlayStyle} />
57
- </Animated.View>
58
- );
59
- }
53
+ const isAnimating = animating && overlayStyle;
54
+
55
+ const dimensions = isAnimating
56
+ ? {
57
+ height: "100%",
58
+ width: "100%",
59
+ }
60
+ : frame;
60
61
 
61
62
  return (
62
63
  <Animated.View
63
64
  pointerEvents={pointerEvents}
64
- style={[style, contentStyle, frame]}
65
+ style={[style, contentStyle, dimensions]}
65
66
  >
66
- <PathnameContext.Provider value={pathname}>
67
- {children}
68
- </PathnameContext.Provider>
67
+ <ScreenDataContext.Provider value={initialScreenData}>
68
+ <PathnameContext.Provider value={pathname}>
69
+ <ScreenContextProvider pathname={pathname}>
70
+ {children}
71
+ </ScreenContextProvider>
72
+ </PathnameContext.Provider>
73
+ </ScreenDataContext.Provider>
74
+ {isAnimating && <Animated.View style={overlayStyle} />}
69
75
  </Animated.View>
70
76
  );
71
77
  }
@@ -4,10 +4,7 @@ import * as R from "ramda";
4
4
 
5
5
  import { AnimationManager } from "./AnimationManager";
6
6
  import { Scene } from "./Scene";
7
- import {
8
- getScreenOrientation,
9
- isOrientationCompatible,
10
- } from "@applicaster/zapp-react-native-utils/appUtils/orientationHelper";
7
+
11
8
  import {
12
9
  getSceneByRoute,
13
10
  shouldSkipAnimationForPreviousWebViewScene,
@@ -277,33 +274,25 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
277
274
  // so only a single scene should be rendered,
278
275
  // instead of dangerous nulls or duplicates.
279
276
  renderSingleScene({ scenes, to }) {
280
- const { contentStyle, layoutData } = this.props;
281
- const screenData = scenes[to.index]?.children?.props?.screenData;
282
-
283
- const orientation = getScreenOrientation({
284
- screenData,
285
- layoutData,
286
- });
277
+ const { contentStyle } = this.props;
278
+ const screenData = this.props.children.props.screenData;
279
+ const pathname = scenes[to.index].key;
287
280
 
288
- // We prevent rendering of the screen until UI is actually rotated to screen desired orientation.
289
- // This saves unnecessary re-renders and user will not see distorted aspect screen.
290
281
  return (
291
282
  <View style={styles.container}>
292
- {scenes[to.index] &&
293
- isOrientationCompatible({
294
- orientation,
295
- layoutData,
296
- }) && (
297
- <Scene
298
- {...{ style: to.style }}
299
- pathname={scenes[to.index].key}
300
- contentStyle={contentStyle}
301
- key={scenes[to.index].key}
302
- screenUniqueId={scenes[to.index].screenUniqueId}
303
- >
304
- {scenes[to.index].children}
305
- </Scene>
306
- )}
283
+ {scenes[to.index] && (
284
+ <Scene
285
+ {...{ style: to.style }}
286
+ pathname={pathname}
287
+ isActive={pathname === this.props.navigator.currentRoute}
288
+ contentStyle={contentStyle}
289
+ key={scenes[to.index].key}
290
+ screenUniqueId={scenes[to.index].screenUniqueId}
291
+ screenData={screenData}
292
+ >
293
+ {scenes[to.index].children}
294
+ </Scene>
295
+ )}
307
296
  </View>
308
297
  );
309
298
  }
@@ -319,12 +308,14 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
319
308
  <Scene
320
309
  key={scenes[from.index].key}
321
310
  pathname={scenes[from.index].key}
311
+ isActive={scenes[from.index].key === this.props.navigator.currentRoute}
322
312
  style={from.style}
323
313
  pointerEvents="none"
324
314
  overlayStyle={from.overlayStyle}
325
315
  animating={this.state.animating}
326
316
  contentStyle={contentStyle}
327
317
  screenUniqueId={scenes[from.index].screenUniqueId}
318
+ screenData={scenes[from.index].children.props.screenData}
328
319
  >
329
320
  {scenes[from.index].children}
330
321
  </Scene>
@@ -333,12 +324,14 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
333
324
  const toScene = scenes[to.index] && (
334
325
  <Scene
335
326
  pathname={scenes[to.index].key}
327
+ isActive={scenes[to.index].key === this.props.navigator.currentRoute}
336
328
  key={scenes[to.index].key}
337
329
  style={to.style}
338
330
  overlayStyle={to.overlayStyle}
339
331
  animating={this.state.animating}
340
332
  contentStyle={contentStyle}
341
333
  screenUniqueId={scenes[to.index].screenUniqueId}
334
+ screenData={this.props.children.props.screenData}
342
335
  >
343
336
  {scenes[to.index].children}
344
337
  </Scene>
@@ -21,7 +21,11 @@ exports[`<Scene /> renders correctly 1`] = `
21
21
  ]
22
22
  }
23
23
  >
24
- <ContextProvider />
24
+ <ContextProvider>
25
+ <ContextProvider>
26
+ <ScreenContextProvider />
27
+ </ContextProvider>
28
+ </ContextProvider>
25
29
  </ForwardRef(AnimatedComponentWrapper)>
26
30
  `;
27
31
 
@@ -37,13 +41,17 @@ exports[`<Scene /> renders the overlay while animating 1`] = `
37
41
  "paddingBottom": 49,
38
42
  },
39
43
  Object {
40
- "height": 1334,
41
- "width": 750,
44
+ "height": "100%",
45
+ "width": "100%",
42
46
  },
43
47
  ]
44
48
  }
45
49
  >
46
- <ContextProvider />
50
+ <ContextProvider>
51
+ <ContextProvider>
52
+ <ScreenContextProvider />
53
+ </ContextProvider>
54
+ </ContextProvider>
47
55
  <ForwardRef(AnimatedComponentWrapper)
48
56
  style={
49
57
  Object {
@@ -10,6 +10,7 @@ exports[`<TransitionerComponent /> renders correctly 1`] = `
10
10
  }
11
11
  >
12
12
  <Scene
13
+ isActive={true}
13
14
  screenUniqueId="mocked-uuid"
14
15
  >
15
16
  <View
@@ -10,7 +10,11 @@ import { Component } from "react";
10
10
 
11
11
  const { log_debug, log_info, log_error } = loggerLiveImageManager;
12
12
 
13
- export type LiveImageManagerEvent = "onEnd" | "onStart" | "onError";
13
+ export type LiveImageManagerEvent =
14
+ | "onEnd"
15
+ | "onStart"
16
+ | "onError"
17
+ | "onDestroy";
14
18
 
15
19
  export type LiveImageManagerListenerData = {
16
20
  id: string;
@@ -102,6 +106,16 @@ export class LiveImageManager implements PlayerLifecycleListener {
102
106
  }
103
107
 
104
108
  this.items = this.items.filter((i) => i !== item);
109
+
110
+ this.invokeListenersUpdate({
111
+ callbackName: "onDestroy",
112
+ event: {
113
+ item,
114
+ playerId: this.currentlyPlaying?.playerId,
115
+ primaryPlayerId: this.primaryPlayer?.playerId,
116
+ entry: item.getPlayer().getEntry(),
117
+ },
118
+ });
105
119
  };
106
120
 
107
121
  public onViewportEnter = (item: LiveImage) => {
@@ -351,6 +365,7 @@ export class LiveImageManager implements PlayerLifecycleListener {
351
365
  item,
352
366
  playerId: this.currentlyPlaying?.playerId,
353
367
  primaryPlayerId: this.primaryPlayer?.playerId,
368
+ entry: item.getPlayer().getEntry(),
354
369
  },
355
370
  });
356
371
  };
@@ -385,6 +400,7 @@ export class LiveImageManager implements PlayerLifecycleListener {
385
400
  item,
386
401
  playerId: this.currentlyPlaying?.playerId,
387
402
  primaryPlayerId: this.primaryPlayer?.playerId,
403
+ entry: item.getPlayer().getEntry(),
388
404
  },
389
405
  });
390
406
  };
@@ -419,6 +435,7 @@ export class LiveImageManager implements PlayerLifecycleListener {
419
435
  error,
420
436
  playerId: currentItem?.playerId,
421
437
  primaryPlayerId: currentItem?.playerId,
438
+ entry: item.getPlayer().getEntry(),
422
439
  },
423
440
  });
424
441
  };
@@ -508,6 +525,16 @@ export class LiveImage implements QuickBrickPlayer.SharedPlayerCallBacks {
508
525
  LiveImageManager.instance.onLiveImageError(this, error);
509
526
  };
510
527
 
528
+ onVideoError = (error: Error) => {
529
+ log_error(
530
+ `onVideoError: live-image, fail to play, switching back to image. error: ${
531
+ error?.message
532
+ }, ${playerInfo(this.player)}`
533
+ );
534
+
535
+ LiveImageManager.instance.onLiveImageError(this, error);
536
+ };
537
+
511
538
  onVideoEnd = (_event) => {
512
539
  log_info(
513
540
  `onVideoEnd: live-image, video completed, switching back to image, ${playerInfo(
@@ -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 () => {