@applicaster/zapp-react-native-ui-components 12.0.0-alpha.4433422595 → 12.0.0-alpha.4536343143

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 (77) hide show
  1. package/Components/BaseFocusable/index.tsx +2 -2
  2. package/Components/Cell/Cell.tsx +5 -9
  3. package/Components/Cell/CellWithFocusable.tsx +17 -5
  4. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +13 -6
  5. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
  6. package/Components/HandlePlayable/HandlePlayable.tsx +3 -0
  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 +26 -116
  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/Image/Image.ios.tsx +5 -3
  16. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -1
  17. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +14 -1
  18. package/Components/MasterCell/DefaultComponents/Text/index.tsx +14 -2
  19. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  20. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +24 -9
  21. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +4 -1
  22. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.tsx +4 -1
  23. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +1 -3
  24. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
  25. package/Components/MasterCell/utils/index.ts +16 -5
  26. package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
  27. package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
  28. package/Components/Navigator/StackNavigator.tsx +48 -0
  29. package/Components/Navigator/index.ts +1 -0
  30. package/Components/PlayerContainer/PlayerContainer.tsx +18 -3
  31. package/Components/PlayerImageBackground/index.tsx +34 -8
  32. package/Components/River/ComponentsMap/ComponentsMap.tsx +92 -22
  33. package/Components/River/RefreshControl.tsx +55 -1
  34. package/Components/River/TV/River.tsx +0 -23
  35. package/Components/River/__tests__/componentsMap.test.js +6 -0
  36. package/Components/RouteManager/index.tsx +2 -2
  37. package/Components/Screen/TV/hooks/index.ts +3 -0
  38. package/Components/Screen/TV/hooks/useInitialFocus.ts +70 -0
  39. package/Components/Screen/TV/hooks/useRestoreFocus.ts +22 -0
  40. package/Components/Screen/TV/index.web.tsx +119 -28
  41. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +4 -0
  42. package/Components/Screen/index.tsx +35 -24
  43. package/Components/ScreenResolver/index.tsx +3 -1
  44. package/Components/Transitioner/Scene.tsx +24 -19
  45. package/Components/Transitioner/Transitioner.tsx +9 -2
  46. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +6 -2
  47. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +1 -0
  48. package/Components/VideoLive/LiveImageManager.ts +18 -1
  49. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +20 -5
  50. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +0 -5
  51. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +78 -0
  52. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +342 -0
  53. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +151 -0
  54. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +438 -0
  55. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +154 -0
  56. package/Components/VideoModal/ModalAnimation/index.ts +15 -0
  57. package/Components/VideoModal/ModalAnimation/utils.ts +299 -0
  58. package/Components/VideoModal/PlayerDetails.tsx +3 -3
  59. package/Components/VideoModal/PlayerWrapper.tsx +77 -47
  60. package/Components/VideoModal/VideoModal.tsx +23 -40
  61. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +13 -1
  62. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +151 -119
  63. package/Components/VideoModal/utils.ts +3 -3
  64. package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
  65. package/Components/Viewport/ViewportTracker/index.tsx +1 -0
  66. package/Components/Viewport/utils.js +1 -1
  67. package/Contexts/MenuToggleContext/{index.js → index.ts} +16 -0
  68. package/Contexts/ScreenContext/__tests__/__snapshots__/index.test.tsx.snap +3 -0
  69. package/Contexts/ScreenContext/__tests__/index.test.tsx +27 -0
  70. package/Contexts/ScreenContext/index.tsx +100 -25
  71. package/Contexts/ScreenDataContext/index.tsx +20 -0
  72. package/Contexts/ZappPipesContext/ZappPipesEntryContext.ts +1 -1
  73. package/events/index.ts +1 -0
  74. package/package.json +5 -5
  75. package/Components/Layout/TV/TransitionOverlay.tsx +0 -64
  76. package/Components/VideoModal/hooks/usePosition.ts +0 -50
  77. /package/Contexts/{index.js → index.ts} +0 -0
@@ -66,14 +66,14 @@ export class BaseFocusable<
66
66
  const { initialFocus } = this.props;
67
67
 
68
68
  if (initialFocus) {
69
- focusManager.setupInitialFocus(this.getId());
69
+ focusManager.setFocus(this.getId());
70
70
  }
71
71
  }
72
72
 
73
73
  getId(props?: { id: string; groupId: string }) {
74
74
  const { id, groupId = null } = props || this.props;
75
75
 
76
- return groupId ? `groupId:${groupId}___${id}` : id;
76
+ return groupId ? `${groupId}-${id}` : id;
77
77
  }
78
78
 
79
79
  getRect() {
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import * as R from "ramda";
2
+ import { join, path, merge } from "ramda";
3
3
  import { View } from "react-native";
4
4
 
5
5
  import { Focusable } from "@applicaster/zapp-react-native-ui-components/Components/Focusable";
@@ -105,8 +105,8 @@ export class CellComponent extends React.Component<Props> {
105
105
  onPress(item, index);
106
106
  } else {
107
107
  const { item, navigator, component, appData } = this.props;
108
- const itemTargetScreen = R.path(["screen_type"], item);
109
- const componentTargetScreen = R.path(["data", "target"], component);
108
+ const itemTargetScreen = path(["screen_type"], item);
109
+ const componentTargetScreen = path(["data", "target"], component);
110
110
  const itemType = getItemType(item, appData?.layoutVersion);
111
111
 
112
112
  sendSelectCellEvent(item, component, item.title, index);
@@ -116,7 +116,7 @@ export class CellComponent extends React.Component<Props> {
116
116
  componentTargetScreen &&
117
117
  !itemTargetScreen
118
118
  ) {
119
- navigator.push(R.merge(item, { screen_type: componentTargetScreen }));
119
+ navigator.push(merge(item, { screen_type: componentTargetScreen }));
120
120
 
121
121
  return;
122
122
  }
@@ -207,11 +207,7 @@ export class CellComponent extends React.Component<Props> {
207
207
 
208
208
  const { id } = item;
209
209
 
210
- const focusableId = R.join("-", [
211
- `componentId:${component?.id}`,
212
- `id:${id}`,
213
- `index:${index}`,
214
- ]);
210
+ const focusableId = join("-", [component?.id, id, index]);
215
211
 
216
212
  const handleFocus = (focusable, mouse) => {
217
213
  const focusFn = onFocus || noop;
@@ -6,12 +6,20 @@ import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
6
6
  import { isAppleTV } from "../../Helpers/Platform";
7
7
  import { useCellState } from "../MasterCell/utils";
8
8
 
9
- const useCellFocusedState = (groupId: string, id: string) => {
9
+ const useCellFocusedState = (
10
+ skipFocusManagerRegistration: boolean,
11
+ groupId: string,
12
+ id: string
13
+ ) => {
10
14
  const [currentCellFocused, setCurrentCellFocused] = React.useState(false);
11
15
 
12
16
  React.useEffect(() => {
13
- const isGroupItemFocused = () =>
14
- setCurrentCellFocused(focusManager.isGroupItemFocused(groupId, id));
17
+ const isGroupItemFocused = () => {
18
+ if (!skipFocusManagerRegistration) {
19
+ const isFocused = focusManager.isGroupItemFocused(groupId, id);
20
+ setCurrentCellFocused(isFocused);
21
+ }
22
+ };
15
23
 
16
24
  const handler = () => {
17
25
  // tvOS hack for properly checking focus
@@ -29,7 +37,7 @@ const useCellFocusedState = (groupId: string, id: string) => {
29
37
  return () => {
30
38
  focusManager.removeHandler(FOCUS_EVENTS.FOCUS, handler);
31
39
  };
32
- }, [groupId]);
40
+ }, [groupId, skipFocusManagerRegistration]);
33
41
 
34
42
  return currentCellFocused;
35
43
  };
@@ -65,7 +73,11 @@ export function CellWithFocusable(props: Props) {
65
73
  selected,
66
74
  } = props;
67
75
 
68
- const isFocused = useCellFocusedState(groupId, id);
76
+ const isFocused = useCellFocusedState(
77
+ skipFocusManagerRegistration,
78
+ groupId,
79
+ id
80
+ );
69
81
 
70
82
  const state = useCellState({
71
83
  id: item.id,
@@ -50,7 +50,11 @@ describe("getTransformedPreset should return the passed components if smartCompo
50
50
  );
51
51
 
52
52
  expect(transformed_preset).toBeDefined();
53
- expect(transformed_preset.id).toEqual("comp10"); // id was transformed
53
+
54
+ expect(transformed_preset.id).toEqual(
55
+ `${mockComp.id}-${mockPreset.feed_url}-0`
56
+ ); // id was transformed
57
+
54
58
  expect(transformed_preset.data.source).toEqual(mockPreset.feed_url); // source was replaced with preset feed_url.
55
59
  });
56
60
  });
@@ -117,7 +121,10 @@ describe("getTransformedPreset should return the passed components if smartCompo
117
121
 
118
122
  expect(Array.isArray(result)).toBe(true);
119
123
  expect(result).toHaveLength(2);
120
- expect(result[0].id).toEqual("smart10");
124
+
125
+ expect(result[0].id).toEqual(
126
+ `${mockSmartComp.id}-${mockFeeds.preset_source.data.entry[0].feed_url}-0`
127
+ );
121
128
 
122
129
  expect(result[0].data.source).toEqual(
123
130
  mockFeeds.preset_source.data.entry[0].feed_url
@@ -287,7 +294,7 @@ describe("getTransformedPreset should return the passed components if smartCompo
287
294
  mockComponents[0],
288
295
  {
289
296
  ...mockLayoutPresets.preset_one,
290
- id: mockComponents[1].id + 1,
297
+ id: `${mockComponents[1].id}-${mockPresetEntry[0].feed_url}-1`,
291
298
  data: { source: mockPresetEntry[0].feed_url },
292
299
  },
293
300
  ];
@@ -344,12 +351,12 @@ describe("getTransformedPreset should return the passed components if smartCompo
344
351
  const mockTransformedComponents = [
345
352
  {
346
353
  ...mockLayoutPresets.preset_one,
347
- id: mockComponents[0].id + 0,
354
+ id: `${mockComponents[0].id}-${mockPresetEntry1[0].feed_url}-0`,
348
355
  data: { source: mockPresetEntry1[0].feed_url },
349
356
  },
350
357
  {
351
358
  ...mockLayoutPresets.preset_one,
352
- id: mockComponents[1].id + 1,
359
+ id: `${mockComponents[1].id}-${mockPresetEntry2[0].feed_url}-1`,
353
360
  data: { source: mockPresetEntry2[0].feed_url },
354
361
  },
355
362
  ];
@@ -412,7 +419,7 @@ describe("getTransformedPreset should return the passed components if smartCompo
412
419
  const mockTransformedComponents = mockPresetEntry.map((preset, i) => {
413
420
  return {
414
421
  ...mockLayoutPresets[preset.preset_name],
415
- id: mockComponents[0].id + i,
422
+ id: `${mockComponents[0].id}-${preset.feed_url}-${i}`,
416
423
  data: { source: preset.feed_url },
417
424
  };
418
425
  });
@@ -41,7 +41,7 @@ export const getTransformedPreset = (
41
41
  }
42
42
 
43
43
  const updatedPresetComponent = produce(presetComponent, (draft) => {
44
- draft.id = `${componentId}${index}`;
44
+ draft.id = `${componentId}-${preset?.feed_url}-${index}`;
45
45
  draft.data.source = preset?.feed_url;
46
46
 
47
47
  if (draft.ui_components) {
@@ -19,6 +19,7 @@ type Props = {
19
19
  modalHeight?: number;
20
20
  modalWidth?: number;
21
21
  mode: VideoModalMode;
22
+ groupId?: string;
22
23
  };
23
24
 
24
25
  const YOUTUBE_PLUGIN_ID = "youtube-player-qb";
@@ -93,6 +94,7 @@ export function HandlePlayable({
93
94
  modalHeight,
94
95
  modalWidth,
95
96
  mode,
97
+ groupId,
96
98
  }: Props): React.ReactElement | null {
97
99
  const state = usePickFromState();
98
100
 
@@ -167,6 +169,7 @@ export function HandlePlayable({
167
169
  isModal={isModal}
168
170
  mode={mode}
169
171
  disableCastAction={playerModuleProperties?.disableCastAction}
172
+ groupId={groupId}
170
173
  />
171
174
  );
172
175
  }
@@ -2,58 +2,18 @@
2
2
 
3
3
  exports[`Layout TV renders 1`] = `
4
4
  <View
5
- style={
6
- Object {
7
- "flex": 1,
8
- "height": 1080,
9
- "width": 1920,
10
- }
11
- }
12
- testID="layout-container"
5
+ excludeFromFocusSearching={true}
6
+ id="/river/A1234"
7
+ preferredFocus={true}
13
8
  >
14
9
  <View
15
- backgroundImageUrl="http://applicaster.com"
16
- testID="background-component"
17
- >
18
- <View
19
- style={
20
- Array [
21
- Object {
22
- "position": "absolute",
23
- "top": 0,
24
- "width": 1920,
25
- "zIndex": 10,
26
- },
27
- Object {
28
- "maxHeight": 10,
29
- },
30
- ]
10
+ Components={
11
+ Object {
12
+ "Background": [Function],
13
+ "NavBar": [Function],
31
14
  }
32
- testID="nav-bar-container"
33
- >
34
- <View
35
- isVisible={true}
36
- menuPlugin={
37
- Object {
38
- "module": [Function],
39
- "name": "resolved-menu-plug",
40
- "type": "menu",
41
- }
42
- }
43
- navigationProps={
44
- Object {
45
- "assets": undefined,
46
- "home": undefined,
47
- "nav_items": undefined,
48
- "rules": undefined,
49
- "selected": undefined,
50
- "styles": undefined,
51
- "title": "",
52
- }
53
- }
54
- testID="nav-bar-component"
55
- />
56
- </View>
57
- </View>
15
+ }
16
+ route="/river/A1234"
17
+ />
58
18
  </View>
59
19
  `;
@@ -1,79 +1,48 @@
1
1
  import * as React from "react";
2
- import * as R from "ramda";
2
+ import { omit } from "ramda";
3
3
  import { View } from "react-native";
4
4
  import { render } from "@testing-library/react-native";
5
5
  import { Provider } from "react-redux";
6
- import { createStore } from "redux";
7
6
  import { NavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NavigationContext";
7
+ import configureStore from "redux-mock-store";
8
8
 
9
- import { ThemeContext } from "@applicaster/zapp-react-native-utils/theme";
9
+ const withoutChildren = omit(["children"]);
10
10
 
11
- jest.mock("@applicaster/quick-brick-core/App/ActionSetters", () => ({
12
- useRiverInitialState: () => ({}),
11
+ jest.mock("../../../Screen/TV/index.web", () => ({
12
+ Screen: View,
13
13
  }));
14
14
 
15
- jest.mock("@applicaster/zapp-react-native-utils/reactHooks/screen");
15
+ const Layout = require("../index.web").default;
16
16
 
17
- const Layout = require("..").default;
18
-
19
- const ResolvedMenuPlug = () => <View testID="resolved-menu-plug" />;
20
-
21
- const plugins = [
22
- {
23
- module: ResolvedMenuPlug,
24
- type: "menu",
25
- name: "resolved-menu-plug",
26
- },
27
- ];
28
-
29
- const bgImage = "http://applicaster.com";
30
- const isNavBarVisible = true;
31
-
32
- const store = createStore(() => ({
17
+ const mockStore = configureStore()({
33
18
  appState: { appReady: true },
34
- remoteConfigurations: { sdkAssets: { bgImage } },
35
- plugins,
36
- }));
19
+ });
37
20
 
38
21
  describe("Layout TV", () => {
39
- const themes = {
40
- myTheme: { screen_margin_top: 10, screen_margin_bottom: 10 },
41
- };
42
-
43
- const selectedThemeId = "myTheme";
44
-
45
22
  const navigator = {
46
- activeRiver: {
47
- navigations: [{ category: "menu", navigation_type: "menu" }],
48
- },
49
- canGoBack: () => false,
50
23
  currentRoute: "/river/A1234",
51
- screenData: {
52
- navigations: [{ category: "menu", navigation_type: "menu" }],
53
- },
54
- isNavBarVisible: isNavBarVisible,
24
+ mainStack: [
25
+ {
26
+ route: "/river/A1234",
27
+ state: "state",
28
+ },
29
+ ],
55
30
  };
56
31
 
57
32
  const wrapper = ({ children }) => (
58
- <Provider store={store}>
33
+ <Provider store={mockStore}>
59
34
  <NavigationContext.Provider value={navigator}>
60
- <ThemeContext.Provider value={{ themes, selectedThemeId }}>
61
- {children}
62
- </ThemeContext.Provider>
35
+ {children}
63
36
  </NavigationContext.Provider>
64
37
  </Provider>
65
38
  );
66
39
 
67
- const Screen = (props) => (
68
- <View testID="screen-component" {...R.omit(["children"])(props)} />
69
- );
70
-
71
40
  const NavBar = (props) => (
72
- <View testID="nav-bar-component" {...R.omit(["children"])(props)} />
41
+ <View testID="nav-bar-component" {...withoutChildren(props)} />
73
42
  );
74
43
 
75
44
  const Background = (props: Record<any, any>) => (
76
- <View testID="background-component" {...R.omit(["children"])(props)}>
45
+ <View testID="background-component" {...withoutChildren(props)}>
77
46
  {props.children}
78
47
  </View>
79
48
  );
@@ -84,33 +53,8 @@ describe("Layout TV", () => {
84
53
  };
85
54
 
86
55
  it("renders", () => {
87
- const { toJSON } = render(
88
- <Layout Components={Components}>
89
- <Screen />
90
- </Layout>,
91
- { wrapper }
92
- );
56
+ const { toJSON } = render(<Layout Components={Components} />, { wrapper });
93
57
 
94
58
  expect(toJSON()).toMatchSnapshot();
95
59
  });
96
-
97
- describe("props passed to background component", () => {
98
- it("passes correct props", () => {
99
- const { getByTestId } = render(
100
- <Layout
101
- Components={Components}
102
- ComponentsExtraProps={{
103
- Background: { testProp: true },
104
- }}
105
- >
106
- <Screen />
107
- </Layout>,
108
- { wrapper }
109
- );
110
-
111
- const bgComponent = getByTestId("background-component");
112
- expect(bgComponent.props.backgroundImageUrl).toBe(bgImage);
113
- expect(bgComponent.props.testProp).toBe(true);
114
- });
115
- });
116
60
  });
@@ -1,15 +1,11 @@
1
1
  import * as React from "react";
2
2
  import * as R from "ramda";
3
- import { View, StyleSheet } from "react-native";
4
3
  import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
5
4
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
6
5
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
7
- import { useNavbarState } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenContext";
8
- import { isApplePlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
9
6
 
10
7
  import {
11
8
  getNavigationProps,
12
- getPathAttributes,
13
9
  resolveNavigationPlugin,
14
10
  routeIsPlayerScreen,
15
11
  } from "@applicaster/zapp-react-native-utils/navigationUtils";
@@ -18,26 +14,12 @@ import { getBackgroundImageUrl } from "../utils";
18
14
  import { LayoutContainer } from "./LayoutContainer";
19
15
  import { NavBarContainer } from "./NavBarContainer";
20
16
  import { ScreenContainer } from "./ScreenContainer";
21
- import { TransitionOverlay } from "./TransitionOverlay";
22
17
 
23
18
  import { ScreenLayoutContextProvider } from "./ScreenLayoutContextProvider";
19
+ import { isApplePlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
24
20
  import { PathnameContext } from "../../../Contexts/PathnameContext";
25
-
26
- import { FocusableGroup } from "../../FocusableGroup";
27
- import { Screen } from "../../Screen/TV/index.web";
28
-
29
- const styles = StyleSheet.create({
30
- container: {
31
- position: "absolute",
32
- width: 1920,
33
- height: 1080,
34
- backgroundColor: "black",
35
- // opacity: 0.5,
36
-
37
- borderWidth: 4,
38
- borderColor: "magenta",
39
- },
40
- });
21
+ import { useNavbarState } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenContext";
22
+ import { ScreenDataContext } from "../../../Contexts/ScreenDataContext";
41
23
 
42
24
  type Components = {
43
25
  NavBar: React.ComponentType<any>;
@@ -45,65 +27,16 @@ type Components = {
45
27
  };
46
28
 
47
29
  type ComponentsExtraProps = {
48
- NavBar?: Record<string, any>;
49
30
  Background?: Record<string, any>;
31
+ NavBar?: Record<string, any>;
50
32
  };
51
33
 
52
34
  type Props = {
53
35
  Components: Components;
54
- componentsExtraProps?: ComponentsExtraProps;
55
- };
56
-
57
- const StackNavigator = ({ Components }: Props) => {
58
- // @ts-ignore
59
- const { mainStack, currentRoute } = useNavigation();
60
-
61
- console.log("DEBUG", { mainStack });
62
-
63
- const renderScreen = ({ route, action, key, state }) => {
64
- const pathAttributes = getPathAttributes({ pathname: route });
65
-
66
- if (R.isEmpty(pathAttributes)) {
67
- return null;
68
- }
69
-
70
- console.log("SCENE:", { route, state, key, action });
71
-
72
- const id = `${route}`;
73
-
74
- return (
75
- <FocusableGroup
76
- id={id}
77
- preferredFocus={route === currentRoute}
78
- excludeFromFocusSearching
79
- key={id}
80
- >
81
- <View style={styles.container}>
82
- <PathnameContext.Provider value={route}>
83
- <Screen route={route} Components={Components} />
84
- </PathnameContext.Provider>
85
- </View>
86
- </FocusableGroup>
87
- );
88
- };
89
-
90
- return mainStack.map(renderScreen);
91
- };
92
-
93
- const TransitionerTV = ({ componentsExtraProps, Components }: Props) => {
94
- return (
95
- <>
96
- <ScreenLayoutContextProvider>
97
- <StackNavigator
98
- componentsExtraProps={componentsExtraProps}
99
- Components={Components}
100
- />
101
- </ScreenLayoutContextProvider>
102
- </>
103
- );
36
+ ComponentsExtraProps?: ComponentsExtraProps;
37
+ children: React.ReactNode;
104
38
  };
105
39
 
106
- // @ts-ignore
107
40
  const Layout = ({ Components, ComponentsExtraProps, children }: Props) => {
108
41
  const navigator = useNavigation();
109
42
  const theme = useTheme();
@@ -164,57 +97,34 @@ const Layout = ({ Components, ComponentsExtraProps, children }: Props) => {
164
97
  return null;
165
98
  }
166
99
 
167
- console.log("DEBUG", "TV Layout");
168
-
169
100
  return (
170
- // @ts-ignore
171
- <TransitionerTV
172
- componentsExtraProps={ComponentsExtraProps}
173
- Components={Components}
174
- >
175
- <LayoutContainer>
176
- <ScreenLayoutContextProvider>
177
- <Components.Background
178
- backgroundColor={backgroundColor}
179
- backgroundImageUrl={backgroundImageUrl}
180
- {...R.omit(["ref"])(ComponentsExtraProps?.Background)}
181
- >
182
- {!isTVOS ? navBarContainer : null}
183
- {navBarReady ? (
184
- /**
101
+ <LayoutContainer>
102
+ <ScreenLayoutContextProvider>
103
+ <Components.Background
104
+ backgroundColor={backgroundColor}
105
+ backgroundImageUrl={backgroundImageUrl}
106
+ {...R.omit(["ref"])(ComponentsExtraProps?.Background)}
107
+ >
108
+ <ScreenDataContext.Provider value={navigator.data}>
109
+ <PathnameContext.Provider value={navigator.currentRoute}>
110
+ {!isTVOS ? navBarContainer : null}
111
+ {navBarReady ? (
112
+ /**
185
113
  Need to re-mount this component on each navigation event
186
114
  It's a hack to work around the fact that we don't support
187
115
  correct screen rendering in our navigator (shared currentRoute state)
188
116
  **/
189
- <PathnameContext.Provider value={navigator.currentRoute}>
190
117
  <ScreenContainer>{children}</ScreenContainer>
191
- </PathnameContext.Provider>
192
- ) : null}
193
- {/** Render NavBarContainer over ScreenContainer to let tvOS native
118
+ ) : null}
119
+ {/** Render NavBarContainer over ScreenContainer to let tvOS native
194
120
  focus manager works correctly to focus nav bar items first **/}
195
- {isTVOS ? navBarContainer : null}
196
- <TransitionOverlay />
197
- </Components.Background>
198
- </ScreenLayoutContextProvider>
199
- </LayoutContainer>
200
- </TransitionerTV>
121
+ {isTVOS ? navBarContainer : null}
122
+ </PathnameContext.Provider>
123
+ </ScreenDataContext.Provider>
124
+ </Components.Background>
125
+ </ScreenLayoutContextProvider>
126
+ </LayoutContainer>
201
127
  );
202
128
  };
203
129
 
204
130
  export default Layout;
205
-
206
- /// Transitioner:
207
- /*
208
- Component: Transitioner
209
- Responsibilities:
210
- - Transitione between screens.
211
- Tehere is no transition on Tv so no need for transitioner.
212
-
213
- Component: StackNavigator
214
- Responsibilities:
215
- - Render the screens in the stack.
216
- - Render the NavBar? I guess navbar should be part of the screen
217
- - Render the screen.
218
-
219
- Q
220
- */
@@ -0,0 +1,33 @@
1
+ import * as React from "react";
2
+ import { pathOr } from "ramda";
3
+
4
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
5
+
6
+ import { ScreenLayoutContextProvider } from "./ScreenLayoutContextProvider";
7
+ import { StackNavigator } from "../../Navigator";
8
+
9
+ type Components = {
10
+ NavBar: React.ComponentType<any>;
11
+ Background: React.ComponentType<any>;
12
+ };
13
+
14
+ type Props = {
15
+ Components: Components;
16
+ };
17
+
18
+ const Layout = ({ Components }: Props) => {
19
+ const { appState } = usePickFromState(["appState"]);
20
+ const appReady = pathOr(false, ["appReady"], appState);
21
+
22
+ if (!appReady) {
23
+ return null;
24
+ }
25
+
26
+ return (
27
+ <ScreenLayoutContextProvider>
28
+ <StackNavigator Components={Components} />
29
+ </ScreenLayoutContextProvider>
30
+ );
31
+ };
32
+
33
+ export default Layout;
@@ -1,20 +1,24 @@
1
1
  import * as React from "react";
2
- import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
3
- import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
4
- import { ScreenContextProvider } from "../../Contexts/ScreenContext";
2
+ import {
3
+ isTV,
4
+ platformSelect,
5
+ } from "@applicaster/zapp-react-native-utils/reactUtils";
5
6
 
6
7
  import Mobile from "./Mobile";
7
- import TV from "./TV";
8
8
 
9
- export default function Layout(props) {
10
- const { currentRoute: pathname } = useNavigation();
9
+ import TVWeb from "./TV/index.web";
10
+ import TVDefault from "./TV/index";
11
+
12
+ const TV = platformSelect({
13
+ samsung_tv: TVWeb,
14
+ lg_tv: TVWeb,
15
+ web: TVWeb,
16
+ default: TVDefault,
17
+ });
11
18
 
19
+ export default function Layout(props) {
12
20
  if (isTV()) {
13
- return (
14
- <ScreenContextProvider pathname={pathname}>
15
- <TV {...props} />
16
- </ScreenContextProvider>
17
- );
21
+ return <TV {...props} />;
18
22
  } else {
19
23
  return <Mobile {...props} />;
20
24
  }
@@ -25,6 +25,7 @@ type Props = {
25
25
  testID?: string;
26
26
  accessibilityLabel?: string;
27
27
  cellUUID?: string;
28
+ extraProps?: Record<string, any>;
28
29
  };
29
30
 
30
31
  function isStringAsset(asset) {
@@ -108,6 +109,7 @@ export function ActionButton(props: Props) {
108
109
  flavour={flavour}
109
110
  asset={getAssetValue(asset, flavour)}
110
111
  cellUUID={cellUUID}
112
+ {...(props?.extraProps ?? {})}
111
113
  />
112
114
  )}
113
115
  </TouchableOpacity>