@applicaster/zapp-react-native-utils 14.0.0-rc.5 → 14.0.0-rc.51

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 (94) hide show
  1. package/actionsExecutor/ActionExecutorContext.tsx +1 -1
  2. package/analyticsUtils/AnalyticsEvents/helper.ts +81 -0
  3. package/analyticsUtils/AnalyticsEvents/sendHeaderClickEvent.ts +1 -1
  4. package/analyticsUtils/AnalyticsEvents/sendMenuClickEvent.ts +2 -1
  5. package/analyticsUtils/AnalyticsEvents/sendOnClickEvent.ts +14 -4
  6. package/analyticsUtils/__tests__/analyticsUtils.test.js +14 -0
  7. package/analyticsUtils/events.ts +8 -0
  8. package/analyticsUtils/index.tsx +3 -4
  9. package/analyticsUtils/manager.ts +1 -1
  10. package/appUtils/HooksManager/Hook.ts +4 -4
  11. package/appUtils/HooksManager/index.ts +11 -1
  12. package/appUtils/accessibilityManager/index.ts +7 -4
  13. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +5 -0
  14. package/appUtils/focusManager/__tests__/focusManager.test.js +1 -1
  15. package/appUtils/focusManager/index.ios.ts +10 -0
  16. package/appUtils/focusManager/index.ts +82 -11
  17. package/appUtils/focusManager/treeDataStructure/Tree/index.js +1 -1
  18. package/appUtils/focusManagerAux/utils/index.ts +106 -3
  19. package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +0 -15
  20. package/appUtils/playerManager/useChapterMarker.tsx +0 -1
  21. package/appUtils/playerManager/usePlayerControllerSetup.tsx +16 -0
  22. package/arrayUtils/__tests__/isEmptyArray.test.ts +63 -0
  23. package/arrayUtils/__tests__/isFilledArray.test.ts +1 -1
  24. package/arrayUtils/index.ts +8 -3
  25. package/audioPlayerUtils/__tests__/getArtworkImage.test.ts +144 -0
  26. package/audioPlayerUtils/__tests__/getBackgroundImage.test.ts +72 -0
  27. package/audioPlayerUtils/__tests__/getImageFromEntry.test.ts +110 -0
  28. package/audioPlayerUtils/assets/index.ts +2 -0
  29. package/audioPlayerUtils/index.ts +242 -0
  30. package/componentsUtils/__tests__/isTabsScreen.test.ts +38 -0
  31. package/componentsUtils/index.ts +4 -1
  32. package/conf/player/__tests__/selectors.test.ts +34 -0
  33. package/conf/player/selectors.ts +10 -0
  34. package/configurationUtils/__tests__/configurationUtils.test.js +0 -31
  35. package/configurationUtils/__tests__/getMediaItems.test.ts +65 -0
  36. package/configurationUtils/__tests__/imageSrcFromMediaItem.test.ts +34 -0
  37. package/configurationUtils/__tests__/manifestKeyParser.test.ts +546 -0
  38. package/configurationUtils/index.ts +63 -34
  39. package/configurationUtils/manifestKeyParser.ts +57 -32
  40. package/focusManager/FocusManager.ts +26 -16
  41. package/focusManager/Tree.ts +25 -21
  42. package/focusManager/__tests__/FocusManager.test.ts +50 -8
  43. package/index.d.ts +0 -9
  44. package/manifestUtils/_internals/getDefaultConfiguration.js +28 -0
  45. package/manifestUtils/{_internals.js → _internals/index.js} +2 -25
  46. package/manifestUtils/createConfig.js +4 -1
  47. package/manifestUtils/defaultManifestConfigurations/player.js +1239 -200
  48. package/manifestUtils/progressBar/__tests__/mobileProgressBar.test.js +0 -30
  49. package/manifestUtils/sharedConfiguration/screenPicker/stylesFields.js +1 -2
  50. package/navigationUtils/__tests__/mapContentTypesToRivers.test.ts +130 -0
  51. package/navigationUtils/index.ts +6 -4
  52. package/package.json +2 -3
  53. package/playerUtils/__tests__/configurationUtils.test.ts +1 -65
  54. package/playerUtils/__tests__/getPlayerActionButtons.test.ts +54 -0
  55. package/playerUtils/_internals/__tests__/utils.test.ts +71 -0
  56. package/playerUtils/_internals/index.ts +1 -0
  57. package/playerUtils/_internals/utils.ts +31 -0
  58. package/playerUtils/configurationUtils.ts +0 -44
  59. package/playerUtils/getPlayerActionButtons.ts +17 -0
  60. package/playerUtils/index.ts +53 -0
  61. package/playerUtils/useValidatePlayerConfig.tsx +22 -19
  62. package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +15 -14
  63. package/reactHooks/debugging/__tests__/index.test.js +0 -1
  64. package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +39 -88
  65. package/reactHooks/feed/useBatchLoading.ts +11 -9
  66. package/reactHooks/feed/useFeedLoader.tsx +12 -8
  67. package/reactHooks/feed/usePipesCacheReset.ts +3 -3
  68. package/reactHooks/flatList/useSequentialRenderItem.tsx +3 -3
  69. package/reactHooks/layout/__tests__/index.test.tsx +3 -1
  70. package/reactHooks/layout/isTablet/index.ts +12 -5
  71. package/reactHooks/layout/useDimensions/__tests__/useDimensions.test.ts +34 -36
  72. package/reactHooks/layout/useDimensions/useDimensions.ts +2 -3
  73. package/reactHooks/layout/useLayoutVersion.ts +5 -5
  74. package/reactHooks/navigation/index.ts +7 -5
  75. package/reactHooks/navigation/useIsScreenActive.ts +9 -5
  76. package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +4 -0
  77. package/reactHooks/screen/useScreenContext.ts +1 -1
  78. package/reactHooks/state/__tests__/ZStoreProvider.test.tsx +2 -1
  79. package/reactHooks/state/index.ts +1 -1
  80. package/reactHooks/state/useHomeRiver.ts +4 -2
  81. package/reactHooks/state/useRivers.ts +7 -8
  82. package/riverComponetsMeasurementProvider/index.tsx +1 -1
  83. package/screenPickerUtils/index.ts +7 -0
  84. package/services/js2native.ts +1 -0
  85. package/testUtils/index.tsx +7 -8
  86. package/time/BackgroundTimer.ts +6 -4
  87. package/utils/__tests__/find.test.ts +36 -0
  88. package/utils/__tests__/pathOr.test.ts +37 -0
  89. package/utils/__tests__/startsWith.test.ts +30 -0
  90. package/utils/find.ts +3 -0
  91. package/utils/index.ts +24 -1
  92. package/utils/pathOr.ts +5 -0
  93. package/utils/startsWith.ts +9 -0
  94. package/playerUtils/configurationGenerator.ts +0 -2572
@@ -11,8 +11,11 @@ const currentPlatform = platformSelect({
11
11
  android_tv: "android",
12
12
  });
13
13
 
14
- const stateSuffixes = ["pressed", "focused"];
14
+ // Do not change the order, focused_selected should be first
15
+ const states = ["focused_selected", "pressed", "focused", "selected"];
16
+
15
17
  const platformSuffixes = ["ios", "tvos", "samsung", "lg", "android"];
18
+ type StateKey = (typeof states)[number] | "default";
16
19
 
17
20
  export type GetAllSpecificStylesProps = {
18
21
  componentName: string;
@@ -33,39 +36,47 @@ export const getAllSpecificStyles = ({
33
36
  subComponentName,
34
37
  outStyles,
35
38
  }: GetAllSpecificStylesProps) => {
36
- if (!outStyles) {
37
- throw new Error("outStyles is required");
38
- }
39
+ if (!outStyles) throw new Error("outStyles is required");
40
+ if (!componentName) throw new Error("componentName is required");
39
41
 
40
- // Pressed, platform specific styles are not supported
41
- const prefix = `${componentName}_style_${subComponentName}_`;
42
+ const prefix =
43
+ subComponentName?.length > 0
44
+ ? `${componentName}_style_${subComponentName}_`
45
+ : `${componentName}_style_`;
42
46
 
43
47
  const defaultKey = "default";
44
48
 
45
- if (!outStyles[defaultKey]) {
46
- outStyles[defaultKey] = {};
47
- }
49
+ if (!outStyles[defaultKey]) outStyles[defaultKey] = {};
50
+
51
+ const tmpGenericDict: Record<StateKey, Record<string, any>> = {};
52
+ const tmpPlatformDict: Record<StateKey, Record<string, any>> = {};
48
53
 
49
- Object.keys(configuration).forEach((key) => {
54
+ const parseKey = (key: string, value: any) => {
50
55
  if (!key.startsWith(prefix)) {
51
56
  return;
52
57
  }
53
58
 
54
59
  let styleName = key.slice(prefix.length);
60
+ if (!styleName || styleName.startsWith("_")) return;
55
61
 
56
- const platform = platformSuffixes.find((suffix) =>
57
- styleName.startsWith(suffix)
62
+ const platform = platformSuffixes.find((prefix) =>
63
+ styleName.startsWith(prefix)
58
64
  );
59
65
 
66
+ let tmpDict = tmpGenericDict;
67
+
60
68
  if (platform) {
61
69
  if (currentPlatform !== platform) {
62
- return; // Continue
70
+ return;
63
71
  }
64
72
 
73
+ tmpDict = tmpPlatformDict;
65
74
  styleName = styleName.slice(platform.length + 1);
66
75
  }
67
76
 
68
- let state = stateSuffixes.find((suffix) => styleName.startsWith(suffix));
77
+ let state = states.find((prefix) => styleName.startsWith(prefix)) as
78
+ | StateKey
79
+ | undefined;
69
80
 
70
81
  if (state) {
71
82
  styleName = styleName.slice(state.length + 1);
@@ -73,30 +84,44 @@ export const getAllSpecificStyles = ({
73
84
  state = defaultKey;
74
85
  }
75
86
 
76
- const camelCaseKey = toCamelCase(styleName);
87
+ if (!styleName) return;
77
88
 
78
- let stateOverrides = outStyles[state];
89
+ const camelCaseKey = toCamelCase(styleName);
79
90
 
80
- if (!stateOverrides) {
81
- stateOverrides = {};
82
- outStyles[state] = stateOverrides;
83
- }
91
+ if (!tmpDict[state]) tmpDict[state] = {};
92
+ tmpDict[state][camelCaseKey] = value;
93
+ };
84
94
 
85
- if (stateOverrides[camelCaseKey]) {
86
- // Add warning, key is already defined
87
- }
95
+ for (const [key, value] of Object.entries(configuration)) {
96
+ parseKey(key, value);
97
+ }
88
98
 
89
- stateOverrides[camelCaseKey] = configuration[key];
90
- });
99
+ const allStates = Array.from(
100
+ new Set<StateKey>([
101
+ defaultKey,
102
+ ...(Object.keys(tmpGenericDict) as StateKey[]),
103
+ ...(Object.keys(tmpPlatformDict) as StateKey[]),
104
+ ...(Object.keys(outStyles) as StateKey[]),
105
+ ])
106
+ );
107
+
108
+ for (const state of allStates) {
109
+ outStyles[state] = Object.assign(
110
+ {},
111
+ outStyles[state] || {},
112
+ tmpGenericDict[state] || {},
113
+ tmpPlatformDict[state] || {}
114
+ );
115
+ }
91
116
 
92
117
  // Merge default styles with state specific styles
93
- if (Object.keys(outStyles).length > 1) {
94
- Object.keys(outStyles).forEach((key) => {
95
- if (key === defaultKey) {
96
- return;
97
- }
118
+ for (const state of Object.keys(outStyles)) {
119
+ if (state === defaultKey) continue;
98
120
 
99
- outStyles[key] = Object.assign({}, outStyles[defaultKey], outStyles[key]);
100
- });
121
+ outStyles[state] = Object.assign(
122
+ {},
123
+ outStyles[defaultKey],
124
+ outStyles[state]
125
+ );
101
126
  }
102
127
  };
@@ -176,18 +176,30 @@ class FocusManager {
176
176
  }
177
177
  }
178
178
 
179
- registerFocusable(
180
- component: FocusManager.TouchableReactRef,
181
- parentFocusable: FocusManager.TouchableReactRef,
182
- isFocusableCell: boolean
183
- ) {
184
- const focusableId = getFocusableId(component);
179
+ registerFocusable({
180
+ touchableRef,
181
+ parentFocusableRef,
182
+ isFocusableCell,
183
+ parentFocusableId,
184
+ }: {
185
+ touchableRef: FocusManager.TouchableReactRef;
186
+ parentFocusableRef: FocusManager.TouchableReactRef;
187
+ isFocusableCell: boolean;
188
+ parentFocusableId: string;
189
+ }) {
190
+ const focusableId = getFocusableId(touchableRef);
191
+
185
192
  const focusableComponent = FocusManager.findFocusable(focusableId);
186
193
 
187
- if (!focusableComponent && component) {
188
- this.focusableComponents.push(component);
194
+ if (!focusableComponent && touchableRef) {
195
+ this.focusableComponents.push(touchableRef);
189
196
 
190
- this.tree.add(component, parentFocusable, isFocusableCell);
197
+ this.tree.add(
198
+ touchableRef,
199
+ parentFocusableRef,
200
+ isFocusableCell,
201
+ parentFocusableId
202
+ );
191
203
  } else {
192
204
  logger.warning("Focusable component already registered", {
193
205
  id: focusableId,
@@ -243,12 +255,10 @@ class FocusManager {
243
255
  }
244
256
 
245
257
  blurPrevious(options?: FocusManager.Android.CallbackOptions) {
246
- if (options) {
247
- FocusManager.instance.prevFocused?.onBlur?.(
248
- FocusManager.instance.prevFocused,
249
- options
250
- );
251
- }
258
+ FocusManager.instance.prevFocused?.onBlur?.(
259
+ FocusManager.instance.prevFocused,
260
+ options ?? {} // Adding fallback to avoid potential regression caused by #7509
261
+ );
252
262
  }
253
263
 
254
264
  onDisableFocusChange = (id) => {
@@ -269,7 +279,7 @@ class FocusManager {
269
279
 
270
280
  if (nextFocus) {
271
281
  // HACK: hack to fix the hack below
272
- // HACK: putting call to the end of the event loop so the next component has a chane to be registered
282
+ // HACK: putting call to the end of the event loop so the next component has a chance to be registered
273
283
  setTimeout(() => {
274
284
  FocusManager.instance.setFocus(nextFocus, {
275
285
  direction: "down",
@@ -8,37 +8,41 @@ export class Tree {
8
8
  this.tree = focusManagerTree;
9
9
  }
10
10
 
11
- add(component, parentFocusable, isFocusableCell) {
12
- const focusableId = getFocusableId(component);
13
- const parentId = getFocusableId(parentFocusable);
11
+ add(
12
+ touchableRef: FocusManager.TouchableReactRef,
13
+ parentFocusableRef: FocusManager.TouchableReactRef,
14
+ isFocusableCell: boolean,
15
+ parentFocusableId: string
16
+ ) {
17
+ const focusableId = getFocusableId(touchableRef);
18
+ const parentId = getFocusableId(parentFocusableRef) || parentFocusableId;
14
19
  const focusableComponentInTree = this.find(focusableId);
15
20
 
16
21
  // update node if it already exists
17
22
  if (focusableComponentInTree) {
18
- focusableComponentInTree.updateNode(component);
23
+ focusableComponentInTree.updateNode(touchableRef);
19
24
  }
20
25
 
21
- if (parentFocusable?.current) {
22
- if (!this.find(parentId)) {
23
- this.tree.push(new TreeNode(null, parentId, null, isFocusableCell));
24
- }
26
+ if (!this.find(parentId)) {
27
+ // create temporary node to the root of the tree
28
+ this.tree.push(new TreeNode(null, parentId, null, isFocusableCell));
29
+ }
25
30
 
26
- const parentNode = this.find(parentId);
31
+ const parentNode = this.find(parentId);
27
32
 
28
- if (parentNode) {
29
- if (focusableComponentInTree) {
30
- focusableComponentInTree.isFocusableCell = isFocusableCell;
31
- focusableComponentInTree.parentId = parentNode.id;
33
+ if (parentNode) {
34
+ if (focusableComponentInTree) {
35
+ focusableComponentInTree.isFocusableCell = isFocusableCell;
36
+ focusableComponentInTree.parentId = parentNode.id;
32
37
 
33
- parentNode.addChild(focusableComponentInTree);
38
+ parentNode.addChild(focusableComponentInTree);
34
39
 
35
- // remove root object from the list
36
- this.tree = this.tree.filter(
37
- (node) => node !== focusableComponentInTree
38
- );
39
- } else {
40
- parentNode.addChild(component, focusableId, isFocusableCell);
41
- }
40
+ // remove root object from the list
41
+ this.tree = this.tree.filter(
42
+ (node) => node !== focusableComponentInTree
43
+ );
44
+ } else {
45
+ parentNode.addChild(touchableRef, focusableId, isFocusableCell);
42
46
  }
43
47
  }
44
48
  }
@@ -1,5 +1,8 @@
1
1
  import { focusManager } from "../FocusManager";
2
2
 
3
+ const isFocusableCell = true;
4
+ const parentFocusableId = "parentFocusableId";
5
+
3
6
  const group = {
4
7
  current: {
5
8
  props: {
@@ -62,13 +65,47 @@ jest.useFakeTimers();
62
65
 
63
66
  describe("FocusManager", () => {
64
67
  beforeAll(() => {
65
- focusManager.registerFocusable(group, { current: null });
66
- focusManager.registerFocusable(child1, group);
67
- focusManager.registerFocusable(child2, group);
68
- focusManager.registerFocusable(child3, child2);
69
-
70
- focusManager.registerFocusable(child4, child2);
71
- focusManager.registerFocusable(child5, child2);
68
+ focusManager.registerFocusable({
69
+ touchableRef: group,
70
+ parentFocusableRef: { current: null },
71
+ isFocusableCell,
72
+ parentFocusableId,
73
+ });
74
+
75
+ focusManager.registerFocusable({
76
+ touchableRef: child1,
77
+ parentFocusableRef: group,
78
+ isFocusableCell,
79
+ parentFocusableId,
80
+ });
81
+
82
+ focusManager.registerFocusable({
83
+ touchableRef: child2,
84
+ parentFocusableRef: group,
85
+ isFocusableCell,
86
+ parentFocusableId,
87
+ });
88
+
89
+ focusManager.registerFocusable({
90
+ touchableRef: child3,
91
+ parentFocusableRef: child2,
92
+ isFocusableCell,
93
+ parentFocusableId,
94
+ });
95
+
96
+ focusManager.registerFocusable({
97
+ touchableRef: child4,
98
+ parentFocusableRef: child2,
99
+ isFocusableCell,
100
+ parentFocusableId,
101
+ });
102
+
103
+ focusManager.registerFocusable({
104
+ touchableRef: child5,
105
+ parentFocusableRef: child2,
106
+ isFocusableCell,
107
+ parentFocusableId,
108
+ });
72
109
  });
73
110
 
74
111
  it("focusManager should be defined", () => {
@@ -199,7 +236,12 @@ describe("FocusManager", () => {
199
236
  });
200
237
 
201
238
  it("focusManager registerFocusable should register", () => {
202
- focusManager.registerFocusable(child5, child2);
239
+ focusManager.registerFocusable({
240
+ touchableRef: child5,
241
+ parentFocusableRef: child2,
242
+ isFocusableCell,
243
+ parentFocusableId,
244
+ });
203
245
 
204
246
  expect(
205
247
  focusManager.isFocusableChildOf(child5.current.props.id, child2)
package/index.d.ts CHANGED
@@ -137,12 +137,3 @@ declare type AccessibilityState = {
137
137
  reduceMotionEnabled: boolean;
138
138
  boldTextEnabled: boolean;
139
139
  };
140
-
141
- declare type AccessibilityProps = {
142
- accessibilityLabel?: string;
143
- accessibilityHint?: string;
144
- "aria-label"?: string;
145
- "aria-description"?: string;
146
- accessibilityRole?: string;
147
- "aria-role"?: string;
148
- };
@@ -0,0 +1,28 @@
1
+ const R = require("ramda");
2
+ const { defaultConfigurations } = require("../defaultManifestConfigurations");
3
+
4
+ /**
5
+ * returns default configuration keys for provided plugin type
6
+ * @param {('general-content'|'player')} pluginType
7
+ * @param options manifest generator information
8
+ * @param {string} options.version manifest version
9
+ * @param {string} options.platform qb platform value
10
+ */
11
+ function getDefaultConfiguration(pluginType, options) {
12
+ const defConfig = R.compose(
13
+ R.unless(R.isNil, (fn) => fn(options)),
14
+ R.propOr(null, pluginType)
15
+ )(defaultConfigurations);
16
+
17
+ if (!defConfig) {
18
+ const availableKeys = R.keys(defaultConfigurations);
19
+
20
+ const message = `Requested key "${pluginType}" doesn't exist in the default configuration\nAvailable keys: ${availableKeys}`;
21
+ // eslint-disable-next-line no-console
22
+ console.warn(message);
23
+ }
24
+
25
+ return defConfig;
26
+ }
27
+
28
+ module.exports = { getDefaultConfiguration };
@@ -1,6 +1,7 @@
1
1
  const R = require("ramda");
2
2
  const camelize = require("camelize");
3
- const { defaultConfigurations } = require("./defaultManifestConfigurations");
3
+
4
+ const { getDefaultConfiguration } = require("./getDefaultConfiguration");
4
5
 
5
6
  const toSnakeCase = R.compose(R.replace(/\s/g, "_"), R.toLower, R.trim);
6
7
 
@@ -173,30 +174,6 @@ function generateFieldsFromDefaultsWithoutPrefixedLabel(
173
174
  )(fields);
174
175
  }
175
176
 
176
- /**
177
- * returns default configuration keys for provided plugin type
178
- * @param {('general-content'|'player')} pluginType
179
- * @param options manifest generator information
180
- * @param {string} options.version manifest version
181
- * @param {string} options.platform qb platform value
182
- */
183
- function getDefaultConfiguration(pluginType, options) {
184
- const defConfig = R.compose(
185
- R.unless(R.isNil, (fn) => fn(options)),
186
- R.propOr(null, pluginType)
187
- )(defaultConfigurations);
188
-
189
- if (!defConfig) {
190
- const availableKeys = R.keys(defaultConfigurations);
191
-
192
- const message = `Requested key "${pluginType}" doesn't exist in the default configuration\nAvailable keys: ${availableKeys}`;
193
- // eslint-disable-next-line no-console
194
- console.warn(message);
195
- }
196
-
197
- return defConfig;
198
- }
199
-
200
177
  module.exports = {
201
178
  toSnakeCase,
202
179
  toCamelCase,
@@ -1,5 +1,8 @@
1
1
  const R = require("ramda");
2
- const { getDefaultConfiguration } = require("./_internals");
2
+
3
+ const {
4
+ getDefaultConfiguration,
5
+ } = require("./_internals/getDefaultConfiguration");
3
6
 
4
7
  const indexByKey = R.indexBy((obj) => R.prop(obj.group ? "label" : "key", obj));
5
8
  const propIfExist = R.curry((prop) => R.when(R.prop(prop), R.prop(prop)));