@applicaster/zapp-react-native-utils 12.0.0-alpha.4201443043 → 12.0.0-alpha.4271512420

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 (35) hide show
  1. package/analyticsUtils/AnalyticsEvents/index.ts +7 -0
  2. package/analyticsUtils/AnalyticsEvents/sendShareEvent.ts +21 -0
  3. package/analyticsUtils/events.ts +6 -0
  4. package/analyticsUtils/index.tsx +6 -0
  5. package/appUtils/accessibilityManager/const.ts +50 -0
  6. package/appUtils/accessibilityManager/hooks.ts +31 -0
  7. package/appUtils/accessibilityManager/index.ts +150 -0
  8. package/appUtils/accessibilityManager/logger.ts +5 -0
  9. package/appUtils/focusManager/index.ts +0 -1
  10. package/appUtils/focusManager/treeDataStructure/Utils/index.js +1 -1
  11. package/appUtils/index.js +2 -0
  12. package/appUtils/keyCodes/keys.web.js +8 -0
  13. package/appUtils/keyCodes/keysByPlatform.js +11 -1
  14. package/appUtils/platform/const.ts +25 -0
  15. package/appUtils/platform/index.ts +3 -0
  16. package/appUtils/platform/platformUtils.ts +185 -0
  17. package/appUtils/playerManager/conts.ts +1 -0
  18. package/appUtils/playerManager/index.ts +11 -5
  19. package/appUtils/playerManager/nativePlayerManager.ts +12 -0
  20. package/appUtils/playerManager/player.ts +9 -3
  21. package/appUtils/playerManager/playerNative.ts +5 -14
  22. package/appUtils/playerManager/usePlayerControllerSetup.tsx +1 -0
  23. package/booleanUtils/index.ts +4 -4
  24. package/cellUtils/index.ts +5 -5
  25. package/keyboardState/index.ts +0 -0
  26. package/navigationUtils/index.ts +48 -0
  27. package/package.json +2 -2
  28. package/pluginUtils/index.ts +9 -0
  29. package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +6 -2
  30. package/reactHooks/feed/useFeedRefresh.tsx +9 -7
  31. package/reactHooks/navigation/index.ts +13 -7
  32. package/reactUtils/index.ts +105 -0
  33. package/appUtils/focusManager/FocusableEvents.ts +0 -8
  34. package/appUtils/focusManager/treeDataStructure/Utils/__tests__/Utils_android.test.js +0 -1094
  35. package/appUtils/focusManager/treeDataStructure/Utils/index.android.js +0 -261
@@ -359,6 +359,13 @@ export class Player {
359
359
  });
360
360
  };
361
361
 
362
+ onVideoError = (error: Error) => {
363
+ this.invokeListenersUpdate({
364
+ callbackName: SharedPlayerCallBacksKeys.OnVideoError,
365
+ event: error,
366
+ });
367
+ };
368
+
362
369
  onError = (error: Error) => {
363
370
  this.invokeListenersUpdate({
364
371
  callbackName: SharedPlayerCallBacksKeys.OnError,
@@ -650,6 +657,7 @@ export class Player {
650
657
  onPlayerSeekComplete: this.onSeekComplete,
651
658
  onVideoEnd: this.onVideoEnd,
652
659
  onError: this.onError,
660
+ onVideoError: this.onVideoError,
653
661
  onLoad: this.onLoad,
654
662
  onPlayerPause: this.onPlayerPause,
655
663
  onPlayerResume: this.onPlayerResume,
@@ -684,9 +692,6 @@ export class Player {
684
692
  play = () => {};
685
693
  pause = () => {};
686
694
  disableBufferAnimation = (): boolean => true;
687
- setLanguage = (
688
- _selected?: QuickBrickPlayer.TextTrack | QuickBrickPlayer.AudioTrack
689
- ) => {};
690
695
 
691
696
  setPlaybackRate = (_rate) => {};
692
697
  startSleepTimer = (_timestamp) => {};
@@ -728,4 +733,5 @@ export class Player {
728
733
 
729
734
  public supportsNativeControls = (): boolean => false;
730
735
  public supportNativeCast = (): boolean => false;
736
+ public destroy = () => {};
731
737
  }
@@ -2,19 +2,10 @@ import * as R from "ramda";
2
2
  import { isEmptyOrNil } from "@applicaster/zapp-react-native-utils/cellUtils";
3
3
  import { createLogger, utilsLogger } from "../../logger";
4
4
  import { Player } from "./player";
5
- import { findNodeHandle, NativeModules } from "react-native";
6
- import { isApplePlatform } from "../../reactUtils";
5
+ import { findNodeHandle } from "react-native";
7
6
  import { PlayerRole } from "./conts";
8
7
  import { toBooleanWithDefaultFalse } from "../../booleanUtils";
9
-
10
- const RNPlayerManager = {
11
- QuickBrickPlayerPlugin: isApplePlatform()
12
- ? NativeModules.PlayerModule
13
- : NativeModules.QuickBrickDefaultPlayerModule,
14
- KalturaPlayerPlugin: isApplePlatform()
15
- ? NativeModules.KalturaPlayerModule
16
- : NativeModules.QBKalturaPlayerModule,
17
- };
8
+ import { RNPlayerManager } from "./nativePlayerManager";
18
9
 
19
10
  const logger = createLogger({
20
11
  category: "PlayerNativeController",
@@ -111,7 +102,7 @@ export class PlayerNative extends Player {
111
102
  return;
112
103
  }
113
104
 
114
- const newPosition = R.clamp(0, position, this.playerState.seekableDuration);
105
+ const newPosition = R.clamp(0, this.playerState.seekableDuration, position);
115
106
 
116
107
  if (
117
108
  !this.invokeNativeFunction(
@@ -197,10 +188,10 @@ export class PlayerNative extends Player {
197
188
 
198
189
  disableBufferAnimation = (): boolean => false;
199
190
 
200
- setLanguage = (
191
+ selectTrack = (
201
192
  selected: QuickBrickPlayer.TextTrack | QuickBrickPlayer.AudioTrack
202
193
  ) => {
203
- this.currentPlayerComponent()?.["setLanguage"]?.(selected);
194
+ this.currentPlayerComponent()?.["selectTrack"]?.(selected);
204
195
  };
205
196
 
206
197
  setPlaybackRate = (rate: number) => {
@@ -72,6 +72,7 @@ export const usePlayerControllerSetup = ({
72
72
 
73
73
  return () => {
74
74
  playerManager.unregisterPlayer(playerId);
75
+ playerController.destroy?.();
75
76
  };
76
77
  }, [playerId, playerController]);
77
78
 
@@ -1,7 +1,7 @@
1
- import * as R from "ramda";
1
+ import { is, toLower } from "ramda";
2
2
 
3
3
  export const toBoolean = (value: any): boolean | undefined => {
4
- if (R.is(Boolean, value)) {
4
+ if (is(Boolean, value)) {
5
5
  return value;
6
6
  }
7
7
 
@@ -17,12 +17,12 @@ export const toBooleanWithDefaultTrue = toBooleanWithDefault(true);
17
17
 
18
18
  export const toBooleanWithDefaultFalse = toBooleanWithDefault(false);
19
19
 
20
- export const isTrue = (value: any): boolean => {
20
+ export const isTrue = (value: unknown): boolean => {
21
21
  if (value === true) {
22
22
  return true;
23
23
  }
24
24
 
25
- if (R.is(String, value) && value.toLowerCase() === "true") {
25
+ if (is(String, value) && toLower(value) === "true") {
26
26
  return true;
27
27
  }
28
28
 
@@ -31,13 +31,12 @@ export const getKeyForLabel = (dataKey, customKey) => {
31
31
  * This method will return true if the argument passed to it is either empty or nil
32
32
  * The method prevents zero from being evaluated as falsey in an || condition
33
33
  * i.e. - NaN, null, {}, "", [], should all return true
34
- * @param {*} argument - argument passed to it could be any type
35
34
  * @returns {Boolean} returns true if empty or nil
35
+ * @param value
36
36
  */
37
- export const isEmptyOrNil = R.either(
38
- R.equals(NaN),
39
- R.either(R.isEmpty, R.isNil)
40
- );
37
+
38
+ export const isEmptyOrNil = (value: any): boolean =>
39
+ Number.isNaN(value) || value == null || R.isEmpty(value);
41
40
 
42
41
  /**
43
42
  * This method is used to find the appropriate label for any given text field.
@@ -320,6 +319,7 @@ export const ifElseFocusedSelected = (
320
319
  * @param {Object} stylesObj styles object with keys from zapp { button_icon_width: "10" }
321
320
  * @returns {*} value, returns any type that can be used as styles
322
321
  */
322
+
323
323
  export const getValue = (stylesObj) => (key) => {
324
324
  return R.propOr(null, key, stylesObj);
325
325
  };
File without changes
@@ -592,3 +592,51 @@ export function isMenuDisabled(
592
592
  export function routeIsPlayerScreen(currentRoute) {
593
593
  return currentRoute?.includes("/playable");
594
594
  }
595
+
596
+ export const getNavBarProps =
597
+ (currentRiver: ZappRiver, pathname: string, title: string) => () => {
598
+ const props = getNavigationPropsV2({
599
+ currentRiver,
600
+ title,
601
+ category: "nav_bar",
602
+ });
603
+
604
+ if (props) {
605
+ return {
606
+ ...props,
607
+ id: pathname,
608
+ pathname: pathname,
609
+ };
610
+ }
611
+
612
+ return null;
613
+ };
614
+
615
+ export const findMenuPlugin = (
616
+ navigations: ZappNavigation[],
617
+ plugins
618
+ ): QuickBrickPlugin => {
619
+ return resolveNavigationPlugin({
620
+ category: "menu",
621
+ navigations,
622
+ plugins,
623
+ }) as QuickBrickPlugin;
624
+ };
625
+
626
+ export const shouldNavBarDisplayMenu = (currentRiver: ZappRiver, plugins) =>
627
+ findMenuPlugin(currentRiver.navigations, plugins)?.identifier ===
628
+ "quick_brick_side_menu" ||
629
+ currentRiver?.navigations.findIndex(
630
+ (nav) => nav.category === "nav_bar" && nav.general?.override_menu_target
631
+ ) > -1;
632
+
633
+ export const getScreenId = (
634
+ screenData: LegacyNavigationScreenData,
635
+ fallbackRiver: ZappRiver
636
+ ) => {
637
+ return screenData?.targetScreen
638
+ ? screenData?.targetScreen?.id ?? fallbackRiver.id
639
+ : "screen_id" in screenData
640
+ ? screenData.screen_id
641
+ : fallbackRiver.id;
642
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-utils",
3
- "version": "12.0.0-alpha.4201443043",
3
+ "version": "12.0.0-alpha.4271512420",
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.4201443043",
31
+ "@applicaster/applicaster-types": "12.0.0-alpha.4271512420",
32
32
  "buffer": "^5.2.1",
33
33
  "camelize": "^1.0.0",
34
34
  "create-react-context": "^0.2.3",
@@ -245,3 +245,12 @@ export function generateManifest({ manifestConfig, version }) {
245
245
 
246
246
  return manifestConfig({ platform, version });
247
247
  }
248
+
249
+ const getPluginType = R.pathOr("unknown_plugin_type", [
250
+ "state",
251
+ "screen",
252
+ "plugin_type",
253
+ ]);
254
+
255
+ export const isPlayerPlugin = (routeState): boolean =>
256
+ getPluginType(routeState) === "player";
@@ -1,9 +1,13 @@
1
1
  import { renderHook } from "@testing-library/react-hooks";
2
2
 
3
- import { useFeedRefresh, feedRefreshLogger } from "../";
4
-
5
3
  jest.useFakeTimers();
6
4
 
5
+ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
6
+ useIsScreenActive: () => true,
7
+ }));
8
+
9
+ const { useFeedRefresh, feedRefreshLogger } = require("..");
10
+
7
11
  describe("useFeedRefresh", () => {
8
12
  const reloadData = jest.fn();
9
13
 
@@ -1,7 +1,8 @@
1
1
  import * as React from "react";
2
- import * as R from "ramda";
2
+ import { path, max } from "ramda";
3
3
  import { isTrue } from "@applicaster/zapp-react-native-utils/booleanUtils";
4
4
  import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
5
+ import { useIsScreenActive } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
5
6
 
6
7
  import { reactHooksLogger } from "../logger";
7
8
  import { ReloadDataFunction } from "./useFeedLoader";
@@ -18,9 +19,8 @@ const minimumRefreshingInterval = 5;
18
19
  const defaultRefreshInterval = 60;
19
20
 
20
21
  export const useFeedRefresh = ({ reloadData, component }: Props): void => {
21
- const enable_data_refreshing = R.path(
22
- ["rules", "enable_data_refreshing"],
23
- component
22
+ const isDataRefreshingEnabled = isTrue(
23
+ path(["rules", "enable_data_refreshing"], component)
24
24
  );
25
25
 
26
26
  const refreshing_interval = toNumberWithDefault(
@@ -29,10 +29,12 @@ export const useFeedRefresh = ({ reloadData, component }: Props): void => {
29
29
  );
30
30
 
31
31
  const refreshingIntervalInMilliseconds =
32
- R.max(refreshing_interval, minimumRefreshingInterval) * 1000;
32
+ max(refreshing_interval, minimumRefreshingInterval) * 1000;
33
+
34
+ const isScreenActive = useIsScreenActive();
33
35
 
34
36
  React.useEffect(() => {
35
- if (isTrue(enable_data_refreshing) && refreshing_interval) {
37
+ if (isDataRefreshingEnabled && refreshing_interval && isScreenActive) {
36
38
  if (refreshing_interval < minimumRefreshingInterval) {
37
39
  feedRefreshLogger.warning({
38
40
  message: `You set your feed refresh interval to ${refreshing_interval} when minimum value is ${minimumRefreshingInterval}seconds.Your feed will refresh after ${minimumRefreshingInterval}seconds.`,
@@ -59,5 +61,5 @@ export const useFeedRefresh = ({ reloadData, component }: Props): void => {
59
61
  clearInterval(refreshInterval);
60
62
  };
61
63
  }
62
- }, [reloadData]);
64
+ }, [reloadData, isScreenActive]);
63
65
  };
@@ -4,7 +4,6 @@
4
4
  import React, { useContext, useEffect, useMemo } from "react";
5
5
  import { BackHandler, InteractionManager, NativeModules } from "react-native";
6
6
  import { useSafeAreaInsets } from "react-native-safe-area-context";
7
- import { isEmpty } from "ramda";
8
7
 
9
8
  import {
10
9
  useContentTypes,
@@ -32,7 +31,7 @@ import { platformSelect } from "../../reactUtils";
32
31
  import { useConnectionInfo } from "../connection";
33
32
  import { getTargetScreenData } from "../screen/useTargetScreenData";
34
33
 
35
- import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
34
+ import { isTV, isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
36
35
  import { useNavbarState } from "../screen";
37
36
  import { useNavigation } from "./useNavigation";
38
37
  import { useModalStore } from "../../modalState";
@@ -79,6 +78,10 @@ export function isNavBarVisible(
79
78
  return false;
80
79
  }
81
80
 
81
+ if (screenData?.plugin_type === "login" && isTV()) {
82
+ return false;
83
+ }
84
+
82
85
  /* Match if screen is Hook */
83
86
  if (route.startsWith("/hooks/")) {
84
87
  const module = screenData?.module;
@@ -211,10 +214,7 @@ export const useRoute = (): {
211
214
  return { screenData: screenDataContext, pathname };
212
215
  }
213
216
 
214
- // Cover cases where screenContext is used before navigation is initialized
215
- const screenData = isEmpty(screenDataContext)
216
- ? navigator.screenData
217
- : screenDataContext;
217
+ const screenData = screenDataContext;
218
218
 
219
219
  return { screenData, pathname };
220
220
  };
@@ -466,7 +466,13 @@ export const useUniqueRouteSuffix = (): Return => {
466
466
  const suffix = `currentRoute:${currentRoute}_pathname:${pathname}`;
467
467
 
468
468
  const withUniqueRouteSuffix = React.useCallback((prefix: string) => {
469
- return `${prefix}___${suffix}`;
469
+ if (isWeb()) {
470
+ // we should use extended route prefix only on Web, where we have stack-navigator
471
+ return `${prefix}___${suffix}`;
472
+ }
473
+
474
+ // for other platforms use previous version
475
+ return prefix;
470
476
  }, []);
471
477
 
472
478
  return withUniqueRouteSuffix;
@@ -108,3 +108,108 @@ export const isAndroidPlatform = () => Platform.OS === "android";
108
108
  export const isTvOSPlatform = () => getPlatform() === "tvos";
109
109
 
110
110
  export const isAndroidTVPlatform = () => getPlatform() === "android_tv";
111
+
112
+ declare global {
113
+ interface Window {
114
+ VIZIO?: {
115
+ Chromevox: {
116
+ play: (text: string) => void;
117
+ };
118
+ exitApplication: () => void;
119
+ setClosedCaptionHandler: (
120
+ callback: (isCCEnabled: boolean) => void
121
+ ) => void;
122
+ };
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Platforms found in userAgent string, please note that simulators
128
+ * might not have the same agents that the devices have
129
+ */
130
+ export const PLATFORMS = {
131
+ webos: "Web0S",
132
+ tizen: "Tizen",
133
+ samsung: "SMART-TV",
134
+ mac: "Mac",
135
+ win: "Win",
136
+ linux: "Linux",
137
+ iphone: "iPhone",
138
+ android: "Android",
139
+ mobile: "Mobile",
140
+ vizio: "VIZIO",
141
+ smartcast: "SmartCast",
142
+ conjure: "Conjure",
143
+ };
144
+
145
+ /**
146
+ * Simple way of identifying if we have access to the tizen APIs
147
+ */
148
+ export const hasTizen = typeof window?.tizen !== "undefined";
149
+
150
+ /**
151
+ * Simple way of identifying if we have access to the webOS APIs
152
+ */
153
+ export const hasWebOS = typeof window?.webOS !== "undefined";
154
+
155
+ export const getUserAgent = () =>
156
+ window?.navigator?.userAgent || global?.navigator?.userAgent;
157
+
158
+ export const isLgPlatform = () => {
159
+ const userAgent = getUserAgent();
160
+
161
+ if (!userAgent) {
162
+ return false;
163
+ }
164
+
165
+ // Note: LG uses the number 0 in their userAgent, possibly because of Palm WebOS
166
+ return hasWebOS || userAgent.includes(PLATFORMS.webos);
167
+ };
168
+
169
+ export const isSamsungPlatform = () => {
170
+ const userAgent = getUserAgent();
171
+
172
+ if (!userAgent) {
173
+ return false;
174
+ }
175
+
176
+ return (
177
+ hasTizen ||
178
+ userAgent.includes(PLATFORMS.samsung) ||
179
+ userAgent.includes(PLATFORMS.tizen)
180
+ );
181
+ };
182
+
183
+ /**
184
+ * Checks if we are on the Vizio platform by using the userAgent string
185
+ *
186
+ * Use this method when you need to identify the platform on runtime
187
+ * before the VIZIO Companion Library has loaded
188
+ */
189
+ export const isVizioPlatform = () => {
190
+ const userAgent = getUserAgent();
191
+
192
+ if (!userAgent) {
193
+ return false;
194
+ }
195
+
196
+ const isVizioAgent =
197
+ userAgent.includes(PLATFORMS.vizio) ||
198
+ userAgent.includes(PLATFORMS.smartcast) ||
199
+ userAgent.includes(PLATFORMS.conjure);
200
+
201
+ return isVizioAgent;
202
+ };
203
+
204
+ /**
205
+ * Checks if we are on the Vizio platform by checking for the global VIZIO object
206
+ * and the VIZIO Companion Library. This method does not use the userAgent string,
207
+ * because it mainly checks whether we have access to apis, which may not be available yet
208
+ */
209
+ export const hasVizioAPIs = () => {
210
+ const hasAPIs =
211
+ typeof window.VIZIO !== "undefined" &&
212
+ window?.applicaster?.vizioLibraryDidLoad;
213
+
214
+ return hasAPIs;
215
+ };
@@ -1,8 +0,0 @@
1
- export const FOCUSABLE_EVENTS = {
2
- IS_REGISTERED: "isRegistered",
3
- WILL_RECEIVE_FOCUS: "willReceiveFocus",
4
- HAS_RECEIVED_FOCUS: "hasReceivedFocus",
5
- WILL_LOSE_FOCUS: "willLoseFocus",
6
- HAS_LOST_FOCUS: "hasLostFocus",
7
- WILL_UNREGISTER: "willUnregister",
8
- };