@applicaster/zapp-react-native-utils 12.0.0-alpha.6631650374 → 12.0.0-alpha.7101461483

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.
@@ -11,11 +11,9 @@ import * as QuickBrickManager from "@applicaster/zapp-react-native-bridge/QuickB
11
11
  import { showConfirmationDialog } from "../alertUtils";
12
12
  import { createCloudEvent, sendCloudEvent } from "../cloudEventsUtils";
13
13
  import { createLogger } from "../logger";
14
- import {
15
- StorageMultiSelectProvider
16
- } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
14
+ import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
17
15
 
18
- const { log_error, log_debug, log_info } = createLogger({
16
+ const { log_error, log_info } = createLogger({
19
17
  subsystem: "ActionExecutorContext",
20
18
  category: "General",
21
19
  });
@@ -110,11 +108,17 @@ const prepareDefaultActions = (actionExecutor) => {
110
108
  const tag = entry?.extensions?.tag;
111
109
 
112
110
  if (keyNamespace && tag) {
113
- const multiSelectProvider = StorageMultiSelectProvider.getProvider(keyNamespace);
111
+ const multiSelectProvider =
112
+ StorageMultiSelectProvider.getProvider(keyNamespace);
114
113
 
115
114
  const selectedItems = await multiSelectProvider.getSelectedAsync();
116
115
  const isTagInSelectedItems = selectedItems.includes(tag);
117
- log_info(`handleAction: localStorageToggleFlag event will ${isTagInSelectedItems ? "remove" : "add"} tag: ${tag} for keyNamespace: ${keyNamespace}, current selectedItems: ${selectedItems}`);
116
+
117
+ log_info(
118
+ `handleAction: localStorageToggleFlag event will ${
119
+ isTagInSelectedItems ? "remove" : "add"
120
+ } tag: ${tag} for keyNamespace: ${keyNamespace}, current selectedItems: ${selectedItems}`
121
+ );
118
122
 
119
123
  if (selectedItems.includes(tag)) {
120
124
  await multiSelectProvider.removeItem(tag);
@@ -122,13 +126,17 @@ const prepareDefaultActions = (actionExecutor) => {
122
126
  await multiSelectProvider.addItem(tag);
123
127
  }
124
128
  } else {
125
- log_error("handleAction: localStorageToggleFlag event missing keyNamespace or tag", { keyNamespace, tag });
129
+ log_error(
130
+ "handleAction: localStorageToggleFlag event missing keyNamespace or tag",
131
+ { keyNamespace, tag }
132
+ );
126
133
 
127
134
  return ActionResult.Error;
128
135
  }
129
136
 
130
137
  return ActionResult.Success;
131
- });
138
+ }
139
+ );
132
140
  };
133
141
 
134
142
  export const ActionExecutorContext =
@@ -278,6 +278,10 @@ export class Player {
278
278
  return this.playerState.isBuffering;
279
279
  };
280
280
 
281
+ isReadyToPlay = (): boolean => {
282
+ return this.playerState.isReadyToPlay;
283
+ };
284
+
281
285
  // Methods to call actions on the player
282
286
  seekTo = (_position: number) => {};
283
287
 
@@ -652,6 +656,10 @@ export class Player {
652
656
  _selected?: QuickBrickPlayer.TextTrack | QuickBrickPlayer.AudioTrack
653
657
  ) => {};
654
658
 
659
+ setPlaybackRate = (_rate) => {};
660
+ startSleepTimer = (_timestamp) => {};
661
+ cancelSleepTimer = () => {};
662
+
655
663
  getPluginConfiguration = () => null;
656
664
  appStateChange = (_appState, _previousAppState) => {};
657
665
 
@@ -1,17 +1,29 @@
1
1
  import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
2
2
  import { findPluginByIdentifier } from "@applicaster/zapp-react-native-utils/pluginUtils";
3
3
  import { Player } from "./player";
4
+ import { PlayerRole } from "./conts";
4
5
 
5
6
  type PlayerFactoryItem = {
6
7
  Component: any;
7
8
  controller: Player;
8
9
  };
9
10
 
11
+ type PlayerFactoryProps = {
12
+ player: any,
13
+ playerId: string,
14
+ autoplay: boolean,
15
+ entry: ZappEntry,
16
+ muted: boolean,
17
+ playerPluginId: string,
18
+ screenConfig: Record<string, any>,
19
+ playerRole: PlayerRole,
20
+ }
21
+
10
22
  interface PlayerConstructor {
11
23
  new (params: any): Player;
12
24
  }
13
25
 
14
- export const playerFactory = (config: any): PlayerFactoryItem | null => {
26
+ export const playerFactory = (config: PlayerFactoryProps): PlayerFactoryItem | null => {
15
27
  const IDENTIFIER = config?.playerPluginId;
16
28
 
17
29
  if (!IDENTIFIER) {
@@ -41,6 +41,9 @@ const PlayerModuleFuncNames = {
41
41
  rewind: "rewind",
42
42
  play: "play",
43
43
  pause: "pause",
44
+ startSleepTimer: "startSleepTimer",
45
+ cancelSleepTimer: "cancelSleepTimer",
46
+ getSleepTimerEnd: "getSleepTimerEnd",
44
47
  };
45
48
 
46
49
  export class PlayerNative extends Player {
@@ -172,6 +175,25 @@ export class PlayerNative extends Player {
172
175
  }
173
176
  };
174
177
 
178
+ startSleepTimer = (sleepTimestamp: number) => {
179
+ if (
180
+ !this.invokeNativeFunction(
181
+ PlayerModuleFuncNames.startSleepTimer,
182
+ sleepTimestamp
183
+ )
184
+ ) {
185
+ this.currentPlayerComponent()?.["startSleepTimer"](sleepTimestamp);
186
+ }
187
+ };
188
+
189
+ cancelSleepTimer = () => {
190
+ if (!this.invokeNativeFunction(PlayerModuleFuncNames.cancelSleepTimer)) {
191
+ this.currentPlayerComponent()?.[
192
+ PlayerModuleFuncNames.cancelSleepTimer
193
+ ]?.();
194
+ }
195
+ };
196
+
175
197
  disableBufferAnimation = (): boolean => false;
176
198
 
177
199
  setLanguage = (
@@ -180,6 +202,10 @@ export class PlayerNative extends Player {
180
202
  this.currentPlayerComponent()?.["setLanguage"]?.(selected);
181
203
  };
182
204
 
205
+ setPlaybackRate = (rate: number) => {
206
+ this.currentPlayerComponent()?.["setPlaybackRate"]?.(rate);
207
+ };
208
+
183
209
  getPluginConfiguration = () => {
184
210
  return (this.currentPlayerComponent() as any)?.props?.pluginConfiguration;
185
211
  };
@@ -9,6 +9,7 @@ type PlayerState = {
9
9
  isLive: boolean;
10
10
  isPaused: boolean;
11
11
  isBuffering: boolean;
12
+ isReadyToPlay: boolean;
12
13
  };
13
14
 
14
15
  export const usePlayerState = (
@@ -20,12 +21,14 @@ export const usePlayerState = (
20
21
  const [seekableDuration, setSeekableDuration] = React.useState<number>(null);
21
22
  const [isLive, setIsLive] = React.useState<boolean>(null);
22
23
  const [isBuffering, setIsBuffering] = React.useState<boolean>(false);
24
+ const [isReadyToPlay, setIsReadyToPlay] = React.useState<boolean>(false);
23
25
  const [isPaused, setIsPaused] = React.useState<boolean>(false);
24
26
 
25
27
  const player: Player = usePlayer(playerId);
26
28
 
27
29
  const onPlayerChangeState = React.useCallback(() => {
28
30
  setIsBuffering(player.isBuffering());
31
+ setIsReadyToPlay(player.isReadyToPlay);
29
32
  setCurrentTime(player.getContentPosition());
30
33
  setDuration(player.getDuration());
31
34
  setSeekableDuration(player.getSeekableDuration());
@@ -60,7 +63,16 @@ export const usePlayerState = (
60
63
  isLive,
61
64
  isPaused,
62
65
  isBuffering,
66
+ isReadyToPlay,
63
67
  }),
64
- [currentTime, duration, seekableDuration, isLive, isPaused, isBuffering]
68
+ [
69
+ currentTime,
70
+ duration,
71
+ seekableDuration,
72
+ isLive,
73
+ isPaused,
74
+ isBuffering,
75
+ isReadyToPlay,
76
+ ]
65
77
  );
66
78
  };
@@ -343,6 +343,19 @@ export const ifElseFocused = R.curry(
343
343
  state === "focused" ? focusedValue : defaultValue
344
344
  );
345
345
 
346
+ export const ifElseSelected = R.curry(
347
+ (state: string, selectedValue, defaultValue) => {
348
+ switch (state) {
349
+ case "selected":
350
+ return selectedValue;
351
+ case "focused_selected":
352
+ return selectedValue;
353
+ default:
354
+ return defaultValue;
355
+ }
356
+ }
357
+ );
358
+
346
359
  /**
347
360
  * Map textAlign values to their corresponding alignSelf values
348
361
  * This is so that we could use the same field for both properties
@@ -0,0 +1,57 @@
1
+ import { create } from "zustand";
2
+
3
+ interface ModalState {
4
+ visible: boolean;
5
+ screen: any;
6
+ options: Record<string, unknown>;
7
+ props: Record<string, unknown>;
8
+ }
9
+
10
+ interface ModalStore {
11
+ modalState: ModalState;
12
+ setModalState: (newState: Partial<ModalState>) => void;
13
+ openModal: (
14
+ item: any,
15
+ options?: Record<string, unknown>,
16
+ props?: Record<string, unknown>
17
+ ) => void;
18
+ dismissModal: () => void;
19
+ }
20
+
21
+ const initialModalState: ModalState = {
22
+ visible: false,
23
+ screen: null,
24
+ options: {},
25
+ props: {},
26
+ };
27
+
28
+ export const useModalStore = create<ModalStore>((set) => ({
29
+ modalState: initialModalState,
30
+ setModalState: (newState) =>
31
+ set((state) => ({
32
+ modalState: { ...state.modalState, ...newState },
33
+ })),
34
+ openModal: ({
35
+ item,
36
+ options = {},
37
+ props = { screenData: {} },
38
+ }: OpenModalArg) =>
39
+ set({
40
+ modalState: {
41
+ visible: true,
42
+ screen: item,
43
+ options: {
44
+ animated: true,
45
+ animationType: "slide",
46
+ onShow: () => {},
47
+ presentationStyle: "overFullScreen",
48
+ transparent: true,
49
+ ...options,
50
+ onDismiss: () => set({ modalState: initialModalState }),
51
+ onRequestClose: () => set({ modalState: initialModalState }),
52
+ },
53
+ props,
54
+ },
55
+ }),
56
+ dismissModal: () => set(() => ({ modalState: initialModalState })),
57
+ }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-utils",
3
- "version": "12.0.0-alpha.6631650374",
3
+ "version": "12.0.0-alpha.7101461483",
4
4
  "description": "Applicaster Zapp React Native utilities package",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "homepage": "https://github.com/applicaster/quickbrick#readme",
30
30
  "dependencies": {
31
- "@applicaster/applicaster-types": "12.0.0-alpha.6631650374",
31
+ "@applicaster/applicaster-types": "12.0.0-alpha.7101461483",
32
32
  "buffer": "^5.2.1",
33
33
  "camelize": "^1.0.0",
34
34
  "create-react-context": "^0.2.3",
@@ -68,11 +68,13 @@ export function findComponentByType({
68
68
  * Returns the plugin for a given identifier, if found
69
69
  * @param identifier of the plugin to look for
70
70
  * @param plugins map of the available plugins
71
+ * @param doNotWarn if set to true, will not log a warning if plugin is not found
71
72
  * @return whole plugin if found, undefined otherwise
72
73
  */
73
74
  export function findPluginByIdentifier(
74
75
  identifier: string,
75
- plugins: (QuickBrickPlugin | ZappPlugin | Plugin)[]
76
+ plugins: (QuickBrickPlugin | ZappPlugin | Plugin)[],
77
+ doNotWarn: boolean = false
76
78
  ): (QuickBrickPlugin | ZappPlugin | Plugin) | undefined {
77
79
  if (!identifier) {
78
80
  return undefined;
@@ -84,10 +86,12 @@ export function findPluginByIdentifier(
84
86
  )(plugins);
85
87
 
86
88
  if (!plugin && identifier !== "river" && identifier !== "hooks") {
87
- pluginUtilsLogger.warning({
88
- message: `Could not find plugin for identifier ${identifier}`,
89
- data: { identifier },
90
- });
89
+ if (!doNotWarn) {
90
+ pluginUtilsLogger.warning({
91
+ message: `Could not find plugin for identifier ${identifier}`,
92
+ data: { identifier },
93
+ });
94
+ }
91
95
  }
92
96
 
93
97
  return plugin;
@@ -1,6 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { cleanup, renderHook } from "@testing-library/react-hooks";
3
3
  import { CellTapContext } from "@applicaster/zapp-react-native-ui-components/Contexts/CellTapContext";
4
+ import { waitFor } from "@testing-library/react-native";
4
5
 
5
6
  const navigator = {
6
7
  getPathname: () => "pathnameMock",
@@ -64,13 +65,16 @@ describe("useCellClick", () => {
64
65
  cleanup();
65
66
  });
66
67
 
67
- it("runs onCellTap", () => {
68
+ it("runs onCellTap", async () => {
68
69
  const { result } = renderHook(() => useCellClick(mockProps), { wrapper });
69
70
  const useCellClickHook = result.current;
70
71
 
71
72
  useCellClickHook();
72
73
 
73
- expect(onCellTap).toHaveBeenCalled();
74
+ await waitFor(() => {
75
+ expect(onCellTap).toHaveBeenCalled();
76
+ });
77
+
74
78
  cleanup();
75
79
  });
76
80
  });
@@ -53,7 +53,7 @@ export const useCellClick = (props: Props) => {
53
53
  );
54
54
 
55
55
  const onPress = React.useCallback(
56
- (_item?: ZappEntry | any, _index?: number) => {
56
+ async (_item?: ZappEntry | any, _index?: number) => {
57
57
  // Making sure we are not getting GestureResponderEvent in here.
58
58
  const isZappEntry = _item?.id && _item?.type;
59
59
  const selectedItem = isZappEntry ? _item : props.item;
@@ -70,7 +70,7 @@ export const useCellClick = (props: Props) => {
70
70
  logOnPress(selectedItem, pathname, component, onCellTap);
71
71
 
72
72
  if (selectedItem) {
73
- actionExecutor?.handleEntryActions(selectedItem);
73
+ await actionExecutor?.handleEntryActions(selectedItem);
74
74
  }
75
75
 
76
76
  if (selectedItem?.type?.value === "action") {
@@ -51,7 +51,7 @@ const modalItem = {
51
51
 
52
52
  const mainStackNavigator = {
53
53
  getStackForPathname: jest.fn().mockReturnValue(homeStack),
54
- modalState: {},
54
+ getModalState: () => {},
55
55
  videoModalState: {},
56
56
  };
57
57
 
@@ -62,9 +62,9 @@ const videoModalNavigator = {
62
62
 
63
63
  const modalNavigator = {
64
64
  ...mainStackNavigator,
65
- modalState: {
66
- screen: modalItem,
67
- },
65
+ getModalState: () => ({
66
+ screen: modalItem || {},
67
+ }),
68
68
  };
69
69
 
70
70
  const hookModalNavigator = {
@@ -219,7 +219,7 @@ describe("useRoute", () => {
219
219
  });
220
220
 
221
221
  expect(result.current.screenData.id).toEqual(
222
- modalNavigator.modalState.screen.id
222
+ modalNavigator.getModalState().screen.id
223
223
  );
224
224
  });
225
225
  });
@@ -177,9 +177,7 @@ export const useNavigationPluginData = (): ZappNavigation | undefined => {
177
177
  ? (useRouteScreenData.targetScreen as ZappRiver).navigations
178
178
  : (useRouteScreenData as ZappRiver).navigations;
179
179
 
180
- const navigationMenu = navigations?.find((nav) => nav.category === "menu");
181
-
182
- return navigationMenu;
180
+ return navigations?.find((nav) => nav.category === "menu");
183
181
  };
184
182
 
185
183
  export const useNavigationType = (): MenuTypes => {
@@ -255,10 +253,10 @@ export const useRoute = () => {
255
253
  ]);
256
254
 
257
255
  const currentStack = navigator.getStackForPathname(pathname);
258
- const modalState = navigator.modalState;
256
+ const modalState: ModalState = navigator.getModalState?.();
259
257
  const hookModalState = useZappHooksModalState();
260
258
 
261
- const modalScreenData = modalState.screen;
259
+ const modalScreenData = modalState?.screen || null;
262
260
 
263
261
  const hookModalScreenData = hookModalState.state.screenData?.payload;
264
262