@applicaster/zapp-react-native-ui-components 14.0.0-rc.8 → 15.0.0-rc.1

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 (163) hide show
  1. package/Components/AnimatedInOut/index.tsx +5 -3
  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/__tests__/CellWIthFocusable.test.js +3 -2
  26. package/Components/Cell/index.js +7 -3
  27. package/Components/ComponentResolver/index.ts +1 -1
  28. package/Components/FeedLoader/FeedLoader.tsx +7 -16
  29. package/Components/FeedLoader/FeedLoaderHOC.tsx +21 -0
  30. package/Components/FeedLoader/index.js +2 -8
  31. package/Components/Focusable/Focusable.tsx +12 -3
  32. package/Components/Focusable/FocusableTvOS.tsx +5 -5
  33. package/Components/Focusable/FocusableiOS.tsx +2 -2
  34. package/Components/Focusable/Touchable.tsx +5 -3
  35. package/Components/Focusable/__tests__/index.android.test.tsx +3 -0
  36. package/Components/Focusable/index.android.tsx +19 -11
  37. package/Components/Focusable/index.tsx +1 -1
  38. package/Components/FocusableGroup/FocusableTvOS.tsx +1 -1
  39. package/Components/FocusableList/FocusableItem.tsx +4 -3
  40. package/Components/FocusableList/FocusableListItemWrapper.tsx +2 -1
  41. package/Components/FocusableList/hooks/useCellState.android.ts +13 -3
  42. package/Components/FocusableList/index.tsx +20 -9
  43. package/Components/FreezeWithCallback/__tests__/index.test.tsx +67 -43
  44. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +42 -59
  45. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +13 -10
  46. package/Components/HandlePlayable/HandlePlayable.tsx +25 -9
  47. package/Components/HookRenderer/HookRenderer.tsx +5 -1
  48. package/Components/Layout/TV/LayoutBackground.tsx +1 -1
  49. package/Components/Layout/TV/__tests__/index.test.tsx +0 -1
  50. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +6 -2
  51. package/Components/MasterCell/DefaultComponents/Button.tsx +1 -1
  52. package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -39
  53. package/Components/MasterCell/DefaultComponents/Image/hoc/withDimensions.tsx +1 -1
  54. package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +1 -1
  55. package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +65 -17
  56. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/Image.test.tsx +21 -3
  57. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +6 -3
  58. package/Components/MasterCell/DefaultComponents/Text/index.tsx +26 -6
  59. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +10 -10
  60. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +18 -18
  61. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/index.test.tsx +10 -10
  62. package/Components/MasterCell/elementMapper.tsx +1 -2
  63. package/Components/MasterCell/index.tsx +1 -1
  64. package/Components/MasterCell/utils/behaviorProvider.ts +82 -14
  65. package/Components/MasterCell/utils/index.ts +11 -5
  66. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +13 -18
  67. package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +9 -0
  68. package/Components/OfflineHandler/__tests__/index.test.tsx +26 -35
  69. package/Components/PlayerContainer/ErrorDisplay/index.ts +1 -1
  70. package/Components/PlayerContainer/PlayerContainer.tsx +46 -33
  71. package/Components/PlayerContainer/ProgramInfo/index.tsx +1 -1
  72. package/Components/PlayerContainer/index.ts +1 -1
  73. package/Components/PlayerImageBackground/index.tsx +1 -1
  74. package/Components/River/ComponentsMap/ComponentsMap.tsx +1 -6
  75. package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +378 -0
  76. package/Components/River/ComponentsMap/hooks/useLoadingState.ts +2 -2
  77. package/Components/River/RefreshControl.tsx +11 -17
  78. package/Components/River/RiverItem.tsx +11 -8
  79. package/Components/River/TV/River.tsx +2 -17
  80. package/Components/River/TV/index.tsx +3 -1
  81. package/Components/River/TV/withPipesV1DataLoader.tsx +43 -0
  82. package/Components/River/TV/withRiverDataLoader.tsx +17 -0
  83. package/Components/River/TV/withTVEventHandler.tsx +1 -1
  84. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +2 -6
  85. package/Components/River/__tests__/river.test.js +12 -26
  86. package/Components/River/index.tsx +1 -1
  87. package/Components/Screen/__tests__/Screen.test.tsx +28 -29
  88. package/Components/Screen/__tests__/navigationHandler.test.ts +133 -22
  89. package/Components/Screen/navigationHandler.ts +20 -2
  90. package/Components/ScreenResolver/index.tsx +15 -0
  91. package/Components/ScreenRevealManager/ScreenRevealManager.ts +76 -0
  92. package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +107 -0
  93. package/Components/ScreenRevealManager/__tests__/withScreenRevealManager.test.tsx +96 -0
  94. package/Components/ScreenRevealManager/index.ts +1 -0
  95. package/Components/ScreenRevealManager/withScreenRevealManager.tsx +79 -0
  96. package/Components/Tabs/TV/Tabs.android.tsx +1 -3
  97. package/Components/Tabs/Tabs.tsx +2 -3
  98. package/Components/TextInputTv/__tests__/__snapshots__/TextInputTv.test.js.snap +13 -0
  99. package/Components/TextInputTv/index.tsx +11 -0
  100. package/Components/Touchable/__tests__/__snapshots__/touchable.test.tsx.snap +34 -0
  101. package/Components/Touchable/__tests__/touchable.test.tsx +12 -17
  102. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +15 -9
  103. package/Components/VideoLive/animationUtils.ts +3 -3
  104. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +3 -9
  105. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.web.tsx +294 -0
  106. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.web.tsx +93 -0
  107. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +73 -29
  108. package/Components/VideoModal/PlayerDetails.tsx +24 -2
  109. package/Components/VideoModal/PlayerWrapper.tsx +26 -142
  110. package/Components/VideoModal/VideoModal.tsx +3 -17
  111. package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +5 -5
  112. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -7
  113. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +44 -180
  114. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +21 -51
  115. package/Components/VideoModal/hooks/index.ts +0 -2
  116. package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +15 -1
  117. package/Components/VideoModal/hooks/useModalSize.ts +18 -2
  118. package/Components/VideoModal/hooks/utils/__tests__/showDetails.test.ts +2 -2
  119. package/Components/VideoModal/hooks/utils/index.ts +4 -0
  120. package/Components/VideoModal/utils.ts +6 -0
  121. package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +12 -16
  122. package/Components/Viewport/ViewportTracker/__tests__/viewportTracker.test.js +84 -24
  123. package/Components/Viewport/VisibilitySensor/VisibilitySensor.tsx +3 -3
  124. package/Components/default-cell-renderer/viewTrees/tv/DefaultCell/index.ts +3 -3
  125. package/Contexts/CellFocusedStateContext/index.tsx +27 -0
  126. package/Contexts/ConfigutaionContext/__tests__/ConfigurationProvider.test.tsx +3 -3
  127. package/Contexts/ScreenContext/index.tsx +46 -6
  128. package/Decorators/ConfigurationWrapper/__tests__/withConfigurationProvider.test.tsx +3 -3
  129. package/Decorators/ConfigurationWrapper/withConfigurationProvider.tsx +2 -2
  130. package/Decorators/RiverFeedLoader/__tests__/__snapshots__/riverFeedLoader.test.tsx.snap +221 -209
  131. package/Decorators/RiverFeedLoader/__tests__/riverFeedLoader.test.tsx +14 -16
  132. package/Decorators/RiverFeedLoader/__tests__/utils.test.ts +0 -20
  133. package/Decorators/RiverFeedLoader/index.tsx +22 -4
  134. package/Decorators/RiverFeedLoader/utils/index.ts +0 -18
  135. package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +3 -6
  136. package/Decorators/ZappPipesDataConnector/ResolverSelector.tsx +25 -0
  137. package/Decorators/ZappPipesDataConnector/__tests__/NullFeedResolver.test.tsx +78 -0
  138. package/Decorators/ZappPipesDataConnector/__tests__/ResolverSelector.test.tsx +205 -0
  139. package/Decorators/ZappPipesDataConnector/__tests__/StaticFeedResolver.test.tsx +251 -0
  140. package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +368 -0
  141. package/Decorators/ZappPipesDataConnector/__tests__/utils.test.ts +39 -0
  142. package/Decorators/ZappPipesDataConnector/index.tsx +26 -293
  143. package/Decorators/ZappPipesDataConnector/resolvers/NullFeedResolver.tsx +25 -0
  144. package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +87 -0
  145. package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +266 -0
  146. package/Decorators/ZappPipesDataConnector/types.ts +29 -0
  147. package/Decorators/ZappPipesDataConnector/utils/mongoFilter.ts +738 -0
  148. package/Decorators/ZappPipesDataConnector/utils/useFilter.tsx +157 -0
  149. package/events/index.ts +3 -0
  150. package/package.json +5 -10
  151. package/Components/AudioPlayer/AudioPlayerLayout.tsx +0 -202
  152. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +0 -66
  153. package/Components/AudioPlayer/__tests__/__snapshots__/channel.test.js.snap +0 -28
  154. package/Components/AudioPlayer/__tests__/audioPlayerLayout.test.js +0 -26
  155. package/Components/AudioPlayer/index.ts +0 -1
  156. package/Components/River/__tests__/__snapshots__/river.test.js.snap +0 -27
  157. package/Components/VideoModal/hooks/useBackgroundColor.ts +0 -10
  158. /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/Runtime.test.js +0 -0
  159. /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/artWork.test.js.snap +0 -0
  160. /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/artWork.test.js +0 -0
  161. /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/channel.test.js +0 -0
  162. /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/summary.test.js +0 -0
  163. /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/title.test.js +0 -0
@@ -1,25 +1,12 @@
1
1
  /// <reference types="@applicaster/applicaster-types" />
2
2
  /// <reference types="@applicaster/zapp-react-native-ui-components" />
3
- import React, { useEffect, useMemo } from "react";
4
-
5
- import * as R from "ramda";
6
- import { Platform } from "react-native";
7
- import Url from "url";
8
- import { favoritesListener } from "@applicaster/zapp-react-native-bridge/Favorites";
9
- import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
3
+ import React from "react";
10
4
  import { useRoute } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
11
- import {
12
- getInflatedDataSourceUrl,
13
- getSearchContext,
14
- useFeedLoader,
15
- useFeedRefresh,
16
- } from "@applicaster/zapp-react-native-utils/reactHooks";
17
-
5
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
18
6
  import { ZappPipesSearchContext } from "@applicaster/zapp-react-native-ui-components/Contexts";
19
7
  import { useScreenContext } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenContext";
20
-
21
- import { isVerticalListOrGrid } from "./utils";
22
- import { subscribeForUrlContextKeyChanges } from "@applicaster/zapp-pipes-v2-client";
8
+ import { ResolverSelector } from "./ResolverSelector";
9
+ import { ComponentDataSourceContext } from "./types";
23
10
 
24
11
  type Props = {
25
12
  component: ZappUIComponent;
@@ -27,186 +14,16 @@ type Props = {
27
14
  riverId: string;
28
15
  getStaticComponentFeed?: GeneralContentScreenProps["getStaticComponentFeed"];
29
16
  componentIndex?: number;
30
-
31
17
  isScreenWrappedInContainer?: boolean;
32
18
  isLast?: boolean;
33
19
  };
34
20
 
35
- const FAVORITES_TYPE = "FAVOURITES";
36
-
37
- function getDataSourceUrl({
38
- component,
39
- feedUrl,
40
- screenData,
41
- entryContext,
42
- searchContext,
43
- screenContext,
44
- }): { dataSourceUrl: string | null; type: string | null } {
45
- if (feedUrl) {
46
- return { dataSourceUrl: feedUrl, type: null };
47
- }
48
-
49
- if (component.data) {
50
- const {
51
- data: { source, type, mapping },
52
- } = component;
53
-
54
- if (type === FAVORITES_TYPE) {
55
- return { dataSourceUrl: source || FAVORITES_TYPE, type };
56
- }
57
-
58
- if (source) {
59
- if (type === "APPLICASTER_COLLECTION" && !R.includes("://", source)) {
60
- return {
61
- dataSourceUrl: `applicaster://fetchData?type=${type}&collectionId=${source}`,
62
- type,
63
- };
64
- }
65
-
66
- if (type === "APPLICASTER_CATEGORY" && !R.includes("://", source)) {
67
- return {
68
- dataSourceUrl: `applicaster://fetchData?type=${type}&categoryId=${source}&platform=${Platform.OS}`,
69
- type,
70
- };
71
- }
72
-
73
- if (mapping) {
74
- const contexts = {
75
- entry: entryContext,
76
- screen: screenContext || screenData,
77
- search: getSearchContext(searchContext, mapping),
78
- };
79
-
80
- const dataSourceUrl = getInflatedDataSourceUrl({
81
- source,
82
- mapping,
83
- contexts,
84
- });
85
-
86
- if (!dataSourceUrl) {
87
- return { dataSourceUrl: null, type: null };
88
- }
89
-
90
- return { dataSourceUrl, type };
91
- }
92
-
93
- return { dataSourceUrl: source, type };
94
- }
95
- }
96
-
97
- return { dataSourceUrl: null, type: null };
98
- }
99
-
100
- function applyItemLimit(zappPipesData, component) {
101
- if (!zappPipesData || !zappPipesData.data) {
102
- return zappPipesData;
103
- }
104
-
105
- const { data } = zappPipesData;
106
-
107
- const {
108
- rules: { item_limit },
109
- } = component;
110
-
111
- if (item_limit && data.entry && data.entry.length) {
112
- return {
113
- ...zappPipesData,
114
- data: {
115
- ...data,
116
- entry: R.slice(
117
- 0,
118
- Math.min(Number(item_limit), R.length(data.entry)),
119
- data.entry
120
- ),
121
- },
122
- };
123
- }
124
-
125
- return zappPipesData;
126
- }
127
-
128
- function getListenerFromPlugin(
129
- dataSourceUrl: string,
130
- plugins: QuickBrickPlugin[]
131
- ): AddDataSourceListener | void {
132
- const url = Url.parse(dataSourceUrl, false);
133
-
134
- const addListener = R.compose(
135
- R.path(["module", "addDataSourceListener"]),
136
- R.find(R.propEq("identifier", url.host))
137
- )(plugins);
138
-
139
- return addListener;
140
- }
141
-
142
- const getMethodAndParams = (component) => {
143
- const method: "get" | "post" = R.pathOr("get", ["data", "method"], component);
144
-
145
- const bodyParams: Record<string, unknown> = R.pathOr(
146
- {},
147
- ["data", "bodyParams"],
148
- component
149
- );
150
-
151
- return {
152
- method,
153
- bodyParams,
154
- };
155
- };
156
-
157
- const generateStaticUrl = (component: ZappUIComponent) => {
158
- const { id, position } = component || {};
159
-
160
- return `static://component?id=${id}&position=${position}`;
161
- };
162
-
163
- const reducer = (state, action) => {
164
- switch (action.type) {
165
- case "SET_DATA":
166
- return { ...state, data: action.payload, loading: false };
167
- case "SET_ERROR":
168
- return { ...state, error: action.payload, loading: false };
169
- default:
170
- return state;
171
- }
172
- };
173
-
174
- const useGetStaticFeed = (getter, component, index) => {
175
- const url = generateStaticUrl(component);
176
-
177
- // refactor above 3 states to use reducer
178
-
179
- const [{ loading, data, error }, dispatch] = React.useReducer(reducer, {
180
- loading: true,
181
- data: null,
182
- error: null,
183
- });
184
-
185
- React.useEffect(() => {
186
- const getData = async () => {
187
- try {
188
- const res = await getter({ index, component });
189
- dispatch({ type: "SET_DATA", payload: res });
190
- } catch (err) {
191
- dispatch({ type: "SET_ERROR", payload: err });
192
- }
193
- };
194
-
195
- if (getter) {
196
- getData();
197
- }
198
- }, [getter, component, index]);
199
-
200
- return { url, loading, data, error };
201
- };
202
-
203
21
  export function zappPipesDataConnector(
204
22
  Component: React.FC<any> | React.ComponentClass<any>
205
23
  ) {
206
24
  return function WrappedWithZappPipesData(props: Props) {
207
25
  const { screenData } = useRoute();
208
26
  const { plugins } = usePickFromState(["plugins"]);
209
-
210
27
  const screenContextData = useScreenContext();
211
28
 
212
29
  const {
@@ -219,12 +36,8 @@ export function zappPipesDataConnector(
219
36
  isLast = false,
220
37
  } = props;
221
38
 
222
- /**
223
- * TODO: HACK for the tabs screen which needs to use 2 types of context.
224
- * ui_components rendered above tabs selector need to use entryContext
225
- * Screens rendered inside tabs selector need to use nested context.
226
- * This hack works because ui_components are rendered using ComponentsMap which doesn't have riverId prop
227
- **/
39
+ // Handle context determination
40
+ // HACK for the tabs screen which needs to use 2 types of context.
228
41
  const shouldUseNestedContext = isScreenWrappedInContainer && riverId;
229
42
 
230
43
  const entryContext =
@@ -240,108 +53,28 @@ export function zappPipesDataConnector(
240
53
 
241
54
  const [searchContext] = ZappPipesSearchContext.useZappPipesContext();
242
55
 
243
- const { dataSourceUrl, type } = useMemo(
244
- () =>
245
- getDataSourceUrl({
246
- component,
247
- feedUrl,
248
- screenData,
249
- entryContext,
250
- searchContext,
251
- screenContext,
252
- }),
253
- [
254
- component.id,
255
- feedUrl,
256
- entryContext,
257
- searchContext,
258
- screenContext,
259
- screenData.id,
260
- ]
261
- );
262
-
263
- const shouldClearCache = useMemo(
264
- () => Boolean(component?.rules?.clear_cache_on_reload),
265
- [component?.id]
266
- );
267
-
268
- const pipesOptions = useMemo(
269
- () => ({
270
- clearCache: type === FAVORITES_TYPE,
271
- loadLocalFavorites: type === FAVORITES_TYPE,
272
- silentRefresh: !shouldClearCache,
273
- ...getMethodAndParams(component),
274
- }),
275
- [type, shouldClearCache, component]
276
- );
277
-
278
- const { reloadData, loadNext, error, loading, url, data } = useFeedLoader({
279
- feedUrl: dataSourceUrl ?? "",
280
- pipesOptions,
281
- });
282
-
283
- const staticFeed = useGetStaticFeed(
284
- getStaticComponentFeed,
56
+ // Prepare context for resolvers
57
+ const resolverProps: ComponentDataSourceContext = {
285
58
  component,
286
- componentIndex
287
- );
288
-
289
- useEffect(() => {
290
- if (dataSourceUrl?.includes("pipesv2://") && reloadData) {
291
- const addListener = getListenerFromPlugin(dataSourceUrl, plugins);
292
-
293
- if (addListener) {
294
- return addListener(reloadData);
295
- }
296
- } else {
297
- return subscribeForUrlContextKeyChanges(dataSourceUrl, {}, reloadData);
298
- }
299
- }, [dataSourceUrl, reloadData]);
300
-
301
- useEffect(() => {
302
- if (type === FAVORITES_TYPE && reloadData) {
303
- favoritesListener.on("FAVORITES_CHANGED", reloadData);
304
-
305
- return () => {
306
- favoritesListener.removeHandler("FAVORITES_CHANGED", reloadData);
307
- };
308
- }
309
- }, [type]);
310
-
311
- const getZappPipesData = React.useCallback(
312
- () =>
313
- getStaticComponentFeed && !url
314
- ? staticFeed
315
- : { error, loading, url, data },
316
- [staticFeed?.loading, staticFeed?.data, data?.next, loading, data]
317
- );
318
-
319
- const zappPipesDataProps = useMemo(() => {
320
- const loadNextData =
321
- !isLast && isVerticalListOrGrid(component) ? undefined : loadNext;
322
-
323
- return {
324
- zappPipesData: applyItemLimit(getZappPipesData(), component),
325
- reloadData,
326
- loadNextData,
327
- };
328
- }, [
329
- dataSourceUrl,
330
- data?.next,
331
- loading,
332
- reloadData,
333
- loadNext,
334
- getZappPipesData,
335
- data,
59
+ feedUrl,
60
+ getStaticComponentFeed,
61
+ componentIndex,
62
+ isScreenWrappedInContainer,
63
+ riverId,
336
64
  isLast,
337
- component,
338
- ]);
339
-
340
- useFeedRefresh({
341
- reloadData,
342
- component,
343
- });
65
+ entryContext,
66
+ screenContext,
67
+ searchContext,
68
+ screenData,
69
+ plugins,
70
+ };
344
71
 
345
- return <Component {...props} {...zappPipesDataProps} />;
72
+ return (
73
+ <ResolverSelector {...resolverProps}>
74
+ {(zappPipesDataProps) => (
75
+ <Component {...props} {...zappPipesDataProps} />
76
+ )}
77
+ </ResolverSelector>
78
+ );
346
79
  };
347
80
  }
@@ -0,0 +1,25 @@
1
+ // NullFeedResolver.tsx
2
+ import React, { useMemo } from "react";
3
+ import { ZappPipesDataProps } from "../types";
4
+
5
+ type NullFeedResolverProps = {
6
+ children: (dataProps: ZappPipesDataProps) => React.ReactNode;
7
+ };
8
+
9
+ export function NullFeedResolver({ children }: NullFeedResolverProps) {
10
+ const zappPipesDataProps = useMemo(
11
+ () => ({
12
+ zappPipesData: {
13
+ url: "",
14
+ loading: false,
15
+ data: null,
16
+ error: null,
17
+ },
18
+ reloadData: () => null,
19
+ loadNextData: undefined,
20
+ }),
21
+ []
22
+ );
23
+
24
+ return <>{children(zappPipesDataProps)}</>;
25
+ }
@@ -0,0 +1,87 @@
1
+ import React, { useEffect, useMemo, useReducer } from "react";
2
+ import { ComponentDataSourceContext, ZappPipesDataProps } from "../types";
3
+
4
+ const generateStaticUrl = (component: ZappUIComponent) => {
5
+ const { id, position } = component || {};
6
+
7
+ return `static://component?id=${id}&position=${position}`;
8
+ };
9
+
10
+ const reducer = (state, action) => {
11
+ switch (action.type) {
12
+ case "SET_DATA":
13
+ return { ...state, data: action.payload, loading: false };
14
+ case "SET_ERROR":
15
+ return { ...state, error: action.payload, loading: false };
16
+ default:
17
+ return state;
18
+ }
19
+ };
20
+
21
+ type StaticFeedResolverProps = ComponentDataSourceContext & {
22
+ children: (dataProps: ZappPipesDataProps) => React.ReactNode;
23
+ };
24
+
25
+ export function StaticFeedResolver({
26
+ children,
27
+ getStaticComponentFeed,
28
+ component,
29
+ componentIndex,
30
+ }: StaticFeedResolverProps) {
31
+ const url = generateStaticUrl(component);
32
+
33
+ const [{ loading, data, error }, dispatch] = useReducer(reducer, {
34
+ loading: true,
35
+ data: null,
36
+ error: null,
37
+ });
38
+
39
+ useEffect(() => {
40
+ const getData = async () => {
41
+ try {
42
+ const res = await getStaticComponentFeed({
43
+ index: componentIndex,
44
+ component,
45
+ });
46
+
47
+ dispatch({ type: "SET_DATA", payload: res });
48
+ } catch (err) {
49
+ dispatch({ type: "SET_ERROR", payload: err });
50
+ }
51
+ };
52
+
53
+ if (getStaticComponentFeed) {
54
+ getData();
55
+ }
56
+ }, [getStaticComponentFeed, component, componentIndex]);
57
+
58
+ const reloadData = async () => {
59
+ if (!getStaticComponentFeed) return Promise.resolve();
60
+
61
+ try {
62
+ const res = await getStaticComponentFeed({
63
+ index: componentIndex,
64
+ component,
65
+ });
66
+
67
+ dispatch({ type: "SET_DATA", payload: res });
68
+
69
+ return res;
70
+ } catch (err) {
71
+ dispatch({ type: "SET_ERROR", payload: err });
72
+
73
+ return Promise.reject(err);
74
+ }
75
+ };
76
+
77
+ const zappPipesDataProps = useMemo(
78
+ () => ({
79
+ zappPipesData: { url, loading, data, error },
80
+ reloadData,
81
+ loadNextData: undefined, // Static resolver doesn't support pagination
82
+ }),
83
+ [url, loading, data, error]
84
+ );
85
+
86
+ return <>{children(zappPipesDataProps)}</>;
87
+ }