@applicaster/zapp-react-native-utils 14.0.0-alpha.3126393935 → 14.0.0-alpha.3140225604

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.
@@ -16,6 +16,7 @@ import { QUICK_BRICK_EVENTS } from "@applicaster/zapp-react-native-bridge/QuickB
16
16
  import { showConfirmationDialog } from "../alertUtils";
17
17
  import { createCloudEvent, sendCloudEvent } from "../cloudEventsUtils";
18
18
  import { createLogger } from "../logger";
19
+ import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
19
20
  import { ACTIVE_LAYOUT_ID_STORAGE_KEY } from "@applicaster/quick-brick-core/App/remoteContextReloader/consts";
20
21
  import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
21
22
  import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
@@ -24,19 +25,15 @@ import {
24
25
  resolveObjectValues,
25
26
  } from "../appUtils/contextKeysManager/contextResolver";
26
27
  import { useNavigation } from "../reactHooks";
28
+ import { get } from "../utils";
27
29
 
28
30
  import {
29
31
  useContentTypes,
30
32
  usePickFromState,
31
33
  } from "@applicaster/zapp-react-native-redux/hooks";
32
- import { useSubscriberFor } from "../reactHooks/useSubscriberFor";
34
+ import { TOGGLE_FLAG_MAX_ITEMS_REACHED_EVENT } from "./consts";
35
+ import { postEvent, useSubscriberFor } from "../reactHooks/useSubscriberFor";
33
36
  import { APP_EVENTS } from "../appUtils/events";
34
- import {
35
- localStorageToggleFlag,
36
- sessionStorageToggleFlag,
37
- } from "./StorageActions";
38
-
39
- import { screenSetVariable, screenToggleFlag } from "./ScreenActions";
40
37
 
41
38
  export const { log_error, log_info, log_debug } = createLogger({
42
39
  subsystem: "ActionExecutorContext",
@@ -85,6 +82,19 @@ function findParentComponent(
85
82
  return null;
86
83
  }
87
84
 
85
+ // send all data just in case (like for message string formatting)
86
+ // Type is not exported for now
87
+ type MaxTagsReachedEvent = {
88
+ selectedItems: string[];
89
+ maxItems: number;
90
+ tag: string;
91
+ keyNamespace: string;
92
+ };
93
+
94
+ async function onMaxTagsReached(data: MaxTagsReachedEvent) {
95
+ postEvent(TOGGLE_FLAG_MAX_ITEMS_REACHED_EVENT, [data]);
96
+ }
97
+
88
98
  const prepareDefaultActions = (actionExecutor) => {
89
99
  actionExecutor.registerAction("localStorageSet", async (action) => {
90
100
  const namespaces = action.options.content;
@@ -168,15 +178,10 @@ const prepareDefaultActions = (actionExecutor) => {
168
178
 
169
179
  const entry = context?.entry || {};
170
180
  const entryResolver = new EntryResolver(entry);
171
- const screenData = context?.screenStateStore.getState().data || {};
172
- const screenResolver = new EntryResolver(screenData || {});
173
181
 
174
182
  const data =
175
183
  options?.data && options.inflateData
176
- ? await resolveObjectValues(options.data, {
177
- entry: entryResolver,
178
- screen: screenResolver,
179
- })
184
+ ? await resolveObjectValues(options.data, { entry: entryResolver })
180
185
  : options?.data || entry;
181
186
 
182
187
  const cloudEvent = await createCloudEvent({
@@ -210,63 +215,81 @@ const prepareDefaultActions = (actionExecutor) => {
210
215
  return ActionResult.Error;
211
216
  });
212
217
 
213
- actionExecutor.registerAction(
214
- "sessionStorageToggleFlag",
215
- async (
216
- action: ActionType,
217
- context?: Record<string, any>
218
- ): Promise<ActionResult> => {
219
- return await sessionStorageToggleFlag(context, action);
220
- }
221
- );
222
-
223
218
  actionExecutor.registerAction(
224
219
  "localStorageToggleFlag",
225
220
  async (
226
221
  action: ActionType,
227
222
  context?: Record<string, any>
228
223
  ): Promise<ActionResult> => {
229
- return await localStorageToggleFlag(context, action);
230
- }
231
- );
224
+ if (!context) {
225
+ log_error(
226
+ "handleAction: localStorageToggleFlag action missing context"
227
+ );
232
228
 
233
- actionExecutor.registerAction(
234
- "screenSetVariable",
235
- async (
236
- action: ActionType,
237
- context?: Record<string, any>
238
- ): Promise<ActionResult> => {
239
- const route = context?.screenRoute;
240
- const screenStateStore = context?.screenStateStore;
241
-
242
- await screenSetVariable(
243
- route,
244
- screenStateStore,
245
- { entry: context?.entry, options: action.options },
246
- action
247
- );
229
+ return ActionResult.Error;
230
+ }
248
231
 
249
- return Promise.resolve(ActionResult.Success);
250
- }
251
- );
232
+ const entry = context?.entry as ZappEntry;
252
233
 
253
- actionExecutor.registerAction(
254
- "screenToggleFlag",
255
- async (
256
- action: ActionType,
257
- context?: Record<string, any>
258
- ): Promise<ActionResult> => {
259
- const screenRoute = context?.screenRoute;
260
- const screenStateStore = context?.screenStateStore;
261
-
262
- await screenToggleFlag(
263
- screenRoute,
264
- screenStateStore,
265
- { entry: context?.entry, options: action.options },
266
- action
267
- );
234
+ if (!entry) {
235
+ log_error(
236
+ "handleAction: localStorageToggleFlag action missing entry. Entry is required to get the tag."
237
+ );
238
+
239
+ return ActionResult.Error;
240
+ }
241
+
242
+ const tag = action.options?.selector
243
+ ? get(entry, action.options.selector)
244
+ : (entry.extensions?.tag ?? entry.id);
245
+
246
+ const keyNamespace = action.options?.key;
247
+
248
+ if (keyNamespace && tag) {
249
+ const multiSelectProvider =
250
+ StorageMultiSelectProvider.getProvider(keyNamespace);
251
+
252
+ const selectedItems = await multiSelectProvider.getSelectedAsync();
253
+ const isTagInSelectedItems = selectedItems.includes(tag);
268
254
 
269
- return Promise.resolve(ActionResult.Success);
255
+ log_info(
256
+ `handleAction: localStorageToggleFlag event will ${
257
+ isTagInSelectedItems ? "remove" : "add"
258
+ } tag: ${tag} for keyNamespace: ${keyNamespace}, current selectedItems: ${selectedItems}`
259
+ );
260
+
261
+ if (selectedItems.includes(tag)) {
262
+ await multiSelectProvider.removeItem(tag);
263
+ } else {
264
+ const maxItems = action.options?.max_items;
265
+
266
+ if (maxItems && selectedItems.length >= maxItems) {
267
+ log_info(
268
+ `handleAction: localStorageToggleFlag event reached max items limit: ${maxItems}, cannot add tag: ${tag}`
269
+ );
270
+
271
+ await onMaxTagsReached({
272
+ selectedItems,
273
+ maxItems,
274
+ tag,
275
+ keyNamespace,
276
+ });
277
+
278
+ return ActionResult.Cancel;
279
+ }
280
+
281
+ await multiSelectProvider.addItem(tag);
282
+ }
283
+ } else {
284
+ log_error(
285
+ "handleAction: localStorageToggleFlag event missing keyNamespace or tag",
286
+ { keyNamespace, tag }
287
+ );
288
+
289
+ return ActionResult.Error;
290
+ }
291
+
292
+ return ActionResult.Success;
270
293
  }
271
294
  );
272
295
  };
@@ -9,7 +9,7 @@ import {
9
9
  } from "../events";
10
10
  import { isEmptyOrNil } from "../../cellUtils";
11
11
  import { get } from "lodash";
12
- import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-utils/storage/StorageMultiSelectProvider";
12
+ import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
13
13
 
14
14
  export enum OfflineItemState {
15
15
  notExist = "NOT_EXISTS",
@@ -143,12 +143,15 @@ export class AccessibilityManager {
143
143
 
144
144
  if (!buttonConfig) {
145
145
  return {
146
+ accessible: true,
146
147
  accessibilityLabel: buttonName,
147
148
  accessibilityHint: `Press button to perform action on ${buttonName}`,
148
149
  "aria-label": buttonName,
149
150
  "aria-description": `Press button to perform action on ${buttonName}`,
150
151
  accessibilityRole: "button" as AccessibilityRole,
151
152
  "aria-role": "button",
153
+ role: "button",
154
+ tabindex: 0,
152
155
  };
153
156
  }
154
157
 
@@ -162,23 +165,29 @@ export class AccessibilityManager {
162
165
  `Press button to perform action on ${buttonName}`;
163
166
 
164
167
  return {
168
+ accessible: true,
165
169
  accessibilityLabel: label,
166
170
  accessibilityHint: hint,
167
171
  "aria-label": label,
168
172
  "aria-description": hint,
169
173
  accessibilityRole: "button" as AccessibilityRole,
170
174
  "aria-role": "button",
175
+ role: "button",
176
+ tabindex: 0,
171
177
  };
172
178
  }
173
179
 
174
180
  public getInputAccessibilityProps(inputName: string): AccessibilityProps {
175
181
  return {
182
+ accessible: true,
176
183
  accessibilityLabel: inputName,
177
184
  accessibilityHint: `Enter text into ${inputName}`,
178
185
  "aria-label": inputName,
179
186
  "aria-description": `Enter text into ${inputName}`,
180
187
  accessibilityRole: "textbox" as AccessibilityRole,
181
188
  "aria-role": "textbox",
189
+ role: "textbox",
190
+ tabindex: 0,
182
191
  };
183
192
  }
184
193
 
@@ -1,11 +1,10 @@
1
1
  import { ContextKeysManager } from "./index";
2
2
  import * as R from "ramda";
3
3
 
4
- export interface IResolver {
4
+ interface IResolver {
5
5
  resolve: (string) => Promise<string | number | object>;
6
6
  }
7
7
 
8
- // TODO: Rename to ObjectKeyResolver or similar
9
8
  export class EntryResolver implements IResolver {
10
9
  entry: ZappEntry;
11
10
 
@@ -22,18 +21,6 @@ export class EntryResolver implements IResolver {
22
21
  }
23
22
  }
24
23
 
25
- // TODO: Move to proper place
26
-
27
- export class ScreenStateResolver implements IResolver {
28
- constructor(private screenStateStore: ScreenStateStore) {}
29
-
30
- async resolve(key: string) {
31
- const screenState = this.screenStateStore.getState().data;
32
-
33
- return screenState?.[key];
34
- }
35
- }
36
-
37
24
  export class ContextResolver implements IResolver {
38
25
  resolve = async (compositeKey: string) =>
39
26
  ContextKeysManager.instance.getKey(compositeKey);
@@ -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
  };