@applicaster/zapp-react-native-utils 14.0.0-alpha.1054425138 → 14.0.0-alpha.1101330035

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 (70) hide show
  1. package/actionsExecutor/ActionExecutorContext.tsx +11 -5
  2. package/actionsExecutor/ScreenActions.ts +82 -9
  3. package/actionsExecutor/StorageActions.ts +1 -1
  4. package/actionsExecutor/feedDecorator.ts +171 -0
  5. package/actionsExecutor/screenResolver.ts +11 -0
  6. package/analyticsUtils/AnalyticsEvents/helper.ts +81 -0
  7. package/analyticsUtils/AnalyticsEvents/sendOnClickEvent.ts +14 -4
  8. package/analyticsUtils/__tests__/analyticsUtils.test.js +14 -0
  9. package/analyticsUtils/events.ts +8 -0
  10. package/appUtils/accessibilityManager/index.ts +5 -2
  11. package/appUtils/contextKeysManager/contextResolver.ts +2 -3
  12. package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +0 -15
  13. package/appUtils/playerManager/useChapterMarker.tsx +0 -1
  14. package/appUtils/playerManager/usePlayerControllerSetup.tsx +16 -0
  15. package/arrayUtils/__tests__/isEmptyArray.test.ts +63 -0
  16. package/arrayUtils/__tests__/isFilledArray.test.ts +1 -1
  17. package/arrayUtils/index.ts +7 -2
  18. package/audioPlayerUtils/__tests__/getArtworkImage.test.ts +144 -0
  19. package/audioPlayerUtils/__tests__/getBackgroundImage.test.ts +72 -0
  20. package/audioPlayerUtils/__tests__/getImageFromEntry.test.ts +110 -0
  21. package/audioPlayerUtils/assets/index.ts +2 -0
  22. package/audioPlayerUtils/index.ts +242 -0
  23. package/conf/player/__tests__/selectors.test.ts +34 -0
  24. package/conf/player/selectors.ts +10 -0
  25. package/configurationUtils/__tests__/configurationUtils.test.js +0 -31
  26. package/configurationUtils/__tests__/getMediaItems.test.ts +65 -0
  27. package/configurationUtils/__tests__/imageSrcFromMediaItem.test.ts +34 -0
  28. package/configurationUtils/__tests__/manifestKeyParser.test.ts +547 -0
  29. package/configurationUtils/index.ts +63 -34
  30. package/configurationUtils/manifestKeyParser.ts +57 -32
  31. package/focusManager/FocusManager.ts +26 -16
  32. package/focusManager/Tree.ts +25 -21
  33. package/focusManager/__tests__/FocusManager.test.ts +50 -8
  34. package/manifestUtils/_internals/getDefaultConfiguration.js +28 -0
  35. package/manifestUtils/{_internals.js → _internals/index.js} +2 -25
  36. package/manifestUtils/createConfig.js +4 -1
  37. package/manifestUtils/defaultManifestConfigurations/player.js +1239 -200
  38. package/manifestUtils/progressBar/__tests__/mobileProgressBar.test.js +0 -30
  39. package/manifestUtils/sharedConfiguration/screenPicker/stylesFields.js +1 -2
  40. package/package.json +2 -2
  41. package/playerUtils/__tests__/configurationUtils.test.ts +1 -65
  42. package/playerUtils/__tests__/getPlayerActionButtons.test.ts +54 -0
  43. package/playerUtils/_internals/__tests__/utils.test.ts +71 -0
  44. package/playerUtils/_internals/index.ts +1 -0
  45. package/playerUtils/_internals/utils.ts +31 -0
  46. package/playerUtils/configurationUtils.ts +0 -44
  47. package/playerUtils/getPlayerActionButtons.ts +17 -0
  48. package/playerUtils/index.ts +59 -0
  49. package/playerUtils/useValidatePlayerConfig.tsx +22 -19
  50. package/reactHooks/cell-click/index.ts +3 -0
  51. package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +20 -0
  52. package/reactHooks/feed/useBatchLoading.ts +3 -3
  53. package/reactHooks/feed/useFeedLoader.tsx +3 -3
  54. package/reactHooks/feed/usePipesCacheReset.ts +1 -1
  55. package/reactHooks/layout/isTablet/index.ts +12 -5
  56. package/reactHooks/navigation/index.ts +7 -3
  57. package/reactHooks/navigation/useIsScreenActive.ts +9 -5
  58. package/reactHooks/navigation/useRoute.ts +7 -2
  59. package/reactHooks/navigation/useScreenStateStore.ts +8 -0
  60. package/reactHooks/screen/useScreenContext.ts +1 -1
  61. package/reactHooks/state/__tests__/ZStoreProvider.test.tsx +2 -1
  62. package/riverComponetsMeasurementProvider/index.tsx +1 -1
  63. package/services/js2native.ts +1 -0
  64. package/storage/ScreenSingleValueProvider.ts +201 -0
  65. package/storage/ScreenStateMultiSelectProvider.ts +290 -0
  66. package/storage/StorageMultiSelectProvider.ts +192 -0
  67. package/storage/StorageSingleSelectProvider.ts +108 -0
  68. package/time/BackgroundTimer.ts +5 -3
  69. package/utils/index.ts +16 -1
  70. package/playerUtils/configurationGenerator.ts +0 -2572
@@ -36,7 +36,6 @@ import {
36
36
  sessionStorageToggleFlag,
37
37
  } from "./StorageActions";
38
38
 
39
- import { ScreenSingleValueProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/ScreenSingleValueProvider";
40
39
  import { screenSetVariable, screenToggleFlag } from "./ScreenActions";
41
40
 
42
41
  export const { log_error, log_info, log_debug } = createLogger({
@@ -169,8 +168,7 @@ const prepareDefaultActions = (actionExecutor) => {
169
168
 
170
169
  const entry = context?.entry || {};
171
170
  const entryResolver = new EntryResolver(entry);
172
- const route = context.screenRoute;
173
- const screenData = ScreenSingleValueProvider.getState(route) as any;
171
+ const screenData = context?.screenStateStore.getState().data || {};
174
172
  const screenResolver = new EntryResolver(screenData || {});
175
173
 
176
174
  const data =
@@ -239,8 +237,14 @@ const prepareDefaultActions = (actionExecutor) => {
239
237
  context?: Record<string, any>
240
238
  ): Promise<ActionResult> => {
241
239
  const route = context?.screenRoute;
242
- const { key, value } = action.options;
243
- screenSetVariable(route, key, value);
240
+ const screenStateStore = context?.screenStateStore;
241
+
242
+ await screenSetVariable(
243
+ route,
244
+ screenStateStore,
245
+ { entry: context?.entry, options: action.options },
246
+ action
247
+ );
244
248
 
245
249
  return Promise.resolve(ActionResult.Success);
246
250
  }
@@ -253,9 +257,11 @@ const prepareDefaultActions = (actionExecutor) => {
253
257
  context?: Record<string, any>
254
258
  ): Promise<ActionResult> => {
255
259
  const screenRoute = context?.screenRoute;
260
+ const screenStateStore = context?.screenStateStore;
256
261
 
257
262
  await screenToggleFlag(
258
263
  screenRoute,
264
+ screenStateStore,
259
265
  { entry: context?.entry, options: action.options },
260
266
  action
261
267
  );
@@ -4,22 +4,94 @@ import { log_error, log_info } from "./ActionExecutorContext";
4
4
  import { ActionResult } from "./ActionExecutor";
5
5
  import { get } from "lodash";
6
6
 
7
- import { ScreenMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/ScreenStateMultiSelectProvider";
8
7
  import { onMaxTagsReached } from "./StorageActions";
8
+ import { ScreenMultiSelectProvider } from "../storage/ScreenStateMultiSelectProvider";
9
+ import { ScreenSingleValueProvider } from "../storage/ScreenSingleValueProvider";
9
10
 
10
- export const screenSetVariable = (
11
- _screenRoute: string,
12
- _key: string,
13
- _value: string
14
- ) => {};
11
+ export const screenSetVariable = async (
12
+ screenRoute: string,
13
+ screenStateStore: ScreenStateStore,
14
+ context: Record<string, any>,
15
+ action: ActionType
16
+ ): Promise<ActionResult> => {
17
+ if (!context) {
18
+ log_error("handleAction: screenSetVariable action missing context");
19
+
20
+ return ActionResult.Error;
21
+ }
22
+
23
+ const entry = context?.entry as ZappEntry;
24
+
25
+ if (!entry) {
26
+ log_error(
27
+ "handleAction: screenSetVariable action missing entry. Entry is required to get the value."
28
+ );
29
+
30
+ return ActionResult.Error;
31
+ }
32
+
33
+ const tag = action.options?.selector
34
+ ? get(entry, action.options.selector)
35
+ : (entry.extensions?.tag ?? entry.id);
36
+
37
+ const keyNamespace = action.options?.key;
38
+
39
+ if (!keyNamespace) {
40
+ log_error("handleAction: screenSetVariable action missing key namespace", {
41
+ keyNamespace,
42
+ });
43
+
44
+ return ActionResult.Error;
45
+ }
46
+
47
+ if (!tag) {
48
+ log_error(
49
+ "handleAction: screenSetVariable action could not determine tag",
50
+ { selector: action.options?.selector, value: action.options?.value }
51
+ );
52
+
53
+ return ActionResult.Error;
54
+ }
55
+
56
+ try {
57
+ const singleValueProvider = ScreenSingleValueProvider.getProvider(
58
+ keyNamespace,
59
+ screenRoute,
60
+ screenStateStore
61
+ );
62
+
63
+ const currentValue = await singleValueProvider.getValueAsync();
64
+
65
+ log_info(
66
+ `handleAction: screenSetVariable setting value: ${tag} for keyNamespace: ${keyNamespace}, previous value: ${currentValue}`
67
+ );
68
+
69
+ await singleValueProvider.setValue(String(tag));
70
+
71
+ log_info(
72
+ `handleAction: screenSetVariable successfully set value: ${tag} for keyNamespace: ${keyNamespace}`
73
+ );
74
+
75
+ return ActionResult.Success;
76
+ } catch (error) {
77
+ log_error("handleAction: screenSetVariable failed to set value", {
78
+ keyNamespace,
79
+ tag,
80
+ error,
81
+ });
82
+
83
+ return ActionResult.Error;
84
+ }
85
+ };
15
86
 
16
87
  export const screenToggleFlag = async (
17
88
  screenRoute: string,
89
+ screenStateStore: ScreenStateStore,
18
90
  context: Record<string, any>,
19
91
  action: ActionType
20
92
  ) => {
21
93
  if (!context) {
22
- log_error("handleAction: localStorageToggleFlag action missing context");
94
+ log_error("handleAction: screenToggleFlag action missing context");
23
95
 
24
96
  return ActionResult.Error;
25
97
  }
@@ -28,7 +100,7 @@ export const screenToggleFlag = async (
28
100
 
29
101
  if (!entry) {
30
102
  log_error(
31
- "handleAction: localStorageToggleFlag action missing entry. Entry is required to get the tag."
103
+ "handleAction: screenToggleFlag action missing entry. Entry is required to get the tag."
32
104
  );
33
105
 
34
106
  return ActionResult.Error;
@@ -43,7 +115,8 @@ export const screenToggleFlag = async (
43
115
  if (keyNamespace && tag) {
44
116
  const multiSelectProvider = ScreenMultiSelectProvider.getProvider(
45
117
  keyNamespace,
46
- screenRoute
118
+ screenRoute,
119
+ screenStateStore
47
120
  );
48
121
 
49
122
  const selectedItems = await multiSelectProvider.getSelectedAsync();
@@ -1,6 +1,6 @@
1
1
  import { ActionResult } from "./ActionExecutor";
2
2
  import { get } from "lodash";
3
- import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
3
+ import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-utils/storage/StorageMultiSelectProvider";
4
4
  import { log_error, log_info } from "./ActionExecutorContext";
5
5
  import { postEvent } from "../reactHooks/useSubscriberFor";
6
6
  import { TOGGLE_FLAG_MAX_ITEMS_REACHED_EVENT } from "./consts";
@@ -0,0 +1,171 @@
1
+ import * as R from "ramda";
2
+ import { getNamespaceAndKey } from "../appUtils/contextKeysManager/utils";
3
+ import { createLogger } from "../logger";
4
+
5
+ const { log_error, log_verbose } = createLogger({
6
+ subsystem: "FeedDecorator",
7
+ category: "General",
8
+ });
9
+
10
+ function getScope(scope) {
11
+ if (scope === "screen") {
12
+ return scope;
13
+ } else if (!scope || scope === "ctx") {
14
+ return "ctx";
15
+ } else {
16
+ log_verbose(
17
+ `decorateFeed: Unsupported scope "${scope}" provided in preference_editor_options. Defaulting to "ctx".`
18
+ );
19
+
20
+ return "ctx";
21
+ }
22
+ }
23
+
24
+ function makeMultiSelect(feed: ZappFeed, key, decoratedFeed) {
25
+ const scope = getScope(
26
+ decoratedFeed.extensions?.preference_editor_options?.scope
27
+ );
28
+
29
+ const behavior = {
30
+ ...feed.extensions?.["behavior"],
31
+ select_mode: "multi",
32
+ current_selection: `@{${scope}/${key}}`,
33
+ };
34
+
35
+ if (!feed.extensions) {
36
+ decoratedFeed.extensions = {
37
+ behavior,
38
+ };
39
+ } else {
40
+ decoratedFeed.extensions.behavior = behavior;
41
+ }
42
+
43
+ const actionType =
44
+ decoratedFeed.extensions?.preference_editor_options?.scope === "screen"
45
+ ? "screenToggleFlag"
46
+ : decoratedFeed.extensions?.preference_editor_options?.scope === "session"
47
+ ? "sessionStorageToggleFlag"
48
+ : "localStorageToggleFlag";
49
+
50
+ decoratedFeed.entry?.forEach((entry: ZappEntry) => {
51
+ entry.type.value = "action";
52
+ entry.id = entry.extensions?.tag || entry.id;
53
+
54
+ entry.extensions = {
55
+ ...(entry.extensions || {}),
56
+ tap_actions: {
57
+ actions: [
58
+ {
59
+ type: actionType,
60
+ options: {
61
+ key,
62
+ },
63
+ },
64
+ ],
65
+ },
66
+ };
67
+ });
68
+
69
+ return decoratedFeed;
70
+ }
71
+
72
+ function makeSingleSelect(feed: ZappFeed, key, decoratedFeed) {
73
+ const scope = getScope(
74
+ decoratedFeed.extensions?.preference_editor_options?.scope
75
+ );
76
+
77
+ const behavior = {
78
+ ...feed.extensions?.["behavior"],
79
+ select_mode: "single",
80
+ current_selection: `@{${scope}/${key}}`,
81
+ };
82
+
83
+ if (!feed.extensions) {
84
+ decoratedFeed.extensions = {
85
+ behavior,
86
+ };
87
+ } else {
88
+ decoratedFeed.extensions.behavior = behavior;
89
+ }
90
+
91
+ const localStorageProducer = (entry: ZappFeed) => {
92
+ entry.id = entry.extensions?.tag || entry.id;
93
+ const { key: keyName, namespace } = getNamespaceAndKey(key);
94
+
95
+ const action =
96
+ decoratedFeed.extensions?.preference_editor_options?.scope === "session"
97
+ ? "sessionStorageSet"
98
+ : "localStorageSet";
99
+
100
+ return {
101
+ type: action,
102
+ options: {
103
+ content: {
104
+ [namespace]: {
105
+ [keyName]: entry.id,
106
+ },
107
+ },
108
+ },
109
+ };
110
+ };
111
+
112
+ const screenStateProducer = (entry: ZappFeed) => {
113
+ entry.id = entry.extensions?.tag || entry.id;
114
+
115
+ return {
116
+ type: "screenSetVariable",
117
+ options: {
118
+ key,
119
+ value: entry.id,
120
+ },
121
+ };
122
+ };
123
+
124
+ const producer =
125
+ decoratedFeed.extensions?.preference_editor_options?.scope === "screen"
126
+ ? screenStateProducer
127
+ : localStorageProducer;
128
+
129
+ decoratedFeed.entry?.forEach((entry: ZappEntry) => {
130
+ entry.type.value = "action";
131
+
132
+ entry.extensions = {
133
+ ...(entry.extensions || {}),
134
+ tap_actions: {
135
+ actions: [producer(entry)],
136
+ },
137
+ };
138
+ });
139
+
140
+ return decoratedFeed;
141
+ }
142
+
143
+ export const decorateFeed = (feed: ZappFeed) => {
144
+ if (!(feed.extensions?.["role"] === "preference_editor")) {
145
+ return feed;
146
+ }
147
+
148
+ const key = feed.extensions?.["preference_editor_options"]?.["key"];
149
+
150
+ if (!key) {
151
+ log_error(
152
+ `decorateFeed: No 'key' provided in feed titled "${feed.title}" with id "${feed.id}" in preference_editor_options. The preference_editor role requires a key for local storage.`
153
+ );
154
+
155
+ throw new Error(
156
+ "decorateFeed: No 'key' provided in feed preference_editor_options"
157
+ );
158
+ }
159
+
160
+ const decoratedFeed = R.clone(feed);
161
+
162
+ const isSingleSelect =
163
+ (feed.extensions?.["preference_editor_options"]?.select_mode ||
164
+ feed.extensions?.["behavior"]?.select_mode) === "single";
165
+
166
+ if (isSingleSelect) {
167
+ return makeSingleSelect(feed, key, decoratedFeed);
168
+ } else {
169
+ return makeMultiSelect(feed, key, decoratedFeed);
170
+ }
171
+ };
@@ -0,0 +1,11 @@
1
+ import { useMemo } from "react";
2
+ import { ScreenStateResolver } from "../appUtils/contextKeysManager/contextResolver";
3
+ import { useScreenStateStore } from "../reactHooks/navigation/useScreenStateStore";
4
+
5
+ export const useScreenResolvers = () => {
6
+ const screenStateStore = useScreenStateStore();
7
+
8
+ return useMemo(() => {
9
+ return { screen: new ScreenStateResolver(screenStateStore) };
10
+ }, [screenStateStore]);
11
+ };
@@ -4,9 +4,12 @@ import {
4
4
  ANALYTICS_COMPONENT_EVENTS,
5
5
  ANALYTICS_CORE_EVENTS,
6
6
  ANALYTICS_ENTRY_EVENTS,
7
+ ANALYTICS_PREFERENCES_EVENTS,
7
8
  DOWNLOADS_EVENTS,
8
9
  } from "../events";
9
10
  import { isEmptyOrNil } from "../../cellUtils";
11
+ import { get } from "lodash";
12
+ import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-utils/storage/StorageMultiSelectProvider";
10
13
 
11
14
  export enum OfflineItemState {
12
15
  notExist = "NOT_EXISTS",
@@ -102,6 +105,84 @@ export function eventForComponent(
102
105
  return analyticsProps;
103
106
  }
104
107
 
108
+ /**
109
+ * Checks if an item is currently selected in localStorage based on its actions
110
+ * @param item - The item to check
111
+ * @returns boolean indicating if the item is currently selected
112
+ */
113
+ function isItemPreviouslySelected(item: any): boolean {
114
+ const actions = item?.extensions?.tap_actions?.actions;
115
+
116
+ if (!actions) {
117
+ return false;
118
+ }
119
+
120
+ const localStorageAction = actions.find(
121
+ (action) => action?.type === "localStorageToggleFlag"
122
+ );
123
+
124
+ if (!localStorageAction?.options?.key) {
125
+ return false;
126
+ }
127
+
128
+ const keyNamespace = localStorageAction.options.key;
129
+
130
+ const tag = localStorageAction.options?.selector
131
+ ? get(item, localStorageAction.options.selector)
132
+ : (item.extensions?.tag ?? item.id);
133
+
134
+ if (!tag) {
135
+ return false;
136
+ }
137
+
138
+ try {
139
+ const multiSelectProvider =
140
+ StorageMultiSelectProvider.getProvider(keyNamespace);
141
+
142
+ const selectedItems = multiSelectProvider.getSelectedItems();
143
+
144
+ return selectedItems.includes(tag);
145
+ } catch (error) {
146
+ return false;
147
+ }
148
+ }
149
+
150
+ export function getLocalStorageSetPayload(extraProps) {
151
+ const { item } = extraProps;
152
+
153
+ const hasLocalStorageSetAction = item?.extensions?.tap_actions?.actions?.some(
154
+ (action) => action?.type === "localStorageSet"
155
+ );
156
+
157
+ if (!hasLocalStorageSetAction) {
158
+ return null;
159
+ }
160
+
161
+ return {
162
+ [ANALYTICS_PREFERENCES_EVENTS.ITEM_SELECTED_STATUS]: true,
163
+ };
164
+ }
165
+
166
+ export function getLocalStorageToggleFlagPayload(extraProps) {
167
+ const { item } = extraProps;
168
+
169
+ const hasLocalStorageToggleAction =
170
+ item?.extensions?.tap_actions?.actions?.some(
171
+ (action) => action?.type === "localStorageToggleFlag"
172
+ );
173
+
174
+ if (!hasLocalStorageToggleAction) {
175
+ return null;
176
+ }
177
+
178
+ const previouslySelected = isItemPreviouslySelected(item);
179
+
180
+ return {
181
+ [ANALYTICS_PREFERENCES_EVENTS.ITEM_SELECTED_STATUS]: !previouslySelected,
182
+ [ANALYTICS_PREFERENCES_EVENTS.PREVIOUS_SELECTED_STATE]: previouslySelected,
183
+ };
184
+ }
185
+
105
186
  export function playEventForType(item) {
106
187
  const itemType = item?.type && item.type?.value;
107
188
 
@@ -1,13 +1,13 @@
1
1
  import { log_error, log_debug } from "../logger";
2
-
3
- import { ANALYTICS_CORE_EVENTS } from "../events";
4
-
2
+ import { ANALYTICS_CORE_EVENTS, ACTION_TYPE } from "../events";
5
3
  import { postAnalyticEvent } from "../manager";
6
4
  import {
7
5
  replaceAnalyticsPropsNils,
8
6
  eventForEntry,
9
7
  eventForComponent,
10
8
  extensionsEvents,
9
+ getLocalStorageSetPayload,
10
+ getLocalStorageToggleFlagPayload,
11
11
  } from "./helper";
12
12
 
13
13
  declare type AnalyticsDefaultHelperProperties = {
@@ -26,7 +26,16 @@ export const sendOnClickEvent = ({
26
26
  const castedExtraProps: ExtraProps = extraProps;
27
27
  const componentData = component || extraProps.component;
28
28
  const data = zappPipesData || extraProps.zappPipesData;
29
- const eventName = ANALYTICS_CORE_EVENTS.TAP_CELL;
29
+
30
+ const actionCellPayload =
31
+ extraProps?.item?.type?.value === ACTION_TYPE
32
+ ? getLocalStorageSetPayload(extraProps) ||
33
+ getLocalStorageToggleFlagPayload(extraProps)
34
+ : null;
35
+
36
+ const eventName = actionCellPayload
37
+ ? ANALYTICS_CORE_EVENTS.TAP_SELECTABLE_CELL
38
+ : ANALYTICS_CORE_EVENTS.TAP_CELL;
30
39
 
31
40
  if (!analyticsScreenData) {
32
41
  log_error(
@@ -44,6 +53,7 @@ export const sendOnClickEvent = ({
44
53
  ...replaceAnalyticsPropsNils({
45
54
  ...analyticsScreenData,
46
55
  }),
56
+ ...actionCellPayload,
47
57
  };
48
58
 
49
59
  if (analyticsCustomProperties) {
@@ -3,8 +3,22 @@ import { ANALYTICS_CORE_EVENTS } from "../events";
3
3
 
4
4
  jest.mock("@applicaster/zapp-react-native-utils/reactUtils", () => ({
5
5
  isWeb: jest.fn(),
6
+ platformSelect: jest.fn(
7
+ (options) => options.android || options.ios || options.web
8
+ ),
6
9
  }));
7
10
 
11
+ jest.mock(
12
+ "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider",
13
+ () => ({
14
+ StorageMultiSelectProvider: {
15
+ getProvider: jest.fn(() => ({
16
+ getSelectedItems: jest.fn(() => []),
17
+ })),
18
+ },
19
+ })
20
+ );
21
+
8
22
  const mock_postAnalyticEvent = jest.fn();
9
23
  const mock_startAnalyticsTimedEvent = jest.fn();
10
24
  const mock_endAnalyticsTimedEvent = jest.fn();
@@ -17,8 +17,11 @@ export const SCREEN_VIEW_EVENTS = {
17
17
  TIME_ON_SCREEN: "time_on_screen",
18
18
  };
19
19
 
20
+ export const ACTION_TYPE = "action";
21
+
20
22
  export const TAPPING_EVENTS = {
21
23
  TAP_CELL: "tap_cell",
24
+ TAP_SELECTABLE_CELL: "tap_selectable_cell",
22
25
  TAP_MENU: "tap_menu",
23
26
  TAP_NAVBAR_BACK_BUTTON: "tap_navbar_back_button",
24
27
  };
@@ -99,6 +102,11 @@ export const ANALYTICS_COMPONENT_EVENTS = {
99
102
  COMPONENT_SOURCE: "component_source",
100
103
  };
101
104
 
105
+ export const ANALYTICS_PREFERENCES_EVENTS = {
106
+ ITEM_SELECTED_STATUS: "item_selected_status",
107
+ PREVIOUS_SELECTED_STATE: "previous_selected_state",
108
+ };
109
+
102
110
  // ---------------- EVENTS ---------------------
103
111
  export const AD_EVENT = {
104
112
  ad_break_start: "player_ad_break_start",
@@ -1,8 +1,9 @@
1
1
  import { BehaviorSubject } from "rxjs";
2
2
  import { accessibilityManagerLogger as logger } from "./logger";
3
- import { TTSManager } from "../platform/platformUtils";
3
+ import { TTSManager } from "../platform";
4
4
  import { BUTTON_ACCESSIBILITY_KEYS } from "./const";
5
5
  import { AccessibilityRole } from "react-native";
6
+ import { toString } from "../../utils";
6
7
 
7
8
  export class AccessibilityManager {
8
9
  private static _instance: AccessibilityManager | null = null;
@@ -135,7 +136,9 @@ export class AccessibilityManager {
135
136
  });
136
137
  }
137
138
 
138
- public getButtonAccessibilityProps(buttonName: string): AccessibilityProps {
139
+ public getButtonAccessibilityProps(name: string): AccessibilityProps {
140
+ const buttonName = toString(name);
141
+
139
142
  const buttonConfig = BUTTON_ACCESSIBILITY_KEYS[buttonName];
140
143
 
141
144
  if (!buttonConfig) {
@@ -1,6 +1,5 @@
1
1
  import { ContextKeysManager } from "./index";
2
2
  import * as R from "ramda";
3
- import { screenStates } from "@applicaster/zapp-react-native-bridge/ZappStorage/ScreenSingleValueProvider";
4
3
 
5
4
  export interface IResolver {
6
5
  resolve: (string) => Promise<string | number | object>;
@@ -26,10 +25,10 @@ export class EntryResolver implements IResolver {
26
25
  // TODO: Move to proper place
27
26
 
28
27
  export class ScreenStateResolver implements IResolver {
29
- constructor(private route: string) {}
28
+ constructor(private screenStateStore: ScreenStateStore) {}
30
29
 
31
30
  async resolve(key: string) {
32
- const screenState = screenStates[this.route];
31
+ const screenState = this.screenStateStore.getState().data;
33
32
 
34
33
  return screenState?.[key];
35
34
  }
@@ -18,13 +18,6 @@ export const { log_verbose, log_debug, log_info, log_error } = createLogger({
18
18
  parent: utilsLogger,
19
19
  });
20
20
 
21
- type ActionChapter = {
22
- type: string;
23
- options?: {
24
- title: string;
25
- };
26
- };
27
-
28
21
  type ChapterMarkerOriginal = {
29
22
  id: string;
30
23
  title: string;
@@ -33,14 +26,6 @@ type ChapterMarkerOriginal = {
33
26
  actions: ActionChapter[];
34
27
  };
35
28
 
36
- export type ChapterMarkerEvent = {
37
- id: string;
38
- title: string;
39
- start_time: number;
40
- end_time: number;
41
- actions: ActionChapter[];
42
- };
43
-
44
29
  export type TitleSummaryEvent = {
45
30
  title: string | number;
46
31
  summary: string | number;
@@ -1,4 +1,3 @@
1
- import { ChapterMarkerEvent } from "./OverlayObserver/OverlaysObserver";
2
1
  import { usePlayer } from "./usePlayer";
3
2
  import * as React from "react";
4
3
 
@@ -5,6 +5,9 @@ import { playerManager } from "./index";
5
5
  import { useValidatePlayerConfig } from "../../playerUtils/useValidatePlayerConfig";
6
6
  import { PlayerRole } from "./conts";
7
7
  import { isAppleTV } from "@applicaster/zapp-react-native-ui-components/Helpers/Platform";
8
+ import { TVSeekController } from "../../reactHooks/player/TVSeekControlller/TVSeekController";
9
+ import { KeyInputHandler } from "../keyInputHandler/KeyInputHandler";
10
+ import { isTV } from "../../reactUtils";
8
11
 
9
12
  // TODO: Rename to ControllerType
10
13
  export const usePlayerControllerSetup = ({
@@ -76,5 +79,18 @@ export const usePlayerControllerSetup = ({
76
79
  };
77
80
  }, [playerId, playerController]);
78
81
 
82
+ useEffect(() => {
83
+ if (!isTV()) {
84
+ return;
85
+ }
86
+
87
+ if (playerController) {
88
+ const seekController = new TVSeekController(playerController);
89
+ playerController.seekController = seekController;
90
+
91
+ return KeyInputHandler.getInstance().addListener(seekController);
92
+ }
93
+ }, [playerController]);
94
+
79
95
  return playerController;
80
96
  };