@applicaster/zapp-react-native-utils 15.0.0-alpha.2463014505 → 15.0.0-alpha.2535277107

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 (37) hide show
  1. package/analyticsUtils/AnalyticPlayerListener.ts +5 -2
  2. package/appUtils/accessibilityManager/const.ts +4 -0
  3. package/appUtils/accessibilityManager/hooks.ts +20 -13
  4. package/appUtils/accessibilityManager/index.ts +28 -1
  5. package/appUtils/accessibilityManager/utils.ts +36 -5
  6. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +1 -0
  7. package/appUtils/focusManager/index.ios.ts +18 -1
  8. package/appUtils/focusManagerAux/utils/index.ts +18 -0
  9. package/appUtils/focusManagerAux/utils/utils.ios.ts +35 -0
  10. package/appUtils/platform/platformUtils.ts +116 -17
  11. package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +94 -4
  12. package/appUtils/playerManager/OverlayObserver/utils.ts +32 -20
  13. package/appUtils/playerManager/conts.ts +21 -0
  14. package/appUtils/playerManager/player.ts +4 -0
  15. package/appUtils/playerManager/usePlayerState.tsx +14 -2
  16. package/arrayUtils/__tests__/allTruthy.test.ts +24 -0
  17. package/arrayUtils/__tests__/anyThruthy.test.ts +24 -0
  18. package/arrayUtils/index.ts +5 -0
  19. package/cellUtils/index.ts +32 -0
  20. package/manifestUtils/defaultManifestConfigurations/player.js +52 -1
  21. package/manifestUtils/keys.js +21 -0
  22. package/manifestUtils/sharedConfiguration/screenPicker/utils.js +1 -0
  23. package/navigationUtils/index.ts +19 -16
  24. package/package.json +2 -2
  25. package/playerUtils/usePlayerTTS.ts +8 -3
  26. package/reactHooks/feed/useBatchLoading.ts +7 -1
  27. package/reactHooks/feed/useFeedLoader.tsx +0 -9
  28. package/reactHooks/feed/useInflatedUrl.ts +23 -29
  29. package/reactHooks/feed/usePipesCacheReset.ts +3 -1
  30. package/reactHooks/layout/index.ts +1 -1
  31. package/reactHooks/player/TVSeekControlller/TVSeekController.ts +27 -10
  32. package/utils/__tests__/mapAccum.test.ts +73 -0
  33. package/utils/index.ts +7 -0
  34. package/utils/mapAccum.ts +23 -0
  35. package/zappFrameworkUtils/HookCallback/callbackNavigationAction.ts +60 -31
  36. package/zappFrameworkUtils/HookCallback/hookCallbackManifestExtensions.config.js +1 -1
  37. package/zappFrameworkUtils/HookCallback/useCallbackActions.ts +1 -7
@@ -0,0 +1,73 @@
1
+ import { mapAccum } from "../mapAccum";
2
+
3
+ describe("mapAccum", () => {
4
+ it("using standard ramda test", () => {
5
+ const digits = ["1", "2", "3", "4"];
6
+ const appender = (a, b) => [a + b, a + b];
7
+
8
+ const [acc, result] = mapAccum(appender, 0, digits); //= > ['01234', ['01', '012', '0123', '01234']]
9
+ expect(acc).toBe("01234");
10
+ expect(result).toEqual(["01", "012", "0123", "01234"]);
11
+ });
12
+
13
+ it("maps and accumulates over an array", () => {
14
+ const fn = (acc, x) => [acc + x, x * 2];
15
+ const [acc, result] = mapAccum(fn, 0, [1, 2, 3]);
16
+
17
+ expect(acc).toBe(6); // final accumulator (0 + 1 + 2 + 3)
18
+ expect(result).toEqual([2, 4, 6]); // mapped values (acc + x*2 at each step)
19
+ });
20
+
21
+ it("returns initial accumulator for empty array", () => {
22
+ const fn = (acc, x) => [acc + x, acc * x];
23
+ const [acc, result] = mapAccum(fn, 10, []);
24
+
25
+ expect(acc).toBe(10);
26
+ expect(result).toEqual([]);
27
+ });
28
+
29
+ it("accumulates strings correctly", () => {
30
+ const fn = (acc, x) => [acc + x, acc + x];
31
+ const [acc, result] = mapAccum(fn, "A", ["B", "C", "D"]);
32
+
33
+ expect(acc).toBe("ABCD");
34
+ expect(result).toEqual(["AB", "ABC", "ABCD"]);
35
+ });
36
+
37
+ it("works with objects as accumulator", () => {
38
+ const fn = (acc, x) => {
39
+ const newAcc = { sum: acc.sum + x };
40
+
41
+ return [newAcc, newAcc.sum];
42
+ };
43
+
44
+ const [acc, result] = mapAccum(fn, { sum: 0 }, [1, 2, 3]);
45
+
46
+ expect(acc).toEqual({ sum: 6 });
47
+ expect(result).toEqual([1, 3, 6]);
48
+ });
49
+
50
+ it("is curried", () => {
51
+ const fn = (acc, x) => [acc + x, x * 2];
52
+ const mapWithFn = mapAccum(fn);
53
+ const withInit = mapWithFn(2);
54
+ const [acc, result] = withInit([1, 2, 3]);
55
+
56
+ expect(acc).toBe(8);
57
+ expect(result).toEqual([2, 4, 6]);
58
+ });
59
+
60
+ it("does not mutate the original array", () => {
61
+ const arr = [1, 2, 3];
62
+ mapAccum((acc, x) => [acc + x, acc + x], 0, arr);
63
+ expect(arr).toEqual([1, 2, 3]);
64
+ });
65
+
66
+ it("handles mixed types in accumulator and result", () => {
67
+ const fn = (acc, x) => [acc + x.length, acc + "-" + x];
68
+ const [acc, result] = mapAccum(fn, 0, ["a", "bb", "ccc"]);
69
+
70
+ expect(acc).toBe(6);
71
+ expect(result).toEqual(["0-a", "1-bb", "3-ccc"]);
72
+ });
73
+ });
package/utils/index.ts CHANGED
@@ -16,6 +16,8 @@ export { endsWith } from "./endsWith";
16
16
 
17
17
  export { take } from "./take";
18
18
 
19
+ export { mapAccum } from "./mapAccum";
20
+
19
21
  export {
20
22
  cloneDeep as clone,
21
23
  flatten,
@@ -34,4 +36,9 @@ export {
34
36
  last,
35
37
  toLower,
36
38
  isEqual as equals,
39
+ uniq,
40
+ uniqWith,
41
+ flowRight as compose,
42
+ partial,
43
+ reverse,
37
44
  } 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
+ });
@@ -15,7 +15,7 @@ export enum ResultType {
15
15
  }
16
16
 
17
17
  export type CallbackResult = hookCallbackArgs & {
18
- options: {
18
+ options?: {
19
19
  resultType?: ResultType;
20
20
  };
21
21
  };
@@ -36,7 +36,7 @@ type General = Record<string, unknown>;
36
36
 
37
37
  const LogPrefix = "useCallbackNavigationAction:";
38
38
 
39
- const { log_info, log_verbose, log_error } = createLogger({
39
+ const { log_info, log_verbose, log_debug } = createLogger({
40
40
  subsystem: "hook-navigation-callback",
41
41
  });
42
42
 
@@ -56,23 +56,39 @@ const legacyMappingKeys = {
56
56
  actionType: "logout_completion_action",
57
57
  targetScreen: "navigate_to_logout_screen",
58
58
  },
59
+ "quick-brick-storefront": {
60
+ actionType: "purchase_completion_action",
61
+ targetScreen: "navigate_to_screen_after_purchase",
62
+ },
63
+ "zapp_login_plugin_oauth_tv_2_0.login": {
64
+ actionType: "login_completion_action",
65
+ targetScreen: "navigate_to_login_screen",
66
+ },
67
+ "zapp_login_plugin_oauth_tv_2_0.logout": {
68
+ actionType: "logout_completion_action",
69
+ targetScreen: "navigate_to_logout_screen",
70
+ },
59
71
  };
60
72
 
61
- const isNonEmptyString = (v: unknown): v is string =>
62
- typeof v === "string" && v.trim().length > 0;
63
-
64
- const NAV_ACTIONS = Object.values(NavigationCallbackOptions) as string[];
73
+ const NAV_ACTIONS = (
74
+ Object.values(NavigationCallbackOptions) as string[]
75
+ ).filter((value) => value !== NavigationCallbackOptions.DEFAULT);
65
76
 
66
77
  const isNavAction = (v: unknown): v is NavigationCallbackOptions =>
67
- typeof v === "string" && NAV_ACTIONS.includes(v.trim());
78
+ typeof v === "string" && NAV_ACTIONS.includes(v);
68
79
 
69
80
  export const getNavigationKeys = (
70
81
  item?: ZappUIComponent | ZappRiver,
71
- resultType: ResultType = null
82
+ resultType: ResultType | null = null
72
83
  ): NavKeys => {
73
84
  const general = (item?.general ?? {}) as General;
74
- const pluginIdentifier = item?.type ?? "";
75
- const legacy = legacyMappingKeys[pluginIdentifier] ?? {};
85
+
86
+ const pluginIdentifier = (item as any).identifier ?? item?.type ?? "";
87
+
88
+ const legacy =
89
+ legacyMappingKeys[`${pluginIdentifier}.${resultType}`] ??
90
+ legacyMappingKeys[pluginIdentifier] ??
91
+ {};
76
92
 
77
93
  const actionKey = resultType
78
94
  ? `${resultType}_${CALLBACK_NAVIGATION_KEY}`
@@ -82,29 +98,27 @@ export const getNavigationKeys = (
82
98
  (general as General)[actionKey] ??
83
99
  (legacy.actionType ? (general as General)[legacy.actionType] : undefined);
84
100
 
85
- let action: NavigationCallbackOptions | null = null;
86
-
87
- if (isNonEmptyString(rawAction)) {
88
- const trimmed = rawAction.trim();
89
- action = isNavAction(trimmed) ? trimmed : null;
90
- }
101
+ const action: NavigationCallbackOptions | null = isNavAction(rawAction)
102
+ ? rawAction
103
+ : null;
91
104
 
92
105
  if (!action) return null;
93
106
 
94
107
  let targetScreenId: string | null = null;
95
108
 
96
109
  if (action === NavigationCallbackOptions.GO_TO_SCREEN) {
110
+ const screenKey = resultType
111
+ ? `${resultType}_${CALLBACK_NAVIGATION_GO_TO_SCREEN_KEY}`
112
+ : CALLBACK_NAVIGATION_GO_TO_SCREEN_KEY;
113
+
97
114
  const screenId: string | null =
98
- ((general as General)[CALLBACK_NAVIGATION_GO_TO_SCREEN_KEY] as string) ??
115
+ ((general as General)[screenKey] as string) ??
99
116
  (legacy.targetScreen
100
117
  ? ((general as General)[legacy.targetScreen] as string)
101
118
  : undefined);
102
119
 
103
120
  if (screenId) {
104
- const trimmedTargetScreenId = screenId.trim();
105
-
106
- targetScreenId =
107
- trimmedTargetScreenId.length > 0 ? trimmedTargetScreenId : null;
121
+ targetScreenId = screenId.length > 0 ? screenId : null;
108
122
  }
109
123
  }
110
124
 
@@ -113,10 +127,12 @@ export const getNavigationKeys = (
113
127
 
114
128
  export const useCallbackNavigationAction = (
115
129
  item?: ZappUIComponent | ZappRiver
116
- ): ((args: CallbackResult) => void | undefined) => {
130
+ ): ((
131
+ args: CallbackResult,
132
+ hookCallback?: hookCallback
133
+ ) => void | undefined) => {
117
134
  const navigation = useNavigation();
118
135
  const rivers = useRivers();
119
- const enabled = Boolean(item?.general?.[CALLBACK_NAVIGATION_KEY]);
120
136
  const screenContext = useScreenContext();
121
137
 
122
138
  const overrideCallbackFromComponent = useMemo(() => {
@@ -131,23 +147,36 @@ export const useCallbackNavigationAction = (
131
147
  }
132
148
 
133
149
  const callbackAction = useCallback<hookCallback>(
134
- (args: CallbackResult) => {
150
+ (args: CallbackResult, hookCallback: hookCallback = null) => {
135
151
  if (!args.success) {
136
- log_error(`${LogPrefix} callback called with no success`);
152
+ log_debug(
153
+ `${LogPrefix} callback called with no success, use original callback`
154
+ );
155
+
156
+ hookCallback?.(args);
137
157
 
138
158
  return;
139
159
  }
140
160
 
141
161
  if (args.cancelled) {
142
- log_error(`${LogPrefix} callback called but cancelled`);
162
+ log_debug(
163
+ `${LogPrefix} callback called but cancelled, use original callback`
164
+ );
165
+
166
+ hookCallback?.(args);
167
+
168
+ return;
169
+ }
170
+
171
+ const data = getNavigationKeys(item, args.options?.resultType ?? null);
172
+
173
+ if (!data) {
174
+ hookCallback?.(args);
143
175
 
144
176
  return;
145
177
  }
146
178
 
147
- const data = getNavigationKeys(item, args.options?.resultType ?? null) ?? {
148
- action: NavigationCallbackOptions.DEFAULT,
149
- targetScreenId: null,
150
- };
179
+ hookCallback?.({ ...args, success: false, cancelled: true });
151
180
 
152
181
  switch (data.action) {
153
182
  case NavigationCallbackOptions.GO_BACK: {
@@ -198,5 +227,5 @@ export const useCallbackNavigationAction = (
198
227
  [item, navigation, rivers]
199
228
  );
200
229
 
201
- return enabled ? overrideCallbackFromComponent || callbackAction : undefined;
230
+ return overrideCallbackFromComponent || callbackAction;
202
231
  };
@@ -5,7 +5,7 @@ const NavigationCallbackOptions = {
5
5
  GO_TO_SCREEN: "go_to_screen",
6
6
  };
7
7
 
8
- export const ResultType = {
8
+ const ResultType = {
9
9
  login: "login",
10
10
  logout: "logout",
11
11
  };
@@ -12,13 +12,7 @@ export const useCallbackActions = (
12
12
 
13
13
  return useCallback(
14
14
  async (data: CallbackResult) => {
15
- if (navigationAction && data.success) {
16
- hookCallback?.({ ...data, success: false, cancelled: true });
17
-
18
- navigationAction(data);
19
- } else {
20
- hookCallback?.(data);
21
- }
15
+ navigationAction(data, hookCallback);
22
16
  },
23
17
  [navigationAction, hookCallback]
24
18
  );