@applicaster/zapp-react-native-utils 15.0.0-alpha.8621453569 → 15.0.0-alpha.8680244503

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 (46) hide show
  1. package/actionsExecutor/ActionExecutorContext.tsx +3 -6
  2. package/actionsExecutor/feedDecorator.ts +6 -6
  3. package/adsUtils/index.ts +2 -2
  4. package/analyticsUtils/README.md +1 -1
  5. package/appUtils/HooksManager/index.ts +10 -10
  6. package/appUtils/accessibilityManager/const.ts +4 -0
  7. package/appUtils/accessibilityManager/hooks.ts +8 -24
  8. package/appUtils/keyCodes/keys/keys.web.ts +1 -4
  9. package/appUtils/orientationHelper.ts +2 -4
  10. package/appUtils/platform/platformUtils.ts +51 -35
  11. package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +94 -4
  12. package/appUtils/playerManager/OverlayObserver/utils.ts +32 -20
  13. package/appUtils/playerManager/player.ts +4 -0
  14. package/appUtils/playerManager/playerNative.ts +29 -16
  15. package/appUtils/playerManager/usePlayerState.tsx +14 -2
  16. package/cellUtils/index.ts +1 -8
  17. package/configurationUtils/__tests__/manifestKeyParser.test.ts +26 -26
  18. package/manifestUtils/defaultManifestConfigurations/player.js +75 -1
  19. package/manifestUtils/keys.js +21 -0
  20. package/manifestUtils/sharedConfiguration/screenPicker/utils.js +1 -0
  21. package/manifestUtils/tvAction/container/index.js +1 -1
  22. package/package.json +2 -2
  23. package/playerUtils/usePlayerTTS.ts +8 -3
  24. package/pluginUtils/index.ts +4 -0
  25. package/reactHooks/advertising/index.ts +2 -2
  26. package/reactHooks/debugging/__tests__/index.test.js +4 -4
  27. package/reactHooks/device/useMemoizedIsTablet.ts +3 -3
  28. package/reactHooks/feed/__tests__/useEntryScreenId.test.tsx +3 -0
  29. package/reactHooks/feed/useEntryScreenId.ts +2 -2
  30. package/reactHooks/flatList/useLoadNextPageIfNeeded.ts +13 -16
  31. package/reactHooks/layout/useDimensions/__tests__/{useDimensions.test.ts → useDimensions.test.tsx} +105 -25
  32. package/reactHooks/layout/useDimensions/useDimensions.ts +2 -2
  33. package/reactHooks/navigation/index.ts +7 -6
  34. package/reactHooks/navigation/useRoute.ts +8 -6
  35. package/reactHooks/player/TVSeekControlller/TVSeekController.ts +27 -10
  36. package/reactHooks/resolvers/useCellResolver.ts +6 -2
  37. package/reactHooks/resolvers/useComponentResolver.ts +8 -2
  38. package/reactHooks/screen/__tests__/useTargetScreenData.test.tsx +10 -2
  39. package/reactHooks/screen/useTargetScreenData.ts +4 -2
  40. package/reactHooks/state/useRivers.ts +1 -1
  41. package/reactHooks/usePluginConfiguration.ts +2 -2
  42. package/testUtils/index.tsx +29 -20
  43. package/utils/__tests__/selectors.test.ts +124 -0
  44. package/utils/index.ts +3 -0
  45. package/utils/selectors.ts +46 -0
  46. package/zappFrameworkUtils/HookCallback/callbackNavigationAction.ts +15 -6
@@ -0,0 +1,124 @@
1
+ import {
2
+ createPluginsByPathSelector,
3
+ createPluginsByModuleSelector,
4
+ combinePluginSelectors,
5
+ } from "../selectors";
6
+
7
+ describe("Plugin Selectors", () => {
8
+ const mockPlugins = [
9
+ {
10
+ identifier: "plugin1",
11
+ module: {
12
+ urlScheme: { host: "test" },
13
+ player: { type: "default" },
14
+ },
15
+ customField: true,
16
+ },
17
+ {
18
+ identifier: "plugin2",
19
+ module: {
20
+ urlScheme: { host: "other" },
21
+ },
22
+ },
23
+ {
24
+ identifier: "plugin3",
25
+ module: {
26
+ player: { type: "custom" },
27
+ },
28
+ },
29
+ ];
30
+
31
+ const mockState = {
32
+ plugins: mockPlugins,
33
+ };
34
+
35
+ describe("createPluginsByPathSelector", () => {
36
+ it("filters plugins by string path", () => {
37
+ const selector = createPluginsByPathSelector("customField");
38
+ const result = selector(mockState);
39
+
40
+ expect(result).toHaveLength(1);
41
+ expect(result[0].identifier).toBe("plugin1");
42
+ });
43
+
44
+ it("filters plugins by array path", () => {
45
+ const selector = createPluginsByPathSelector(["module", "urlScheme"]);
46
+ const result = selector(mockState);
47
+
48
+ expect(result).toHaveLength(2);
49
+ expect(result.map((p) => p.identifier)).toEqual(["plugin1", "plugin2"]);
50
+ });
51
+
52
+ it("handles missing plugins array", () => {
53
+ const selector = createPluginsByPathSelector("customField");
54
+ const result = selector({});
55
+
56
+ expect(result).toEqual([]);
57
+ });
58
+
59
+ it("handles non-existent path", () => {
60
+ const selector = createPluginsByPathSelector("nonexistent");
61
+ const result = selector(mockState);
62
+
63
+ expect(result).toEqual([]);
64
+ });
65
+ });
66
+
67
+ describe("createPluginsByModuleSelector", () => {
68
+ it("filters plugins by module path", () => {
69
+ const selector = createPluginsByModuleSelector("player");
70
+ const result = selector(mockState);
71
+
72
+ expect(result).toHaveLength(2);
73
+ expect(result.map((p) => p.identifier)).toEqual(["plugin1", "plugin3"]);
74
+ });
75
+
76
+ it("handles non-existent module", () => {
77
+ const selector = createPluginsByModuleSelector("nonexistent");
78
+ const result = selector(mockState);
79
+
80
+ expect(result).toEqual([]);
81
+ });
82
+ });
83
+
84
+ describe("combinePluginSelectors", () => {
85
+ it("combines multiple selectors with AND logic", () => {
86
+ const urlSchemeSelector = createPluginsByModuleSelector("urlScheme");
87
+ const playerSelector = createPluginsByModuleSelector("player");
88
+
89
+ const combinedSelector = combinePluginSelectors(
90
+ urlSchemeSelector,
91
+ playerSelector
92
+ );
93
+
94
+ const result = combinedSelector(mockState);
95
+
96
+ expect(result).toHaveLength(1);
97
+ expect(result[0].identifier).toBe("plugin1");
98
+ });
99
+
100
+ it("returns empty array when no plugins match all conditions", () => {
101
+ const urlSchemeSelector = createPluginsByModuleSelector("urlScheme");
102
+ const customSelector = createPluginsByPathSelector("nonexistent");
103
+
104
+ const combinedSelector = combinePluginSelectors(
105
+ urlSchemeSelector,
106
+ customSelector
107
+ );
108
+
109
+ const result = combinedSelector(mockState);
110
+
111
+ expect(result).toEqual([]);
112
+ });
113
+
114
+ it("handles empty state", () => {
115
+ const selector = combinePluginSelectors(
116
+ createPluginsByModuleSelector("urlScheme")
117
+ );
118
+
119
+ const result = selector({});
120
+
121
+ expect(result).toEqual([]);
122
+ });
123
+ });
124
+ });
package/utils/index.ts CHANGED
@@ -40,5 +40,8 @@ export {
40
40
  uniqWith,
41
41
  flowRight as compose,
42
42
  partial,
43
+ clamp,
43
44
  reverse,
45
+ set,
46
+ compact,
44
47
  } from "lodash";
@@ -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
 
@@ -135,6 +136,12 @@ export const useCallbackNavigationAction = (
135
136
  const rivers = useRivers();
136
137
  const screenContext = useScreenContext();
137
138
 
139
+ const navigationRef = useRef(navigation);
140
+
141
+ useEffect(() => {
142
+ navigationRef.current = navigation;
143
+ }, [navigation]);
144
+
138
145
  const overrideCallbackFromComponent = useMemo(() => {
139
146
  log_verbose(`${LogPrefix}: overridden callbackAction by component`);
140
147
 
@@ -177,11 +184,13 @@ export const useCallbackNavigationAction = (
177
184
  }
178
185
 
179
186
  hookCallback?.({ ...args, success: false, cancelled: true });
187
+ const currentNavigation = navigationRef.current;
180
188
 
181
189
  switch (data.action) {
182
190
  case NavigationCallbackOptions.GO_BACK: {
183
- if (navigation.canGoBack()) {
184
- navigation.goBack();
191
+ if (currentNavigation.canGoBack()) {
192
+ currentNavigation.goBack();
193
+
185
194
  log_info(`${LogPrefix} performing 'GO BACK' action`);
186
195
  } else {
187
196
  log_info(`${LogPrefix} cannot perform 'GO BACK' action — ignoring`);
@@ -191,7 +200,7 @@ export const useCallbackNavigationAction = (
191
200
  }
192
201
 
193
202
  case NavigationCallbackOptions.GO_HOME: {
194
- navigation.goHome();
203
+ currentNavigation.goHome();
195
204
  log_info(`${LogPrefix} performing 'GO HOME' action`);
196
205
  break;
197
206
  }
@@ -207,7 +216,7 @@ export const useCallbackNavigationAction = (
207
216
  const screen = rivers[screenId];
208
217
 
209
218
  if (screen) {
210
- navigation.replace(screen);
219
+ currentNavigation.replace(screen);
211
220
 
212
221
  log_info(
213
222
  `${LogPrefix} performing 'GO TO SCREEN' action to screen: ${screenId}`
@@ -224,7 +233,7 @@ export const useCallbackNavigationAction = (
224
233
  }
225
234
  }
226
235
  },
227
- [item, navigation, rivers]
236
+ [item, rivers]
228
237
  );
229
238
 
230
239
  return overrideCallbackFromComponent || callbackAction;