@applicaster/zapp-react-native-ui-components 14.0.0-rc.9 → 14.0.0-rc.91

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 (179) hide show
  1. package/Components/AnimatedInOut/index.tsx +68 -23
  2. package/Components/AudioPlayer/index.tsx +15 -0
  3. package/Components/AudioPlayer/mobile/Layout.tsx +66 -0
  4. package/Components/AudioPlayer/{__tests__/__snapshots__/audioPlayer.test.js.snap → mobile/__tests__/__snapshots__/audioPlayerMobileLayout.test.js.snap} +2 -2
  5. package/Components/AudioPlayer/mobile/__tests__/audioPlayerMobileLayout.test.js +18 -0
  6. package/Components/AudioPlayer/mobile/index.tsx +18 -0
  7. package/Components/AudioPlayer/{Artwork.tsx → tv/Artwork.tsx} +3 -2
  8. package/Components/AudioPlayer/{Channel.tsx → tv/Channel.tsx} +7 -7
  9. package/Components/AudioPlayer/tv/Layout.tsx +168 -0
  10. package/Components/AudioPlayer/{Runtime.tsx → tv/Runtime.tsx} +7 -1
  11. package/Components/AudioPlayer/{Summary.tsx → tv/Summary.tsx} +6 -2
  12. package/Components/AudioPlayer/{Title.tsx → tv/Title.tsx} +6 -2
  13. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/Runtime.test.js.snap +2 -2
  14. package/Components/AudioPlayer/tv/__tests__/__snapshots__/audioPlayer.test.js.snap +164 -0
  15. package/Components/AudioPlayer/tv/__tests__/__snapshots__/channel.test.js.snap +19 -0
  16. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/summary.test.js.snap +1 -2
  17. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/title.test.js.snap +1 -2
  18. package/Components/AudioPlayer/{__tests__ → tv/__tests__}/audioPlayer.test.js +7 -3
  19. package/Components/AudioPlayer/{helpers.tsx → tv/helpers.tsx} +11 -5
  20. package/Components/AudioPlayer/{AudioPlayer.tsx → tv/index.tsx} +17 -58
  21. package/Components/AudioPlayer/types.ts +40 -0
  22. package/Components/BaseFocusable/index.tsx +23 -12
  23. package/Components/Cell/Cell.tsx +91 -64
  24. package/Components/Cell/CellWithFocusable.tsx +3 -0
  25. package/Components/Cell/FocusableWrapper.tsx +44 -0
  26. package/Components/Cell/TvOSCellComponent.tsx +92 -17
  27. package/Components/Cell/__tests__/CellWIthFocusable.test.js +3 -2
  28. package/Components/Cell/index.js +7 -3
  29. package/Components/ComponentResolver/index.ts +1 -1
  30. package/Components/FeedLoader/FeedLoader.tsx +7 -16
  31. package/Components/FeedLoader/FeedLoaderHOC.tsx +21 -0
  32. package/Components/FeedLoader/index.js +2 -8
  33. package/Components/Focusable/Focusable.tsx +12 -3
  34. package/Components/Focusable/FocusableTvOS.tsx +5 -5
  35. package/Components/Focusable/FocusableiOS.tsx +2 -2
  36. package/Components/Focusable/Touchable.tsx +5 -3
  37. package/Components/Focusable/__tests__/index.android.test.tsx +3 -0
  38. package/Components/Focusable/index.android.tsx +19 -11
  39. package/Components/Focusable/index.tsx +1 -1
  40. package/Components/FocusableGroup/FocusableTvOS.tsx +1 -1
  41. package/Components/FocusableList/FocusableItem.tsx +4 -3
  42. package/Components/FocusableList/FocusableListItemWrapper.tsx +2 -1
  43. package/Components/FocusableList/hooks/useCellState.android.ts +13 -3
  44. package/Components/FocusableList/index.tsx +20 -9
  45. package/Components/FreezeWithCallback/__tests__/index.test.tsx +67 -43
  46. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +42 -59
  47. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +22 -21
  48. package/Components/HandlePlayable/HandlePlayable.tsx +39 -74
  49. package/Components/HandlePlayable/const.ts +3 -0
  50. package/Components/HandlePlayable/utils.ts +74 -0
  51. package/Components/Layout/TV/LayoutBackground.tsx +1 -1
  52. package/Components/Layout/TV/__tests__/index.test.tsx +0 -1
  53. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +6 -2
  54. package/Components/MasterCell/DefaultComponents/Button.tsx +1 -1
  55. package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -39
  56. package/Components/MasterCell/DefaultComponents/Image/hoc/withDimensions.tsx +1 -1
  57. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +1 -1
  58. package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +65 -17
  59. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/Image.test.tsx +21 -3
  60. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +6 -3
  61. package/Components/MasterCell/DefaultComponents/Text/index.tsx +26 -6
  62. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +10 -10
  63. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +18 -18
  64. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/index.test.tsx +10 -10
  65. package/Components/MasterCell/elementMapper.tsx +1 -2
  66. package/Components/MasterCell/index.tsx +1 -1
  67. package/Components/MasterCell/utils/behaviorProvider.ts +82 -14
  68. package/Components/MasterCell/utils/index.ts +11 -5
  69. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +13 -18
  70. package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +9 -0
  71. package/Components/OfflineHandler/__tests__/index.test.tsx +26 -35
  72. package/Components/PlayerContainer/ErrorDisplay/index.ts +1 -1
  73. package/Components/PlayerContainer/PlayerContainer.tsx +45 -47
  74. package/Components/PlayerContainer/ProgramInfo/index.tsx +1 -1
  75. package/Components/PlayerContainer/index.ts +1 -1
  76. package/Components/PlayerImageBackground/index.tsx +4 -23
  77. package/Components/River/ComponentsMap/ComponentsMap.tsx +49 -43
  78. package/Components/River/ComponentsMap/ContextProviders/ComponentsMapHeightContext.ts +8 -0
  79. package/Components/River/ComponentsMap/ContextProviders/ComponentsMapRefContext.ts +8 -0
  80. package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +378 -0
  81. package/Components/River/ComponentsMap/hooks/useLoadingState.ts +2 -2
  82. package/Components/River/RefreshControl.tsx +11 -17
  83. package/Components/River/TV/River.tsx +2 -17
  84. package/Components/River/TV/index.tsx +3 -1
  85. package/Components/River/TV/withPipesV1DataLoader.tsx +43 -0
  86. package/Components/River/TV/withRiverDataLoader.tsx +17 -0
  87. package/Components/River/TV/withTVEventHandler.tsx +1 -1
  88. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +2 -0
  89. package/Components/River/__tests__/river.test.js +12 -26
  90. package/Components/River/index.tsx +1 -1
  91. package/Components/Screen/TV/hooks/useInitialFocus.ts +14 -4
  92. package/Components/Screen/__tests__/Screen.test.tsx +28 -29
  93. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +2 -0
  94. package/Components/Screen/__tests__/navigationHandler.test.ts +133 -22
  95. package/Components/Screen/index.tsx +22 -5
  96. package/Components/Screen/navigationHandler.ts +20 -2
  97. package/Components/ScreenRevealManager/ScreenRevealManager.ts +76 -0
  98. package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +107 -0
  99. package/Components/ScreenRevealManager/__tests__/withScreenRevealManager.test.tsx +96 -0
  100. package/Components/ScreenRevealManager/index.ts +1 -0
  101. package/Components/ScreenRevealManager/utils/index.ts +23 -0
  102. package/Components/ScreenRevealManager/withScreenRevealManager.tsx +109 -0
  103. package/Components/Tabs/TV/Tabs.android.tsx +1 -3
  104. package/Components/Tabs/Tabs.tsx +2 -3
  105. package/Components/TextInputTv/__tests__/__snapshots__/TextInputTv.test.js.snap +13 -0
  106. package/Components/TextInputTv/index.tsx +11 -0
  107. package/Components/Touchable/__tests__/__snapshots__/touchable.test.tsx.snap +34 -0
  108. package/Components/Touchable/__tests__/touchable.test.tsx +12 -17
  109. package/Components/Transitioner/Scene.tsx +15 -2
  110. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +15 -9
  111. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +1 -0
  112. package/Components/VideoLive/animationUtils.ts +3 -3
  113. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +120 -133
  114. package/Components/VideoModal/ModalAnimation/index.ts +2 -13
  115. package/Components/VideoModal/ModalAnimation/utils.ts +1 -327
  116. package/Components/VideoModal/PlayerDetails.tsx +29 -7
  117. package/Components/VideoModal/PlayerWrapper.tsx +25 -215
  118. package/Components/VideoModal/VideoModal.tsx +4 -22
  119. package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +5 -5
  120. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +2 -7
  121. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +44 -240
  122. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +9 -1
  123. package/Components/VideoModal/hooks/index.ts +0 -2
  124. package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +40 -15
  125. package/Components/VideoModal/hooks/useModalSize.ts +23 -2
  126. package/Components/VideoModal/hooks/utils/__tests__/showDetails.test.ts +2 -2
  127. package/Components/VideoModal/hooks/utils/index.ts +4 -0
  128. package/Components/VideoModal/playerWrapperStyle.ts +70 -0
  129. package/Components/VideoModal/playerWrapperUtils.ts +91 -0
  130. package/Components/VideoModal/utils.ts +13 -0
  131. package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +12 -16
  132. package/Components/Viewport/ViewportTracker/__tests__/viewportTracker.test.js +84 -24
  133. package/Components/Viewport/VisibilitySensor/VisibilitySensor.tsx +3 -3
  134. package/Components/default-cell-renderer/viewTrees/tv/DefaultCell/index.ts +3 -3
  135. package/Contexts/CellFocusedStateContext/index.tsx +27 -0
  136. package/Contexts/ConfigutaionContext/__tests__/ConfigurationProvider.test.tsx +3 -3
  137. package/Contexts/ScreenContext/index.tsx +46 -6
  138. package/Decorators/ConfigurationWrapper/__tests__/withConfigurationProvider.test.tsx +3 -3
  139. package/Decorators/ConfigurationWrapper/withConfigurationProvider.tsx +2 -2
  140. package/Decorators/RiverFeedLoader/__tests__/__snapshots__/riverFeedLoader.test.tsx.snap +221 -209
  141. package/Decorators/RiverFeedLoader/__tests__/riverFeedLoader.test.tsx +14 -16
  142. package/Decorators/RiverFeedLoader/__tests__/utils.test.ts +0 -20
  143. package/Decorators/RiverFeedLoader/index.tsx +22 -4
  144. package/Decorators/RiverFeedLoader/utils/getDatasourceUrl.ts +6 -10
  145. package/Decorators/RiverFeedLoader/utils/index.ts +0 -18
  146. package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +3 -6
  147. package/Decorators/ZappPipesDataConnector/ResolverSelector.tsx +25 -0
  148. package/Decorators/ZappPipesDataConnector/__tests__/NullFeedResolver.test.tsx +78 -0
  149. package/Decorators/ZappPipesDataConnector/__tests__/ResolverSelector.test.tsx +205 -0
  150. package/Decorators/ZappPipesDataConnector/__tests__/StaticFeedResolver.test.tsx +251 -0
  151. package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +368 -0
  152. package/Decorators/ZappPipesDataConnector/__tests__/utils.test.ts +39 -0
  153. package/Decorators/ZappPipesDataConnector/index.tsx +26 -293
  154. package/Decorators/ZappPipesDataConnector/resolvers/NullFeedResolver.tsx +25 -0
  155. package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +87 -0
  156. package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +266 -0
  157. package/Decorators/ZappPipesDataConnector/types.ts +29 -0
  158. package/Decorators/ZappPipesDataConnector/utils/mongoFilter.ts +738 -0
  159. package/Decorators/ZappPipesDataConnector/utils/useFilter.tsx +157 -0
  160. package/events/index.ts +3 -0
  161. package/package.json +5 -10
  162. package/Components/AudioPlayer/AudioPlayerLayout.tsx +0 -202
  163. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +0 -66
  164. package/Components/AudioPlayer/__tests__/__snapshots__/channel.test.js.snap +0 -28
  165. package/Components/AudioPlayer/__tests__/audioPlayerLayout.test.js +0 -26
  166. package/Components/AudioPlayer/index.ts +0 -1
  167. package/Components/River/__tests__/__snapshots__/river.test.js.snap +0 -27
  168. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +0 -60
  169. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +0 -421
  170. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +0 -176
  171. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +0 -500
  172. package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +0 -108
  173. package/Components/VideoModal/hooks/useBackgroundColor.ts +0 -10
  174. /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/Runtime.test.js +0 -0
  175. /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/artWork.test.js.snap +0 -0
  176. /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/artWork.test.js +0 -0
  177. /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/channel.test.js +0 -0
  178. /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/summary.test.js +0 -0
  179. /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/title.test.js +0 -0
@@ -10,6 +10,8 @@ import {
10
10
  setFocusOnMenu,
11
11
  } from "@applicaster/zapp-react-native-utils/appUtils/focusManagerAux";
12
12
 
13
+ import { waitUntilScreenRevealManagerIsReady } from "@applicaster/zapp-react-native-ui-components/Components/ScreenRevealManager/utils";
14
+
13
15
  type Return =
14
16
  | {
15
17
  onContent: true;
@@ -57,14 +59,22 @@ export const useInitialFocus = (): void => {
57
59
  React.useEffect(() => {
58
60
  const initialFocus = getInitialFocus(focusOnContent, isNavBarVisible);
59
61
 
60
- if (initialFocus.onContent) {
61
- setFocusOnContent(currentRoute);
62
+ if (initialFocus.onMenu) {
63
+ setFocusOnMenu(currentRoute);
62
64
 
63
65
  return;
64
66
  }
65
67
 
66
- if (initialFocus.onMenu) {
67
- setFocusOnMenu(currentRoute);
68
+ if (initialFocus.onContent) {
69
+ const subscription = waitUntilScreenRevealManagerIsReady().subscribe(
70
+ () => {
71
+ setFocusOnContent(currentRoute);
72
+ }
73
+ );
74
+
75
+ return () => {
76
+ subscription.unsubscribe();
77
+ };
68
78
  }
69
79
  }, []);
70
80
  };
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { View } from "react-native";
3
- import { act, create } from "react-test-renderer";
3
+ import { render } from "@testing-library/react-native";
4
4
 
5
5
  const Mocked_RouteManager = jest.fn((props) => (
6
6
  <View testID="routeManager" {...props} />
@@ -68,12 +68,33 @@ jest.mock(
68
68
  })
69
69
  );
70
70
 
71
+ jest.mock(
72
+ "@applicaster/zapp-react-native-utils/reactHooks/state/useRivers",
73
+ () => ({
74
+ useRivers: jest.fn(() => ({
75
+ rivers: [{ id: "testId", name: "Test River" }],
76
+ })),
77
+ })
78
+ );
79
+
71
80
  jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
72
81
  isNavBarVisible: mockIsNavBarVisible,
73
82
  useIsScreenActive: jest.fn().mockReturnValue(true),
83
+ useNavigation: jest.fn(() => ({
84
+ canGoBack: () => false,
85
+ currentRoute: "/river/testId",
86
+ activeRiver: { id: "testId" },
87
+ screenData: { id: "testId" },
88
+ data: { screen: { id: "testId" } },
89
+ })),
90
+ useRoute: jest.fn(() => ({
91
+ pathname: "/river/testId",
92
+ screenData: { id: "testId" },
93
+ })),
74
94
  }));
75
95
 
76
96
  jest.mock("@applicaster/zapp-react-native-utils/reactHooks", () => ({
97
+ ...jest.requireActual("@applicaster/zapp-react-native-utils/reactHooks"),
77
98
  useCurrentScreenData: jest.fn(() => ({
78
99
  id: "testId",
79
100
  })),
@@ -84,17 +105,6 @@ jest.mock("@applicaster/zapp-react-native-utils/reactHooks", () => ({
84
105
  id: "testId",
85
106
  navigations: [{ id: "testId", category: "nav_bar" }],
86
107
  })),
87
- useNavigation: jest.fn(() => ({
88
- canGoBack: () => false,
89
- currentRoute: "/river/testId",
90
- activeRiver: { id: "testId" },
91
- screenData: { id: "testId" },
92
- data: { screen: { id: "testId" } },
93
- })),
94
- useRoute: jest.fn(() => ({
95
- pathname: "/river/testId",
96
- screenData: { id: "testId" },
97
- })),
98
108
  useDimensions: jest.fn(() => ({
99
109
  width: 1920,
100
110
  height: 1080,
@@ -102,10 +112,11 @@ jest.mock("@applicaster/zapp-react-native-utils/reactHooks", () => ({
102
112
  useIsTablet: jest.fn(() => false),
103
113
  }));
104
114
 
105
- jest.mock("@applicaster/zapp-react-native-redux/hooks/usePickFromState", () => {
115
+ jest.mock("@applicaster/zapp-react-native-redux/hooks", () => {
106
116
  const View = jest.requireActual("react-native").View;
107
117
 
108
118
  return {
119
+ ...jest.requireActual("@applicaster/zapp-react-native-redux/hooks"),
109
120
  usePickFromState: () => ({
110
121
  plugins: [
111
122
  {
@@ -141,8 +152,6 @@ const screenProps = {
141
152
  const { Screen } = require("..");
142
153
 
143
154
  describe("<Screen Component />", () => {
144
- let wrapper;
145
-
146
155
  beforeEach(() => {
147
156
  allowedOrientationsForScreen.mockClear();
148
157
  getOrientation.mockClear();
@@ -150,26 +159,16 @@ describe("<Screen Component />", () => {
150
159
  });
151
160
 
152
161
  describe("when the navbar should show", () => {
153
- act(() => {
154
- wrapper = create(<Screen {...screenProps} />);
155
- });
156
-
157
162
  it("renders correctly", () => {
158
- expect(wrapper.toJSON()).toMatchSnapshot();
163
+ const { toJSON } = render(<Screen {...screenProps} />);
164
+ expect(toJSON()).toMatchSnapshot();
159
165
  });
160
166
  });
161
167
 
162
168
  describe("when the navbar should be hidden", () => {
163
- beforeEach(() => {
164
- wrapper = create(<Screen {...screenProps} />);
165
- });
166
-
167
169
  it("renders correctly", () => {
168
- act(() => {
169
- wrapper = create(<Screen {...screenProps} />);
170
- });
171
-
172
- expect(wrapper.toJSON()).toMatchSnapshot();
170
+ const { toJSON } = render(<Screen {...screenProps} />);
171
+ expect(toJSON()).toMatchSnapshot();
173
172
  });
174
173
  });
175
174
  });
@@ -2,6 +2,7 @@
2
2
 
3
3
  exports[`<Screen Component /> when the navbar should be hidden renders correctly 1`] = `
4
4
  <View
5
+ importantForAccessibility="yes"
5
6
  style={
6
7
  {
7
8
  "backgroundColor": "blue",
@@ -34,6 +35,7 @@ exports[`<Screen Component /> when the navbar should be hidden renders correctly
34
35
 
35
36
  exports[`<Screen Component /> when the navbar should show renders correctly 1`] = `
36
37
  <View
38
+ importantForAccessibility="yes"
37
39
  style={
38
40
  {
39
41
  "backgroundColor": "blue",
@@ -3,61 +3,172 @@ import { isMenuVisible } from "../navigationHandler";
3
3
  describe("NavigationHandler", () => {
4
4
  describe("isMenuVisible", () => {
5
5
  it("returns false when the route is a player route", () => {
6
- const menuVisible = isMenuVisible("/playable/some_vod_item", {});
6
+ const menuVisible = isMenuVisible("/playable/some_vod_item", {}, [
7
+ {
8
+ identifier: "quick-brick-bottom-tabs",
9
+ category: "menu",
10
+ name: "Bottom Tabs",
11
+ },
12
+ ]);
13
+
7
14
  expect(menuVisible).toBe(false);
8
15
  });
9
16
 
10
17
  describe("when screen is a hook", () => {
11
18
  it("returns true if the `showNavBar` flag is set to true", () => {
12
- const menuVisible = isMenuVisible("", {
13
- hookPlugin: {
14
- module: {
15
- showNavBar: true,
19
+ const menuVisible = isMenuVisible(
20
+ "",
21
+ {
22
+ hookPlugin: {
23
+ module: {
24
+ showNavBar: true,
25
+ },
16
26
  },
27
+ navigations: [
28
+ {
29
+ navigation_type: "quick-brick-bottom-tabs",
30
+ identifier: "quick-brick-bottom-tabs",
31
+ category: "menu",
32
+ name: "Bottom Tabs",
33
+ },
34
+ ],
17
35
  },
18
- });
36
+ [
37
+ {
38
+ identifier: "quick-brick-bottom-tabs",
39
+ category: "menu",
40
+ name: "Bottom Tabs",
41
+ },
42
+ ]
43
+ );
19
44
 
20
45
  expect(menuVisible).toBe(true);
21
46
  });
22
47
 
23
48
  it("returns true if presentFullScreen flag is set to false", () => {
24
- const menuVisible = isMenuVisible("", {
25
- hookPlugin: {
26
- module: {
27
- presentFullScreen: false,
49
+ const menuVisible = isMenuVisible(
50
+ "",
51
+ {
52
+ hookPlugin: {
53
+ module: {
54
+ presentFullScreen: false,
55
+ },
28
56
  },
57
+ navigations: [
58
+ {
59
+ navigation_type: "quick-brick-bottom-tabs",
60
+ identifier: "quick-brick-bottom-tabs",
61
+ category: "menu",
62
+ name: "Bottom Tabs",
63
+ },
64
+ ],
29
65
  },
30
- });
66
+ [
67
+ {
68
+ identifier: "quick-brick-bottom-tabs",
69
+ category: "menu",
70
+ name: "Bottom Tabs",
71
+ },
72
+ ]
73
+ );
31
74
 
32
75
  expect(menuVisible).toBe(true);
33
76
  });
34
77
 
35
78
  it("returns false if presentFullScreen flag is set to true", () => {
36
- const menuVisible = isMenuVisible("", {
37
- hookPlugin: {
38
- module: {
39
- presentFullScreen: true,
79
+ const menuVisible = isMenuVisible(
80
+ "",
81
+ {
82
+ hookPlugin: {
83
+ module: {
84
+ presentFullScreen: true,
85
+ },
40
86
  },
87
+ navigations: [
88
+ {
89
+ navigation_type: "quick-brick-bottom-tabs",
90
+ identifier: "quick-brick-bottom-tabs",
91
+ category: "menu",
92
+ name: "Bottom Tabs",
93
+ },
94
+ ],
41
95
  },
42
- });
96
+ [
97
+ {
98
+ identifier: "quick-brick-bottom-tabs",
99
+ category: "menu",
100
+ name: "Bottom Tabs",
101
+ },
102
+ ]
103
+ );
43
104
 
44
105
  expect(menuVisible).toBe(false);
45
106
  });
46
107
  });
47
108
 
48
109
  it("returns false if the screen's general settings allow screen presentation", () => {
49
- const menuVisible = isMenuVisible("", {
50
- general: {
51
- allow_screen_plugin_presentation: true,
110
+ const menuVisible = isMenuVisible(
111
+ "",
112
+ {
113
+ general: {
114
+ allow_screen_plugin_presentation: true,
115
+ },
116
+ navigations: [
117
+ {
118
+ navigation_type: "quick-brick-bottom-tabs",
119
+ identifier: "quick-brick-bottom-tabs",
120
+ category: "menu",
121
+ name: "Bottom Tabs",
122
+ },
123
+ ],
52
124
  },
53
- });
125
+ [
126
+ {
127
+ identifier: "quick-brick-bottom-tabs",
128
+ category: "menu",
129
+ name: "Bottom Tabs",
130
+ },
131
+ ]
132
+ );
54
133
 
55
134
  expect(menuVisible).toBe(false);
56
135
  });
57
136
 
58
- it("returns true otherwise", () => {
59
- const menuVisible = isMenuVisible("", {});
137
+ it("returns false otherwise", () => {
138
+ const menuVisible = isMenuVisible(
139
+ "any",
140
+ {
141
+ navigations: [
142
+ {
143
+ navigation_type: "quick-brick-bottom-tabs",
144
+ identifier: "quick-brick-bottom-tabs",
145
+ category: "menu",
146
+ name: "Bottom Tabs",
147
+ },
148
+ ],
149
+ },
150
+ [
151
+ {
152
+ identifier: "quick-brick-bottom-tabs",
153
+ category: "menu",
154
+ name: "Bottom Tabs",
155
+ },
156
+ ]
157
+ );
158
+
60
159
  expect(menuVisible).toBe(true);
61
160
  });
161
+
162
+ it("returns false otherwise", () => {
163
+ const menuVisible = isMenuVisible("", {}, [
164
+ {
165
+ identifier: "quick-brick-bottom-tabs",
166
+ category: "menu",
167
+ name: "Bottom Tabs",
168
+ },
169
+ ]);
170
+
171
+ expect(menuVisible).toBe(false);
172
+ });
62
173
  });
63
174
  });
@@ -1,6 +1,6 @@
1
1
  /// <reference types="@applicaster/applicaster-types" />
2
2
  import React from "react";
3
- import { View } from "react-native";
3
+ import { AccessibilityInfo, findNodeHandle, View } from "react-native";
4
4
  import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
5
5
 
6
6
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
@@ -12,6 +12,7 @@ import {
12
12
  } from "@applicaster/zapp-react-native-utils/navigationUtils";
13
13
  import {
14
14
  useCurrentScreenData,
15
+ useIsScreenActive,
15
16
  useNavbarState,
16
17
  useNavigation,
17
18
  useRoute,
@@ -57,8 +58,8 @@ export function Screen(_props: Props) {
57
58
  const hasMenu = shouldNavBarDisplayMenu(currentRiver, plugins);
58
59
 
59
60
  const navBarProps = React.useMemo<MobileNavBarPluginProps | null>(
60
- getNavBarProps(currentRiver, pathname, title),
61
- [currentRiver, pathname]
61
+ () => getNavBarProps(currentRiver, pathname, title),
62
+ [currentRiver, pathname, title]
62
63
  );
63
64
 
64
65
  const NavBar = React.useMemo(
@@ -89,13 +90,29 @@ export function Screen(_props: Props) {
89
90
  [theme.app_background_color, backgroundColor]
90
91
  );
91
92
 
92
- // Set ready state when screen is rotated to desired orientation
93
+ const isActive = useIsScreenActive();
94
+
95
+ const ref = React.useRef(null);
93
96
  const isReady = useWaitForValidOrientation();
94
97
 
98
+ React.useEffect(() => {
99
+ if (ref.current && isActive && isReady) {
100
+ const nodeHandle = findNodeHandle(ref.current);
101
+
102
+ if (nodeHandle != null) {
103
+ AccessibilityInfo.setAccessibilityFocus(nodeHandle);
104
+ }
105
+ }
106
+ }, [isActive, isReady]);
107
+
95
108
  // We prevent rendering of the screen until UI is actually rotated to screen desired orientation.
96
109
  // This saves unnecessary re-renders and user will not see distorted aspect screen.
97
110
  return (
98
- <View style={style}>
111
+ <View
112
+ ref={ref}
113
+ style={style}
114
+ importantForAccessibility={!isActive ? "no-hide-descendants" : "yes"}
115
+ >
99
116
  {isReady ? (
100
117
  <>
101
118
  {navBarProps ? <NavBar {...navBarProps} hasMenu={hasMenu} /> : null}
@@ -1,3 +1,5 @@
1
+ import { resolveNavigationPlugin } from "@applicaster/zapp-react-native-utils/navigationUtils";
2
+
1
3
  /**
2
4
  * This function helps to decide wether the menu should be presented on the screen
3
5
  * based on route and / or screen Data
@@ -14,12 +16,28 @@
14
16
  * @param {Object} screenData payload associated with the currently presented screen
15
17
  * @returns {Boolean}
16
18
  */
17
- export function isMenuVisible(route, screenData) {
19
+ export function isMenuVisible(route, screenData, plugins) {
20
+ const plugin = resolveNavigationPlugin({
21
+ category: "menu",
22
+ navigations:
23
+ screenData?.navigations || screenData?.targetScreen?.navigations,
24
+ plugins,
25
+ });
26
+
27
+ const isBottomTabsPlugin = plugin?.identifier === "quick-brick-bottom-tabs";
28
+
29
+ if (!isBottomTabsPlugin) {
30
+ return false;
31
+ }
32
+
18
33
  if (route.includes("playable")) {
19
34
  return false;
20
35
  }
21
36
 
22
- if (screenData.type === "qb_search_screen") {
37
+ if (
38
+ screenData.type === "qb_search_screen" ||
39
+ screenData?.targetScreen?.type === "qb_search_screen"
40
+ ) {
23
41
  return false;
24
42
  }
25
43
 
@@ -0,0 +1,76 @@
1
+ import { makeListOf } from "@applicaster/zapp-react-native-utils/arrayUtils";
2
+ import { isFirstComponentGallery } from "@applicaster/zapp-react-native-utils/componentsUtils";
3
+ import { once } from "ramda";
4
+
5
+ const INITIAL_NUMBER_TO_LOAD = 3;
6
+
7
+ // Infer the values of COMPONENT_LOADING_STATE as a type
8
+ type ComponentLoadingState =
9
+ (typeof COMPONENT_LOADING_STATE)[keyof typeof COMPONENT_LOADING_STATE];
10
+
11
+ export const COMPONENT_LOADING_STATE = {
12
+ UNKNOWN: "UNKNOWN",
13
+ LOADED_WITH_SUCCESS: "LOADED_WITH_SUCCESS",
14
+ LOADED_WITH_FAILURE: "LOADED_WITH_FAILURE",
15
+ } as const;
16
+
17
+ // Function to get the number of loaded components
18
+ const getNumberOfLoaded = (states: ComponentLoadingState[]): number => {
19
+ return states.filter((value) => value !== COMPONENT_LOADING_STATE.UNKNOWN)
20
+ .length;
21
+ };
22
+
23
+ const getNumberOfComponentsWaitToLoadBeforePresent = (
24
+ componentsToRender: ZappUIComponent[]
25
+ ): number => {
26
+ // when Gallery is the first component, no need to wait the others
27
+ if (isFirstComponentGallery(componentsToRender)) {
28
+ return 1;
29
+ }
30
+
31
+ return Math.min(INITIAL_NUMBER_TO_LOAD, componentsToRender.length);
32
+ };
33
+
34
+ export class ScreenRevealManager {
35
+ public numberOfComponentsWaitToLoadBeforePresent: number;
36
+ private renderingState: Array<ComponentLoadingState>;
37
+ private callback: Callback;
38
+
39
+ constructor(componentsToRender: ZappUIComponent[], callback: Callback) {
40
+ this.numberOfComponentsWaitToLoadBeforePresent =
41
+ getNumberOfComponentsWaitToLoadBeforePresent(componentsToRender);
42
+
43
+ this.renderingState = makeListOf<ComponentLoadingState>(
44
+ COMPONENT_LOADING_STATE.UNKNOWN,
45
+ this.numberOfComponentsWaitToLoadBeforePresent
46
+ );
47
+
48
+ this.callback = once(callback);
49
+ }
50
+
51
+ onLoadFinished = (index: number): void => {
52
+ this.renderingState[index] = COMPONENT_LOADING_STATE.LOADED_WITH_SUCCESS;
53
+
54
+ if (
55
+ getNumberOfLoaded(this.renderingState) >=
56
+ this.numberOfComponentsWaitToLoadBeforePresent
57
+ ) {
58
+ this.setIsReadyToShow();
59
+ }
60
+ };
61
+
62
+ onLoadFailed = (index: number): void => {
63
+ this.renderingState[index] = COMPONENT_LOADING_STATE.LOADED_WITH_FAILURE;
64
+
65
+ if (
66
+ getNumberOfLoaded(this.renderingState) >=
67
+ this.numberOfComponentsWaitToLoadBeforePresent
68
+ ) {
69
+ this.setIsReadyToShow();
70
+ }
71
+ };
72
+
73
+ setIsReadyToShow = (): void => {
74
+ this.callback();
75
+ };
76
+ }
@@ -0,0 +1,107 @@
1
+ import {
2
+ ScreenRevealManager,
3
+ COMPONENT_LOADING_STATE,
4
+ } from "../ScreenRevealManager";
5
+
6
+ describe("ScreenRevealManager", () => {
7
+ const mockCallback = jest.fn();
8
+
9
+ beforeEach(() => {
10
+ jest.clearAllMocks();
11
+ });
12
+
13
+ it("should initialize with the correct number of components to wait for", () => {
14
+ const componentsToRender: ZappUIComponent[] = [
15
+ { component_type: "component1" },
16
+ { component_type: "component2" },
17
+ { component_type: "component3" },
18
+ ];
19
+
20
+ const manager = new ScreenRevealManager(componentsToRender, mockCallback);
21
+
22
+ expect(manager.numberOfComponentsWaitToLoadBeforePresent).toBe(3);
23
+
24
+ expect(manager.renderingState).toEqual([
25
+ COMPONENT_LOADING_STATE.UNKNOWN,
26
+ COMPONENT_LOADING_STATE.UNKNOWN,
27
+ COMPONENT_LOADING_STATE.UNKNOWN,
28
+ ]);
29
+ });
30
+
31
+ it("should call the callback when the required number of components are loaded successfully", () => {
32
+ const componentsToRender: ZappUIComponent[] = [
33
+ { component_type: "component1" },
34
+ { component_type: "component2" },
35
+ { component_type: "component3" },
36
+ ];
37
+
38
+ const manager = new ScreenRevealManager(componentsToRender, mockCallback);
39
+
40
+ manager.onLoadFinished(0);
41
+ manager.onLoadFinished(1);
42
+ manager.onLoadFinished(2);
43
+
44
+ expect(mockCallback).toHaveBeenCalledTimes(1);
45
+ });
46
+
47
+ it("should call the callback when the required number of components fail to load", () => {
48
+ const componentsToRender: ZappUIComponent[] = [
49
+ { component_type: "component1" },
50
+ { component_type: "component2" },
51
+ { component_type: "component3" },
52
+ ];
53
+
54
+ const manager = new ScreenRevealManager(componentsToRender, mockCallback);
55
+
56
+ manager.onLoadFailed(0);
57
+ manager.onLoadFailed(1);
58
+ manager.onLoadFailed(2);
59
+
60
+ expect(mockCallback).toHaveBeenCalledTimes(1);
61
+ });
62
+
63
+ it("should call the callback when a mix of successful and failed loads meet the required number", () => {
64
+ const componentsToRender: ZappUIComponent[] = [
65
+ { component_type: "component1" },
66
+ { component_type: "component2" },
67
+ { component_type: "component3" },
68
+ ];
69
+
70
+ const manager = new ScreenRevealManager(componentsToRender, mockCallback);
71
+
72
+ manager.onLoadFinished(0);
73
+ manager.onLoadFailed(1);
74
+ manager.onLoadFinished(2);
75
+
76
+ expect(mockCallback).toHaveBeenCalledTimes(1);
77
+ });
78
+
79
+ it("should not call the callback if the required number of components are not loaded", () => {
80
+ const componentsToRender: ZappUIComponent[] = [
81
+ { component_type: "component1" },
82
+ { component_type: "component2" },
83
+ { component_type: "component3" },
84
+ ];
85
+
86
+ const manager = new ScreenRevealManager(componentsToRender, mockCallback);
87
+
88
+ manager.onLoadFinished(0);
89
+ manager.onLoadFailed(1);
90
+
91
+ expect(mockCallback).not.toHaveBeenCalled();
92
+ });
93
+
94
+ it("should call the callback when the when first component is gallery and it was loaded successfully", () => {
95
+ const componentsToRender: ZappUIComponent[] = [
96
+ { component_type: "gallery-qb" },
97
+ { component_type: "component2" },
98
+ { component_type: "component3" },
99
+ ];
100
+
101
+ const manager = new ScreenRevealManager(componentsToRender, mockCallback);
102
+
103
+ manager.onLoadFinished(0);
104
+
105
+ expect(mockCallback).toHaveBeenCalledTimes(1);
106
+ });
107
+ });