@applicaster/zapp-react-native-utils 12.0.0-rc.11 → 12.0.0-rc.110

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 (117) hide show
  1. package/actionsExecutor/ActionExecutorContext.tsx +16 -8
  2. package/analyticsUtils/AnalyticPlayerListener.ts +141 -0
  3. package/analyticsUtils/AnalyticsEvents/index.ts +13 -0
  4. package/analyticsUtils/AnalyticsEvents/searchEvents.ts +21 -0
  5. package/analyticsUtils/AnalyticsEvents/sendShareEvent.ts +21 -0
  6. package/analyticsUtils/PlayerAnalyticsManager.ts +90 -0
  7. package/analyticsUtils/__tests__/analyticsManager.test.js +75 -73
  8. package/analyticsUtils/analyticsPlugins.ts +25 -0
  9. package/analyticsUtils/events.ts +12 -0
  10. package/analyticsUtils/helpers/hooks.ts +1 -1
  11. package/analyticsUtils/index.tsx +12 -0
  12. package/analyticsUtils/{analyticsTracker.ts → playerAnalyticsTracker.ts} +19 -10
  13. package/appUtils/HooksManager/index.js +3 -1
  14. package/appUtils/accessibilityManager/const.ts +50 -0
  15. package/appUtils/accessibilityManager/hooks.ts +40 -0
  16. package/appUtils/accessibilityManager/index.ts +166 -0
  17. package/appUtils/accessibilityManager/logger.ts +5 -0
  18. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +2 -3
  19. package/appUtils/focusManager/__tests__/focusManager.test.js +4 -24
  20. package/appUtils/focusManager/__tests__/index.test.ts +2 -3
  21. package/appUtils/focusManager/index.ts +76 -57
  22. package/appUtils/focusManager/treeDataStructure/Utils/index.js +75 -35
  23. package/appUtils/focusManager/utils/index.ts +100 -0
  24. package/appUtils/focusManagerAux/index.ts +76 -0
  25. package/appUtils/focusManagerAux/utils/index.ts +100 -0
  26. package/appUtils/index.js +2 -0
  27. package/appUtils/keyCodes/__tests__/__snapshots__/keyCodes.test.js.snap +1 -1
  28. package/appUtils/keyCodes/__tests__/keyCodes.test.js +80 -85
  29. package/appUtils/keyCodes/keys.web.js +9 -0
  30. package/appUtils/keyCodes/keysByPlatform.js +11 -1
  31. package/appUtils/platform/const.ts +25 -0
  32. package/appUtils/platform/index.ts +3 -0
  33. package/appUtils/platform/platformUtils.ts +185 -0
  34. package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +53 -0
  35. package/appUtils/playerManager/conts.ts +6 -0
  36. package/appUtils/playerManager/index.ts +20 -32
  37. package/appUtils/playerManager/nativePlayerManager.ts +12 -0
  38. package/appUtils/playerManager/player.ts +56 -7
  39. package/appUtils/playerManager/playerFactory.ts +15 -1
  40. package/appUtils/playerManager/playerNative.ts +41 -15
  41. package/appUtils/playerManager/usePlayerControllerSetup.tsx +7 -1
  42. package/appUtils/playerManager/usePlayerState.tsx +13 -1
  43. package/appUtils/playerManager/usePlayerTitleSummaryOverlay.tsx +50 -0
  44. package/arrayUtils/__tests__/isFilledArray.test.ts +63 -0
  45. package/arrayUtils/index.ts +5 -0
  46. package/booleanUtils/index.ts +4 -4
  47. package/cellUtils/__tests__/cellUtils.test.ts +48 -0
  48. package/cellUtils/__tests__/fixtures.ts +13 -0
  49. package/cellUtils/index.ts +78 -7
  50. package/dateUtils/index.ts +11 -0
  51. package/focusManager/index.ts +1 -1
  52. package/functionUtils/__tests__/__snapshots__/functionUtils.test.js.snap +2 -2
  53. package/functionUtils/__tests__/functionUtils.test.js +244 -248
  54. package/headersUtils/index.ts +1 -0
  55. package/index.d.ts +15 -0
  56. package/inflatedUrlUtils/index.ts +4 -4
  57. package/keyboardState/index.ts +0 -0
  58. package/localizationUtils/__tests__/localizationUtils.test.ts +78 -55
  59. package/localizationUtils/index.ts +13 -19
  60. package/logger/index.ts +1 -1
  61. package/manifestUtils/defaultManifestConfigurations/generalContent.js +6 -0
  62. package/manifestUtils/defaultManifestConfigurations/player.js +10 -1
  63. package/manifestUtils/index.js +5 -1
  64. package/manifestUtils/secondaryImage/index.js +18 -15
  65. package/modalState/index.ts +57 -0
  66. package/navigationUtils/index.ts +104 -7
  67. package/numberUtils/__tests__/isLikeNumber.test.ts +18 -0
  68. package/numberUtils/__tests__/toNumber.test.ts +2 -2
  69. package/numberUtils/index.ts +9 -18
  70. package/package.json +3 -2
  71. package/playerUtils/configurationGenerator.ts +11 -1
  72. package/playerUtils/imaScriptDom.ts +59 -0
  73. package/pluginUtils/index.ts +20 -7
  74. package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +2 -0
  75. package/reactHooks/autoscrolling/__tests__/{useTrackedView.test.ts → useTrackedView.test.tsx} +18 -1
  76. package/reactHooks/cell-click/__tests__/index.test.js +16 -3
  77. package/reactHooks/cell-click/index.ts +14 -14
  78. package/reactHooks/debugging/__tests__/index.test.js +81 -11
  79. package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +30 -70
  80. package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +6 -2
  81. package/reactHooks/feed/__tests__/useInflatedUrl.test.ts +18 -3
  82. package/reactHooks/feed/useBuildPipesUrl.ts +7 -10
  83. package/reactHooks/feed/useFeedRefresh.tsx +9 -7
  84. package/reactHooks/feed/useInflatedUrl.ts +44 -15
  85. package/reactHooks/flatList/useLoadNextPageIfNeeded.ts +16 -9
  86. package/reactHooks/index.ts +2 -0
  87. package/reactHooks/layout/__tests__/{index.test.js → index.test.tsx} +66 -59
  88. package/reactHooks/layout/getDeviceInfo/index.ts +4 -2
  89. package/reactHooks/layout/types/index.ts +2 -0
  90. package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.native.test.js +11 -16
  91. package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.test.js +12 -14
  92. package/reactHooks/layout/useDimensions/useDimensions.ts +13 -7
  93. package/reactHooks/navigation/__mocks__/index.ts +15 -0
  94. package/reactHooks/navigation/__mocks__/useNavigation.ts +7 -0
  95. package/reactHooks/navigation/__tests__/index.test.tsx +240 -81
  96. package/reactHooks/navigation/index.ts +239 -80
  97. package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +3 -1
  98. package/reactHooks/resolvers/useCellResolver.ts +5 -1
  99. package/reactHooks/screen/__mocks__/useScreenContext.ts +3 -1
  100. package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +21 -23
  101. package/reactHooks/screen/index.ts +4 -0
  102. package/reactHooks/screen/useScreenBackgroundColor.ts +23 -0
  103. package/reactHooks/screen/useScreenContext.ts +4 -4
  104. package/reactHooks/screen/useScreenData.ts +1 -1
  105. package/reactHooks/screen/useTargetScreenData.ts +7 -0
  106. package/reactHooks/state/useRivers.ts +3 -1
  107. package/reactHooks/useListenEventBusEvent.ts +1 -4
  108. package/reactHooks/videoModal/hooks/useVideoModalScreenData.tsx +10 -9
  109. package/reactUtils/index.ts +104 -0
  110. package/riverComponetsMeasurementProvider/index.tsx +2 -2
  111. package/stringUtils/index.ts +5 -0
  112. package/testUtils/getByTestId.ts +14 -0
  113. package/testUtils/index.tsx +38 -23
  114. package/types.ts +4 -0
  115. package/appUtils/focusManager/FocusableEvents.ts +0 -8
  116. package/appUtils/focusManager/treeDataStructure/Utils/__tests__/Utils_android.test.js +0 -1094
  117. package/appUtils/focusManager/treeDataStructure/Utils/index.android.js +0 -261
@@ -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 =
@@ -0,0 +1,141 @@
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
+ onPlayerPause = (event) => {
43
+ this.handleAnalyticEvent(PLAYBACK_EVENT.pause, event);
44
+ };
45
+
46
+ onPlayerResume = (event) => {
47
+ this.handleAnalyticEvent(PLAYBACK_EVENT.play, event);
48
+ };
49
+
50
+ onPlayerSeekComplete = (event) => {
51
+ this.handleAnalyticEvent(PLAYBACK_EVENT.seek_complete, event);
52
+ };
53
+
54
+ onPlayerSeekStart = (event) => {
55
+ this.handleAnalyticEvent(PLAYBACK_EVENT.seek_start, event);
56
+ };
57
+
58
+ onBufferStart = (event) => {
59
+ this.handleAnalyticEvent(PLAYBACK_EVENT.buffer_start, event);
60
+ };
61
+
62
+ onBufferComplete = (event) => {
63
+ this.handleAnalyticEvent(PLAYBACK_EVENT.buffer_complete, event);
64
+ };
65
+
66
+ // Not implemented
67
+ onPlayerStop = (event) => {
68
+ this.handleAnalyticEvent(PLAYBACK_EVENT.stop, event);
69
+ };
70
+
71
+ // TODO: Implement method on native
72
+ onVideoBandwidthUpdate = (event) => {
73
+ this.handleAnalyticEvent(QOS_EVENT.bitrate_changed, event);
74
+ };
75
+
76
+ onAdBegin = (event) => {
77
+ this.handleAnalyticEvent(AD_EVENT.ad_start, event);
78
+ };
79
+
80
+ onAdBreakBegin = (event) => {
81
+ this.handleAnalyticEvent(AD_EVENT.ad_break_start, event);
82
+ };
83
+
84
+ onAdBreakEnd = (event) => {
85
+ this.handleAnalyticEvent(AD_EVENT.ad_break_completed, event);
86
+ };
87
+
88
+ onAdEnd = (event) => {
89
+ this.handleAnalyticEvent(AD_EVENT.ad_complete, event);
90
+ };
91
+
92
+ onAdError = (event) => {
93
+ this.handleAnalyticEvent(AD_EVENT.ad_error, event);
94
+ };
95
+
96
+ onAdRequest = (event) => {
97
+ this.handleAnalyticEvent(AD_EVENT.ad_request, event);
98
+ };
99
+
100
+ onAdClicked = (event) => {
101
+ this.handleAnalyticEvent(AD_EVENT.ad_clicked, event);
102
+ };
103
+
104
+ onAdTapped = (event) => {
105
+ this.handleAnalyticEvent(AD_EVENT.ad_tapped, event);
106
+ };
107
+
108
+ onVideoLoad = () => {
109
+ // if (!this.state.isAd && !this.onVideoLoadCalled) {
110
+ if (!this.player.isAd() && !this.onVideoLoadCalled) {
111
+ this.onVideoLoadCalled = true;
112
+
113
+ this.handleAnalyticEvent(PLAYBACK_EVENT.load_video, {
114
+ player_type: this.player.playerPluginId,
115
+ });
116
+ }
117
+ };
118
+
119
+ onPlayerSessionEnd = () => {
120
+ // TODO: Implement method on native android, ios exists
121
+ this.handleAnalyticEvent(GENERAL_EVENT.session_end);
122
+ };
123
+
124
+ onPlayerSessionStart = () => {
125
+ // TODO: Implement method on native android, ios exists
126
+
127
+ this.handleAnalyticEvent(GENERAL_EVENT.session_start);
128
+ };
129
+
130
+ onPlayerNext = ({ nativeEvent }) => {
131
+ // TODO: Implement method on native
132
+
133
+ this.handleAnalyticEvent(PLAYBACK_EVENT.next, nativeEvent);
134
+ };
135
+
136
+ onPlayerPrevious = ({ nativeEvent }) => {
137
+ // TODO: Implement method on native
138
+
139
+ this.handleAnalyticEvent(PLAYBACK_EVENT.previous, nativeEvent);
140
+ };
141
+ }
@@ -7,6 +7,15 @@ import { sendHeaderClickEvent } from "./sendHeaderClickEvent";
7
7
  import { sendHardwareBackButtonClickEvent } from "./sendHardwareBackButtonClickEvent";
8
8
  import { sendDownloadsEvent } from "./sendDownloadsEvent";
9
9
  import { sendScreenEvent } from "./sendScreenEvent";
10
+ import {
11
+ sendSearchCanceledEvent,
12
+ sendSearchExecutedEvent,
13
+ } from "./searchEvents";
14
+
15
+ import {
16
+ sendShareInitiatedEvent,
17
+ sendShareSuccessEvent,
18
+ } from "./sendShareEvent";
10
19
 
11
20
  export {
12
21
  sendScreenEvent,
@@ -18,4 +27,8 @@ export {
18
27
  sendHeaderClickEvent,
19
28
  sendHardwareBackButtonClickEvent,
20
29
  sendDownloadsEvent,
30
+ sendSearchCanceledEvent,
31
+ sendSearchExecutedEvent,
32
+ sendShareInitiatedEvent,
33
+ sendShareSuccessEvent,
21
34
  };
@@ -0,0 +1,21 @@
1
+ import { log_debug } from "../logger";
2
+ import { postAnalyticEvent } from "../manager";
3
+ import { ANALYTICS_CORE_EVENTS } from "../events";
4
+
5
+ export const sendSearchCanceledEvent = (analyticsProps) => {
6
+ const eventName = ANALYTICS_CORE_EVENTS.SEARCH_CANCELED;
7
+ postAnalyticEvent(eventName, analyticsProps);
8
+
9
+ log_debug(`sendSearchCanceledEvent: send event: ${eventName}`, {
10
+ analyticsProps,
11
+ });
12
+ };
13
+
14
+ export const sendSearchExecutedEvent = (analyticsProps) => {
15
+ const eventName = ANALYTICS_CORE_EVENTS.SEARCH_EXECUTED;
16
+ postAnalyticEvent(eventName, analyticsProps);
17
+
18
+ log_debug(`sendSearchExecutedEvent: send event: ${eventName}`, {
19
+ analyticsProps,
20
+ });
21
+ };
@@ -0,0 +1,21 @@
1
+ import { log_debug } from "../logger";
2
+ import { postAnalyticEvent } from "../manager";
3
+ import { ANALYTICS_CORE_EVENTS } from "../events";
4
+
5
+ export const sendShareInitiatedEvent = (analyticsProps) => {
6
+ const eventName = ANALYTICS_CORE_EVENTS.SHARE_INITIATED;
7
+ postAnalyticEvent(eventName, analyticsProps);
8
+
9
+ log_debug(`sendShareInitiatedEvent: send event: ${eventName}`, {
10
+ analyticsProps,
11
+ });
12
+ };
13
+
14
+ export const sendShareSuccessEvent = (analyticsProps) => {
15
+ const eventName = ANALYTICS_CORE_EVENTS.SHARE_SUCCESS;
16
+ postAnalyticEvent(eventName, analyticsProps);
17
+
18
+ log_debug(`sendShareSuccessEvent: send event: ${eventName}`, {
19
+ analyticsProps,
20
+ });
21
+ };
@@ -0,0 +1,90 @@
1
+ import {
2
+ PlayerAnalyticsTracker,
3
+ PlayerAnalyticsTrackerI,
4
+ } from "./playerAnalyticsTracker";
5
+ import {
6
+ PlayerLifecycleListener,
7
+ PlayerManager,
8
+ } from "../appUtils/playerManager";
9
+ import { Player } from "../appUtils/playerManager/player";
10
+ import { AnalyticPlayerListener } from "./AnalyticPlayerListener";
11
+ import { PlayerRole } from "../appUtils/playerManager/conts";
12
+
13
+ enum PlayerAnalyticsTrackerType {
14
+ PlayerAnalyticsTracker = "PlayerAnalyticsTracker",
15
+ }
16
+
17
+ class PlayerAnalyticsTrackerFactory {
18
+ createTracker(type: PlayerAnalyticsTrackerType) {
19
+ switch (type) {
20
+ case PlayerAnalyticsTrackerType.PlayerAnalyticsTracker:
21
+ return new PlayerAnalyticsTracker();
22
+ default:
23
+ return new PlayerAnalyticsTracker();
24
+ }
25
+ }
26
+ }
27
+
28
+ export class PlayerAnalyticsManager implements PlayerLifecycleListener {
29
+ static instance: PlayerAnalyticsManager;
30
+ private trackers: Record<string, PlayerAnalyticsTrackerI> = {};
31
+ private trackerFactory: PlayerAnalyticsTrackerFactory;
32
+
33
+ public getTracker(
34
+ id: string,
35
+ type: PlayerAnalyticsTrackerType = PlayerAnalyticsTrackerType.PlayerAnalyticsTracker
36
+ ): PlayerAnalyticsTrackerI {
37
+ if (!this.trackers[id]) {
38
+ this.trackers[id] = this.trackerFactory.createTracker(type);
39
+ }
40
+
41
+ return this.trackers[id];
42
+ }
43
+
44
+ constructor(trackerFactory: PlayerAnalyticsTrackerFactory) {
45
+ this.trackerFactory = trackerFactory;
46
+ this.startListenPlayerManager();
47
+ }
48
+
49
+ static getInstance(
50
+ trackerFactory: PlayerAnalyticsTrackerFactory = new PlayerAnalyticsTrackerFactory()
51
+ ): PlayerAnalyticsManager {
52
+ if (!PlayerAnalyticsManager.instance) {
53
+ PlayerAnalyticsManager.instance = new PlayerAnalyticsManager(
54
+ trackerFactory
55
+ );
56
+ }
57
+
58
+ return PlayerAnalyticsManager.instance;
59
+ }
60
+
61
+ private startListenPlayerManager() {
62
+ PlayerManager.getInstance().addLifecycleListener(this);
63
+ }
64
+
65
+ // PlayerLifecycleListener
66
+
67
+ onRegistered = (player: Player) => {
68
+ if (player.playerRole !== PlayerRole.Primary) {
69
+ return;
70
+ }
71
+
72
+ const tracker = this.getTracker(player.playerId);
73
+ tracker.setPlayer(player);
74
+
75
+ const analyticsListener = new AnalyticPlayerListener({
76
+ analyticsTracker: tracker,
77
+ player,
78
+ });
79
+
80
+ player.addListener({
81
+ id: AnalyticPlayerListener.analyticsListenerID,
82
+ listener: analyticsListener,
83
+ });
84
+ };
85
+
86
+ onUnRegistered = (player: Player) => {
87
+ player.removeListener(AnalyticPlayerListener.analyticsListenerID);
88
+ delete this.trackers[player.playerId];
89
+ };
90
+ }
@@ -1,18 +1,18 @@
1
+ import * as ReactNative from "react-native";
2
+
1
3
  const mock_postEvent = jest.fn();
2
4
  const mock_setPlugins = jest.fn();
3
5
  const mock_postTimedEvent = jest.fn();
4
6
  const mock_endTimedEvent = jest.fn();
5
7
 
6
- jest.mock("react-native", () => ({
7
- NativeModules: {
8
- AnalyticsBridge: {
9
- postEvent: mock_postEvent,
10
- setPlugins: mock_setPlugins,
11
- postTimedEvent: mock_postTimedEvent,
12
- endTimedEvent: mock_endTimedEvent,
13
- },
14
- },
15
- }));
8
+ const AnalyticsBridge = {
9
+ postEvent: mock_postEvent,
10
+ setPlugins: mock_setPlugins,
11
+ postTimedEvent: mock_postTimedEvent,
12
+ endTimedEvent: mock_endTimedEvent,
13
+ };
14
+
15
+ ReactNative.NativeModules.AnalyticsBridge = AnalyticsBridge;
16
16
 
17
17
  const eventName = "event";
18
18
  const payload = {};
@@ -26,90 +26,92 @@ function clearAllMocks() {
26
26
  mock_endTimedEvent.mockClear();
27
27
  }
28
28
 
29
- describe("isValidAnalyticsData", () => {
30
- beforeEach(clearAllMocks);
29
+ describe("AnalyticsManager", () => {
30
+ describe("isValidAnalyticsData", () => {
31
+ beforeEach(clearAllMocks);
31
32
 
32
- it("returns false if eventName is not a string", () => {
33
- expect(analyticsManager.isValidAnalyticsData(42)).toBe(false);
34
- expect(analyticsManager.isValidAnalyticsData({})).toBe(false);
35
- expect(analyticsManager.isValidAnalyticsData([])).toBe(false);
36
- expect(analyticsManager.isValidAnalyticsData(() => ({}))).toBe(false);
37
- });
33
+ it("returns false if eventName is not a string", () => {
34
+ expect(analyticsManager.isValidAnalyticsData(42)).toBe(false);
35
+ expect(analyticsManager.isValidAnalyticsData({})).toBe(false);
36
+ expect(analyticsManager.isValidAnalyticsData([])).toBe(false);
37
+ expect(analyticsManager.isValidAnalyticsData(() => ({}))).toBe(false);
38
+ });
38
39
 
39
- it("returns false if payload is not an object", () => {
40
- expect(analyticsManager.isValidAnalyticsData(eventName, "string")).toBe(
41
- false
42
- );
40
+ it("returns false if payload is not an object", () => {
41
+ expect(analyticsManager.isValidAnalyticsData(eventName, "string")).toBe(
42
+ false
43
+ );
43
44
 
44
- expect(analyticsManager.isValidAnalyticsData(eventName, 42)).toBe(false);
45
+ expect(analyticsManager.isValidAnalyticsData(eventName, 42)).toBe(false);
45
46
 
46
- expect(analyticsManager.isValidAnalyticsData(eventName, () => ({}))).toBe(
47
- false
48
- );
49
- });
47
+ expect(analyticsManager.isValidAnalyticsData(eventName, () => ({}))).toBe(
48
+ false
49
+ );
50
+ });
50
51
 
51
- it("returns true if eventName is a string and payload is null or an object", () => {
52
- expect(analyticsManager.isValidAnalyticsData(eventName)).toBe(true);
52
+ it("returns true if eventName is a string and payload is null or an object", () => {
53
+ expect(analyticsManager.isValidAnalyticsData(eventName)).toBe(true);
53
54
 
54
- expect(analyticsManager.isValidAnalyticsData(eventName, payload)).toBe(
55
- true
56
- );
55
+ expect(analyticsManager.isValidAnalyticsData(eventName, payload)).toBe(
56
+ true
57
+ );
58
+ });
57
59
  });
58
- });
59
60
 
60
- describe("postAnalyticEvent", () => {
61
- beforeEach(clearAllMocks);
61
+ describe("postAnalyticEvent", () => {
62
+ beforeEach(clearAllMocks);
62
63
 
63
- it("calls the postEvent method of the analytic bridge", () => {
64
- analyticsManager.postAnalyticEvent(eventName, payload);
65
- expect(mock_postEvent).toHaveBeenCalledWith(eventName, payload);
66
- });
64
+ it("calls the postEvent method of the analytic bridge", () => {
65
+ analyticsManager.postAnalyticEvent(eventName, payload);
66
+ expect(mock_postEvent).toHaveBeenCalledWith(eventName, payload);
67
+ });
67
68
 
68
- it("skips the event if it is not valid", () => {
69
- analyticsManager.postAnalyticEvent(42);
70
- expect(mock_postTimedEvent).not.toHaveBeenCalled();
69
+ it("skips the event if it is not valid", () => {
70
+ analyticsManager.postAnalyticEvent(42);
71
+ expect(mock_postTimedEvent).not.toHaveBeenCalled();
72
+ });
71
73
  });
72
- });
73
74
 
74
- describe("providePlugins", () => {
75
- beforeEach(clearAllMocks);
75
+ describe("providePlugins", () => {
76
+ beforeEach(clearAllMocks);
76
77
 
77
- it("calls the setPlugins method of the analytic bridge", () => {
78
- const plugins = [];
79
- const plugin_configurations = {};
80
- const callback = jest.fn();
78
+ it("calls the setPlugins method of the analytic bridge", () => {
79
+ const plugins = [];
80
+ const plugin_configurations = {};
81
+ const callback = jest.fn();
81
82
 
82
- analyticsManager.providePlugins(plugins, plugin_configurations, callback);
83
+ analyticsManager.providePlugins(plugins, plugin_configurations, callback);
83
84
 
84
- expect(mock_setPlugins).toHaveBeenCalledWith(
85
- plugins,
86
- plugin_configurations,
87
- callback
88
- );
85
+ expect(mock_setPlugins).toHaveBeenCalledWith(
86
+ plugins,
87
+ plugin_configurations,
88
+ callback
89
+ );
90
+ });
89
91
  });
90
- });
91
92
 
92
- describe("startAnalyticsTimedEvent", () => {
93
- beforeEach(clearAllMocks);
93
+ describe("startAnalyticsTimedEvent", () => {
94
+ beforeEach(clearAllMocks);
94
95
 
95
- it("skips the event if it is not valid", () => {
96
- analyticsManager.startAnalyticsTimedEvent(42);
97
- expect(mock_postTimedEvent).not.toHaveBeenCalled();
96
+ it("skips the event if it is not valid", () => {
97
+ analyticsManager.startAnalyticsTimedEvent(42);
98
+ expect(mock_postTimedEvent).not.toHaveBeenCalled();
99
+ });
98
100
  });
99
- });
100
101
 
101
- describe("endAnalyticsTimedEvent", () => {
102
- beforeEach(clearAllMocks);
102
+ describe("endAnalyticsTimedEvent", () => {
103
+ beforeEach(clearAllMocks);
103
104
 
104
- it("emits a time_on_screen event and adds duration to payload", () => {
105
- analyticsManager.endAnalyticsTimedEvent(eventName, payload);
106
- const newEventName = "time_on_screen";
107
- payload.duration = "N/A";
108
- expect(mock_postEvent).toHaveBeenCalledWith(newEventName, payload);
109
- });
105
+ it("emits a time_on_screen event and adds duration to payload", () => {
106
+ analyticsManager.endAnalyticsTimedEvent(eventName, payload);
107
+ const newEventName = "time_on_screen";
108
+ payload.duration = "N/A";
109
+ expect(mock_postEvent).toHaveBeenCalledWith(newEventName, payload);
110
+ });
110
111
 
111
- it("skips the event if it is not valid", () => {
112
- analyticsManager.endAnalyticsTimedEvent(42);
113
- expect(mock_postEvent).not.toHaveBeenCalled();
112
+ it("skips the event if it is not valid", () => {
113
+ analyticsManager.endAnalyticsTimedEvent(42);
114
+ expect(mock_postEvent).not.toHaveBeenCalled();
115
+ });
114
116
  });
115
117
  });
@@ -0,0 +1,25 @@
1
+ import * as R from "ramda";
2
+ import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
3
+
4
+ export const getVideojsAnalyticPluginsConfig = async (entry: ZappEntry) => {
5
+ let videojsConfiguration = {};
6
+
7
+ const plugins = appStore.get("plugins");
8
+ const analyticPlugins = R.filter(R.propEq("type", "analytics"), plugins);
9
+
10
+ const configurations = await Promise.all(
11
+ analyticPlugins.map(async (plugin) => {
12
+ const { configuration, module } = plugin;
13
+
14
+ return module?.getPlayerConfiguration?.(configuration, entry);
15
+ })
16
+ );
17
+
18
+ configurations.forEach((analyticConfig) => {
19
+ if (typeof analyticConfig === "object" && analyticConfig !== null) {
20
+ videojsConfiguration = { ...videojsConfiguration, ...analyticConfig };
21
+ }
22
+ });
23
+
24
+ return videojsConfiguration;
25
+ };
@@ -23,10 +23,22 @@ export const TAPPING_EVENTS = {
23
23
  TAP_NAVBAR_BACK_BUTTON: "tap_navbar_back_button",
24
24
  };
25
25
 
26
+ export const SEARCH_EVENTS = {
27
+ SEARCH_EXECUTED: "search_executed",
28
+ SEARCH_CANCELED: "search_canceled",
29
+ };
30
+
31
+ export const SHARE_EVENTS = {
32
+ SHARE_INITIATED: "share_initiated",
33
+ SHARE_SUCCESS: "share_success",
34
+ };
35
+
26
36
  export const ANALYTICS_CORE_EVENTS = {
27
37
  ...LEGACY_EVENTS,
28
38
  ...SCREEN_VIEW_EVENTS,
29
39
  ...TAPPING_EVENTS,
40
+ ...SEARCH_EVENTS,
41
+ ...SHARE_EVENTS,
30
42
  };
31
43
 
32
44
  export const WEBVIEW_EVENTS = {
@@ -26,7 +26,7 @@ export const useHookAnalytics = (props): void => {
26
26
  if (screenData?.hookPlugin?.module?.runInBackground) {
27
27
  sendScreenEvent({ analyticsScreenData });
28
28
  }
29
- }, [hookPlugin.screen_id]);
29
+ }, [sendScreenEvent, screenData, hookPlugin.screen_id]);
30
30
  };
31
31
 
32
32
  export const useScreenAnalytics = (props) => {
@@ -18,6 +18,10 @@ import {
18
18
  sendHardwareBackButtonClickEvent,
19
19
  sendDownloadsEvent,
20
20
  sendScreenEvent,
21
+ sendSearchCanceledEvent,
22
+ sendSearchExecutedEvent,
23
+ sendShareInitiatedEvent,
24
+ sendShareSuccessEvent,
21
25
  } from "./AnalyticsEvents";
22
26
 
23
27
  import { postAnalyticEvent } from "./manager";
@@ -66,6 +70,10 @@ type AnalyticsFunctions = {
66
70
  item: ZappEntry;
67
71
  state: OfflineItemState;
68
72
  }) => void;
73
+ sendSearchCanceledEvent: (props: AnalyticsDefaultProperties) => void;
74
+ sendSearchExecutedEvent: (props: AnalyticsDefaultProperties) => void;
75
+ sendShareInitiatedEvent: (props: AnalyticsDefaultProperties) => void;
76
+ sendShareSuccessEvent: (props: AnalyticsDefaultProperties) => void;
69
77
  };
70
78
 
71
79
  type GetAnalyticsFunctions = (
@@ -102,6 +110,10 @@ export function getAnalyticsFunctions({
102
110
  sendHardwareBackButtonClickEvent,
103
111
  sendScreenEvent,
104
112
  sendDownloadsEvent,
113
+ sendSearchCanceledEvent,
114
+ sendSearchExecutedEvent,
115
+ sendShareInitiatedEvent,
116
+ sendShareSuccessEvent,
105
117
  };
106
118
  }
107
119