@applicaster/zapp-react-native-ui-components 16.0.0-rc.9 → 16.0.0-rc.90

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 (144) hide show
  1. package/Components/AudioPlayer/tv/__tests__/audioPlayer.test.js +19 -0
  2. package/Components/AudioPlayer/tv/__tests__/index.test.tsx +120 -0
  3. package/Components/AudioPlayer/tv/index.tsx +5 -1
  4. package/Components/Cell/Cell.tsx +3 -6
  5. package/Components/Cell/TvOSCellComponent.tsx +0 -1
  6. package/Components/CellRendererResolver/index.ts +2 -2
  7. package/Components/ComponentResolver/__tests__/componentResolver.test.js +1 -1
  8. package/Components/FocusableGroup/FocusableTvOS.tsx +11 -7
  9. package/Components/GeneralContentScreen/GeneralContentScreenHookAdapter.tsx +54 -0
  10. package/Components/GeneralContentScreen/__tests__/GeneralContentScreenHookAdapter.test.tsx +64 -0
  11. package/Components/GeneralContentScreen/__tests__/HookContentFocusGroup.web.test.tsx +91 -0
  12. package/Components/GeneralContentScreen/hookAdapter/__tests__/networkService.test.ts +74 -0
  13. package/Components/GeneralContentScreen/hookAdapter/__tests__/runInBackground.test.ts +139 -0
  14. package/Components/GeneralContentScreen/hookAdapter/__tests__/skipExpression.test.ts +294 -0
  15. package/Components/GeneralContentScreen/hookAdapter/__tests__/validationHelper.test.ts +188 -0
  16. package/Components/GeneralContentScreen/hookAdapter/logger.ts +6 -0
  17. package/Components/GeneralContentScreen/hookAdapter/networkService.ts +53 -0
  18. package/Components/GeneralContentScreen/hookAdapter/runInBackground.ts +48 -0
  19. package/Components/GeneralContentScreen/hookAdapter/skipExpression.ts +252 -0
  20. package/Components/GeneralContentScreen/hookAdapter/validationHelper.ts +90 -0
  21. package/Components/GeneralContentScreen/hookFocus/index.tsx +13 -0
  22. package/Components/GeneralContentScreen/hookFocus/index.web.tsx +69 -0
  23. package/Components/GeneralContentScreen/index.ts +2 -0
  24. package/Components/Layout/FullWidthRow.tsx +38 -0
  25. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +21 -6
  26. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/placement.test.ts +47 -21
  27. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/ActionButtonController.tsx +19 -4
  28. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/__tests__/ActionButtonController.test.tsx +43 -1
  29. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/placement.ts +34 -6
  30. package/Components/MasterCell/DefaultComponents/Button.tsx +1 -0
  31. package/Components/MasterCell/DefaultComponents/Image/hoc/utils/__tests__/withDimensions.test.ts +420 -125
  32. package/Components/MasterCell/DefaultComponents/Image/hoc/utils/index.ts +114 -19
  33. package/Components/MasterCell/DefaultComponents/Image/hoc/withDimensions.tsx +19 -8
  34. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -3
  35. package/Components/MasterCell/DefaultComponents/PressableView.tsx +29 -9
  36. package/Components/MasterCell/DefaultComponents/Text/hooks/useText.ts +4 -0
  37. package/Components/MasterCell/DefaultComponents/Toggle.tsx +36 -14
  38. package/Components/MasterCell/DefaultComponents/__tests__/Toggle.test.tsx +167 -0
  39. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/ActionButton.tsx +154 -100
  40. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/AssetComponent.tsx +15 -4
  41. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Button.ts +56 -22
  42. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Spacer.ts +6 -4
  43. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabelsContainer.ts +3 -1
  44. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/PressableView.test.tsx +32 -21
  45. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/index.test.ts +15 -4
  46. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/index.ts +23 -16
  47. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/__tests__/insertButtons.test.ts +8 -3
  48. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/index.ts +2 -2
  49. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/insertButtonsBetweenLabels.test.ts +45 -13
  50. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +2 -2
  51. package/Components/MasterCell/contexts/PressedStateContext.ts +3 -0
  52. package/Components/MasterCell/dataAdapter.ts +15 -5
  53. package/Components/MasterCell/hooks/index.ts +2 -0
  54. package/Components/MasterCell/hooks/usePressedState.ts +4 -0
  55. package/Components/MasterCell/index.tsx +30 -5
  56. package/Components/MasterCell/utils/__tests__/resolveColor.test.js +169 -132
  57. package/Components/MasterCell/utils/__tests__/resolveColorForProp.test.js +92 -0
  58. package/Components/MasterCell/utils/index.ts +85 -46
  59. package/Components/ModalComponent/ActionsBottomSheet/ActionButton.tsx +56 -0
  60. package/Components/ModalComponent/ActionsBottomSheet/__tests__/openActionsBottomSheet.test.ts +38 -0
  61. package/Components/ModalComponent/ActionsBottomSheet/boundActionButton.tsx +24 -0
  62. package/Components/ModalComponent/ActionsBottomSheet/index.ts +9 -0
  63. package/Components/ModalComponent/ActionsBottomSheet/openActionsBottomSheet.ts +61 -0
  64. package/Components/ModalComponent/AudioPlayer/Components/Button.tsx +385 -0
  65. package/Components/ModalComponent/AudioPlayer/Components/Header.tsx +728 -0
  66. package/Components/ModalComponent/AudioPlayer/Components/Input.tsx +628 -0
  67. package/Components/ModalComponent/AudioPlayer/Components/Item.tsx +982 -0
  68. package/Components/ModalComponent/AudioPlayer/Components/NowPlayingHeaderSection.tsx +94 -0
  69. package/Components/ModalComponent/AudioPlayer/Components/__tests__/Item.test.tsx +113 -0
  70. package/Components/ModalComponent/AudioPlayer/Components/index.ts +9 -0
  71. package/Components/ModalComponent/AudioPlayer/utils/__tests__/mergeStyles.test.ts +248 -0
  72. package/Components/ModalComponent/AudioPlayer/utils/mergeStyles.ts +386 -0
  73. package/Components/ModalComponent/BottomSheetDragArea.tsx +33 -0
  74. package/Components/ModalComponent/BottomSheetModalContent.tsx +431 -49
  75. package/Components/ModalComponent/Button/index.tsx +5 -3
  76. package/Components/ModalComponent/Header/CloseButton.tsx +12 -0
  77. package/Components/ModalComponent/Header/__tests__/CloseButton.test.tsx +72 -0
  78. package/Components/ModalComponent/Header/index.tsx +20 -7
  79. package/Components/ModalComponent/Header/utils.ts +1 -1
  80. package/Components/ModalComponent/ModalBlocksStyleContext.tsx +10 -0
  81. package/Components/ModalComponent/SortableList.tsx +157 -0
  82. package/Components/ModalComponent/SortableList.web.tsx +34 -0
  83. package/Components/ModalComponent/TextInputContent.tsx +112 -0
  84. package/Components/ModalComponent/__tests__/BottomSheetDragArea.test.tsx +74 -0
  85. package/Components/ModalComponent/__tests__/BottomSheetModalContent.test.tsx +255 -0
  86. package/Components/ModalComponent/__tests__/SortableList.web.test.tsx +16 -0
  87. package/Components/ModalComponent/__tests__/TextInputContent.test.tsx +156 -0
  88. package/Components/ModalComponent/__tests__/showTextInput.test.ts +95 -0
  89. package/Components/ModalComponent/index.tsx +18 -9
  90. package/Components/ModalComponent/presets/__tests__/getCell.test.ts +90 -0
  91. package/Components/ModalComponent/presets/dynamicCollectionCell.tsx +78 -0
  92. package/Components/ModalComponent/presets/index.ts +27 -0
  93. package/Components/ModalComponent/presets/selectableCell.tsx +28 -0
  94. package/Components/ModalComponent/presets/standardCell.tsx +41 -0
  95. package/Components/ModalComponent/presets/types.ts +35 -0
  96. package/Components/ModalComponent/showTextInput.ts +43 -0
  97. package/Components/ModalComponent/utils.ts +82 -21
  98. package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +4 -85
  99. package/Components/OfflineHandler/__tests__/index.test.tsx +78 -18
  100. package/Components/OfflineHandler/hooks.ts +111 -0
  101. package/Components/OfflineHandler/index.tsx +51 -73
  102. package/Components/OfflineHandler/utils/index.ts +1 -13
  103. package/Components/PlayerContainer/PlayerContainer.tsx +25 -17
  104. package/Components/PlayerContainer/ProgramInfo/index.tsx +3 -4
  105. package/Components/PlayerContainer/__tests__/PlayerContainer.test.tsx +337 -0
  106. package/Components/PreloaderWrapper/index.tsx +1 -1
  107. package/Components/River/ComponentsMap/ComponentsMap.tsx +87 -61
  108. package/Components/River/River.tsx +4 -0
  109. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +140 -89
  110. package/Components/River/__tests__/componentsMap.test.js +8 -3
  111. package/Components/River/__tests__/resultCallback.test.tsx +47 -0
  112. package/Components/Screen/index.tsx +8 -4
  113. package/Components/Screen/navigationHandler.ts +8 -8
  114. package/Components/ScreenFeedLoader/ScreenFeedLoader.tsx +5 -3
  115. package/Components/ScreenResolverFeedProvider/ScreenResolverFeedProvider.tsx +1 -1
  116. package/Components/ScreenRevealManager/ScreenRevealManager.ts +18 -2
  117. package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +36 -0
  118. package/Components/ScreenRevealManager/__tests__/withScreenRevealManager.test.tsx +56 -0
  119. package/Components/ScreenRevealManager/withScreenRevealManager.tsx +21 -4
  120. package/Components/TopCutoffOverlay/index.tsx +2 -2
  121. package/Components/Transitioner/Transitioner.tsx +28 -17
  122. package/Components/VideoLive/LiveImageManager.ts +1 -1
  123. package/Components/VideoModal/utils.ts +6 -1
  124. package/Components/ZappFrameworkComponents/BarView/BarView.tsx +12 -5
  125. package/Components/ZappFrameworkComponents/BarView/__tests__/BarView.test.tsx +2 -2
  126. package/Contexts/CachedDimensionsContext/__tests__/index.test.ts +154 -0
  127. package/Contexts/CachedDimensionsContext/index.ts +17 -2
  128. package/Contexts/ModalNavigationContext/__tests__/index.test.tsx +15 -0
  129. package/Contexts/ModalNavigationContext/index.tsx +2 -2
  130. package/Helpers/ComponentCellSelectionHelper/index.js +0 -6
  131. package/Helpers/index.js +0 -39
  132. package/Hooks/useEntryActionsExpander.ts +63 -0
  133. package/package.json +6 -5
  134. package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +0 -112
  135. package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +0 -107
  136. package/Components/OfflineHandler/NotificationView/NotificationView.tsx +0 -153
  137. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +0 -66
  138. package/Components/OfflineHandler/NotificationView/utils.ts +0 -34
  139. package/Components/Screen/utils.ts +0 -16
  140. package/Helpers/Analytics/index.js +0 -95
  141. /package/Components/BackgroundImage/{BackgroundImage.tv.android.tsx → BackgroundImage.android.tv.tsx} +0 -0
  142. /package/Components/BackgroundImage/{BackgroundImage.tv.ios.tsx → BackgroundImage.ios.tv.tsx} +0 -0
  143. /package/Components/MasterCell/DefaultComponents/ButtonContainerView/{index.tv.android.tsx → index.android.tv.tsx} +0 -0
  144. /package/Decorators/ZappPipesDataConnector/__tests__/{Hero.js → Hero.tsx} +0 -0
@@ -10,103 +10,129 @@ exports[`componentsMap renders renders components map correctly 1`] = `
10
10
  >
11
11
  <View
12
12
  onLayout={[Function]}
13
- style={
14
- {
15
- "flex": 1,
16
- }
17
- }
13
+ style={{}}
18
14
  >
19
15
  <RCTScrollView
20
16
  ListFooterComponent={
21
- <Memo(RiverFooterComponent)
22
- flatListHeight={null}
23
- loadingState={
24
- BehaviorSubject {
25
- "_value": {
26
- "done": false,
27
- "index": -1,
28
- "waitForAllComponents": false,
29
- },
30
- "closed": false,
31
- "currentObservers": null,
32
- "hasError": false,
33
- "isStopped": false,
34
- "observers": [
35
- SafeSubscriber {
36
- "_finalizers": [
37
- Subscription {
38
- "_finalizers": null,
39
- "_parentage": [Circular],
40
- "closed": false,
41
- "initialTeardown": [Function],
42
- },
43
- ],
44
- "_parentage": null,
45
- "closed": false,
46
- "destination": ConsumerObserver {
47
- "partialObserver": {
48
- "complete": undefined,
49
- "error": undefined,
50
- "next": [Function],
51
- },
52
- },
53
- "initialTeardown": undefined,
54
- "isStopped": false,
17
+ <React.Fragment>
18
+ <Memo(RiverFooterComponent)
19
+ flatListHeight={null}
20
+ loadingState={
21
+ BehaviorSubject {
22
+ "_value": {
23
+ "done": false,
24
+ "index": -1,
25
+ "waitForAllComponents": false,
55
26
  },
56
- SafeSubscriber {
57
- "_finalizers": [
58
- Subscription {
59
- "_finalizers": null,
60
- "_parentage": [Circular],
61
- "closed": false,
62
- "initialTeardown": [Function],
63
- },
64
- ],
65
- "_parentage": null,
66
- "closed": false,
67
- "destination": ConsumerObserver {
68
- "partialObserver": {
69
- "complete": undefined,
70
- "error": undefined,
71
- "next": [Function],
27
+ "closed": false,
28
+ "currentObservers": null,
29
+ "hasError": false,
30
+ "isStopped": false,
31
+ "observers": [
32
+ SafeSubscriber {
33
+ "_finalizers": [
34
+ Subscription {
35
+ "_finalizers": null,
36
+ "_parentage": [Circular],
37
+ "closed": false,
38
+ "initialTeardown": [Function],
39
+ },
40
+ ],
41
+ "_parentage": null,
42
+ "closed": false,
43
+ "destination": ConsumerObserver {
44
+ "partialObserver": {
45
+ "complete": undefined,
46
+ "error": undefined,
47
+ "next": [Function],
48
+ },
72
49
  },
50
+ "initialTeardown": undefined,
51
+ "isStopped": false,
73
52
  },
74
- "initialTeardown": undefined,
75
- "isStopped": false,
76
- },
77
- SafeSubscriber {
78
- "_finalizers": [
79
- Subscription {
80
- "_finalizers": null,
81
- "_parentage": [Circular],
82
- "closed": false,
83
- "initialTeardown": [Function],
53
+ SafeSubscriber {
54
+ "_finalizers": [
55
+ Subscription {
56
+ "_finalizers": null,
57
+ "_parentage": [Circular],
58
+ "closed": false,
59
+ "initialTeardown": [Function],
60
+ },
61
+ ],
62
+ "_parentage": null,
63
+ "closed": false,
64
+ "destination": ConsumerObserver {
65
+ "partialObserver": {
66
+ "complete": undefined,
67
+ "error": undefined,
68
+ "next": [Function],
69
+ },
84
70
  },
85
- ],
86
- "_parentage": null,
87
- "closed": false,
88
- "destination": ConsumerObserver {
89
- "partialObserver": {
90
- "complete": undefined,
91
- "error": undefined,
92
- "next": [Function],
71
+ "initialTeardown": undefined,
72
+ "isStopped": false,
73
+ },
74
+ SafeSubscriber {
75
+ "_finalizers": [
76
+ Subscription {
77
+ "_finalizers": null,
78
+ "_parentage": [Circular],
79
+ "closed": false,
80
+ "initialTeardown": [Function],
81
+ },
82
+ ],
83
+ "_parentage": null,
84
+ "closed": false,
85
+ "destination": ConsumerObserver {
86
+ "partialObserver": {
87
+ "complete": undefined,
88
+ "error": undefined,
89
+ "next": [Function],
90
+ },
93
91
  },
92
+ "initialTeardown": undefined,
93
+ "isStopped": false,
94
94
  },
95
- "initialTeardown": undefined,
96
- "isStopped": false,
97
- },
98
- ],
99
- "thrownError": null,
95
+ ],
96
+ "thrownError": null,
97
+ }
98
+ }
99
+ />
100
+ <View
101
+ edges={
102
+ {
103
+ "bottom": "off",
104
+ }
105
+ }
106
+ mode="margin"
107
+ style={
108
+ {
109
+ "height": 0.5,
110
+ "paddingBottom": undefined,
111
+ }
112
+ }
113
+ />
114
+ </React.Fragment>
115
+ }
116
+ ListHeaderComponent={
117
+ <View
118
+ edges={
119
+ {
120
+ "top": "off",
121
+ }
122
+ }
123
+ mode="margin"
124
+ style={
125
+ {
126
+ "height": 0.5,
127
+ "paddingTop": undefined,
100
128
  }
101
129
  }
102
130
  />
103
131
  }
104
132
  contentContainerStyle={
105
133
  {
106
- "paddingBottom": undefined,
107
134
  "paddingLeft": undefined,
108
135
  "paddingRight": undefined,
109
- "paddingTop": undefined,
110
136
  }
111
137
  }
112
138
  data={
@@ -161,17 +187,32 @@ exports[`componentsMap renders renders components map correctly 1`] = `
161
187
  >
162
188
  <View>
163
189
  <View
164
- onFocusCapture={[Function]}
190
+ collapsable={false}
165
191
  onLayout={[Function]}
166
- style={null}
167
192
  >
168
193
  <View
169
- onLayout={[Function]}
194
+ edges={
195
+ {
196
+ "top": "off",
197
+ }
198
+ }
199
+ mode="margin"
170
200
  style={
171
201
  {
172
- "flex": 1,
202
+ "height": 0.5,
203
+ "paddingTop": undefined,
173
204
  }
174
205
  }
206
+ />
207
+ </View>
208
+ <View
209
+ onFocusCapture={[Function]}
210
+ onLayout={[Function]}
211
+ style={null}
212
+ >
213
+ <View
214
+ onLayout={[Function]}
215
+ style={{}}
175
216
  >
176
217
  <View />
177
218
  </View>
@@ -183,11 +224,7 @@ exports[`componentsMap renders renders components map correctly 1`] = `
183
224
  >
184
225
  <View
185
226
  onLayout={[Function]}
186
- style={
187
- {
188
- "flex": 1,
189
- }
190
- }
227
+ style={{}}
191
228
  />
192
229
  </View>
193
230
  <View
@@ -212,6 +249,20 @@ exports[`componentsMap renders renders components map correctly 1`] = `
212
249
  size="large"
213
250
  />
214
251
  </View>
252
+ <View
253
+ edges={
254
+ {
255
+ "bottom": "off",
256
+ }
257
+ }
258
+ mode="margin"
259
+ style={
260
+ {
261
+ "height": 0.5,
262
+ "paddingBottom": undefined,
263
+ }
264
+ }
265
+ />
215
266
  </View>
216
267
  </View>
217
268
  </RCTScrollView>
@@ -11,9 +11,14 @@ jest.mock(
11
11
  () => () => null
12
12
  );
13
13
 
14
- jest.mock("react-native-safe-area-context", () => ({
15
- useSafeAreaInsets: () => ({ top: 50 }),
16
- }));
14
+ jest.mock("react-native-safe-area-context", () => {
15
+ const { View } = jest.requireActual("react-native");
16
+
17
+ return {
18
+ SafeAreaView: View,
19
+ useSafeAreaInsets: () => ({ top: 50 }),
20
+ };
21
+ });
17
22
 
18
23
  jest.mock("react-native", () => {
19
24
  const RN = jest.genMockFromModule("react-native");
@@ -0,0 +1,47 @@
1
+ import React from "react";
2
+ import { render } from "@testing-library/react-native";
3
+
4
+ import { RiverComponent } from "../River";
5
+
6
+ const mockResolverProps: any[] = [];
7
+
8
+ jest.mock("../../ScreenResolver", () => ({
9
+ ScreenResolver: (props: any) => {
10
+ mockResolverProps.push(props);
11
+
12
+ return null;
13
+ },
14
+ }));
15
+
16
+ const river = { id: "river-parent-lock", type: "parent_lock" } as any;
17
+
18
+ const baseProps = {
19
+ river,
20
+ screenData: {},
21
+ groupId: "group-1",
22
+ scrollViewExtraProps: {},
23
+ setIsScreenWrappedInContainer: jest.fn(),
24
+ screenContext: { navBar: { setTitle: jest.fn(), setSummary: jest.fn() } },
25
+ } as any;
26
+
27
+ const resolved = () => mockResolverProps[mockResolverProps.length - 1];
28
+
29
+ describe("RiverComponent", () => {
30
+ beforeEach(() => {
31
+ mockResolverProps.length = 0;
32
+ });
33
+
34
+ it("forwards resultCallback to the screen it resolves", () => {
35
+ const resultCallback = jest.fn();
36
+
37
+ render(<RiverComponent {...baseProps} resultCallback={resultCallback} />);
38
+
39
+ expect(resolved().resultCallback).toBe(resultCallback);
40
+ });
41
+
42
+ it("resolves the screen without a resultCallback when none was given", () => {
43
+ render(<RiverComponent {...baseProps} />);
44
+
45
+ expect(resolved().resultCallback).toBeUndefined();
46
+ });
47
+ });
@@ -18,10 +18,13 @@ import {
18
18
  useScreenData,
19
19
  } from "@applicaster/zapp-react-native-utils/reactHooks";
20
20
  import { getNavigationPluginModule } from "@applicaster/zapp-react-native-app/App/Layout/layoutHelpers";
21
+ import {
22
+ isValidColor,
23
+ isTransparentColor,
24
+ } from "@applicaster/zapp-react-native-utils/colorUtils";
21
25
 
22
26
  import { RouteManager } from "../RouteManager";
23
27
  import { useScreenConfiguration } from "../River/useScreenConfiguration";
24
- import { isValidColor } from "./utils";
25
28
  import { useWaitForValidOrientation } from "./hooks";
26
29
 
27
30
  const screenStyles = {
@@ -82,9 +85,10 @@ export function Screen(_props: Props) {
82
85
  const style = React.useMemo(
83
86
  () => ({
84
87
  ...screenStyles,
85
- backgroundColor: isValidColor(backgroundColor)
86
- ? backgroundColor
87
- : theme.app_background_color,
88
+ backgroundColor:
89
+ isValidColor(backgroundColor) && !isTransparentColor(backgroundColor)
90
+ ? backgroundColor
91
+ : theme.app_background_color,
88
92
  }),
89
93
  [theme.app_background_color, backgroundColor]
90
94
  );
@@ -18,10 +18,9 @@ function shouldShowNavigation(route, screenData) {
18
18
  return false;
19
19
  }
20
20
 
21
- if (
22
- screenData.type === "qb_search_screen" ||
23
- screenData?.targetScreen?.type === "qb_search_screen"
24
- ) {
21
+ const currentScreenData = screenData?.targetScreen || screenData;
22
+
23
+ if (currentScreenData.type === "qb_search_screen") {
25
24
  return false;
26
25
  }
27
26
 
@@ -31,10 +30,11 @@ function shouldShowNavigation(route, screenData) {
31
30
  return hookPlugin?.showNavBar || hookPlugin?.presentFullScreen !== true;
32
31
  }
33
32
 
34
- if (
35
- screenData?.general?.allow_screen_plugin_presentation ||
36
- screenData?.targetScreen?.general?.allow_screen_plugin_presentation
37
- ) {
33
+ if (currentScreenData?.general?.hide_menu) {
34
+ return false;
35
+ }
36
+
37
+ if (currentScreenData?.general?.allow_screen_plugin_presentation) {
38
38
  return false;
39
39
  }
40
40
 
@@ -8,9 +8,11 @@ import { componentsLogger } from "../../Helpers/logger";
8
8
  const logger = componentsLogger.addSubsystem("ScreenFeedLoader");
9
9
 
10
10
  /** Loads and provides `feedData` and store to */
11
- export const ScreenFeedLoader: React.FC<
12
- React.PropsWithChildren<{ id: string; feedData: any }>
13
- > = ({ id, feedData, children }) => {
11
+ export const ScreenFeedLoader: React.FC<{
12
+ id: string;
13
+ feedData: any;
14
+ children: React.ReactElement | null;
15
+ }> = ({ id, feedData, children }) => {
14
16
  const { source: feedUrl, mapping } = feedData;
15
17
 
16
18
  const { data, loading, error } = useFeedLoader({
@@ -8,7 +8,7 @@ export const ScreenResolverFeedProvider = ({
8
8
  useFeedData,
9
9
  }: {
10
10
  id: string;
11
- children: React.ReactNode;
11
+ children: React.ReactElement | null;
12
12
  useFeedData: (id: string) => Option<ZappDataSource>;
13
13
  }) => {
14
14
  const feedData = useFeedData(id);
@@ -42,9 +42,25 @@ export class ScreenRevealManager {
42
42
  private subject$ = new Subject<void>();
43
43
  private subscription: Subscription;
44
44
 
45
- constructor(componentsToRender: ZappUIComponent[], callback: Callback) {
45
+ /**
46
+ * @param initialNumberToLoad how many components to wait for before revealing
47
+ * the screen. Staggering exists so a screen full of network-backed components
48
+ * does not load them all at once. A caller that has nothing to stagger - see
49
+ * `disableIncrementalLoading` on the HOC - passes the full count here so the
50
+ * reveal waits for exactly what gets rendered. Omitted, the count is derived
51
+ * from the components themselves.
52
+ */
53
+ constructor(
54
+ componentsToRender: ZappUIComponent[],
55
+ callback: Callback,
56
+ initialNumberToLoad?: number
57
+ ) {
46
58
  this.numberOfComponentsWaitToLoadBeforePresent =
47
- getNumberOfComponentsWaitToLoadBeforePresent(componentsToRender);
59
+ initialNumberToLoad == null
60
+ ? getNumberOfComponentsWaitToLoadBeforePresent(componentsToRender)
61
+ : // Clamped like the computed path: waiting for components that do not
62
+ // exist would hold the screen behind its overlay until the timeout.
63
+ Math.min(initialNumberToLoad, componentsToRender.length);
48
64
 
49
65
  this.renderingState = makeListOf<ComponentLoadingState>(
50
66
  COMPONENT_LOADING_STATE.UNKNOWN,
@@ -22,6 +22,42 @@ import { makeListOf } from "@applicaster/zapp-react-native-utils/arrayUtils";
22
22
  import { isFirstComponentGallery } from "@applicaster/zapp-react-native-utils/componentsUtils";
23
23
  import { withTimeout$ } from "@applicaster/zapp-react-native-utils/idleUtils";
24
24
 
25
+ describe("ScreenRevealManager explicit component count", () => {
26
+ beforeEach(() => {
27
+ (isFirstComponentGallery as jest.Mock).mockReturnValue(false);
28
+
29
+ (makeListOf as jest.Mock).mockImplementation((value, length) =>
30
+ Array(length).fill(value)
31
+ );
32
+
33
+ (withTimeout$ as jest.Mock).mockReturnValue(new Subject());
34
+ });
35
+
36
+ it("waits for the number of components it is given, not the computed default", () => {
37
+ const components = Array(6).fill({}) as any;
38
+
39
+ const manager = new ScreenRevealManager(components, jest.fn(), 6);
40
+
41
+ expect(manager.numberOfComponentsWaitToLoadBeforePresent).toBe(6);
42
+ });
43
+
44
+ it("never waits for more components than it was handed", () => {
45
+ const components = Array(3).fill({}) as any;
46
+
47
+ const manager = new ScreenRevealManager(components, jest.fn(), 10);
48
+
49
+ expect(manager.numberOfComponentsWaitToLoadBeforePresent).toBe(3);
50
+ });
51
+
52
+ it("falls back to the computed default when given no explicit count", () => {
53
+ const components = Array(6).fill({}) as any;
54
+
55
+ const manager = new ScreenRevealManager(components, jest.fn());
56
+
57
+ expect(manager.numberOfComponentsWaitToLoadBeforePresent).toBe(3);
58
+ });
59
+ });
60
+
25
61
  describe("ScreenRevealManager", () => {
26
62
  let mockCallback: jest.Mock;
27
63
  let timeout$: Subject<void>;
@@ -9,6 +9,12 @@ import {
9
9
  TIMEOUT,
10
10
  } from "../withScreenRevealManager";
11
11
 
12
+ jest.mock("@applicaster/zapp-react-native-utils/theme", () => ({
13
+ useTheme: () => ({ app_background_color: "#000000" }),
14
+ }));
15
+
16
+ jest.mock("../Overlay", () => ({ Overlay: () => null }));
17
+
12
18
  // jest.mock("react-native/Libraries/Animated/NativeAnimatedHelper");
13
19
 
14
20
  const MockComponent = ({
@@ -37,6 +43,56 @@ const MockComponent = ({
37
43
 
38
44
  const WrappedComponent = withScreenRevealManager(MockComponent);
39
45
 
46
+ describe("withScreenRevealManager disableIncrementalLoading", () => {
47
+ const components = (count: number) =>
48
+ Array(count).fill({ component_type: "grid-qb" });
49
+
50
+ beforeEach(() => {
51
+ jest.clearAllMocks();
52
+ });
53
+
54
+ it("asks for every component at once when incremental loading is disabled", () => {
55
+ render(
56
+ <WrappedComponent
57
+ componentsToRender={components(6)}
58
+ disableIncrementalLoading
59
+ />
60
+ );
61
+
62
+ expect(screen.getByTestId("mock-component").props.initialNumberToLoad).toBe(
63
+ 6
64
+ );
65
+ });
66
+
67
+ it("still tracks the component count after it changes", () => {
68
+ const { rerender } = render(
69
+ <WrappedComponent
70
+ componentsToRender={components(6)}
71
+ disableIncrementalLoading
72
+ />
73
+ );
74
+
75
+ rerender(
76
+ <WrappedComponent
77
+ componentsToRender={components(9)}
78
+ disableIncrementalLoading
79
+ />
80
+ );
81
+
82
+ expect(screen.getByTestId("mock-component").props.initialNumberToLoad).toBe(
83
+ 9
84
+ );
85
+ });
86
+
87
+ it("loads incrementally when the flag is not set", () => {
88
+ render(<WrappedComponent componentsToRender={components(6)} />);
89
+
90
+ expect(screen.getByTestId("mock-component").props.initialNumberToLoad).toBe(
91
+ 3
92
+ );
93
+ });
94
+ });
95
+
40
96
  describe.skip("withScreenRevealManager", () => {
41
97
  beforeEach(() => {
42
98
  jest.clearAllMocks();
@@ -21,11 +21,23 @@ export const SHOWN = 1; // opacity = 1
21
21
  type Props = {
22
22
  componentsToRender: ZappUIComponent[];
23
23
  backgroundColor?: string;
24
+ /**
25
+ * Renders every component at once instead of revealing them a few at a time.
26
+ *
27
+ * For a screen that builds its own components and holds all of them already -
28
+ * a form, say - staggering buys nothing and costs: each rebuild of the list
29
+ * tears it back down to the first few and lets the rest crawl in again.
30
+ *
31
+ * This is a flag rather than a count on purpose. A count would have to be
32
+ * re-read whenever the number of components changes, while "do not stagger"
33
+ * stays true whatever the screen ends up holding.
34
+ */
35
+ disableIncrementalLoading?: boolean;
24
36
  };
25
37
 
26
38
  export const withScreenRevealManager = (Component) => {
27
39
  return function WithScreenRevealManager(props: Props) {
28
- const { componentsToRender } = props;
40
+ const { componentsToRender, disableIncrementalLoading } = props;
29
41
 
30
42
  const [isContentReadyToBeShown, setIsContentReadyToBeShown] =
31
43
  React.useState(false);
@@ -42,7 +54,8 @@ export const withScreenRevealManager = (Component) => {
42
54
  () =>
43
55
  new ScreenRevealManager(
44
56
  componentsToRender,
45
- handleSetIsContentReadyToBeShown
57
+ handleSetIsContentReadyToBeShown,
58
+ disableIncrementalLoading ? componentsToRender.length : undefined
46
59
  )
47
60
  );
48
61
 
@@ -72,7 +85,7 @@ export const withScreenRevealManager = (Component) => {
72
85
 
73
86
  if (isFirstComponentScreenPicker(componentsToRender)) {
74
87
  // for screen-picker with have additional internal ComponentsMap, no need to add this wrapper
75
- return <Component {...props} />;
88
+ return <Component {...props} initialNumberToLoad={1} />;
76
89
  }
77
90
 
78
91
  return (
@@ -80,7 +93,11 @@ export const withScreenRevealManager = (Component) => {
80
93
  <Component
81
94
  {...props}
82
95
  initialNumberToLoad={
83
- managerRef.current.numberOfComponentsWaitToLoadBeforePresent
96
+ // Recomputed on every render, so the count follows the components
97
+ // even though the manager settled its own expectation at mount.
98
+ disableIncrementalLoading
99
+ ? componentsToRender.length
100
+ : managerRef.current.numberOfComponentsWaitToLoadBeforePresent
84
101
  }
85
102
  onLoadFinishedFromScreenRevealManager={
86
103
  managerRef.current.onLoadFinished
@@ -7,7 +7,7 @@ import { useMarginTop } from "./hooks";
7
7
 
8
8
  interface IProps {
9
9
  targetScreenId?: string;
10
- children?: React.ReactNode;
10
+ children: React.ReactElement | null;
11
11
  applyTopCutoff?: boolean;
12
12
  }
13
13
 
@@ -21,7 +21,7 @@ export const TopCutoffOverlay: React.FC<IProps> = ({
21
21
  targetScreenId,
22
22
  children,
23
23
  applyTopCutoff = true,
24
- }: IProps) => {
24
+ }) => {
25
25
  const cutoffHeight = useMarginTop(targetScreenId);
26
26
 
27
27
  const { backgroundColor: screenBackgroundColor } =