@applicaster/zapp-react-native-utils 15.0.0-rc.98 → 15.1.0-alpha.2915689988

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/actionsExecutor/ActionExecutorContext.tsx +51 -5
  2. package/actionsExecutor/feedDecorator.ts +6 -6
  3. package/adsUtils/index.ts +2 -2
  4. package/analyticsUtils/AnalyticsEvents/sendMenuClickEvent.ts +2 -2
  5. package/analyticsUtils/PlayerAnalyticsManager.ts +11 -1
  6. package/analyticsUtils/README.md +1 -1
  7. package/analyticsUtils/__tests__/analyticsMapper.test.ts +35 -0
  8. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testACP_events.json +1 -1
  9. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testBlockUnlistedParams_rules.json +1 -1
  10. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testEmptyRenameKeepsName_events.json +4 -0
  11. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testEmptyRenameKeepsName_rules.json +6 -0
  12. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testEventRegex_events.json +3 -9
  13. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testIgnoreOrdering_events.json +18 -0
  14. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testIgnoreOrdering_rules.json +16 -0
  15. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexEventNoFallback_events.json +4 -0
  16. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexEventNoFallback_rules.json +6 -0
  17. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexMultiGroupRename_events.json +4 -0
  18. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexMultiGroupRename_rules.json +6 -0
  19. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexNonNamedFullMatch_events.json +4 -0
  20. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexNonNamedFullMatch_rules.json +6 -0
  21. package/analyticsUtils/__tests__/fixtures/index.js +20 -0
  22. package/analyticsUtils/analyticsMapper.ts +4 -1
  23. package/analyticsUtils/playerAnalyticsTracker.ts +26 -3
  24. package/appUtils/HooksManager/__tests__/__snapshots__/hooksManager.test.js.snap +188 -0
  25. package/appUtils/HooksManager/__tests__/hooksManager.test.js +2 -16
  26. package/appUtils/HooksManager/index.ts +47 -17
  27. package/appUtils/RiverFocusManager/{index.ts → index.js} +18 -25
  28. package/appUtils/accessibilityManager/const.ts +0 -4
  29. package/appUtils/accessibilityManager/utils.ts +1 -0
  30. package/appUtils/contextKeysManager/__tests__/getKeys/failure.test.ts +2 -7
  31. package/appUtils/contextKeysManager/__tests__/getKeys/success.test.ts +0 -48
  32. package/appUtils/contextKeysManager/contextResolver.ts +22 -51
  33. package/appUtils/contextKeysManager/index.ts +10 -65
  34. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +0 -3
  35. package/appUtils/focusManager/index.ios.ts +4 -43
  36. package/appUtils/focusManagerAux/utils/index.ts +3 -5
  37. package/appUtils/focusManagerAux/utils/utils.ios.ts +3 -199
  38. package/appUtils/keyCodes/keys/keys.web.ts +4 -1
  39. package/appUtils/localizationsHelper.ts +4 -0
  40. package/appUtils/orientationHelper.ts +4 -2
  41. package/appUtils/platform/platformUtils.ts +1 -1
  42. package/appUtils/playerManager/__tests__/playerFactory.test.ts +150 -0
  43. package/appUtils/playerManager/index.ts +9 -0
  44. package/appUtils/playerManager/player.ts +1 -5
  45. package/appUtils/playerManager/playerFactory.ts +17 -34
  46. package/appUtils/playerManager/playerNative.ts +22 -30
  47. package/appUtils/playerManager/usePlayer.tsx +5 -3
  48. package/appUtils/playerManager/usePlayerState.tsx +2 -14
  49. package/cellUtils/__tests__/cellUtils.test.ts +39 -0
  50. package/cellUtils/index.ts +11 -1
  51. package/cloudEventsUtils/index.ts +1 -65
  52. package/configurationUtils/__tests__/manifestKeyParser.test.ts +26 -26
  53. package/dateUtils/__tests__/dayjs.test.ts +0 -3
  54. package/dateUtils/index.ts +2 -0
  55. package/focusManager/aux/index.ts +1 -1
  56. package/headersUtils/__tests__/headersUtils.test.js +1 -11
  57. package/headersUtils/index.ts +1 -2
  58. package/manifestUtils/defaultManifestConfigurations/player.js +7 -75
  59. package/manifestUtils/platformIsTV.js +13 -0
  60. package/manifestUtils/tvAction/container/index.js +1 -1
  61. package/numberUtils/__tests__/toNumber.test.ts +0 -12
  62. package/numberUtils/index.ts +1 -19
  63. package/package.json +4 -4
  64. package/playerUtils/index.ts +24 -2
  65. package/pluginUtils/index.ts +4 -9
  66. package/reactHooks/advertising/index.ts +2 -2
  67. package/reactHooks/app/__tests__/useAppState.test.ts +1 -1
  68. package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +1 -1
  69. package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +2 -1
  70. package/reactHooks/casting/index.ts +1 -0
  71. package/reactHooks/casting/useIsCasting.tsx +57 -0
  72. package/reactHooks/cell-click/__tests__/index.test.js +3 -1
  73. package/reactHooks/componentsMap/index.ts +55 -0
  74. package/reactHooks/configuration/__tests__/index.test.tsx +1 -1
  75. package/reactHooks/connection/__tests__/index.test.js +1 -1
  76. package/reactHooks/debugging/__tests__/index.test.js +4 -4
  77. package/reactHooks/device/useIsTablet.tsx +19 -14
  78. package/reactHooks/device/useMemoizedIsTablet.ts +3 -3
  79. package/reactHooks/events/index.ts +20 -0
  80. package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +23 -32
  81. package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +19 -19
  82. package/reactHooks/feed/__tests__/useEntryScreenId.test.tsx +1 -4
  83. package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +30 -42
  84. package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +1 -1
  85. package/reactHooks/feed/__tests__/useInflatedUrl.test.tsx +1 -1
  86. package/reactHooks/feed/useBatchLoading.ts +1 -7
  87. package/reactHooks/feed/useEntryScreenId.ts +2 -2
  88. package/reactHooks/feed/useInflatedUrl.ts +1 -1
  89. package/reactHooks/feed/usePipesCacheReset.ts +1 -3
  90. package/reactHooks/flatList/useLoadNextPageIfNeeded.ts +16 -13
  91. package/reactHooks/index.ts +2 -0
  92. package/reactHooks/layout/__tests__/index.test.tsx +1 -1
  93. package/reactHooks/layout/__tests__/useLayoutVersion.test.tsx +1 -1
  94. package/reactHooks/layout/useDimensions/__tests__/{useDimensions.test.tsx → useDimensions.test.ts} +25 -105
  95. package/reactHooks/layout/useDimensions/useDimensions.ts +2 -2
  96. package/reactHooks/navigation/__tests__/index.test.tsx +4 -2
  97. package/reactHooks/navigation/index.ts +6 -7
  98. package/reactHooks/navigation/useRoute.ts +6 -8
  99. package/reactHooks/player/TVSeekControlller/TVSeekController.ts +10 -27
  100. package/reactHooks/player/__tests__/useAutoSeek._test.tsx +1 -1
  101. package/reactHooks/player/__tests__/useTapSeek._test.ts +1 -1
  102. package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +1 -1
  103. package/reactHooks/resolvers/__tests__/useComponentResolver.test.tsx +1 -1
  104. package/reactHooks/resolvers/useCellResolver.ts +2 -6
  105. package/reactHooks/resolvers/useComponentResolver.ts +13 -9
  106. package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +2 -2
  107. package/reactHooks/screen/__tests__/useCurrentScreenIsHook.test.ts +103 -0
  108. package/reactHooks/screen/__tests__/useCurrentScreenIsStartupHook.test.ts +94 -0
  109. package/reactHooks/screen/__tests__/useScreenBackgroundColor.test.tsx +1 -1
  110. package/reactHooks/screen/__tests__/useScreenData.test.tsx +1 -1
  111. package/reactHooks/screen/__tests__/useTargetScreenData.test.tsx +4 -12
  112. package/reactHooks/screen/index.ts +6 -0
  113. package/reactHooks/screen/useCurrentScreenIsHook.ts +9 -0
  114. package/reactHooks/screen/useCurrentScreenIsStartupHook.ts +8 -0
  115. package/reactHooks/screen/useIsStandaloneFullscreen.ts +12 -0
  116. package/reactHooks/screen/useTargetScreenData.ts +2 -4
  117. package/reactHooks/state/__tests__/useComponentScreenState.test.ts +246 -0
  118. package/reactHooks/state/index.ts +2 -0
  119. package/reactHooks/state/useComponentScreenState.ts +45 -0
  120. package/reactHooks/state/useRivers.ts +1 -1
  121. package/reactHooks/usePluginConfiguration.ts +2 -2
  122. package/reactHooks/utils/__tests__/index.test.js +1 -1
  123. package/reactHooks/videoModal/hooks/useVideoModalScreenData.tsx +22 -4
  124. package/rectUtils/index.ts +2 -2
  125. package/screenPickerUtils/index.ts +5 -0
  126. package/screenState/__tests__/index.test.ts +1 -1
  127. package/stringUtils/index.ts +1 -1
  128. package/testUtils/index.tsx +21 -30
  129. package/typeGuards/index.ts +0 -4
  130. package/utils/__tests__/clone.test.ts +158 -0
  131. package/utils/clone.ts +7 -0
  132. package/utils/index.ts +1 -13
  133. package/utils/path.ts +3 -6
  134. package/utils/pathOr.ts +1 -5
  135. package/zappFrameworkUtils/HookCallback/callbackNavigationAction.ts +2 -2
  136. package/zappFrameworkUtils/HookCallback/hookCallbackManifestExtensions.config.js +1 -1
  137. package/zappFrameworkUtils/loginPluginUtils.ts +1 -1
  138. package/adsUtils/__tests__/createVMAP.test.ts +0 -419
  139. package/appDataUtils/__tests__/urlScheme.test.ts +0 -678
  140. package/appUtils/focusManagerAux/utils/index.ios.ts +0 -122
  141. package/cloudEventsUtils/__tests__/index.test.ts +0 -529
  142. package/enumUtils/__tests__/getEnumKeyByEnumValue.test.ts +0 -207
  143. package/errorUtils/__tests__/GeneralError.test.ts +0 -97
  144. package/errorUtils/__tests__/HttpStatusCode.test.ts +0 -344
  145. package/errorUtils/__tests__/MissingPluginError.test.ts +0 -113
  146. package/errorUtils/__tests__/NetworkError.test.ts +0 -202
  147. package/errorUtils/__tests__/getParsedResponse.test.ts +0 -188
  148. package/errorUtils/__tests__/invariant.test.ts +0 -112
  149. package/numberUtils/__tests__/toPositiveNumber.test.ts +0 -165
  150. package/reactHooks/analytics/__tests__/useSendAnalyticsOnPress.test.ts +0 -537
  151. package/reactHooks/dev/__tests__/useReRenderLog.test.ts +0 -188
  152. package/reactHooks/ui/__tests__/useFadeOutWhenBlurred.test.ts +0 -580
  153. package/rectUtils/__tests__/index.test.ts +0 -549
  154. package/screenPickerUtils/__tests__/index.test.ts +0 -333
  155. package/searchUtils/const.ts +0 -7
  156. package/searchUtils/index.ts +0 -3
  157. package/time/__tests__/BackgroundTimer.test.ts +0 -156
  158. package/time/__tests__/Timer.test.ts +0 -236
  159. package/typeGuards/__tests__/isString.test.ts +0 -21
  160. package/utils/__tests__/mergeRight.test.ts +0 -48
  161. package/utils/__tests__/selectors.test.ts +0 -124
  162. package/utils/mergeRight.ts +0 -5
  163. package/utils/selectors.ts +0 -46
@@ -1,4 +1,4 @@
1
- import { isNil } from "@applicaster/zapp-react-native-utils/utils";
1
+ import * as R from "ramda";
2
2
 
3
3
  import { StorageLevel, StorageType } from "./consts";
4
4
  import {
@@ -13,7 +13,6 @@ import {
13
13
  localStorage as LocalStorage,
14
14
  secureStorage as SecureStorage,
15
15
  } from "./storage";
16
- import { NativeModules } from "react-native";
17
16
 
18
17
  export { StorageLevel };
19
18
 
@@ -155,65 +154,11 @@ export class ContextKeysManager {
155
154
  }
156
155
 
157
156
  public async getKeys(
158
- keys: Array<KeyName>,
159
- contextObj?: { key: string; required?: boolean }[]
157
+ keys: Array<KeyName>
160
158
  ): Promise<Map<KeyName, ValueOrNothing>> {
161
- if (NativeModules.ContextResolverBridge) {
162
- const keysObj: Record<string, boolean> = {};
159
+ const values = await Promise.all(keys.map((key) => this.getKey(key)));
163
160
 
164
- const requiredByKey = new Map(
165
- contextObj?.map((item) => [item.key, item.required ?? false]) ?? []
166
- );
167
-
168
- let hasResolvableKeys = false;
169
-
170
- const normalizedKeys: Array<{
171
- original: KeyName;
172
- normalized: string | null;
173
- }> = [];
174
-
175
- for (const key of keys) {
176
- const {
177
- isValid: isValidKey,
178
- key: parsedKey,
179
- namespace: parsedNamespace,
180
- } = this.parseKey(key);
181
-
182
- if (!isValidKey) {
183
- normalizedKeys.push({ original: key, normalized: null });
184
- continue;
185
- }
186
-
187
- const normalized = buildNamespaceKey(parsedKey, parsedNamespace);
188
-
189
- keysObj[normalized] = requiredByKey.get(normalized) ?? false;
190
- hasResolvableKeys = true;
191
- normalizedKeys.push({ original: key, normalized });
192
- }
193
-
194
- if (!hasResolvableKeys) {
195
- return new Map(
196
- normalizedKeys.map(({ original }) => [original, NOTHING])
197
- );
198
- }
199
-
200
- const res =
201
- await NativeModules.ContextResolverBridge.resolveContextKeys(keysObj);
202
-
203
- const resolved = res ?? {};
204
-
205
- return new Map(
206
- normalizedKeys.map(({ original, normalized }) => {
207
- if (!normalized) return [original, NOTHING];
208
-
209
- return [original, resolved[normalized] ?? NOTHING];
210
- })
211
- );
212
- } else {
213
- const values = await Promise.all(keys.map((key) => this.getKey(key)));
214
-
215
- return new Map(keys.map((key, index) => [key, values[index]]));
216
- }
161
+ return new Map(R.zip(keys, values));
217
162
  }
218
163
 
219
164
  public async getKey(key: KeyName): Promise<ValueOrNothing> {
@@ -236,7 +181,7 @@ export class ContextKeysManager {
236
181
  parsedNamespace
237
182
  );
238
183
 
239
- if (!isNil(resultByReference)) {
184
+ if (!R.isNil(resultByReference)) {
240
185
  return resultByReference;
241
186
  }
242
187
 
@@ -247,7 +192,7 @@ export class ContextKeysManager {
247
192
  parsedNamespace
248
193
  );
249
194
 
250
- if (!isNil(resultFromSessionStorage)) {
195
+ if (!R.isNil(resultFromSessionStorage)) {
251
196
  return resultFromSessionStorage;
252
197
  }
253
198
 
@@ -256,7 +201,7 @@ export class ContextKeysManager {
256
201
  parsedNamespace
257
202
  );
258
203
 
259
- if (!isNil(resultFromLocalStorage)) {
204
+ if (!R.isNil(resultFromLocalStorage)) {
260
205
  return resultFromLocalStorage;
261
206
  }
262
207
 
@@ -265,7 +210,7 @@ export class ContextKeysManager {
265
210
  parsedNamespace
266
211
  );
267
212
 
268
- if (!isNil(resultFromSecureStorage)) {
213
+ if (!R.isNil(resultFromSecureStorage)) {
269
214
  return resultFromSecureStorage;
270
215
  }
271
216
 
@@ -330,7 +275,7 @@ export class ContextKeysManager {
330
275
  keysProp.map((keyProp) => this.setKey(keyProp))
331
276
  );
332
277
 
333
- return new Map(keys.map((key, index) => [key, values[index]]));
278
+ return new Map(R.zip(keys, values));
334
279
  }
335
280
 
336
281
  // when succeed saving - return true
@@ -439,7 +384,7 @@ export class ContextKeysManager {
439
384
  public async removeKeys(keys: KeyName[]): Promise<Map<KeyName, boolean>> {
440
385
  const values = await Promise.all(keys.map((key) => this.removeKey(key)));
441
386
 
442
- return new Map(keys.map((key, index) => [key, values[index]]));
387
+ return new Map(R.zip(keys, values));
443
388
  }
444
389
  // REMOVE
445
390
  }
@@ -71,9 +71,6 @@ exports[`focusManagerIOS should be defined 1`] = `
71
71
  "invokeHandler": [Function],
72
72
  "isChildOf": [Function],
73
73
  "isFocusOn": [Function],
74
- "isFocusOnContent": [Function],
75
- "isFocusOnMenu": [Function],
76
- "isFocusOnTabsScreenContent": [Function],
77
74
  "isGroupItemFocused": [Function],
78
75
  "moveFocus": [Function],
79
76
  "on": [Function],
@@ -4,11 +4,7 @@ import * as R from "ramda";
4
4
  import {
5
5
  isCurrentFocusOn,
6
6
  isChildOf as isChildOfUtils,
7
- isPartOfMenu,
8
- isPartOfContent,
9
- isPartOfTabsScreenContent,
10
- } from "../focusManagerAux/utils/index.ios";
11
-
7
+ } from "../focusManagerAux/utils";
12
8
  import { Tree } from "./treeDataStructure/Tree";
13
9
  import { findFocusableNode } from "./treeDataStructure/Utils";
14
10
  import { subscriber } from "../../functionUtils";
@@ -192,15 +188,9 @@ export const focusManager = (function () {
192
188
  function register({ id, component }) {
193
189
  const { isGroup = false } = component;
194
190
 
195
- if (isGroup) {
196
- registerGroup(id, component);
197
- } else {
198
- registerItem(id, component);
199
- }
191
+ emitRegistered(id);
200
192
 
201
- const groupId = component?.props?.groupId;
202
-
203
- emitRegistered({ id, groupId, isGroup });
193
+ return isGroup ? registerGroup(id, component) : registerItem(id, component);
204
194
  }
205
195
 
206
196
  function unregister(id, { group = false } = {}) {
@@ -283,9 +273,7 @@ export const focusManager = (function () {
283
273
  function setFocus(
284
274
  id: string,
285
275
  direction?: FocusManager.IOS.Direction,
286
- options?: Partial<{
287
- groupFocusedChanged: boolean;
288
- }>,
276
+ options?: Partial<{ groupFocusedChanged: boolean }>,
289
277
  callback?: any
290
278
  ) {
291
279
  blur(direction);
@@ -424,30 +412,6 @@ export const focusManager = (function () {
424
412
  return id && isCurrentFocusOn(id, currentFocusNode);
425
413
  }
426
414
 
427
- function isFocusOnMenu(): boolean {
428
- const currentFocusable = getCurrentFocus();
429
-
430
- return isPartOfMenu(focusableTree, currentFocusable?.props?.id);
431
- }
432
-
433
- function isFocusOnContent(): boolean {
434
- const currentFocusable = getCurrentFocus();
435
-
436
- return isPartOfContent(focusableTree, currentFocusable?.props?.id);
437
- }
438
-
439
- function isFocusOnTabsScreenContent(
440
- screenPickerContentContainerId: string
441
- ): boolean {
442
- const currentFocusable = getCurrentFocus();
443
-
444
- return isPartOfTabsScreenContent(
445
- focusableTree,
446
- screenPickerContentContainerId,
447
- currentFocusable?.props?.id
448
- );
449
- }
450
-
451
415
  function isChildOf(childId, parentId): boolean {
452
416
  return isChildOfUtils(focusableTree, childId, parentId);
453
417
  }
@@ -474,9 +438,6 @@ export const focusManager = (function () {
474
438
  isGroupItemFocused,
475
439
  getPreferredFocusChild,
476
440
  isFocusOn,
477
- isFocusOnMenu,
478
- isFocusOnContent,
479
- isFocusOnTabsScreenContent,
480
441
  isChildOf,
481
442
  };
482
443
  })();
@@ -13,7 +13,7 @@ import {
13
13
 
14
14
  import {
15
15
  getFocusableId,
16
- SCREEN_PICKER_CONTAINER,
16
+ isTabsScreenContentContainerId,
17
17
  } from "@applicaster/zapp-react-native-utils/screenPickerUtils";
18
18
 
19
19
  // run check each 300 ms
@@ -24,8 +24,6 @@ const isTopMenu = (node) => startsWith(QUICK_BRICK_NAVBAR, node?.id);
24
24
  const isContent = (node) => startsWith(QUICK_BRICK_CONTENT, node?.id);
25
25
  const isRoot = (node) => node?.id === "root";
26
26
 
27
- const isScrenPicker = (node) => startsWith(SCREEN_PICKER_CONTAINER, node?.id);
28
-
29
27
  type Props = {
30
28
  maxTimeout: number;
31
29
  conditionFn: () => boolean;
@@ -102,7 +100,7 @@ export const getNavbarNode = (focusableTree) => {
102
100
 
103
101
  export const waitForContent = (focusableTree) => {
104
102
  const contentHasAnyChildren = (): boolean => {
105
- const countOfChildren = pathOr<number>(
103
+ const countOfChildren = pathOr(
106
104
  0,
107
105
  ["children", "length"],
108
106
  getContentNode(focusableTree)
@@ -136,7 +134,7 @@ export const isTabsScreenOnContentFocused = (node) => {
136
134
  return false;
137
135
  }
138
136
 
139
- if (isScrenPicker(node)) {
137
+ if (isTabsScreenContentContainerId(node?.id)) {
140
138
  return true;
141
139
  }
142
140
 
@@ -1,9 +1,7 @@
1
- import { ReplaySubject, Subject } from "rxjs";
2
- import { filter, switchMap, take, withLatestFrom, map } from "rxjs/operators";
3
-
1
+ import { ReplaySubject } from "rxjs";
2
+ import { filter } from "rxjs/operators";
4
3
  import { BUTTON_PREFIX } from "@applicaster/zapp-react-native-ui-components/Components/MasterCell/DefaultComponents/tv/TvActionButtons/const";
5
4
  import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager/index.ios";
6
- import { isPartOfMenu, isPartOfContent } from "./index.ios";
7
5
 
8
6
  type FocusableID = string;
9
7
  type RegistrationEvent = {
@@ -11,25 +9,6 @@ type RegistrationEvent = {
11
9
  registered: boolean;
12
10
  };
13
11
 
14
- let focusableViewRegistrationSubject$ = new Subject<{
15
- id: FocusableID;
16
- groupId: FocusableID;
17
- }>();
18
-
19
- let focusableGroupRegistrationSubject$ = new ReplaySubject<{
20
- id: FocusableID;
21
- }>();
22
-
23
- let focusableNativeViewRegistrationSubject$ = new Subject<{
24
- id: FocusableID;
25
- groupId: FocusableID;
26
- }>();
27
-
28
- let focusableNativeGroupRegistrationSubject$ = new ReplaySubject<{
29
- id: FocusableID;
30
- groupId: FocusableID;
31
- }>();
32
-
33
12
  const isFocusableButton = (id: Option<FocusableID>): boolean =>
34
13
  id && id.includes?.(BUTTON_PREFIX);
35
14
 
@@ -43,189 +22,14 @@ export const focusableButtonsRegistration$ = (focusableGroupId: string) =>
43
22
  )
44
23
  );
45
24
 
46
- export const resetFocusableRegistration = () => {
47
- // complete the old subject so subscribers are notified and resources are freed
48
- if (!focusableViewRegistrationSubject$.closed) {
49
- focusableViewRegistrationSubject$.complete();
50
- }
51
-
52
- if (!focusableGroupRegistrationSubject$.closed) {
53
- focusableGroupRegistrationSubject$.complete();
54
- }
55
-
56
- if (!focusableNativeViewRegistrationSubject$.closed) {
57
- focusableNativeViewRegistrationSubject$.complete();
58
- }
59
-
60
- if (!focusableNativeGroupRegistrationSubject$.closed) {
61
- focusableNativeGroupRegistrationSubject$.complete();
62
- }
63
-
64
- focusableViewRegistrationSubject$ = new Subject<{
65
- id: FocusableID;
66
- groupId: FocusableID;
67
- }>();
68
-
69
- focusableGroupRegistrationSubject$ = new ReplaySubject<{
70
- id: FocusableID;
71
- }>();
72
-
73
- focusableNativeViewRegistrationSubject$ = new Subject<{
74
- id: FocusableID;
75
- groupId: FocusableID;
76
- }>();
77
-
78
- focusableNativeGroupRegistrationSubject$ = new ReplaySubject<{
79
- id: FocusableID;
80
- groupId: FocusableID;
81
- }>();
82
- };
83
-
84
- const focusableNativeViewRegistration = ({ focusableView, focusableGroup }) => {
85
- return focusableNativeViewRegistrationSubject$.pipe(
86
- filter(
87
- (focusableNativeView) => focusableNativeView.id === focusableView.id
88
- ),
89
- take(1),
90
- switchMap((focusableNativeView) =>
91
- // start waiting registration of its parent FocusableNativeGroup
92
- focusableNativeGroupRegistrationSubject$.pipe(
93
- filter(
94
- (focusableNativeGroup) =>
95
- focusableNativeGroup.id === focusableNativeView.groupId
96
- ),
97
- take(1),
98
- map((focusableNativeGroup) => ({
99
- focusableNativeGroup,
100
- focusableNativeView,
101
- focusableView,
102
- focusableGroup,
103
- }))
104
- )
105
- )
106
- );
107
- };
108
-
109
- export const firstFocusableViewRegistrationFactory = () =>
110
- focusableViewRegistrationSubject$.pipe(
111
- take(1), // we care about only first FocusableView registration
112
- switchMap((focusableView) =>
113
- // start waiting registration of its parent FocusableGroup
114
- focusableGroupRegistrationSubject$.pipe(
115
- filter((focusableGroup) => focusableGroup.id === focusableView.groupId),
116
- take(1),
117
- map((focusableGroup) => ({
118
- focusableView,
119
- focusableGroup,
120
- }))
121
- )
122
- ),
123
- // start waiting registration for FocusableNativeView and its parent FocusableNativeGroup
124
- switchMap(({ focusableView, focusableGroup }) =>
125
- focusableNativeViewRegistration({
126
- focusableView,
127
- focusableGroup,
128
- })
129
- )
130
- );
131
-
132
- // registration on RN level(into RN focusManager)
133
- export const emitRegistered = ({
134
- id,
135
- groupId,
136
- isGroup,
137
- }: {
138
- id: Option<FocusableID>;
139
- groupId: Option<FocusableID>;
140
- isGroup: boolean;
141
- }): void => {
25
+ export const emitRegistered = (id: Option<FocusableID>): void => {
142
26
  if (isFocusableButton(id)) {
143
27
  registeredSubject$.next({ id, registered: true });
144
28
  }
145
-
146
- if (isGroup && id) {
147
- focusableGroupRegistrationSubject$.next({ id });
148
- }
149
-
150
- if (!isGroup && id && groupId) {
151
- focusableViewRegistrationSubject$.next({ id, groupId });
152
- }
153
29
  };
154
30
 
155
- // unregistration on RN level(into RN focusManager)
156
31
  export const emitUnregistered = (id: Option<FocusableID>): void => {
157
32
  if (isFocusableButton(id)) {
158
33
  registeredSubject$.next({ id, registered: false });
159
34
  }
160
35
  };
161
-
162
- // registration focusableNativeView and focusableNativeGroup
163
- export const emitNativeRegistered = ({
164
- id,
165
- groupId,
166
- isGroup,
167
- }: {
168
- id: Option<FocusableID>;
169
- groupId: Option<FocusableID>;
170
- isGroup: boolean;
171
- }): void => {
172
- if (!isGroup && id && groupId) {
173
- focusableNativeViewRegistrationSubject$.next({ id, groupId });
174
- }
175
-
176
- if (isGroup && id && groupId) {
177
- focusableNativeGroupRegistrationSubject$.next({ id, groupId });
178
- }
179
- };
180
-
181
- // /////
182
-
183
- const focusedSubject$ = new Subject<FocusableID>();
184
-
185
- const focused$ = focusedSubject$.asObservable();
186
-
187
- export const emitFocused = (id: FocusableID): void => {
188
- focusedSubject$.next(id);
189
- };
190
-
191
- export const topMenuItemFocused$ = focused$.pipe(
192
- filter((id) => id && isPartOfMenu(focusManager.focusableTree, id))
193
- );
194
-
195
- export const contentFocused$ = focused$.pipe(
196
- filter((id) => {
197
- const isContent = isPartOfContent(focusManager.focusableTree, id);
198
-
199
- return id && isContent;
200
- })
201
- );
202
-
203
- const createFocusableRegistry = () => {
204
- const subject$ = new ReplaySubject<FocusableID | undefined>(1);
205
-
206
- return {
207
- observable$: subject$.asObservable(),
208
- register: (id: FocusableID) => {
209
- // save focusable_id on registration
210
- subject$.next(id);
211
- },
212
- unregister: () => {
213
- // reset focusable_id on unregistration
214
- subject$.next(undefined);
215
- },
216
- };
217
- };
218
-
219
- /// HOME_TOP_MENU_ITEM
220
- export const HomeTopMenuItemRegistry = createFocusableRegistry();
221
-
222
- export const homeTopMenuItemFocused$ = topMenuItemFocused$.pipe(
223
- withLatestFrom(HomeTopMenuItemRegistry.observable$),
224
- filter(([id, homeId]) => id === homeId)
225
- );
226
-
227
- /// SCREEN_PICKER
228
- export const ScreenPickerContentContainerRegistry = createFocusableRegistry();
229
-
230
- /// SEARCH_INPUT
231
- export const SearchInputRegistry = createFocusableRegistry();
@@ -10,7 +10,10 @@ import { Platform } from "react-native";
10
10
  * platformKeys[Platform.OS] should only include keys
11
11
  * that are unique to that platform, i.e. Exit: { keyCode: 10182 }
12
12
  */
13
- export const KEYS = Object.assign(platformKeys.web, platformKeys[Platform.OS]);
13
+ export const KEYS = Object.assign(
14
+ platformKeys["web"],
15
+ platformKeys[Platform.OS]
16
+ );
14
17
 
15
18
  export const ARROW_KEYS = [
16
19
  KEYS.ArrowUp,
@@ -85,6 +85,10 @@ export const toDayJSLocaleMap = (code) => {
85
85
  tt: null,
86
86
  "es-LA": "es",
87
87
  "en-UK": "en-gb",
88
+ "en-ZA": null,
89
+ "en-NG": null,
90
+ "en-ZW": null,
91
+ "en-ZM": null,
88
92
  };
89
93
 
90
94
  if (map[code] === null) {
@@ -1,5 +1,5 @@
1
1
  import * as ReactNative from "react-native";
2
- import { useAppData } from "@applicaster/zapp-react-native-redux/hooks";
2
+ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
3
3
 
4
4
  import { isTV, platformSelect } from "../reactUtils";
5
5
  import { useIsTablet } from "../reactHooks";
@@ -184,7 +184,9 @@ export const getScreenOrientation = ({
184
184
 
185
185
  export const useGetScreenOrientation = (screenData) => {
186
186
  const isTablet = useIsTablet();
187
- const { isTabletPortrait } = useAppData();
187
+
188
+ const { appData } = usePickFromState(["appData"]);
189
+ const isTabletPortrait = appData?.isTabletPortrait;
188
190
 
189
191
  return getScreenOrientation({
190
192
  screenData,
@@ -79,7 +79,7 @@ export class ClosedCaptioningManager {
79
79
  private constructor() {
80
80
  this.initialize();
81
81
 
82
- window.vizioDebug = {
82
+ window["vizioDebug"] = {
83
83
  setCCEnabled: (isCCEnabled: boolean) => {
84
84
  this.ccState$.next(isCCEnabled);
85
85
  },
@@ -0,0 +1,150 @@
1
+ const mockAppStoreGet = jest.fn();
2
+ const mockFindPluginByIdentifier = jest.fn();
3
+
4
+ jest.mock("@applicaster/zapp-react-native-redux/AppStore", () => ({
5
+ appStore: { get: (key: string) => mockAppStoreGet(key) },
6
+ }));
7
+
8
+ jest.mock("@applicaster/zapp-react-native-utils/pluginUtils", () => ({
9
+ findPluginByIdentifier: (id: string, plugins: any) =>
10
+ mockFindPluginByIdentifier(id, plugins),
11
+ }));
12
+
13
+ import { PlayerRole } from "../conts";
14
+ import { playerFactory } from "../playerFactory";
15
+
16
+ const fakeComponent = () => null;
17
+
18
+ class FakeController {
19
+ receivedConfig: any;
20
+ constructor(config: any) {
21
+ this.receivedConfig = config;
22
+ }
23
+ }
24
+
25
+ const baseConfig = {
26
+ player: {},
27
+ playerId: "p1",
28
+ autoplay: false,
29
+ entry: { id: "entry-1" } as any,
30
+ muted: false,
31
+ playerPluginId: "test-plugin",
32
+ screenConfig: { foo: "bar" },
33
+ playerRole: PlayerRole.Cell,
34
+ };
35
+
36
+ const installPluginWithProtocol = (
37
+ protocolReturn: any | ((screenConfig: any, entry: any) => any)
38
+ ) => {
39
+ const playerProtocol =
40
+ typeof protocolReturn === "function"
41
+ ? protocolReturn
42
+ : () => protocolReturn;
43
+
44
+ mockAppStoreGet.mockImplementation((key: string) =>
45
+ key === "plugins" ? { "test-plugin": {} } : null
46
+ );
47
+
48
+ mockFindPluginByIdentifier.mockReturnValue({
49
+ module: { playerProtocol },
50
+ });
51
+ };
52
+
53
+ describe("playerFactory", () => {
54
+ beforeEach(() => {
55
+ mockAppStoreGet.mockReset();
56
+ mockFindPluginByIdentifier.mockReset();
57
+ });
58
+
59
+ it("resolves with controller and Component when playerProtocol returns synchronously", async () => {
60
+ installPluginWithProtocol({
61
+ Component: fakeComponent,
62
+ controllerClass: FakeController,
63
+ });
64
+
65
+ const item = await playerFactory(baseConfig);
66
+
67
+ expect(item).not.toBeNull();
68
+ expect(item?.Component).toBe(fakeComponent);
69
+ expect(item?.controller).toBeInstanceOf(FakeController);
70
+
71
+ expect((item?.controller as FakeController).receivedConfig).toBe(
72
+ baseConfig
73
+ );
74
+ });
75
+
76
+ it("resolves with controller and Component when playerProtocol returns a Promise (delayed import)", async () => {
77
+ installPluginWithProtocol(async () => ({
78
+ Component: fakeComponent,
79
+ controllerClass: FakeController,
80
+ }));
81
+
82
+ const item = await playerFactory(baseConfig);
83
+
84
+ expect(item).not.toBeNull();
85
+ expect(item?.Component).toBe(fakeComponent);
86
+ expect(item?.controller).toBeInstanceOf(FakeController);
87
+ });
88
+
89
+ it("passes screenConfig and entry through to playerProtocol", async () => {
90
+ const playerProtocol = jest.fn(() => ({
91
+ Component: fakeComponent,
92
+ controllerClass: FakeController,
93
+ }));
94
+
95
+ mockAppStoreGet.mockImplementation((key: string) =>
96
+ key === "plugins" ? { "test-plugin": {} } : null
97
+ );
98
+
99
+ mockFindPluginByIdentifier.mockReturnValue({ module: { playerProtocol } });
100
+
101
+ await playerFactory(baseConfig);
102
+
103
+ expect(playerProtocol).toHaveBeenCalledWith(
104
+ baseConfig.screenConfig,
105
+ baseConfig.entry
106
+ );
107
+ });
108
+
109
+ it("resolves to null when playerPluginId is missing", async () => {
110
+ expect(
111
+ await playerFactory({ ...baseConfig, playerPluginId: "" } as any)
112
+ ).toBeNull();
113
+ });
114
+
115
+ it("resolves to null when appStore has no plugins", async () => {
116
+ mockAppStoreGet.mockReturnValue(null);
117
+
118
+ expect(await playerFactory(baseConfig)).toBeNull();
119
+ });
120
+
121
+ it("resolves to null when the plugin has no playerProtocol", async () => {
122
+ mockAppStoreGet.mockImplementation((key: string) =>
123
+ key === "plugins" ? { "test-plugin": {} } : null
124
+ );
125
+
126
+ mockFindPluginByIdentifier.mockReturnValue({ module: {} });
127
+
128
+ expect(await playerFactory(baseConfig)).toBeNull();
129
+ });
130
+
131
+ it("resolves to null when playerProtocol returns without a Component", async () => {
132
+ installPluginWithProtocol({ controllerClass: FakeController });
133
+
134
+ expect(await playerFactory(baseConfig)).toBeNull();
135
+ });
136
+
137
+ it("resolves to null when playerProtocol returns without a controllerClass", async () => {
138
+ installPluginWithProtocol({ Component: fakeComponent });
139
+
140
+ expect(await playerFactory(baseConfig)).toBeNull();
141
+ });
142
+
143
+ it("rejects when playerProtocol throws synchronously", async () => {
144
+ installPluginWithProtocol(() => {
145
+ throw new Error("boom");
146
+ });
147
+
148
+ await expect(playerFactory(baseConfig)).rejects.toThrow("boom");
149
+ });
150
+ });