@applicaster/zapp-react-native-utils 15.0.0-rc.11 → 15.0.0-rc.110

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 (157) hide show
  1. package/README.md +0 -6
  2. package/actionsExecutor/ActionExecutorContext.tsx +3 -6
  3. package/actionsExecutor/feedDecorator.ts +6 -6
  4. package/adsUtils/__tests__/createVMAP.test.ts +419 -0
  5. package/adsUtils/index.ts +2 -2
  6. package/analyticsUtils/README.md +1 -1
  7. package/analyticsUtils/analyticsMapper.ts +10 -2
  8. package/appDataUtils/__tests__/urlScheme.test.ts +678 -0
  9. package/appUtils/HooksManager/__tests__/__snapshots__/hooksManager.test.js.snap +0 -188
  10. package/appUtils/HooksManager/__tests__/hooksManager.test.js +16 -2
  11. package/appUtils/HooksManager/index.ts +10 -10
  12. package/appUtils/RiverFocusManager/{index.js → index.ts} +25 -18
  13. package/appUtils/accessibilityManager/__tests__/utils.test.ts +360 -0
  14. package/appUtils/accessibilityManager/const.ts +4 -0
  15. package/appUtils/accessibilityManager/hooks.ts +20 -13
  16. package/appUtils/accessibilityManager/index.ts +28 -1
  17. package/appUtils/accessibilityManager/utils.ts +59 -8
  18. package/appUtils/contextKeysManager/__tests__/getKeys/failure.test.ts +7 -2
  19. package/appUtils/contextKeysManager/__tests__/getKeys/success.test.ts +48 -0
  20. package/appUtils/contextKeysManager/contextResolver.ts +51 -22
  21. package/appUtils/contextKeysManager/index.ts +65 -10
  22. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +4 -0
  23. package/appUtils/focusManager/index.ios.ts +59 -3
  24. package/appUtils/focusManager/treeDataStructure/Tree/__tests__/Tree.test.js +46 -0
  25. package/appUtils/focusManager/treeDataStructure/Tree/index.js +18 -18
  26. package/appUtils/focusManagerAux/utils/index.ios.ts +122 -0
  27. package/appUtils/focusManagerAux/utils/index.ts +21 -5
  28. package/appUtils/focusManagerAux/utils/utils.ios.ts +234 -0
  29. package/appUtils/keyCodes/keys/keys.web.ts +1 -4
  30. package/appUtils/orientationHelper.ts +2 -4
  31. package/appUtils/platform/platformUtils.ts +117 -18
  32. package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +94 -4
  33. package/appUtils/playerManager/OverlayObserver/utils.ts +32 -20
  34. package/appUtils/playerManager/player.ts +4 -0
  35. package/appUtils/playerManager/playerNative.ts +31 -17
  36. package/appUtils/playerManager/usePlayerState.tsx +14 -2
  37. package/arrayUtils/__tests__/allTruthy.test.ts +24 -0
  38. package/arrayUtils/__tests__/anyThruthy.test.ts +24 -0
  39. package/arrayUtils/index.ts +5 -0
  40. package/cellUtils/index.ts +32 -0
  41. package/cloudEventsUtils/__tests__/index.test.ts +529 -0
  42. package/cloudEventsUtils/index.ts +65 -1
  43. package/configurationUtils/__tests__/imageSrcFromMediaItem.test.ts +38 -0
  44. package/configurationUtils/__tests__/manifestKeyParser.test.ts +26 -26
  45. package/configurationUtils/index.ts +17 -11
  46. package/dateUtils/__tests__/dayjs.test.ts +330 -0
  47. package/enumUtils/__tests__/getEnumKeyByEnumValue.test.ts +207 -0
  48. package/errorUtils/__tests__/GeneralError.test.ts +97 -0
  49. package/errorUtils/__tests__/HttpStatusCode.test.ts +344 -0
  50. package/errorUtils/__tests__/MissingPluginError.test.ts +113 -0
  51. package/errorUtils/__tests__/NetworkError.test.ts +202 -0
  52. package/errorUtils/__tests__/getParsedResponse.test.ts +188 -0
  53. package/errorUtils/__tests__/invariant.test.ts +112 -0
  54. package/focusManager/aux/index.ts +1 -1
  55. package/headersUtils/__tests__/headersUtils.test.js +11 -1
  56. package/headersUtils/index.ts +2 -1
  57. package/manifestUtils/defaultManifestConfigurations/player.js +109 -11
  58. package/manifestUtils/keys.js +21 -0
  59. package/manifestUtils/platformIsTV.js +13 -0
  60. package/manifestUtils/sharedConfiguration/screenPicker/utils.js +1 -0
  61. package/manifestUtils/tvAction/container/index.js +1 -1
  62. package/navigationUtils/index.ts +15 -5
  63. package/numberUtils/__tests__/toNumber.test.ts +12 -0
  64. package/numberUtils/__tests__/toPositiveNumber.test.ts +165 -0
  65. package/numberUtils/index.ts +19 -1
  66. package/package.json +4 -4
  67. package/playerUtils/usePlayerTTS.ts +8 -3
  68. package/pluginUtils/index.ts +4 -0
  69. package/reactHooks/advertising/index.ts +2 -2
  70. package/reactHooks/analytics/__tests__/useSendAnalyticsOnPress.test.ts +537 -0
  71. package/reactHooks/app/__tests__/useAppState.test.ts +1 -1
  72. package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +1 -1
  73. package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +1 -2
  74. package/reactHooks/cell-click/__tests__/index.test.js +1 -3
  75. package/reactHooks/configuration/__tests__/index.test.tsx +1 -1
  76. package/reactHooks/connection/__tests__/index.test.js +1 -1
  77. package/reactHooks/debugging/__tests__/index.test.js +4 -4
  78. package/reactHooks/dev/__tests__/useReRenderLog.test.ts +188 -0
  79. package/reactHooks/device/useIsTablet.tsx +14 -19
  80. package/reactHooks/device/useMemoizedIsTablet.ts +3 -3
  81. package/reactHooks/events/index.ts +20 -0
  82. package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +32 -23
  83. package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +19 -19
  84. package/reactHooks/feed/__tests__/useEntryScreenId.test.tsx +4 -1
  85. package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +42 -30
  86. package/reactHooks/feed/__tests__/{useInflatedUrl.test.ts → useInflatedUrl.test.tsx} +62 -7
  87. package/reactHooks/feed/index.ts +0 -2
  88. package/reactHooks/feed/useBatchLoading.ts +7 -1
  89. package/reactHooks/feed/useEntryScreenId.ts +2 -2
  90. package/reactHooks/feed/useInflatedUrl.ts +43 -17
  91. package/reactHooks/feed/usePipesCacheReset.ts +3 -1
  92. package/reactHooks/flatList/useLoadNextPageIfNeeded.ts +13 -16
  93. package/reactHooks/hookModal/hooks/useHookModalScreenData.ts +12 -8
  94. package/reactHooks/index.ts +2 -0
  95. package/reactHooks/layout/__tests__/index.test.tsx +1 -1
  96. package/reactHooks/layout/__tests__/useLayoutVersion.test.tsx +1 -1
  97. package/reactHooks/layout/index.ts +1 -1
  98. package/reactHooks/layout/useDimensions/__tests__/{useDimensions.test.ts → useDimensions.test.tsx} +105 -25
  99. package/reactHooks/layout/useDimensions/useDimensions.ts +2 -2
  100. package/reactHooks/navigation/__tests__/index.test.tsx +40 -9
  101. package/reactHooks/navigation/index.ts +27 -11
  102. package/reactHooks/navigation/useRoute.ts +11 -7
  103. package/reactHooks/player/TVSeekControlller/TVSeekController.ts +27 -10
  104. package/reactHooks/player/__tests__/useAutoSeek._test.tsx +1 -1
  105. package/reactHooks/player/__tests__/useTapSeek._test.ts +1 -1
  106. package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +1 -1
  107. package/reactHooks/resolvers/__tests__/useComponentResolver.test.tsx +1 -1
  108. package/reactHooks/resolvers/useCellResolver.ts +6 -2
  109. package/reactHooks/resolvers/useComponentResolver.ts +8 -2
  110. package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +2 -2
  111. package/reactHooks/screen/__tests__/useScreenBackgroundColor.test.tsx +1 -1
  112. package/reactHooks/screen/__tests__/useScreenData.test.tsx +1 -1
  113. package/reactHooks/screen/__tests__/useTargetScreenData.test.tsx +12 -4
  114. package/reactHooks/screen/useTargetScreenData.ts +4 -2
  115. package/reactHooks/state/__tests__/useComponentScreenState.test.ts +246 -0
  116. package/reactHooks/state/index.ts +2 -0
  117. package/reactHooks/state/useComponentScreenState.ts +45 -0
  118. package/reactHooks/state/useRefWithInitialValue.ts +10 -0
  119. package/reactHooks/state/useRivers.ts +1 -1
  120. package/reactHooks/ui/__tests__/useFadeOutWhenBlurred.test.ts +580 -0
  121. package/reactHooks/usePluginConfiguration.ts +2 -2
  122. package/reactHooks/utils/__tests__/index.test.js +1 -1
  123. package/rectUtils/__tests__/index.test.ts +549 -0
  124. package/rectUtils/index.ts +2 -2
  125. package/refreshUtils/RefreshCoordinator/__tests__/refreshCoordinator.test.ts +161 -0
  126. package/refreshUtils/RefreshCoordinator/index.ts +216 -0
  127. package/refreshUtils/RefreshCoordinator/utils/__tests__/getDataRefreshConfig.test.ts +104 -0
  128. package/refreshUtils/RefreshCoordinator/utils/index.ts +29 -0
  129. package/screenPickerUtils/__tests__/index.test.ts +333 -0
  130. package/screenPickerUtils/index.ts +5 -0
  131. package/screenState/__tests__/index.test.ts +1 -1
  132. package/searchUtils/const.ts +7 -0
  133. package/searchUtils/index.ts +3 -0
  134. package/services/storageServiceSync.web.ts +1 -1
  135. package/stringUtils/index.ts +1 -1
  136. package/testUtils/index.tsx +30 -21
  137. package/time/__tests__/BackgroundTimer.test.ts +156 -0
  138. package/time/__tests__/Timer.test.ts +236 -0
  139. package/typeGuards/__tests__/isString.test.ts +21 -0
  140. package/typeGuards/index.ts +4 -0
  141. package/utils/__tests__/clone.test.ts +158 -0
  142. package/utils/__tests__/mapAccum.test.ts +73 -0
  143. package/utils/__tests__/mergeRight.test.ts +48 -0
  144. package/utils/__tests__/path.test.ts +7 -0
  145. package/utils/__tests__/selectors.test.ts +124 -0
  146. package/utils/clone.ts +7 -0
  147. package/utils/index.ts +22 -1
  148. package/utils/mapAccum.ts +23 -0
  149. package/utils/mergeRight.ts +5 -0
  150. package/utils/path.ts +6 -3
  151. package/utils/pathOr.ts +5 -1
  152. package/utils/selectors.ts +46 -0
  153. package/zappFrameworkUtils/HookCallback/callbackNavigationAction.ts +49 -12
  154. package/zappFrameworkUtils/HookCallback/hookCallbackManifestExtensions.config.js +1 -1
  155. package/reactHooks/componentsMap/index.ts +0 -55
  156. package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +0 -75
  157. package/reactHooks/feed/useFeedRefresh.tsx +0 -65
package/utils/index.ts CHANGED
@@ -16,8 +16,13 @@ export { endsWith } from "./endsWith";
16
16
 
17
17
  export { take } from "./take";
18
18
 
19
+ export { mapAccum } from "./mapAccum";
20
+
21
+ export { mergeRight } from "./mergeRight";
22
+
23
+ export { clone } from "./clone";
24
+
19
25
  export {
20
- cloneDeep as clone,
21
26
  flatten,
22
27
  drop,
23
28
  size,
@@ -34,4 +39,20 @@ export {
34
39
  last,
35
40
  toLower,
36
41
  isEqual as equals,
42
+ uniq,
43
+ uniqWith,
44
+ flowRight as compose,
45
+ partial,
46
+ clamp,
47
+ reverse,
48
+ takeRight,
49
+ fromPairs,
50
+ sortBy,
51
+ merge,
52
+ values,
53
+ head,
54
+ findIndex,
55
+ set,
56
+ compact,
57
+ identity,
37
58
  } from "lodash";
@@ -0,0 +1,23 @@
1
+ import { curry } from "lodash";
2
+
3
+ /**
4
+ * A native reimplementation of Ramda's mapAccum.
5
+ *
6
+ * @template A, B, C
7
+ * @param {(acc: A, value: B) => [A, C]} fn - Function returning [newAcc, mappedValue]
8
+ * @param {A} acc - Initial accumulator
9
+ * @param {B[]} list - List to process
10
+ * @returns {[A, C[]]} - Tuple of [final accumulator, mapped array]
11
+ */
12
+ export const mapAccum = curry((fn, acc, list) => {
13
+ const result = [];
14
+ let currentAcc = acc;
15
+
16
+ for (let i = 0; i < list.length; i++) {
17
+ const [nextAcc, mapped] = fn(currentAcc, list[i]);
18
+ currentAcc = nextAcc;
19
+ result.push(mapped);
20
+ }
21
+
22
+ return [currentAcc, result];
23
+ });
@@ -0,0 +1,5 @@
1
+ import { assign } from "lodash";
2
+
3
+ export const mergeRight = (a, b) => {
4
+ return assign({}, a, b);
5
+ };
package/utils/path.ts CHANGED
@@ -1,5 +1,8 @@
1
- import { get } from "lodash";
1
+ import { pathOr } from "./pathOr";
2
2
 
3
- export const path = (route, record) => {
4
- return get(record, route, undefined);
3
+ export const path = <T = any>(
4
+ route: (string | number) | (string | number)[],
5
+ record: any
6
+ ) => {
7
+ return pathOr<T>(undefined, route, record);
5
8
  };
package/utils/pathOr.ts CHANGED
@@ -1,5 +1,9 @@
1
1
  import { get } from "lodash";
2
2
 
3
- export const pathOr = (defaultValue, path, record) => {
3
+ export const pathOr = <T = any>(
4
+ defaultValue: T,
5
+ path: (number | string) | (number | string)[],
6
+ record: any
7
+ ): T => {
4
8
  return get(record, path, defaultValue);
5
9
  };
@@ -0,0 +1,46 @@
1
+ import { get } from "lodash";
2
+
3
+ export type Selector<T> = (state: any) => T;
4
+
5
+ /**
6
+ * Creates a selector for filtering plugins by path
7
+ * @param path - Path to check in plugin. Can be a dot notation string or array
8
+ * @returns A selector function that returns matching plugins
9
+ */
10
+ export const createPluginsByPathSelector = (
11
+ path: string | string[]
12
+ ): Selector<any[]> => {
13
+ return (state: any) => {
14
+ const plugins = state.plugins || [];
15
+
16
+ return plugins.filter((plugin: any) => get(plugin, path));
17
+ };
18
+ };
19
+
20
+ /**
21
+ * Creates a selector for filtering plugins by module path
22
+ * @param modulePath - Module path to check in plugin (e.g., "urlScheme", "player")
23
+ * @returns A selector function that returns plugins with specified module
24
+ */
25
+ export const createPluginsByModuleSelector = (
26
+ modulePath: string
27
+ ): Selector<any[]> => {
28
+ return createPluginsByPathSelector(["module", modulePath]);
29
+ };
30
+
31
+ /**
32
+ * Creates a selector that combines multiple plugin selectors
33
+ * @param selectors - Array of plugin selectors to combine
34
+ * @returns A selector function that returns plugins matching all conditions
35
+ */
36
+ export const combinePluginSelectors = (
37
+ ...selectors: Selector<any[]>[]
38
+ ): Selector<any[]> => {
39
+ return (state: any) => {
40
+ return selectors.reduce((filtered, selector) => {
41
+ const selected = selector(state);
42
+
43
+ return filtered.filter((plugin) => selected.includes(plugin));
44
+ }, state.plugins || []);
45
+ };
46
+ };
@@ -1,6 +1,6 @@
1
1
  import { useNavigation, useRivers, useScreenContext } from "../../reactHooks";
2
2
  import { createLogger } from "../../logger";
3
- import { useCallback, useMemo } from "react";
3
+ import { useCallback, useMemo, useRef, useEffect } from "react";
4
4
 
5
5
  export enum NavigationCallbackOptions {
6
6
  DEFAULT = "default",
@@ -17,6 +17,7 @@ export enum ResultType {
17
17
  export type CallbackResult = hookCallbackArgs & {
18
18
  options?: {
19
19
  resultType?: ResultType;
20
+ navigator?: QuickBrickAppNavigator;
20
21
  };
21
22
  };
22
23
 
@@ -45,7 +46,7 @@ const legacyMappingKeys = {
45
46
  actionType: "login_completion_action",
46
47
  targetScreen: "navigate_to_login_screen",
47
48
  },
48
- "quick-brick-user-account-ui-component": {
49
+ "quick-brick-user-account-ui-component.login": {
49
50
  actionType: "callbackAction",
50
51
  },
51
52
  "quick-brick-login-multi-login-providers.login": {
@@ -56,9 +57,23 @@ const legacyMappingKeys = {
56
57
  actionType: "logout_completion_action",
57
58
  targetScreen: "navigate_to_logout_screen",
58
59
  },
60
+ "quick-brick-storefront": {
61
+ actionType: "purchase_completion_action",
62
+ targetScreen: "navigate_to_screen_after_purchase",
63
+ },
64
+ "zapp_login_plugin_oauth_tv_2_0.login": {
65
+ actionType: "login_completion_action",
66
+ targetScreen: "navigate_to_login_screen",
67
+ },
68
+ "zapp_login_plugin_oauth_tv_2_0.logout": {
69
+ actionType: "logout_completion_action",
70
+ targetScreen: "navigate_to_logout_screen",
71
+ },
59
72
  };
60
73
 
61
- const NAV_ACTIONS = Object.values(NavigationCallbackOptions) as string[];
74
+ const NAV_ACTIONS = (
75
+ Object.values(NavigationCallbackOptions) as string[]
76
+ ).filter((value) => value !== NavigationCallbackOptions.DEFAULT);
62
77
 
63
78
  const isNavAction = (v: unknown): v is NavigationCallbackOptions =>
64
79
  typeof v === "string" && NAV_ACTIONS.includes(v);
@@ -69,7 +84,8 @@ export const getNavigationKeys = (
69
84
  ): NavKeys => {
70
85
  const general = (item?.general ?? {}) as General;
71
86
 
72
- const pluginIdentifier = (item as any).identifier ?? item?.type ?? "";
87
+ const pluginIdentifier =
88
+ (item as any).identifier ?? item?.type ?? item?.component_type ?? "";
73
89
 
74
90
  const legacy =
75
91
  legacyMappingKeys[`${pluginIdentifier}.${resultType}`] ??
@@ -121,6 +137,12 @@ export const useCallbackNavigationAction = (
121
137
  const rivers = useRivers();
122
138
  const screenContext = useScreenContext();
123
139
 
140
+ const navigationRef = useRef(navigation);
141
+
142
+ useEffect(() => {
143
+ navigationRef.current = navigation;
144
+ }, [navigation]);
145
+
124
146
  const overrideCallbackFromComponent = useMemo(() => {
125
147
  log_verbose(`${LogPrefix}: overridden callbackAction by component`);
126
148
 
@@ -154,20 +176,35 @@ export const useCallbackNavigationAction = (
154
176
  return;
155
177
  }
156
178
 
157
- const data = getNavigationKeys(item, args.options?.resultType ?? null);
179
+ let data = getNavigationKeys(item, args.options?.resultType ?? null);
158
180
 
159
181
  if (!data) {
160
- hookCallback?.(args);
182
+ const isScreen = !hookCallback;
161
183
 
162
- return;
184
+ if (isScreen && args.options?.resultType === ResultType.login) {
185
+ log_debug(
186
+ `${LogPrefix} no navigation data found, applying GO BACK for login screen`
187
+ );
188
+
189
+ data = {
190
+ action: NavigationCallbackOptions.GO_BACK,
191
+ targetScreenId: null,
192
+ };
193
+ } else {
194
+ hookCallback?.(args);
195
+
196
+ return;
197
+ }
163
198
  }
164
199
 
165
200
  hookCallback?.({ ...args, success: false, cancelled: true });
201
+ const currentNavigation = navigationRef.current;
166
202
 
167
203
  switch (data.action) {
168
204
  case NavigationCallbackOptions.GO_BACK: {
169
- if (navigation.canGoBack()) {
170
- navigation.goBack();
205
+ if (currentNavigation.canGoBack()) {
206
+ currentNavigation.goBack();
207
+
171
208
  log_info(`${LogPrefix} performing 'GO BACK' action`);
172
209
  } else {
173
210
  log_info(`${LogPrefix} cannot perform 'GO BACK' action — ignoring`);
@@ -177,7 +214,7 @@ export const useCallbackNavigationAction = (
177
214
  }
178
215
 
179
216
  case NavigationCallbackOptions.GO_HOME: {
180
- navigation.goHome();
217
+ currentNavigation.goHome();
181
218
  log_info(`${LogPrefix} performing 'GO HOME' action`);
182
219
  break;
183
220
  }
@@ -193,7 +230,7 @@ export const useCallbackNavigationAction = (
193
230
  const screen = rivers[screenId];
194
231
 
195
232
  if (screen) {
196
- navigation.replace(screen);
233
+ currentNavigation.replace(screen);
197
234
 
198
235
  log_info(
199
236
  `${LogPrefix} performing 'GO TO SCREEN' action to screen: ${screenId}`
@@ -210,7 +247,7 @@ export const useCallbackNavigationAction = (
210
247
  }
211
248
  }
212
249
  },
213
- [item, navigation, rivers]
250
+ [item, rivers]
214
251
  );
215
252
 
216
253
  return overrideCallbackFromComponent || callbackAction;
@@ -20,7 +20,7 @@ const callbackKeyPrefix = (key, prefix, keySeparator = "_") =>
20
20
 
21
21
  const extendManifestWithHookCallback = (prefix = null) => ({
22
22
  group: true,
23
- label: "CallBack Navigation",
23
+ label: `CallBack Navigation: ${prefix}`,
24
24
  folded: true,
25
25
  fields: [
26
26
  {
@@ -1,55 +0,0 @@
1
- import * as React from "react";
2
-
3
- const layoutReducer = (state, { payload }) => {
4
- return state.map((item, index, _state) => ({
5
- height: index === payload.index ? payload.height : item.height,
6
- y:
7
- index > 0
8
- ? _state.slice(0, index).reduce((acc, value) => acc + value.height, 0)
9
- : 0,
10
- }));
11
- };
12
-
13
- export const useComponentsLayout = (count, onFinishLoadingVisible) => {
14
- const [itemsLayout, dispatchItemLayout] = React.useReducer(
15
- layoutReducer,
16
- Array.from({ length: count }, () => ({ height: 0, y: 0 }))
17
- );
18
-
19
- const notified = React.useRef(false);
20
- const [listHeight, setListHeight] = React.useState<number>(0);
21
-
22
- const onItemLayout = React.useCallback(
23
- (index) => (event) => {
24
- const { height } = event.nativeEvent.layout;
25
- dispatchItemLayout({ payload: { index, height } });
26
- },
27
- []
28
- );
29
-
30
- const onListLayout = React.useCallback((event) => {
31
- const { height } = event.nativeEvent.layout;
32
- setListHeight(height);
33
- }, []);
34
-
35
- React.useEffect(() => {
36
- if (!notified.current) {
37
- const finishLoadingVisible = !!itemsLayout.find(
38
- (item) => item.y > listHeight
39
- );
40
-
41
- if (finishLoadingVisible) {
42
- notified.current = true;
43
- onFinishLoadingVisible?.();
44
- }
45
- }
46
- }, [itemsLayout, listHeight]);
47
-
48
- return React.useMemo(
49
- () => ({
50
- onItemLayout,
51
- onListLayout,
52
- }),
53
- []
54
- );
55
- };
@@ -1,75 +0,0 @@
1
- import { renderHook } from "@testing-library/react-hooks";
2
-
3
- jest.useFakeTimers();
4
-
5
- jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
6
- useIsScreenActive: () => true,
7
- }));
8
-
9
- const { useFeedRefresh, feedRefreshLogger } = require("..");
10
-
11
- describe("useFeedRefresh", () => {
12
- const reloadData = jest.fn();
13
-
14
- const component = {
15
- id: "foo",
16
- rules: { enable_data_refreshing: true, refreshing_interval: 61 },
17
- };
18
-
19
- it("Calls reloadData after passed time lapses", () => {
20
- renderHook(() => useFeedRefresh({ reloadData, component }));
21
-
22
- expect(reloadData).not.toBeCalled();
23
- jest.runOnlyPendingTimers();
24
- expect(reloadData).toBeCalled();
25
- });
26
-
27
- it("Logs warning message if refresh time set below minimum value", () => {
28
- const loggerSpy = jest.spyOn(feedRefreshLogger, "warning");
29
-
30
- renderHook(() =>
31
- useFeedRefresh({
32
- reloadData,
33
- component: {
34
- ...component,
35
- rules: { enable_data_refreshing: true, refreshing_interval: 2 },
36
- },
37
- })
38
- );
39
-
40
- expect(loggerSpy).toBeCalled();
41
- });
42
-
43
- it("Calls reloadData on a Component that had a timer setup and was re-mounted", () => {
44
- reloadData.mockReset();
45
-
46
- // it is not called before rendering hook"
47
- expect(reloadData).not.toBeCalled();
48
-
49
- // it is not called when rendering new component (Not previously rendered)
50
- renderHook(() =>
51
- useFeedRefresh({ reloadData, component: { ...component, id: "bar" } })
52
- );
53
-
54
- expect(reloadData).not.toBeCalled();
55
-
56
- // it is called when rendering previously rendered component",
57
- renderHook(() => useFeedRefresh({ reloadData, component }));
58
- expect(reloadData).toBeCalled();
59
- });
60
-
61
- it("Doesn't refresh data when enable_data_refreshing if false", () => {
62
- reloadData.mockReset();
63
-
64
- renderHook(() =>
65
- useFeedRefresh({
66
- reloadData,
67
- component: { ...component, rules: { enable_data_refreshing: false } },
68
- })
69
- );
70
-
71
- jest.runOnlyPendingTimers();
72
-
73
- expect(reloadData).not.toBeCalled();
74
- });
75
- });
@@ -1,65 +0,0 @@
1
- import * as React from "react";
2
- import { path, max } from "ramda";
3
- import { isTrue } from "@applicaster/zapp-react-native-utils/booleanUtils";
4
- import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
5
- import { useIsScreenActive } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
6
-
7
- import { reactHooksLogger } from "../logger";
8
- import { ReloadDataFunction } from "./useFeedLoader";
9
-
10
- export const feedRefreshLogger = reactHooksLogger.addSubsystem("feed-refresh");
11
-
12
- type Props = {
13
- reloadData?: ReloadDataFunction;
14
- component: ZappUIComponent;
15
- };
16
-
17
- const previousTimersMap = {};
18
- const minimumRefreshingInterval = 5;
19
- const defaultRefreshInterval = 60;
20
-
21
- export const useFeedRefresh = ({ reloadData, component }: Props): void => {
22
- const isDataRefreshingEnabled = isTrue(
23
- path(["rules", "enable_data_refreshing"], component)
24
- );
25
-
26
- const refreshing_interval = toNumberWithDefault(
27
- defaultRefreshInterval,
28
- component?.rules?.refreshing_interval
29
- );
30
-
31
- const refreshingIntervalInMilliseconds =
32
- max(refreshing_interval, minimumRefreshingInterval) * 1000;
33
-
34
- const isScreenActive = useIsScreenActive();
35
-
36
- React.useEffect(() => {
37
- if (isDataRefreshingEnabled && refreshing_interval && isScreenActive) {
38
- if (refreshing_interval < minimumRefreshingInterval) {
39
- feedRefreshLogger.warning({
40
- message: `You set your feed refresh interval to ${refreshing_interval} when minimum value is ${minimumRefreshingInterval}seconds.Your feed will refresh after ${minimumRefreshingInterval}seconds.`,
41
- });
42
- }
43
-
44
- if (!reloadData || typeof reloadData !== "function") {
45
- feedRefreshLogger.warning({
46
- message:
47
- "reloadData function is undefined, feed refresh feature won't work properly",
48
- });
49
- }
50
-
51
- if (previousTimersMap[component?.id]) {
52
- reloadData?.();
53
- }
54
-
55
- const refreshInterval = setInterval(() => {
56
- reloadData?.();
57
- }, refreshingIntervalInMilliseconds);
58
-
59
- return () => {
60
- previousTimersMap[component?.id] = true;
61
- clearInterval(refreshInterval);
62
- };
63
- }
64
- }, [reloadData, isScreenActive]);
65
- };