@applicaster/zapp-react-native-ui-components 12.0.0-alpha.5468407101 → 12.0.0-alpha.5471145113

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 (53) hide show
  1. package/Components/BaseFocusable/index.tsx +1 -1
  2. package/Components/Cell/Cell.tsx +5 -5
  3. package/Components/Cell/CellWithFocusable.tsx +17 -5
  4. package/Components/FocusableGroup/index.tsx +1 -0
  5. package/Components/HandlePlayable/HandlePlayable.tsx +3 -0
  6. package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +2 -2
  7. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +10 -50
  8. package/Components/Layout/TV/__tests__/index.test.tsx +19 -75
  9. package/Components/Layout/TV/index.tsx +12 -11
  10. package/Components/Layout/TV/index.web.tsx +33 -0
  11. package/Components/Layout/index.tsx +15 -11
  12. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -0
  13. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +80 -109
  14. package/Components/MasterCell/DefaultComponents/DynamicBadge.tsx +4 -2
  15. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -1
  16. package/Components/MasterCell/DefaultComponents/Text/index.tsx +14 -2
  17. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +24 -9
  18. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +4 -1
  19. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.tsx +4 -1
  20. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
  21. package/Components/MasterCell/utils/index.ts +12 -29
  22. package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
  23. package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
  24. package/Components/Navigator/StackNavigator.tsx +48 -0
  25. package/Components/Navigator/index.ts +1 -0
  26. package/Components/PlayerContainer/PlayerContainer.tsx +8 -1
  27. package/Components/River/ComponentsMap/ComponentsMap.tsx +6 -0
  28. package/Components/River/RefreshControl.tsx +2 -2
  29. package/Components/River/TV/River.tsx +0 -23
  30. package/Components/RouteManager/index.tsx +2 -2
  31. package/Components/Screen/TV/hooks/index.ts +3 -0
  32. package/Components/Screen/TV/hooks/useInitialFocus.ts +70 -0
  33. package/Components/Screen/TV/hooks/useRestoreFocus.ts +22 -0
  34. package/Components/Screen/TV/index.web.tsx +179 -0
  35. package/Components/Screen/__tests__/Screen.test.tsx +3 -0
  36. package/Components/Screen/index.tsx +29 -1
  37. package/Components/ScreenResolver/index.tsx +3 -1
  38. package/Components/Transitioner/Scene.tsx +24 -19
  39. package/Components/Transitioner/Transitioner.tsx +21 -28
  40. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +6 -2
  41. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +1 -0
  42. package/Components/VideoLive/LiveImageManager.ts +18 -1
  43. package/Components/VideoModal/PlayerDetails.tsx +3 -3
  44. package/Components/VideoModal/PlayerWrapper.tsx +67 -60
  45. package/Components/VideoModal/VideoModal.tsx +4 -4
  46. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +7 -0
  47. package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
  48. package/Contexts/ScreenContext/index.tsx +6 -0
  49. package/Contexts/ScreenDataContext/index.tsx +20 -0
  50. package/Contexts/ZappPipesContext/ZappPipesEntryContext.ts +1 -1
  51. package/events/index.ts +1 -0
  52. package/package.json +5 -5
  53. package/Components/Layout/TV/TransitionOverlay.tsx +0 -64
@@ -7,14 +7,10 @@ import * as R from "ramda";
7
7
  import {
8
8
  useFeedLoader,
9
9
  useLayoutVersion,
10
- useNavigationPluginData,
11
10
  } from "@applicaster/zapp-react-native-utils/reactHooks";
12
11
  import { GeneralContentScreen } from "../../GeneralContentScreen";
13
12
  import { ScreenResolver } from "@applicaster/zapp-react-native-ui-components/Components/ScreenResolver";
14
13
  import { utilsLogger } from "@applicaster/zapp-react-native-utils/logger";
15
- import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils";
16
- import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
17
- import { isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
18
14
  import {
19
15
  useNavbarState,
20
16
  useSetNavbarState,
@@ -51,8 +47,6 @@ export const River = (props: Props) => {
51
47
  const { setTitle: setScreenTitle, setSummary: setScreenSummary } =
52
48
  useSetNavbarState();
53
49
 
54
- const navigationPluginData = useNavigationPluginData();
55
-
56
50
  const rivers = useRivers();
57
51
  const isV2 = useLayoutVersion({ isV2: true });
58
52
 
@@ -99,23 +93,6 @@ export const River = (props: Props) => {
99
93
  }
100
94
  }, [feedData, screenData, screenTitle, screenSummary]);
101
95
 
102
- React.useEffect(() => {
103
- if (
104
- isWeb() &&
105
- toBooleanWithDefaultFalse(
106
- navigationPluginData?.rules?.focus_on_content
107
- ) &&
108
- river &&
109
- river.type !== "general_content"
110
- ) {
111
- const groupId = R.pathOr("river", ["groupId"], componentsMapExtraProps);
112
-
113
- focusManager.setupInitialFocus(groupId, true);
114
- focusManager.setInitialFocus();
115
- focusManager.enableAutomaticFocus();
116
- }
117
- }, [river, componentsMapExtraProps]);
118
-
119
96
  if (!river) {
120
97
  utilsLogger.error({
121
98
  message: `River ${screenData.id} not found!`,
@@ -14,7 +14,7 @@ type Props = { pathname: string; screenData: Record<string, any> };
14
14
  * @param {Props}: see props above
15
15
  */
16
16
  export function RouteManager(props: Props) {
17
- const { pathname, screenData: _screenData } = useRoute();
17
+ const { pathname, screenData } = useRoute();
18
18
  const pathAttributes = getPathAttributes({ pathname });
19
19
 
20
20
  const { screenType, screenId } = R.last(pathAttributes);
@@ -25,7 +25,7 @@ export function RouteManager(props: Props) {
25
25
  screenType={screenType}
26
26
  screenId={screenId}
27
27
  {...props}
28
- screenData={props.screenData}
28
+ screenData={screenData}
29
29
  />
30
30
  </TestId>
31
31
  );
@@ -0,0 +1,3 @@
1
+ export { useInitialFocus } from "./useInitialFocus";
2
+
3
+ export { useRestoreFocus } from "./useRestoreFocus";
@@ -0,0 +1,70 @@
1
+ import * as React from "react";
2
+ import {
3
+ useNavigationPluginData,
4
+ useIsNavBarVisible,
5
+ useRoute,
6
+ } from "@applicaster/zapp-react-native-utils/reactHooks";
7
+ import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
8
+ import {
9
+ setFocusOnContent,
10
+ setFocusOnMenu,
11
+ } from "@applicaster/zapp-react-native-utils/appUtils/focusManagerAux";
12
+
13
+ type Return =
14
+ | {
15
+ onContent: true;
16
+ onMenu: false;
17
+ }
18
+ | {
19
+ onContent: false;
20
+ onMenu: true;
21
+ };
22
+
23
+ const getInitialFocus = (focusOnContent, isNavBarVisible): Return => {
24
+ if (focusOnContent) {
25
+ return {
26
+ onContent: true,
27
+ onMenu: false,
28
+ };
29
+ }
30
+
31
+ if (!focusOnContent && isNavBarVisible) {
32
+ // put focus on navbar
33
+ return {
34
+ onContent: false,
35
+ onMenu: true,
36
+ };
37
+ }
38
+
39
+ // we don't have navbar, put focus on content anyway
40
+ return {
41
+ onContent: true,
42
+ onMenu: false,
43
+ };
44
+ };
45
+
46
+ export const useInitialFocus = (): void => {
47
+ const navigationPluginData = useNavigationPluginData();
48
+
49
+ const focusOnContent = toBooleanWithDefaultFalse(
50
+ navigationPluginData?.rules?.focus_on_content
51
+ );
52
+
53
+ const isNavBarVisible = useIsNavBarVisible();
54
+
55
+ const { pathname: currentRoute } = useRoute();
56
+
57
+ React.useEffect(() => {
58
+ const initialFocus = getInitialFocus(focusOnContent, isNavBarVisible);
59
+
60
+ if (initialFocus.onContent) {
61
+ setFocusOnContent(currentRoute);
62
+
63
+ return;
64
+ }
65
+
66
+ if (initialFocus.onMenu) {
67
+ setFocusOnMenu(currentRoute);
68
+ }
69
+ }, []);
70
+ };
@@ -0,0 +1,22 @@
1
+ import * as React from "react";
2
+ import { isNil } from "ramda";
3
+ import { useIsScreenActive } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
4
+ import { usePrevious } from "@applicaster/zapp-react-native-utils/reactHooks/utils";
5
+ import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
6
+
7
+ export const useRestoreFocus = (): void => {
8
+ const isScreenActive = useIsScreenActive();
9
+ const previousIsScreenActive = usePrevious(isScreenActive);
10
+
11
+ React.useEffect(() => {
12
+ if (isNil(previousIsScreenActive)) {
13
+ // it's initial mounting of the screen, do nothing here
14
+ return;
15
+ }
16
+
17
+ if (!previousIsScreenActive && isScreenActive) {
18
+ // restore focus when we go back from next screen
19
+ focusManager.setInitialFocus();
20
+ }
21
+ }, [previousIsScreenActive, isScreenActive]);
22
+ };
@@ -0,0 +1,179 @@
1
+ import * as React from "react";
2
+ import { last, pathOr } from "ramda";
3
+ import { View, StyleSheet } from "react-native";
4
+ import {
5
+ getNavigationProps,
6
+ getPathAttributes,
7
+ resolveNavigationPlugin,
8
+ } from "@applicaster/zapp-react-native-utils/navigationUtils";
9
+ import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
10
+ import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
11
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
12
+ import { useScreenBackgroundColor } from "@applicaster/zapp-react-native-utils/reactHooks/screen";
13
+ import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
14
+
15
+ import { NavBarContainer } from "../../Layout/TV/NavBarContainer";
16
+ import { ScreenResolver } from "../../ScreenResolver";
17
+ import { useInitialFocus, useRestoreFocus } from "./hooks";
18
+
19
+ const styles = StyleSheet.create({
20
+ container: {
21
+ position: "absolute",
22
+ top: 0,
23
+ left: 0,
24
+ right: 0,
25
+ bottom: 0,
26
+ },
27
+ });
28
+
29
+ type Components = {
30
+ NavBar: React.ComponentType<any>;
31
+ Background: React.ComponentType<any>;
32
+ };
33
+
34
+ type Props = {
35
+ route: string;
36
+ Components: Components;
37
+ };
38
+
39
+ const getPluginType = pathOr("unknown_plugin_type", [
40
+ "state",
41
+ "screen",
42
+ "plugin_type",
43
+ ]);
44
+
45
+ const isPlayerPlugin = (routeState): boolean =>
46
+ getPluginType(routeState) === "player";
47
+
48
+ const isLoginPlugin = (routeState): boolean =>
49
+ getPluginType(routeState) === "login";
50
+
51
+ const getActiveRiver = ({
52
+ screenId,
53
+ screenType,
54
+ routeState,
55
+ rivers,
56
+ fallbackActiveRiver,
57
+ }) => {
58
+ if (rivers[screenId]) {
59
+ if (screenType === "hooks") {
60
+ const navigations = routeState?.state?.entry?.payload?.navigations;
61
+
62
+ if (navigations) {
63
+ return routeState.state.entry.payload;
64
+ }
65
+ }
66
+
67
+ return routeState?.state?.screen;
68
+ }
69
+
70
+ // screenId is not presented into rivers, use fallback instead
71
+ return fallbackActiveRiver;
72
+ };
73
+
74
+ const getNavigations = ({
75
+ screenId,
76
+ screenType,
77
+ routeState,
78
+ rivers,
79
+ fallbackNavigations,
80
+ }) => {
81
+ if (rivers[screenId]) {
82
+ // river presents
83
+ if (screenType === "hooks") {
84
+ const navigations = routeState?.state?.entry?.payload?.navigations;
85
+
86
+ if (navigations) {
87
+ return navigations;
88
+ }
89
+ }
90
+
91
+ return routeState?.state?.screen?.navigations;
92
+ }
93
+
94
+ // screenId is not presented into rivers, use fallback instead
95
+ return fallbackNavigations;
96
+ };
97
+
98
+ export const Screen = ({ route, Components }: Props) => {
99
+ if (isNilOrEmpty(route)) {
100
+ throw Error("Required props: route is missing");
101
+ }
102
+
103
+ const navigator = useNavigation();
104
+ const { plugins = [], rivers = [] } = usePickFromState(["plugins", "rivers"]);
105
+
106
+ const pathAttributes = getPathAttributes({ pathname: route });
107
+ const routeState = navigator.getStackForPathname(route);
108
+
109
+ const { screenType, screenId } = last(pathAttributes);
110
+
111
+ const backgroundColor = useScreenBackgroundColor(screenId);
112
+
113
+ useInitialFocus();
114
+ useRestoreFocus();
115
+
116
+ const activeRiver = getActiveRiver({
117
+ screenId,
118
+ screenType,
119
+ routeState,
120
+ rivers,
121
+ fallbackActiveRiver: navigator.activeRiver,
122
+ });
123
+
124
+ const navigationProps = getNavigationProps({
125
+ navigator: {
126
+ // @ts-ignore
127
+ activeRiver,
128
+ // @ts-ignore
129
+ screenTitle: routeState.state.entry?.title || routeState.screen?.name,
130
+ },
131
+ category: "menu",
132
+ });
133
+
134
+ const navigations = getNavigations({
135
+ screenId,
136
+ screenType,
137
+ routeState,
138
+ rivers,
139
+ fallbackNavigations: navigator.activeRiver.navigations,
140
+ });
141
+
142
+ const menuPlugin = resolveNavigationPlugin({
143
+ category: "menu",
144
+ navigations,
145
+ plugins,
146
+ }) as QuickBrickPlugin;
147
+
148
+ const NavBar = (Components.NavBar ||
149
+ menuPlugin.module) as React.ComponentType<any>;
150
+
151
+ const isPlayer = isPlayerPlugin(routeState);
152
+ const isLogin = isLoginPlugin(routeState);
153
+
154
+ const isNavBarVisible = !isPlayer && !isLogin;
155
+
156
+ const screenData =
157
+ screenType === "hooks" || isPlayer
158
+ ? routeState?.state?.entry
159
+ : routeState?.state?.screen;
160
+
161
+ return (
162
+ <View style={[styles.container, { backgroundColor }]}>
163
+ <NavBarContainer isVisible={isNavBarVisible} onReady={noop}>
164
+ <NavBar
165
+ groupId={route}
166
+ isVisible={isNavBarVisible}
167
+ menuPlugin={menuPlugin}
168
+ navigationProps={navigationProps}
169
+ />
170
+ </NavBarContainer>
171
+ <ScreenResolver
172
+ screenType={screenType}
173
+ screenId={screenId}
174
+ screenData={screenData}
175
+ groupId={route}
176
+ />
177
+ </View>
178
+ );
179
+ };
@@ -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,6 +3,10 @@ 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";
@@ -69,7 +73,11 @@ export function Screen(_props: Props) {
69
73
  const { backgroundColor } = useScreenConfiguration(currentScreenData.id);
70
74
  const insets = useSafeAreaInsets();
71
75
 
72
- const { width: screenWidth } = useDimensions("screen", {
76
+ const {
77
+ width: screenWidth,
78
+ height,
79
+ deviceInfo,
80
+ } = useDimensions("screen", {
73
81
  fullDimensions: true,
74
82
  });
75
83
 
@@ -81,6 +89,13 @@ export function Screen(_props: Props) {
81
89
 
82
90
  const { title } = useNavbarState();
83
91
 
92
+ const isTablet = deviceInfo?.isTablet;
93
+
94
+ const { appData } = usePickFromState(["appData"]);
95
+ const isTabletPortrait = appData?.isTabletPortrait;
96
+
97
+ const layoutData = { isTablet, isTabletPortrait, width: screenWidth, height };
98
+
84
99
  const hasMenu =
85
100
  resolveNavigationPlugin({
86
101
  category: "menu",
@@ -143,6 +158,19 @@ export function Screen(_props: Props) {
143
158
 
144
159
  useScreenOrientationHandler({ screenData: targetScreenData });
145
160
 
161
+ const orientation = useGetScreenOrientation(targetScreenData);
162
+
163
+ // We prevent rendering of the screen until UI is actually rotated to screen desired orientation.
164
+ // This saves unnecessary re-renders and user will not see distorted aspect screen.
165
+ if (
166
+ !isOrientationCompatible({
167
+ orientation,
168
+ layoutData,
169
+ })
170
+ ) {
171
+ return null;
172
+ }
173
+
146
174
  return (
147
175
  <ScreenContextProvider pathname={pathname}>
148
176
  <View style={style}>
@@ -32,12 +32,13 @@ type Props = {
32
32
  nextFocusLeft?: React.Ref<any>;
33
33
  nextFocusUp?: React.Ref<any>;
34
34
  };
35
+ groupId?: string;
35
36
  };
36
37
 
37
38
  export function ScreenResolverComponent(props: Props) {
38
39
  useScreenAnalytics(props);
39
40
 
40
- const { screenType, screenId, screenData } = props;
41
+ const { screenType, screenId, screenData, groupId } = props;
41
42
 
42
43
  const { hookPlugin } = screenData || {};
43
44
 
@@ -81,6 +82,7 @@ export function ScreenResolverComponent(props: Props) {
81
82
  item={screenData}
82
83
  mode={mode === "PIP" ? "PIP" : "FULLSCREEN"}
83
84
  isModal={false}
85
+ groupId={groupId}
84
86
  />
85
87
  );
86
88
  }
@@ -7,6 +7,7 @@ import {
7
7
  } from "react-native";
8
8
  import { useSafeAreaFrame } from "react-native-safe-area-context";
9
9
  import { PathnameContext } from "../../Contexts/PathnameContext";
10
+ import { ScreenDataContext } from "../../Contexts/ScreenDataContext";
10
11
 
11
12
  type Props = {
12
13
  children: any;
@@ -16,6 +17,8 @@ type Props = {
16
17
  animating: boolean;
17
18
  contentStyle: ViewStyle;
18
19
  pathname: string;
20
+ isActive: boolean;
21
+ screenData: NavigationScreenData;
19
22
  };
20
23
 
21
24
  /**
@@ -38,34 +41,36 @@ export function Scene({
38
41
  animating,
39
42
  contentStyle,
40
43
  pathname,
44
+ isActive = false,
45
+ screenData,
41
46
  }: Props) {
47
+ const [initialScreenData, setInitialScreenData] = React.useState(screenData);
48
+
49
+ React.useLayoutEffect(() => {
50
+ if (isActive) {
51
+ setInitialScreenData(screenData);
52
+ }
53
+ }, [screenData, isActive]);
54
+
42
55
  const frame = useSafeAreaFrame();
43
56
  const { height, width } = useWindowDimensions();
44
57
 
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
- }
58
+ // Safe frame takes too long to update,
59
+ // so we can not rely on it there, and use height and width instead.
60
+ const isAnimating = animating && overlayStyle;
61
+ const dimensions = isAnimating ? { height, width } : frame;
60
62
 
61
63
  return (
62
64
  <Animated.View
63
65
  pointerEvents={pointerEvents}
64
- style={[style, contentStyle, frame]}
66
+ style={[style, contentStyle, dimensions]}
65
67
  >
66
- <PathnameContext.Provider value={pathname}>
67
- {children}
68
- </PathnameContext.Provider>
68
+ <ScreenDataContext.Provider value={initialScreenData}>
69
+ <PathnameContext.Provider value={pathname}>
70
+ {children}
71
+ </PathnameContext.Provider>
72
+ </ScreenDataContext.Provider>
73
+ {isAnimating && <Animated.View style={overlayStyle} />}
69
74
  </Animated.View>
70
75
  );
71
76
  }
@@ -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,9 @@ exports[`<Scene /> renders correctly 1`] = `
21
21
  ]
22
22
  }
23
23
  >
24
- <ContextProvider />
24
+ <ContextProvider>
25
+ <ContextProvider />
26
+ </ContextProvider>
25
27
  </ForwardRef(AnimatedComponentWrapper)>
26
28
  `;
27
29
 
@@ -43,7 +45,9 @@ exports[`<Scene /> renders the overlay while animating 1`] = `
43
45
  ]
44
46
  }
45
47
  >
46
- <ContextProvider />
48
+ <ContextProvider>
49
+ <ContextProvider />
50
+ </ContextProvider>
47
51
  <ForwardRef(AnimatedComponentWrapper)
48
52
  style={
49
53
  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
  };