@applicaster/zapp-react-native-utils 12.0.0-alpha.5000126055 → 12.0.0-alpha.5001350756

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 (53) hide show
  1. package/analyticsUtils/AnalyticsEvents/index.ts +7 -0
  2. package/analyticsUtils/AnalyticsEvents/sendShareEvent.ts +21 -0
  3. package/analyticsUtils/{playerAnalyticsTracker.ts → analyticsTracker.ts} +10 -19
  4. package/analyticsUtils/events.ts +6 -0
  5. package/analyticsUtils/index.tsx +6 -0
  6. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +2 -3
  7. package/appUtils/focusManager/__tests__/focusManager.test.js +4 -24
  8. package/appUtils/focusManager/__tests__/index.test.ts +2 -3
  9. package/appUtils/focusManager/index.ts +76 -56
  10. package/appUtils/focusManager/treeDataStructure/Utils/index.js +75 -44
  11. package/appUtils/focusManager/utils/index.ts +100 -0
  12. package/appUtils/focusManagerAux/index.ts +76 -0
  13. package/appUtils/focusManagerAux/utils/index.ts +100 -0
  14. package/appUtils/keyCodes/keys.web.js +8 -0
  15. package/appUtils/keyCodes/keysByPlatform.js +11 -1
  16. package/appUtils/platform/const.ts +25 -0
  17. package/appUtils/platform/index.ts +3 -0
  18. package/appUtils/platform/platformUtils.ts +223 -0
  19. package/appUtils/playerManager/conts.ts +1 -0
  20. package/appUtils/playerManager/index.ts +38 -14
  21. package/appUtils/playerManager/nativePlayerManager.ts +12 -0
  22. package/appUtils/playerManager/player.ts +13 -16
  23. package/appUtils/playerManager/playerNative.ts +6 -16
  24. package/appUtils/playerManager/usePlayerControllerSetup.tsx +3 -17
  25. package/arrayUtils/__tests__/isFilledArray.test.ts +63 -0
  26. package/arrayUtils/index.ts +5 -0
  27. package/booleanUtils/index.ts +4 -4
  28. package/keyboardState/index.ts +0 -0
  29. package/numberUtils/__tests__/isLikeNumber.test.ts +18 -0
  30. package/numberUtils/index.ts +5 -18
  31. package/package.json +2 -2
  32. package/reactHooks/cell-click/__tests__/index.test.js +9 -5
  33. package/reactHooks/cell-click/index.ts +11 -11
  34. package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +30 -70
  35. package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +6 -2
  36. package/reactHooks/feed/useBuildPipesUrl.ts +7 -10
  37. package/reactHooks/feed/useFeedRefresh.tsx +9 -7
  38. package/reactHooks/navigation/index.ts +40 -7
  39. package/reactHooks/player/__tests__/useAutoSeek.test.tsx +1 -8
  40. package/reactHooks/player/useAutoSeek.tsx +8 -28
  41. package/reactHooks/player/useSeek.tsx +2 -4
  42. package/reactHooks/player/useTapSeek.tsx +7 -34
  43. package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +21 -23
  44. package/reactHooks/screen/index.ts +2 -0
  45. package/reactHooks/screen/useScreenBackgroundColor.ts +23 -0
  46. package/reactHooks/screen/useScreenContext.ts +1 -2
  47. package/reactUtils/index.ts +102 -0
  48. package/analyticsUtils/AnalyticPlayerListener.ts +0 -155
  49. package/analyticsUtils/PlayerAnalyticsManager.ts +0 -90
  50. package/appUtils/focusManager/FocusableEvents.ts +0 -8
  51. package/appUtils/focusManager/treeDataStructure/Utils/__tests__/Utils_android.test.js +0 -1094
  52. package/appUtils/focusManager/treeDataStructure/Utils/index.android.js +0 -261
  53. package/appUtils/playerManager/DelayedSeekPlayerWrapper.tsx +0 -180
@@ -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,
@@ -13,7 +12,11 @@ import {
13
12
  import { HooksManager } from "@applicaster/zapp-react-native-utils/appUtils/HooksManager";
14
13
 
15
14
  import { legacyScreenData } from "@applicaster/quick-brick-core/App/NavigationProvider/utils";
16
- import { LONG_KEY_PRESS_TIMEOUT } from "@applicaster/quick-brick-core/const";
15
+ import {
16
+ LONG_KEY_PRESS_TIMEOUT,
17
+ QUICK_BRICK_NAVBAR,
18
+ QUICK_BRICK_CONTENT,
19
+ } from "@applicaster/quick-brick-core/const";
17
20
  import { useZappHooksModalState } from "@applicaster/zapp-react-dom-ui-components/Components/ZappHooksModal/ZappHooksModal";
18
21
  import { ZappHookModalContext } from "@applicaster/zapp-react-native-ui-components/Contexts";
19
22
  import { PathnameContext } from "@applicaster/zapp-react-native-ui-components/Contexts/PathnameContext";
@@ -28,7 +31,7 @@ import { platformSelect } from "../../reactUtils";
28
31
  import { useConnectionInfo } from "../connection";
29
32
  import { getTargetScreenData } from "../screen/useTargetScreenData";
30
33
 
31
- import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
34
+ import { isTV, isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
32
35
  import { useNavbarState } from "../screen";
33
36
  import { useNavigation } from "./useNavigation";
34
37
  import { useModalStore } from "../../modalState";
@@ -207,10 +210,7 @@ export const useRoute = (): {
207
210
  return { screenData: screenDataContext, pathname };
208
211
  }
209
212
 
210
- // Cover cases where screenContext is used before navigation is initialized
211
- const screenData = isEmpty(screenDataContext)
212
- ? navigator.screenData
213
- : screenDataContext;
213
+ const screenData = screenDataContext;
214
214
 
215
215
  return { screenData, pathname };
216
216
  };
@@ -452,3 +452,36 @@ export const useIsScreenActive = () => {
452
452
 
453
453
  return pathname === currentRoute;
454
454
  };
455
+
456
+ type Return = (prefix: string) => string;
457
+
458
+ export const useUniqueRouteSuffix = (): Return => {
459
+ const pathname = usePathname();
460
+ const { currentRoute } = useNavigation();
461
+
462
+ const suffix = `currentRoute:${currentRoute}_pathname:${pathname}`;
463
+
464
+ const withUniqueRouteSuffix = React.useCallback((prefix: string) => {
465
+ if (isWeb()) {
466
+ // we should use extended route prefix only on Web, where we have stack-navigator
467
+ return `${prefix}___${suffix}`;
468
+ }
469
+
470
+ // for other platforms use previous version
471
+ return prefix;
472
+ }, []);
473
+
474
+ return withUniqueRouteSuffix;
475
+ };
476
+
477
+ export const useNavbarId = () => {
478
+ const withUniqueRouteSuffix = useUniqueRouteSuffix();
479
+
480
+ return withUniqueRouteSuffix(QUICK_BRICK_NAVBAR);
481
+ };
482
+
483
+ export const useContentId = () => {
484
+ const withUniqueRouteSuffix = useUniqueRouteSuffix();
485
+
486
+ return withUniqueRouteSuffix(QUICK_BRICK_CONTENT);
487
+ };
@@ -9,18 +9,11 @@ jest.useFakeTimers();
9
9
 
10
10
  const rewind = jest.fn();
11
11
  const forward = jest.fn();
12
- const exitDelayedSeek = jest.fn();
13
- const enterDelayedSeek = jest.fn();
14
12
 
15
13
  jest
16
14
  .spyOn(playerManager, "getInstanceController")
17
15
  // @ts-ignore
18
- .mockImplementation(() => ({
19
- rewind,
20
- forward,
21
- exitDelayedSeek,
22
- enterDelayedSeek,
23
- }));
16
+ .mockImplementation(() => ({ rewind, forward }));
24
17
 
25
18
  describe("useAutoSeek", () => {
26
19
  beforeEach(() => {
@@ -14,24 +14,19 @@ export const useAutoSeek = (resetHUDTimer = noop) => {
14
14
  const [isRunning, setIsRunning] = useState<boolean>(false);
15
15
  const [direction, setDirection] = useState<Nullable<SEEK_TYPE>>(null);
16
16
  const [multiplier, setMultiplier] = useState(1);
17
-
18
17
  const intervalTimer = React.useRef(null);
19
18
  const prevRunning = usePrevious(isRunning);
20
19
 
21
20
  const setIntervalTimer = (cb) => {
22
- if (intervalTimer.current) {
23
- return;
24
- }
25
-
26
- intervalTimer.current = setInterval(() => {
27
- intervalTimer.current = null;
28
- cb();
29
- }, ON_HOLD_INTERVAL);
21
+ intervalTimer.current = setInterval(cb, ON_HOLD_INTERVAL);
30
22
  };
31
23
 
32
24
  const clearIntervalTimer = () => {
33
- clearInterval(intervalTimer.current);
34
- intervalTimer.current = null;
25
+ try {
26
+ clearInterval(intervalTimer.current);
27
+ } catch (err) {
28
+ intervalTimer.current = null;
29
+ }
35
30
  };
36
31
 
37
32
  const resetState = () => {
@@ -42,21 +37,6 @@ export const useAutoSeek = (resetHUDTimer = noop) => {
42
37
  };
43
38
 
44
39
  useEffect(() => {
45
- const player = playerManager.getInstanceController();
46
- if (!player) return;
47
-
48
- if (isRunning) {
49
- player?.enterDelayedSeek();
50
- } else if (!isRunning) {
51
- player.exitDelayedSeek();
52
- }
53
- }, [isRunning]);
54
-
55
- useEffect(() => {
56
- if (!isRunning) {
57
- return;
58
- }
59
-
60
40
  const player = playerManager.getInstanceController();
61
41
 
62
42
  if (!player) return;
@@ -65,7 +45,7 @@ export const useAutoSeek = (resetHUDTimer = noop) => {
65
45
  player[direction](R.min(MAX_SEEK_TIME, SKIP_TIME_BASE * multiplier));
66
46
  resetHUDTimer();
67
47
  }
68
- }, [multiplier, direction, isRunning]);
48
+ }, [multiplier, direction]);
69
49
 
70
50
  useEffect(() => {
71
51
  if (isRunning && isRunning !== prevRunning) {
@@ -95,7 +75,7 @@ export const useAutoSeek = (resetHUDTimer = noop) => {
95
75
  setDirection(eventType);
96
76
  setIsRunning(true);
97
77
  },
98
- [isRunning, autoSeekStop]
78
+ [isRunning]
99
79
  );
100
80
 
101
81
  return React.useMemo(
@@ -9,11 +9,11 @@ export const useSeek = (resetHUDTimer = noop) => {
9
9
  const { autoSeekStart, autoSeekStop } = useAutoSeek(resetHUDTimer);
10
10
 
11
11
  const onForwardPress = () => {
12
- // handlePressEvent(SEEK_TYPE.FORWARD);
12
+ handlePressEvent(SEEK_TYPE.FORWARD);
13
13
  };
14
14
 
15
15
  const onRewindPress = () => {
16
- // handlePressEvent(SEEK_TYPE.REWIND);
16
+ handlePressEvent(SEEK_TYPE.REWIND);
17
17
  };
18
18
 
19
19
  const onForwardPressIn = () => {
@@ -21,7 +21,6 @@ export const useSeek = (resetHUDTimer = noop) => {
21
21
  };
22
22
 
23
23
  const onForwardPressOut = () => {
24
- handlePressEvent(SEEK_TYPE.FORWARD);
25
24
  autoSeekStop();
26
25
  };
27
26
 
@@ -38,7 +37,6 @@ export const useSeek = (resetHUDTimer = noop) => {
38
37
  };
39
38
 
40
39
  const onRewindPressOut = () => {
41
- handlePressEvent(SEEK_TYPE.REWIND);
42
40
  autoSeekStop();
43
41
  };
44
42
 
@@ -1,4 +1,4 @@
1
- import { useCallback, useRef, useState } from "react";
1
+ import { useCallback, useRef } from "react";
2
2
  import * as R from "ramda";
3
3
  import {
4
4
  MAX_SEEK_TIME,
@@ -10,11 +10,13 @@ import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
10
10
 
11
11
  type SeekType = SEEK_TYPE | null;
12
12
 
13
- const getSkipTime = (multiplier) =>
14
- R.min(MAX_SEEK_TIME, SKIP_TIME_BASE * multiplier);
13
+ const getSkipTime = (multiplier) => {
14
+ const skipTime = R.min(MAX_SEEK_TIME, SKIP_TIME_BASE * multiplier);
15
+
16
+ return skipTime;
17
+ };
15
18
 
16
19
  export const useTapSeek = () => {
17
- const [resumeTimer, setResumeTimer] = useState<NodeJS.Timeout>(null);
18
20
  const onPressMultiplier = useRef(1);
19
21
  const lastPressTime = useRef(0);
20
22
  const currentOnPressEventType = useRef<SeekType>(null);
@@ -44,41 +46,12 @@ export const useTapSeek = () => {
44
46
  }
45
47
 
46
48
  const seekTime = getSkipTime(onPressMultiplier.current);
47
-
48
49
  player[eventType](seekTime);
49
50
 
50
- if (resumeTimer) {
51
- clearTimeout(resumeTimer);
52
-
53
- const timer = setTimeout(() => {
54
- player.exitDelayedSeek();
55
- setResumeTimer(null);
56
- }, 2000);
57
-
58
- setResumeTimer(timer);
59
- }
60
-
61
- const clicksBeforePause = 3;
62
-
63
- // Only pause player if user starts to seek on large increments
64
- if (onPressMultiplier.current > clicksBeforePause) {
65
- if (!player.isPaused()) {
66
- player.enterDelayedSeek();
67
-
68
- const timer = setTimeout(() => {
69
- player.exitDelayedSeek();
70
- setResumeTimer(null);
71
- }, 2000);
72
-
73
- clearTimeout(resumeTimer);
74
- setResumeTimer(timer);
75
- }
76
- }
77
-
78
51
  lastPressTime.current = now;
79
52
  currentOnPressEventType.current = eventType;
80
53
  },
81
- [resetMultiplier, resumeTimer]
54
+ [resetMultiplier]
82
55
  );
83
56
 
84
57
  return handlePressEvent;
@@ -3,23 +3,28 @@ import { Provider } from "react-redux";
3
3
  import { renderHook } from "@testing-library/react-hooks";
4
4
  import configureStore from "redux-mock-store";
5
5
  import thunk from "redux-thunk";
6
- import { NavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NavigationContext";
7
6
 
8
7
  const mockStore = configureStore([thunk]);
9
8
 
10
- import { useCurrentScreenData } from "../useCurrentScreenData";
11
-
12
- describe("useScreenData", function () {
13
- const river_id_2: ZappRiver = {
14
- name: "River 2",
15
- id: "A1234",
16
- home: false,
17
- home_offline: false,
18
- supports_offline: false,
19
- navigations: [],
20
- hooks: { preload_plugins: [] },
21
- };
22
-
9
+ const river_id_2: ZappRiver = {
10
+ name: "River 2",
11
+ id: "A1234",
12
+ home: false,
13
+ home_offline: false,
14
+ supports_offline: false,
15
+ navigations: [],
16
+ hooks: { preload_plugins: [] },
17
+ };
18
+
19
+ jest.mock("../useScreenContext", () => ({
20
+ useScreenContext: () => ({
21
+ screen: river_id_2,
22
+ }),
23
+ }));
24
+
25
+ const { useCurrentScreenData } = require("../useCurrentScreenData");
26
+
27
+ describe("useScreenData", () => {
23
28
  const river_id_1 = { id: "B5678" };
24
29
 
25
30
  const store = mockStore({
@@ -27,17 +32,10 @@ describe("useScreenData", function () {
27
32
  });
28
33
 
29
34
  const wrapper: React.FC<any> = ({ children }) => (
30
- <NavigationContext.Provider
31
- value={{
32
- currentRoute: "/river/river_id_1/river/river_id_2",
33
- data: { screen: river_id_2 },
34
- }}
35
- >
36
- <Provider store={store}>{children}</Provider>
37
- </NavigationContext.Provider>
35
+ <Provider store={store}>{children}</Provider>
38
36
  );
39
37
 
40
- it("should return river data for the current screen/route", function () {
38
+ it("should return river data for the current screen/route", () => {
41
39
  const { result } = renderHook(() => useCurrentScreenData(), { wrapper });
42
40
 
43
41
  expect(result.current).toBe(river_id_2);
@@ -10,3 +10,5 @@ export {
10
10
  useNavbarState,
11
11
  useSetNavbarState,
12
12
  } from "./useScreenContext";
13
+
14
+ export { useScreenBackgroundColor } from "./useScreenBackgroundColor";
@@ -0,0 +1,23 @@
1
+ import * as React from "react";
2
+ import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
3
+ import { useScreenConfiguration } from "@applicaster/zapp-react-native-ui-components/Components/River/useScreenConfiguration";
4
+ import { ifEmptyUseFallback } from "@applicaster/zapp-react-native-utils/cellUtils";
5
+
6
+ export const useScreenBackgroundColor = (screenId: string): string => {
7
+ const { backgroundColor: screenBackgroundColor } =
8
+ useScreenConfiguration(screenId);
9
+
10
+ const theme = useTheme();
11
+
12
+ const themeBackgroundColor = React.useMemo(
13
+ () => theme.app_background_color,
14
+ [theme.app_background_color]
15
+ );
16
+
17
+ const backgroundColor = ifEmptyUseFallback(
18
+ screenBackgroundColor,
19
+ themeBackgroundColor
20
+ );
21
+
22
+ return backgroundColor;
23
+ };
@@ -45,8 +45,7 @@ export function useSetNavbarState() {
45
45
 
46
46
  export function useScreenContext(): NavigationScreenData {
47
47
  const navigator = useNavigation();
48
- // Cover cases where screenContext is used before navigation is initialized
49
- const screenData = useContext(ScreenDataContext) || navigator.data;
48
+ const screenData = useContext(ScreenDataContext);
50
49
 
51
50
  const modalScreenData = navigator?.modalData;
52
51
 
@@ -108,3 +108,105 @@ 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
+ exitApplication: () => void;
116
+ setClosedCaptionHandler: (
117
+ callback: (isCCEnabled: boolean) => void
118
+ ) => void;
119
+ };
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Platforms found in userAgent string, please note that simulators
125
+ * might not have the same agents that the devices have
126
+ */
127
+ export const PLATFORMS = {
128
+ webos: "Web0S",
129
+ tizen: "Tizen",
130
+ samsung: "SMART-TV",
131
+ mac: "Mac",
132
+ win: "Win",
133
+ linux: "Linux",
134
+ iphone: "iPhone",
135
+ android: "Android",
136
+ mobile: "Mobile",
137
+ vizio: "VIZIO",
138
+ smartcast: "SmartCast",
139
+ conjure: "Conjure",
140
+ };
141
+
142
+ /**
143
+ * Simple way of identifying if we have access to the tizen APIs
144
+ */
145
+ export const hasTizen = typeof window?.tizen !== "undefined";
146
+
147
+ /**
148
+ * Simple way of identifying if we have access to the webOS APIs
149
+ */
150
+ export const hasWebOS = typeof window?.webOS !== "undefined";
151
+
152
+ export const getUserAgent = () =>
153
+ window?.navigator?.userAgent || global?.navigator?.userAgent;
154
+
155
+ export const isLgPlatform = () => {
156
+ const userAgent = getUserAgent();
157
+
158
+ if (!userAgent) {
159
+ return false;
160
+ }
161
+
162
+ // Note: LG uses the number 0 in their userAgent, possibly because of Palm WebOS
163
+ return hasWebOS || userAgent.includes(PLATFORMS.webos);
164
+ };
165
+
166
+ export const isSamsungPlatform = () => {
167
+ const userAgent = getUserAgent();
168
+
169
+ if (!userAgent) {
170
+ return false;
171
+ }
172
+
173
+ return (
174
+ hasTizen ||
175
+ userAgent.includes(PLATFORMS.samsung) ||
176
+ userAgent.includes(PLATFORMS.tizen)
177
+ );
178
+ };
179
+
180
+ /**
181
+ * Checks if we are on the Vizio platform by using the userAgent string
182
+ *
183
+ * Use this method when you need to identify the platform on runtime
184
+ * before the VIZIO Companion Library has loaded
185
+ */
186
+ export const isVizioPlatform = () => {
187
+ const userAgent = getUserAgent();
188
+
189
+ if (!userAgent) {
190
+ return false;
191
+ }
192
+
193
+ const isVizioAgent =
194
+ userAgent.includes(PLATFORMS.vizio) ||
195
+ userAgent.includes(PLATFORMS.smartcast) ||
196
+ userAgent.includes(PLATFORMS.conjure);
197
+
198
+ return isVizioAgent;
199
+ };
200
+
201
+ /**
202
+ * Checks if we are on the Vizio platform by checking for the global VIZIO object
203
+ * and the VIZIO Companion Library. This method does not use the userAgent string,
204
+ * because it mainly checks whether we have access to apis, which may not be available yet
205
+ */
206
+ export const hasVizioAPIs = () => {
207
+ const hasAPIs =
208
+ typeof window.VIZIO !== "undefined" &&
209
+ window?.applicaster?.vizioLibraryDidLoad;
210
+
211
+ return hasAPIs;
212
+ };
@@ -1,155 +0,0 @@
1
- import { PlayerAnalyticsTracker } from "./playerAnalyticsTracker";
2
- import { Player } from "../appUtils/playerManager/player";
3
- import { AD_EVENT, GENERAL_EVENT, PLAYBACK_EVENT, QOS_EVENT } from "./events";
4
-
5
- type Props = {
6
- analyticsTracker: any;
7
- player: any;
8
- };
9
-
10
- /* eslint brace-style: 0 */ // --> OFF
11
- export class AnalyticPlayerListener
12
- implements QuickBrickPlayer.SharedPlayerCallBacks
13
- {
14
- static analyticsListenerID = "analytics-listener";
15
- private analyticsTracker: PlayerAnalyticsTracker;
16
- private player: Player;
17
-
18
- private onVideoLoadCalled; // android only
19
-
20
- constructor(props: Props) {
21
- this.analyticsTracker = props.analyticsTracker;
22
- this.player = props.player;
23
- }
24
-
25
- handleAnalyticEvent = (event, data = {}) => {
26
- if (this.analyticsTracker?.handleAnalyticEvent) {
27
- this.analyticsTracker?.handleAnalyticEvent?.(event, {
28
- ...data,
29
- player_type: this.player.playerPluginId,
30
- });
31
- }
32
- };
33
-
34
- onVideoEnd = () => {
35
- this.handleAnalyticEvent(PLAYBACK_EVENT.complete);
36
- };
37
-
38
- onError = (err: Error) => {
39
- this.handleAnalyticEvent(PLAYBACK_EVENT.error, err); // TODO: Check error format
40
- };
41
-
42
- // HACK: This is a hack to ignore the next resume event after a delayed seek
43
- private ignoreNextResume = false;
44
- onLoad = () => {
45
- this.ignoreNextResume = false;
46
- }
47
-
48
- onPlayerPause = (event) => {
49
- if (!this.player.isInDelayedSeek()) {
50
- this.handleAnalyticEvent(PLAYBACK_EVENT.pause, event);
51
- } else {
52
- this.ignoreNextResume = true;
53
- }
54
- };
55
-
56
- onPlayerResume = (event) => {
57
- if (!this.player.isInDelayedSeek() && !this.ignoreNextResume) {
58
- this.handleAnalyticEvent(PLAYBACK_EVENT.play, event);
59
- } else {
60
- this.ignoreNextResume = false;
61
- }
62
- };
63
-
64
- onPlayerSeekComplete = (event) => {
65
- this.handleAnalyticEvent(PLAYBACK_EVENT.seek_complete, event);
66
- };
67
-
68
- onPlayerSeekStart = (event) => {
69
- this.handleAnalyticEvent(PLAYBACK_EVENT.seek_start, event);
70
- };
71
-
72
- onBufferStart = (event) => {
73
- this.handleAnalyticEvent(PLAYBACK_EVENT.buffer_start, event);
74
- };
75
-
76
- onBufferComplete = (event) => {
77
- this.handleAnalyticEvent(PLAYBACK_EVENT.buffer_complete, event);
78
- };
79
-
80
- // Not implemented
81
- onPlayerStop = (event) => {
82
- this.handleAnalyticEvent(PLAYBACK_EVENT.stop, event);
83
- };
84
-
85
- // TODO: Implement method on native
86
- onVideoBandwidthUpdate = (event) => {
87
- this.handleAnalyticEvent(QOS_EVENT.bitrate_changed, event);
88
- };
89
-
90
- onAdBegin = (event) => {
91
- this.handleAnalyticEvent(AD_EVENT.ad_start, event);
92
- };
93
-
94
- onAdBreakBegin = (event) => {
95
- this.handleAnalyticEvent(AD_EVENT.ad_break_start, event);
96
- };
97
-
98
- onAdBreakEnd = (event) => {
99
- this.handleAnalyticEvent(AD_EVENT.ad_break_completed, event);
100
- };
101
-
102
- onAdEnd = (event) => {
103
- this.handleAnalyticEvent(AD_EVENT.ad_complete, event);
104
- };
105
-
106
- onAdError = (event) => {
107
- this.handleAnalyticEvent(AD_EVENT.ad_error, event);
108
- };
109
-
110
- onAdRequest = (event) => {
111
- this.handleAnalyticEvent(AD_EVENT.ad_request, event);
112
- };
113
-
114
- onAdClicked = (event) => {
115
- this.handleAnalyticEvent(AD_EVENT.ad_clicked, event);
116
- };
117
-
118
- onAdTapped = (event) => {
119
- this.handleAnalyticEvent(AD_EVENT.ad_tapped, event);
120
- };
121
-
122
- onVideoLoad = () => {
123
- // if (!this.state.isAd && !this.onVideoLoadCalled) {
124
- if (!this.player.isAd() && !this.onVideoLoadCalled) {
125
- this.onVideoLoadCalled = true;
126
-
127
- this.handleAnalyticEvent(PLAYBACK_EVENT.load_video, {
128
- player_type: this.player.playerPluginId,
129
- });
130
- }
131
- };
132
-
133
- onPlayerSessionEnd = () => {
134
- // TODO: Implement method on native android, ios exists
135
- this.handleAnalyticEvent(GENERAL_EVENT.session_end);
136
- };
137
-
138
- onPlayerSessionStart = () => {
139
- // TODO: Implement method on native android, ios exists
140
-
141
- this.handleAnalyticEvent(GENERAL_EVENT.session_start);
142
- };
143
-
144
- onPlayerNext = ({ nativeEvent }) => {
145
- // TODO: Implement method on native
146
-
147
- this.handleAnalyticEvent(PLAYBACK_EVENT.next, nativeEvent);
148
- };
149
-
150
- onPlayerPrevious = ({ nativeEvent }) => {
151
- // TODO: Implement method on native
152
-
153
- this.handleAnalyticEvent(PLAYBACK_EVENT.previous, nativeEvent);
154
- };
155
- }