@applicaster/zapp-react-native-ui-components 12.0.0-alpha.3804385444 → 12.0.0-alpha.4201443043

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 (64) 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/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +13 -6
  6. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
  7. package/Components/HandlePlayable/HandlePlayable.tsx +3 -0
  8. package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +2 -2
  9. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +10 -50
  10. package/Components/Layout/TV/__tests__/index.test.tsx +18 -74
  11. package/Components/Layout/TV/index.tsx +9 -105
  12. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -0
  13. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +111 -52
  14. package/Components/MasterCell/DefaultComponents/DynamicBadge.tsx +4 -2
  15. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -3
  16. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -1
  17. package/Components/MasterCell/DefaultComponents/Text/index.tsx +14 -2
  18. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  19. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +24 -9
  20. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +4 -1
  21. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.tsx +4 -1
  22. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +1 -3
  23. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
  24. package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
  25. package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
  26. package/Components/Navigator/StackNavigator.tsx +48 -0
  27. package/Components/Navigator/index.ts +1 -0
  28. package/Components/PlayerContainer/PlayerContainer.tsx +12 -6
  29. package/Components/River/ComponentsMap/ComponentsMap.tsx +92 -22
  30. package/Components/River/RefreshControl.tsx +55 -1
  31. package/Components/River/TV/River.tsx +0 -23
  32. package/Components/RouteManager/index.tsx +2 -2
  33. package/Components/Screen/TV/hooks/index.ts +3 -0
  34. package/Components/Screen/TV/hooks/useInitialFocus.ts +70 -0
  35. package/Components/Screen/TV/hooks/useRestoreFocus.ts +22 -0
  36. package/Components/Screen/TV/index.web.tsx +179 -0
  37. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +4 -0
  38. package/Components/Screen/index.tsx +35 -24
  39. package/Components/ScreenResolver/index.tsx +3 -1
  40. package/Components/Transitioner/Scene.tsx +24 -19
  41. package/Components/Transitioner/Transitioner.tsx +9 -2
  42. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +6 -2
  43. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +1 -0
  44. package/Components/VideoLive/LiveImageManager.ts +18 -1
  45. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +0 -5
  46. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +11 -4
  47. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +9 -2
  48. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +13 -2
  49. package/Components/VideoModal/PlayerWrapper.tsx +67 -60
  50. package/Components/VideoModal/VideoModal.tsx +19 -19
  51. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +7 -0
  52. package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
  53. package/Components/Viewport/ViewportTracker/index.tsx +1 -0
  54. package/Components/Viewport/utils.js +1 -1
  55. package/Contexts/MenuToggleContext/{index.js → index.ts} +16 -0
  56. package/Contexts/ScreenContext/__tests__/__snapshots__/index.test.tsx.snap +3 -0
  57. package/Contexts/ScreenContext/__tests__/index.test.tsx +27 -0
  58. package/Contexts/ScreenContext/index.tsx +94 -25
  59. package/Contexts/ScreenDataContext/index.ts +3 -0
  60. package/Contexts/ZappPipesContext/ZappPipesEntryContext.ts +1 -1
  61. package/events/index.ts +1 -0
  62. package/package.json +5 -5
  63. package/Components/Layout/TV/TransitionOverlay.tsx +0 -64
  64. /package/Contexts/{index.js → index.ts} +0 -0
@@ -7,33 +7,72 @@ type BorderPosition = "inside" | "outside" | "center";
7
7
  interface Props {
8
8
  style: ImageStyle | ViewStyle;
9
9
  borderPosition: BorderPosition;
10
- borderPaddingTop: number;
11
- borderPaddingRight: number;
12
- borderPaddingBottom: number;
13
- borderPaddingLeft: number;
14
10
  children: React.ReactNode;
15
11
  }
16
12
 
17
- const COLOR_TRANSPARENT = "transparent";
13
+ const MARGINS = [
14
+ "marginTop",
15
+ "marginBottom",
16
+ "marginLeft",
17
+ "marginRight",
18
+ ] as const;
18
19
 
19
- const styles = StyleSheet.create({
20
- container: {
21
- overflow: "visible",
22
- borderWidth: 0,
23
- borderColor: COLOR_TRANSPARENT,
24
- },
25
- });
20
+ const PADDINGS = [
21
+ "paddingTop",
22
+ "paddingBottom",
23
+ "paddingLeft",
24
+ "paddingRight",
25
+ ] as const;
26
26
 
27
- const getBorderPadding = (borderPosition: BorderPosition, borderWidth) => {
27
+ const isPercentageValue = (value: number | string) => {
28
+ if (typeof value === "string" && value.endsWith("%")) {
29
+ return true;
30
+ }
31
+
32
+ return false;
33
+ };
34
+
35
+ const calculateContainerSpacing = ({
36
+ spacingKey,
37
+ style,
38
+ additionalSpacing,
39
+ }: {
40
+ spacingKey: typeof MARGINS[number] | typeof PADDINGS[number];
41
+ style: ImageStyle | ViewStyle;
42
+ additionalSpacing: number;
43
+ }) => {
44
+ return {
45
+ [spacingKey]:
46
+ toNumberWithDefaultZero(style[spacingKey]) + additionalSpacing,
47
+ };
48
+ };
49
+
50
+ const getContainerBorderWidth = (
51
+ borderPosition: BorderPosition,
52
+ borderWidth
53
+ ) => {
28
54
  switch (borderPosition) {
29
55
  case "inside":
30
56
  return 0;
31
57
  case "center":
32
- return -borderWidth / 2;
58
+ return borderWidth / 2;
33
59
  case "outside":
34
- return -borderWidth;
60
+ return borderWidth;
35
61
  default:
36
- return -borderWidth;
62
+ return borderWidth;
63
+ }
64
+ };
65
+
66
+ const getContainerPadding = (borderPosition: BorderPosition, borderWidth) => {
67
+ switch (borderPosition) {
68
+ case "inside":
69
+ return borderWidth;
70
+ case "center":
71
+ return borderWidth / 2;
72
+ case "outside":
73
+ return 0;
74
+ default:
75
+ return 0;
37
76
  }
38
77
  };
39
78
 
@@ -44,64 +83,84 @@ const InsideBorder = ({
44
83
  style: ViewStyle;
45
84
  borderPosition: BorderPosition;
46
85
  }) => {
47
- if (!borderPosition) {
86
+ if (borderPosition === "outside") {
48
87
  return null;
49
88
  }
50
89
 
51
- const borderWidth = toNumberWithDefaultZero(style.borderWidth);
52
- const containerPadding = getBorderPadding(borderPosition, borderWidth);
53
-
54
- const borderRadius =
55
- toNumberWithDefaultZero(style.borderRadius) -
56
- getBorderPadding(borderPosition, borderWidth);
90
+ const insideBorderWidth =
91
+ borderPosition === "center" ? style.borderWidth / 2 : style.borderWidth;
57
92
 
58
93
  return (
59
94
  <View
60
95
  style={{
61
96
  ...StyleSheet.absoluteFillObject,
62
- right: containerPadding,
63
- bottom: containerPadding,
64
- left: containerPadding,
65
- top: containerPadding,
66
- borderWidth: borderWidth,
97
+ borderWidth: insideBorderWidth,
67
98
  borderColor: style.borderColor,
68
- borderRadius,
99
+ borderRadius: style.borderRadius,
69
100
  }}
70
101
  />
71
102
  );
72
103
  };
73
104
 
74
105
  export const BorderContainerView = (props: Props) => {
75
- const {
76
- borderPosition,
77
- borderPaddingTop,
78
- borderPaddingRight,
79
- borderPaddingBottom,
80
- borderPaddingLeft,
81
- style,
82
- children,
83
- } = props;
106
+ const { style, children } = props;
107
+ // Return border position prop after re-implementing
108
+ const borderPosition = "outside";
109
+
110
+ const borderWidth = toNumberWithDefaultZero(style.borderWidth);
111
+ const spacing = getContainerPadding(borderPosition, borderWidth);
84
112
 
85
113
  const borderStyleForMissingBorder =
86
114
  style?.borderWidth === 0 || !style?.borderColor ? { borderRadius: 0 } : {};
87
115
 
88
- const padding =
89
- borderPosition === "outside"
90
- ? {
91
- paddingTop: borderPaddingTop,
92
- paddingRight: borderPaddingRight,
93
- paddingBottom: borderPaddingBottom,
94
- paddingLeft: borderPaddingLeft,
95
- }
96
- : {};
116
+ const updatedMargins = MARGINS.reduce((acc, margin) => {
117
+ const marginValue = calculateContainerSpacing({
118
+ spacingKey: margin,
119
+ style,
120
+ additionalSpacing: spacing,
121
+ });
122
+
123
+ return { ...acc, ...marginValue };
124
+ }, {});
125
+
126
+ const updatedPaddings = PADDINGS.reduce((acc, padding) => {
127
+ const paddingValue = calculateContainerSpacing({
128
+ spacingKey: padding,
129
+ style,
130
+ additionalSpacing: spacing,
131
+ });
132
+
133
+ return { ...acc, ...paddingValue };
134
+ }, {});
135
+
136
+ const updatedWidth = style.width
137
+ ? isPercentageValue(style.width)
138
+ ? style.width
139
+ : toNumberWithDefaultZero(style.width) - spacing * 2
140
+ : undefined;
141
+
142
+ const updatedHeight = style.height
143
+ ? isPercentageValue(style.height)
144
+ ? style.height
145
+ : toNumberWithDefaultZero(style.height) - spacing * 2
146
+ : undefined;
147
+
148
+ const containerStyle = {
149
+ borderWidth: getContainerBorderWidth(borderPosition, borderWidth),
150
+ padding: spacing,
151
+ ...updatedMargins,
152
+ ...updatedPaddings,
153
+ width: updatedWidth,
154
+ height: updatedHeight,
155
+ };
97
156
 
98
157
  return (
99
- <View
100
- {...props}
101
- style={[style, styles.container, borderStyleForMissingBorder, padding]}
102
- >
158
+ <View {...props} style={[style, containerStyle]}>
103
159
  {children}
104
- <InsideBorder style={style} borderPosition={borderPosition} />
160
+ <InsideBorder
161
+ style={{ ...style, ...borderStyleForMissingBorder }}
162
+ borderPosition={borderPosition}
163
+ />
105
164
  </View>
106
165
  );
107
166
  };
@@ -4,6 +4,7 @@ import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerM
4
4
 
5
5
  type DynamicBadgeProps = {
6
6
  cellUUID?: string;
7
+ uri?: string;
7
8
  };
8
9
 
9
10
  const DynamicBadgeComponent = (props: DynamicBadgeProps) => {
@@ -12,11 +13,12 @@ const DynamicBadgeComponent = (props: DynamicBadgeProps) => {
12
13
  // TODO: Initial value should depends on player state (playing or not)
13
14
  const [showImage, setShowImage] = React.useState(true);
14
15
  const player = usePlayer(playerId);
16
+ const uri = props?.uri;
15
17
 
16
18
  React.useEffect(() => {
17
19
  if (playerId && player) {
18
20
  return player.addListener({
19
- id: "dynamic-badges",
21
+ id: `dynamic-badges-${uri}`,
20
22
  listener: {
21
23
  onPlayerClose: () => {
22
24
  setShowImage(true);
@@ -35,7 +37,7 @@ const DynamicBadgeComponent = (props: DynamicBadgeProps) => {
35
37
  } else {
36
38
  setShowImage(true);
37
39
  }
38
- }, [player]);
40
+ }, [player, uri]);
39
41
 
40
42
  if (!showImage) {
41
43
  return null;
@@ -43,14 +43,16 @@ function Image({
43
43
  [source, error]
44
44
  );
45
45
 
46
+ const _source = shouldRenderImg
47
+ ? withDimensions(source)
48
+ : defaultPlaceHolderImage;
49
+
46
50
  return (
47
51
  // @ts-ignore
48
52
  <MemoizedImage
49
53
  style={style as ImageStyle}
50
54
  onError={() => setErrorState(true)}
51
- source={
52
- shouldRenderImg ? withDimensions(source) : defaultPlaceHolderImage
53
- }
55
+ source={_source?.uri ? _source : undefined}
54
56
  {...R.omit(["source"], otherProps)}
55
57
  />
56
58
  );
@@ -2,6 +2,7 @@ import React from "react";
2
2
  import { isVideoPreviewEnabled } from "@applicaster/zapp-react-native-ui-components/Components/MasterCell/utils";
3
3
  import { LiveImage } from "../LiveImage";
4
4
  import PureImage from "../Image";
5
+ import { useIsScreenActive } from "@applicaster/zapp-react-native-utils/reactHooks";
5
6
 
6
7
  type Props = {
7
8
  enable_video_preview: boolean;
@@ -9,7 +10,10 @@ type Props = {
9
10
  };
10
11
 
11
12
  export const ImageContainer = (props: Props) => {
12
- const Component = isVideoPreviewEnabled(props) ? LiveImage : PureImage;
13
+ const isActive = useIsScreenActive();
14
+
15
+ const Component =
16
+ isVideoPreviewEnabled(props) && isActive ? LiveImage : PureImage;
13
17
 
14
18
  return <Component {...props} />;
15
19
  };
@@ -1,7 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { Text } from "react-native";
3
3
  import { omit } from "ramda";
4
- import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
5
4
  import {
6
5
  textTransform,
7
6
  dateFormat,
@@ -9,6 +8,9 @@ import {
9
8
 
10
9
  import { useTextLabel, withFocusedStyles } from "./hooks";
11
10
  import { withScaledLineHeight } from "./utils";
11
+ import { toNumber } from "@applicaster/zapp-react-native-utils/numberUtils";
12
+ import { MeasurementPortalContext } from "../../../MeasurmentsPortal";
13
+ import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
12
14
 
13
15
  type Props = {
14
16
  style: any;
@@ -32,14 +34,24 @@ const _Text = ({
32
34
  ...otherProps
33
35
  }: Props) => {
34
36
  const _label = useTextLabel({ label, entry });
37
+ const isMeasurement = React.useContext(MeasurementPortalContext);
35
38
 
36
39
  if (isNilOrEmpty(_label)) {
37
40
  return null;
38
41
  }
39
42
 
43
+ // set maximum possible height for the text in case of measurement
44
+ const height =
45
+ isMeasurement && otherProps.numberOfLines && style.lineHeight
46
+ ? toNumber(otherProps.numberOfLines) * toNumber(style.lineHeight)
47
+ : undefined;
48
+
40
49
  return (
41
50
  <Text
42
- style={withScaledLineHeight(withFocusedStyles({ style, otherProps }))}
51
+ style={[
52
+ withScaledLineHeight(withFocusedStyles({ style, otherProps })),
53
+ { height },
54
+ ]}
43
55
  {...withoutLabel(otherProps)}
44
56
  >
45
57
  {dateTransformEnabled
@@ -39,6 +39,6 @@ describe("image with no source", () => {
39
39
  );
40
40
 
41
41
  const testInstance = testRenderer.root;
42
- expect(testInstance.findByType(Image).props.source).toEqual({ uri: "" });
42
+ expect(testInstance.findByType(Image).props.source).toBeUndefined();
43
43
  });
44
44
  });
@@ -1,11 +1,23 @@
1
1
  import React from "react";
2
- import { Text } from "react-native";
2
+ import RN from "react-native";
3
3
  import { Provider } from "react-redux";
4
4
  import TestRenderer from "react-test-renderer";
5
- import configureStore from "redux-mock-store";
6
- import CustomText from "../Text";
5
+ import configureStoreFn from "redux-mock-store";
7
6
 
8
- const mockStore = configureStore();
7
+ const mockUseIsRTL = jest.fn(() => true);
8
+ const mockGetIsRTL = jest.fn(() => true);
9
+ const mockUseLocalizedStrings = jest.fn(() => ({}));
10
+ const mockGetUILanguage = jest.fn(() => "he-HE");
11
+
12
+ jest.mock("@applicaster/zapp-react-native-utils/localizationUtils", () => ({
13
+ useIsRTL: mockUseIsRTL,
14
+ getIsRTL: mockGetIsRTL,
15
+ useLocalizedStrings: mockUseLocalizedStrings,
16
+ getUILanguage: mockGetUILanguage,
17
+ }));
18
+
19
+ const CustomText = require("../Text").default;
20
+ const mockStore = configureStoreFn();
9
21
 
10
22
  const defaultProps = {
11
23
  entry: {},
@@ -22,7 +34,7 @@ const getRenderedText = (label: string, store: any) => {
22
34
  </Provider>
23
35
  );
24
36
 
25
- return testRenderer.root.findByType(Text).props.children;
37
+ return testRenderer.root.findByType(RN.Text).props.children;
26
38
  };
27
39
 
28
40
  describe("RTL app: Hebrew text contains english word", () => {
@@ -34,7 +46,7 @@ describe("RTL app: Hebrew text contains english word", () => {
34
46
  remoteConfigurations: { localizations: { he: {} } },
35
47
  appData: {
36
48
  languageCode: "he",
37
- countryCode: "HE",
49
+ countryCode: "IL",
38
50
  },
39
51
  });
40
52
 
@@ -47,18 +59,22 @@ describe("RTL app: Hebrew text contains english word", () => {
47
59
 
48
60
  it("Hebrew text contains not first english word", () => {
49
61
  const renderedText = getRenderedText(textWithNotFirstEnglishWord, store);
50
-
51
62
  expect(renderedText).toEqual(textWithNotFirstEnglishWord);
52
63
  });
53
64
 
54
65
  it("Hebrew text doesn't contain english word", () => {
55
66
  const renderedText = getRenderedText(textWithoutEnglishWord, store);
56
-
57
67
  expect(renderedText).toEqual(textWithoutEnglishWord);
58
68
  });
59
69
  });
60
70
 
61
71
  describe("LTR app: English text", () => {
72
+ beforeAll(() => {
73
+ mockUseIsRTL.mockReturnValue(false);
74
+ mockGetIsRTL.mockReturnValue(false);
75
+ mockGetUILanguage.mockReturnValue("en-US");
76
+ });
77
+
62
78
  const englishText = "Test sentence";
63
79
 
64
80
  const store = mockStore({
@@ -71,7 +87,6 @@ describe("LTR app: English text", () => {
71
87
 
72
88
  it("English text", () => {
73
89
  const renderedText = getRenderedText(englishText, store);
74
-
75
90
  expect(renderedText).toEqual(englishText);
76
91
  });
77
92
  });
@@ -61,7 +61,10 @@ export function ButtonContainerView({
61
61
  <View style={applyRTLStylesIfNeeded(style, isRTL)}>
62
62
  {insertBetween(
63
63
  (index) => (
64
- <HorizontalSeparator key={index} width={horizontalGutter} />
64
+ <HorizontalSeparator
65
+ key={`separator_${index}`}
66
+ width={horizontalGutter}
67
+ />
65
68
  ),
66
69
  cloneElementsWithIds(buttonIds, filteredChildren)
67
70
  )}
@@ -29,7 +29,10 @@ export function ButtonContainerView({
29
29
  <View style={style}>
30
30
  {insertBetween(
31
31
  (index) => (
32
- <HorizontalSeparator key={index} width={horizontalGutter} />
32
+ <HorizontalSeparator
33
+ key={`separator_${index}`}
34
+ width={horizontalGutter}
35
+ />
33
36
  ),
34
37
  filteredChildren
35
38
  )}
@@ -51,9 +51,7 @@ export const CollapsibleTextContainer = ({
51
51
  func: (data) => {
52
52
  return getColorFromData({
53
53
  data,
54
- getValue,
55
- key: "background_color",
56
- defaultColor: additionalStyles.backgroundColor,
54
+ valueFromLayout: additionalStyles.backgroundColor,
57
55
  });
58
56
  },
59
57
  propName: "backgroundColor",
@@ -53,7 +53,7 @@ export const useAsyncRendering = (viewRef: React.RefObject<View>): Return => {
53
53
  measure(viewRef?.current, ({ width, height }) => {
54
54
  setDimensions({
55
55
  width,
56
- height,
56
+ height: Math.ceil(height),
57
57
  });
58
58
  });
59
59
  })
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
  import { View, StyleSheet } from "react-native";
3
+ import { MeasurementPortalContext } from "./MeasurementsPortal";
3
4
 
4
5
  type Props = {
5
6
  Component: React.ElementType;
@@ -19,13 +20,16 @@ const _MeasurementsPortal = (
19
20
  { Component, onLayout, componentProps, containerStyle }: Props,
20
21
  ref
21
22
  ) => (
22
- <View
23
- onLayout={onLayout}
24
- style={[styles.container, containerStyle]}
25
- ref={ref}
26
- >
27
- <Component {...componentProps} />
28
- </View>
23
+ // hack for cell to determine if cell is in measurement mode
24
+ <MeasurementPortalContext.Provider value={{}}>
25
+ <View
26
+ onLayout={onLayout}
27
+ style={[styles.container, containerStyle]}
28
+ ref={ref}
29
+ >
30
+ <Component {...componentProps} />
31
+ </View>
32
+ </MeasurementPortalContext.Provider>
29
33
  );
30
34
 
31
35
  export const MeasurementsPortal = React.forwardRef(_MeasurementsPortal);
@@ -35,7 +35,16 @@ const MeasurementsPortal = ({ Component, onLayout, componentProps }: Props) => {
35
35
  );
36
36
  };
37
37
 
38
- const MeasurementPortalContext = React.createContext(null);
38
+ type MeasurementPortalContextType = {
39
+ measureComponent?: (
40
+ comp: React.ElementType,
41
+ props: Record<any, any>
42
+ ) => Promise<any>;
43
+ measuringInProgress?: boolean;
44
+ };
45
+
46
+ const MeasurementPortalContext =
47
+ React.createContext<null | MeasurementPortalContextType>(null);
39
48
 
40
49
  const MeasurementsPortalContextProvider = ({ children }) => {
41
50
  const Component = React.useRef(View);
@@ -0,0 +1,48 @@
1
+ import * as React from "react";
2
+ import { isEmpty } from "ramda";
3
+
4
+ import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
5
+ import { getPathAttributes } from "@applicaster/zapp-react-native-utils/navigationUtils";
6
+ import { FocusableGroup } from "@applicaster/zapp-react-native-ui-components/Components/FocusableGroup";
7
+ import { ScreenDataContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenDataContext";
8
+ import { PathnameContext } from "@applicaster/zapp-react-native-ui-components/Contexts/PathnameContext";
9
+
10
+ import { Screen } from "../Screen/TV/index.web";
11
+
12
+ type Components = {
13
+ NavBar: React.ComponentType<any>;
14
+ Background: React.ComponentType<any>;
15
+ };
16
+
17
+ type Props = {
18
+ Components: Components;
19
+ };
20
+
21
+ export const StackNavigator = ({ Components }: Props) => {
22
+ const { mainStack, currentRoute } = useNavigation();
23
+
24
+ const renderScreen = ({ route, state }) => {
25
+ const pathAttributes = getPathAttributes({ pathname: route });
26
+
27
+ if (isEmpty(pathAttributes)) {
28
+ return null;
29
+ }
30
+
31
+ return (
32
+ <FocusableGroup
33
+ id={route}
34
+ preferredFocus={route === currentRoute}
35
+ excludeFromFocusSearching
36
+ key={route}
37
+ >
38
+ <ScreenDataContext.Provider value={state}>
39
+ <PathnameContext.Provider value={route}>
40
+ <Screen route={route} Components={Components} />
41
+ </PathnameContext.Provider>
42
+ </ScreenDataContext.Provider>
43
+ </FocusableGroup>
44
+ );
45
+ };
46
+
47
+ return <>{mainStack.map(renderScreen)}</>;
48
+ };
@@ -0,0 +1 @@
1
+ export { StackNavigator } from "./StackNavigator";
@@ -54,7 +54,10 @@ import { toNumber } from "@applicaster/zapp-react-native-utils/numberUtils";
54
54
  import { usePlayNextOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayNextOverlay";
55
55
  import { PlayNextState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/OverlayObserver/OverlaysObserver";
56
56
 
57
- import { useModalAnimationContext } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
57
+ import {
58
+ useModalAnimationContext,
59
+ PlayerAnimationStateEnum,
60
+ } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
58
61
 
59
62
  type Props = {
60
63
  Player: React.ComponentType<any>;
@@ -65,6 +68,7 @@ type Props = {
65
68
  mode?: VideoModalMode;
66
69
  loadPipesData: (url: string, options: {}) => void;
67
70
  disableCastAction?: boolean;
71
+ groupId?: string;
68
72
  };
69
73
 
70
74
  type ScreenStyles = ZappRiver["styles"] & {
@@ -197,6 +201,7 @@ const PlayerContainerComponent = (props: Props) => {
197
201
  style: videoStyle,
198
202
  mode = VideoModalMode.MAXIMIZED,
199
203
  disableCastAction = false,
204
+ groupId,
200
205
  } = props;
201
206
 
202
207
  // Hooks
@@ -231,6 +236,9 @@ const PlayerContainerComponent = (props: Props) => {
231
236
  const screenData = useTargetScreenData(item);
232
237
  const { setVisible: showNavBar } = useSetNavbarState();
233
238
 
239
+ const { isActiveGesture, startComponentsAnimation, setPlayerAnimationState } =
240
+ useModalAnimationContext();
241
+
234
242
  const playerEvent = (event, ...args) => {
235
243
  playerManager.invokeHandler(event, ...args);
236
244
  };
@@ -243,7 +251,6 @@ const PlayerContainerComponent = (props: Props) => {
243
251
  return;
244
252
  }
245
253
 
246
- navigator.goBack();
247
254
  showNavBar(true);
248
255
  }, [isModal, navigator.goBack, showNavBar]);
249
256
 
@@ -448,7 +455,7 @@ const PlayerContainerComponent = (props: Props) => {
448
455
  if (disableMiniPlayer) {
449
456
  navigator.closeVideoModal();
450
457
  } else {
451
- navigator.minimiseVideoModal();
458
+ setPlayerAnimationState(PlayerAnimationStateEnum.minimize);
452
459
  }
453
460
  }
454
461
 
@@ -600,9 +607,6 @@ const PlayerContainerComponent = (props: Props) => {
600
607
  pluginConfiguration,
601
608
  };
602
609
 
603
- const { isActiveGesture, startComponentsAnimation } =
604
- useModalAnimationContext();
605
-
606
610
  return (
607
611
  <PlayerStateContext.Provider value={value}>
608
612
  <PlayerContainerContextProvider
@@ -626,6 +630,7 @@ const PlayerContainerComponent = (props: Props) => {
626
630
  style={styles.focusableGroup}
627
631
  preferredFocus
628
632
  shouldUsePreferredFocus
633
+ groupId={groupId}
629
634
  >
630
635
  {/* Video player and components */}
631
636
  <View
@@ -668,6 +673,7 @@ const PlayerContainerComponent = (props: Props) => {
668
673
  setNextVideoPreloadThresholdPercentage={
669
674
  setNextVideoPreloadThresholdPercentage
670
675
  }
676
+ startComponentsAnimation={startComponentsAnimation}
671
677
  >
672
678
  {renderApplePlayer(applePlayerProps)}
673
679
  </Player>