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

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 (40) hide show
  1. package/analyticsUtils/AnalyticPlayerListener.ts +155 -0
  2. package/analyticsUtils/AnalyticsEvents/index.ts +6 -0
  3. package/analyticsUtils/AnalyticsEvents/searchEvents.ts +21 -0
  4. package/analyticsUtils/PlayerAnalyticsManager.ts +90 -0
  5. package/analyticsUtils/analyticsPlugins.ts +25 -0
  6. package/analyticsUtils/events.ts +6 -0
  7. package/analyticsUtils/index.tsx +6 -0
  8. package/analyticsUtils/{analyticsTracker.ts → playerAnalyticsTracker.ts} +19 -10
  9. package/appUtils/playerManager/DelayedSeekPlayerWrapper.tsx +180 -0
  10. package/appUtils/playerManager/index.ts +9 -27
  11. package/appUtils/playerManager/player.ts +14 -5
  12. package/appUtils/playerManager/playerNative.ts +9 -3
  13. package/appUtils/playerManager/usePlayerControllerSetup.tsx +23 -4
  14. package/cellUtils/__tests__/cellUtils.test.ts +9 -20
  15. package/cellUtils/index.ts +6 -12
  16. package/dateUtils/index.ts +11 -0
  17. package/headersUtils/index.ts +1 -0
  18. package/inflatedUrlUtils/index.ts +4 -4
  19. package/localizationUtils/__tests__/localizationUtils.test.ts +72 -53
  20. package/localizationUtils/index.ts +13 -22
  21. package/numberUtils/index.ts +4 -0
  22. package/package.json +2 -2
  23. package/reactHooks/cell-click/__tests__/index.test.js +5 -0
  24. package/reactHooks/cell-click/index.ts +2 -2
  25. package/reactHooks/feed/__tests__/useInflatedUrl.test.ts +18 -3
  26. package/reactHooks/feed/useInflatedUrl.ts +44 -15
  27. package/reactHooks/navigation/__mocks__/index.ts +13 -0
  28. package/reactHooks/navigation/__mocks__/useNavigation.ts +3 -0
  29. package/reactHooks/navigation/__tests__/index.test.tsx +11 -8
  30. package/reactHooks/navigation/index.ts +21 -65
  31. package/reactHooks/player/__tests__/useAutoSeek.test.tsx +8 -1
  32. package/reactHooks/player/useAutoSeek.tsx +28 -8
  33. package/reactHooks/player/useSeek.tsx +4 -2
  34. package/reactHooks/player/useTapSeek.tsx +34 -7
  35. package/reactHooks/screen/useScreenContext.ts +4 -3
  36. package/screenState/index.ts +0 -8
  37. package/stringUtils/index.ts +5 -0
  38. package/testUtils/getByTestId.ts +14 -0
  39. package/testUtils/index.tsx +24 -22
  40. package/types.ts +4 -0
@@ -0,0 +1,155 @@
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
+ }
@@ -7,6 +7,10 @@ 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";
10
14
 
11
15
  export {
12
16
  sendScreenEvent,
@@ -18,4 +22,6 @@ export {
18
22
  sendHeaderClickEvent,
19
23
  sendHardwareBackButtonClickEvent,
20
24
  sendDownloadsEvent,
25
+ sendSearchCanceledEvent,
26
+ sendSearchExecutedEvent,
21
27
  };
@@ -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,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
+ }
@@ -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,16 @@ 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
+
26
31
  export const ANALYTICS_CORE_EVENTS = {
27
32
  ...LEGACY_EVENTS,
28
33
  ...SCREEN_VIEW_EVENTS,
29
34
  ...TAPPING_EVENTS,
35
+ ...SEARCH_EVENTS,
30
36
  };
31
37
 
32
38
  export const WEBVIEW_EVENTS = {
@@ -18,6 +18,8 @@ import {
18
18
  sendHardwareBackButtonClickEvent,
19
19
  sendDownloadsEvent,
20
20
  sendScreenEvent,
21
+ sendSearchCanceledEvent,
22
+ sendSearchExecutedEvent,
21
23
  } from "./AnalyticsEvents";
22
24
 
23
25
  import { postAnalyticEvent } from "./manager";
@@ -66,6 +68,8 @@ type AnalyticsFunctions = {
66
68
  item: ZappEntry;
67
69
  state: OfflineItemState;
68
70
  }) => void;
71
+ sendSearchCanceledEvent: (props: AnalyticsDefaultProperties) => void;
72
+ sendSearchExecutedEvent: (props: AnalyticsDefaultProperties) => void;
69
73
  };
70
74
 
71
75
  type GetAnalyticsFunctions = (
@@ -102,6 +106,8 @@ export function getAnalyticsFunctions({
102
106
  sendHardwareBackButtonClickEvent,
103
107
  sendScreenEvent,
104
108
  sendDownloadsEvent,
109
+ sendSearchCanceledEvent,
110
+ sendSearchExecutedEvent,
105
111
  };
106
112
  }
107
113
 
@@ -5,16 +5,25 @@ import { postAnalyticEvent } from "./manager";
5
5
  import { isLive } from "../playerUtils";
6
6
  import { extensionsEvents } from "./AnalyticsEvents/helper";
7
7
  import { AD_EVENT, EVENT_TYPES, PLAYER_DISPLAY_STATES } from "./events";
8
+ import { Player } from "../appUtils/playerManager/player";
8
9
 
9
- export class AnalyticsTracker {
10
+ export interface PlayerAnalyticsTrackerI {
11
+ handleAnalyticEvent(
12
+ event: QuickBrickPlayer.Events,
13
+ eventData?: QuickBrickPlayer.EventData
14
+ ): void;
15
+ setPlayer(player: Player): void;
16
+ }
17
+
18
+ export class PlayerAnalyticsTracker implements PlayerAnalyticsTrackerI {
10
19
  adTime: number | string;
11
20
  mediaTime: number | string;
12
- entry: ZappEntry;
13
21
  eventType: string;
14
22
  playerState: QuickBrickPlayer.NativePlayerState;
23
+ private player: Player;
15
24
 
16
- constructor(entry: any) {
17
- this.entry = entry;
25
+ setPlayer(player: Player) {
26
+ this.player = player;
18
27
  }
19
28
 
20
29
  isAdBreak(event: string): boolean {
@@ -30,6 +39,10 @@ export class AnalyticsTracker {
30
39
  return !!isAdBreak;
31
40
  }
32
41
 
42
+ get entry(): ZappEntry {
43
+ return this.player?.getEntry();
44
+ }
45
+
33
46
  getDuration(
34
47
  event: QuickBrickPlayer.Events,
35
48
  eventData: QuickBrickPlayer.EventData
@@ -215,13 +228,9 @@ export class AnalyticsTracker {
215
228
 
216
229
  handleAnalyticEvent(
217
230
  event: QuickBrickPlayer.Events,
218
- eventData: QuickBrickPlayer.EventData = {},
219
- entry: ZappEntry,
220
- playerState = null
231
+ eventData: QuickBrickPlayer.EventData = {}
221
232
  ) {
222
- this.entry = entry;
223
- this.playerState = playerState;
224
-
233
+ this.playerState = this.player?.getState();
225
234
  postAnalyticEvent(event, this.prepareAnalyticPayload(event, eventData));
226
235
  }
227
236
  }
@@ -0,0 +1,180 @@
1
+ import { Player } from "./player";
2
+ import { BehaviorSubject } from "rxjs";
3
+
4
+ export class DelayedSeekPlayerWrapper extends Player {
5
+ private wrappedPlayer: Player;
6
+ private delayedSeekPosition: number;
7
+ private wasPlaying: boolean;
8
+
9
+ constructor(props, player: Player) {
10
+ super(props);
11
+ this.wrappedPlayer = player;
12
+ this.delayedSeekPosition = null;
13
+
14
+ this.wrappedPlayer.addListener({
15
+ id: "Master-Wrapper-Listener",
16
+ listener: this,
17
+ });
18
+
19
+ this.onPlayerSeekComplete = this.onPlayerSeekComplete.bind(this);
20
+ }
21
+
22
+ getOverlayObservable = () => {
23
+ return this.wrappedPlayer.getOverlayObservable();
24
+ };
25
+
26
+ getEntryObservable = (): BehaviorSubject<ZappEntry | null> => {
27
+ return this.wrappedPlayer.getEntryObservable();
28
+ };
29
+
30
+ getEntry = (): ZappEntry | null => this.wrappedPlayer.getEntry();
31
+
32
+ getListener = (): QuickBrickPlayer.SharedPlayerCallBacks => {
33
+ return this.wrappedPlayer.getListener();
34
+ };
35
+
36
+ togglePlayPause = () => {
37
+ this.wrappedPlayer.togglePlayPause();
38
+ };
39
+
40
+ selectTrack = (_track) => this.wrappedPlayer.selectTrack(_track);
41
+
42
+ // Implement all default methods by delegating them to wrapped player
43
+ public seekTo = (position: number) => {
44
+ this.wrappedPlayer.seekTo(position);
45
+ };
46
+
47
+ public isPlaying = () => {
48
+ return this.wrappedPlayer.isPlaying();
49
+ };
50
+
51
+ public isPaused = () => {
52
+ return this.wrappedPlayer.isPaused();
53
+ };
54
+
55
+ public play = () => {
56
+ this.wrappedPlayer.play();
57
+ };
58
+
59
+ public pause = () => {
60
+ this.wrappedPlayer.pause();
61
+ };
62
+
63
+ getState = () => {
64
+ const currentState = this.wrappedPlayer.getState();
65
+
66
+ if (this.delayedSeekPosition === null) {
67
+ return currentState;
68
+ }
69
+
70
+ return {
71
+ ...currentState,
72
+ contentPosition: this.delayedSeekPosition,
73
+ isPaused: false,
74
+ seekPosition: this.delayedSeekPosition,
75
+ };
76
+ };
77
+
78
+ forward = (deltaTime: number) => {
79
+ if (this.delayedSeekPosition !== null) {
80
+ this.delayedSeekPosition += deltaTime;
81
+ this.playerState.seekPosition = this.delayedSeekPosition;
82
+
83
+ this.onVideoProgress({
84
+ currentTime: this.playerState.seekPosition,
85
+ duration: this.getDuration(),
86
+ seekableDuration: this.playerState.seekableDuration,
87
+ isLive: this.playerState.isLive,
88
+ });
89
+
90
+ // this.scheduleResumePlayback(DELAYED_SEEK_DELAY, this.delayedSeekPosition);
91
+
92
+ return;
93
+ }
94
+
95
+ if (this.playerState.seekPosition == null) {
96
+ this.playerState.seekPosition = this.playerState.contentPosition;
97
+ }
98
+
99
+ this.playerState.seekPosition += deltaTime;
100
+
101
+ this.wrappedPlayer.forward(deltaTime);
102
+ };
103
+
104
+ rewind = (deltaTime: number) => {
105
+ if (this.delayedSeekPosition !== null) {
106
+ this.delayedSeekPosition -= deltaTime;
107
+
108
+ if (this.delayedSeekPosition < 0) {
109
+ this.delayedSeekPosition = 0;
110
+ }
111
+
112
+ this.playerState.seekPosition = this.delayedSeekPosition;
113
+
114
+ this.onVideoProgress({
115
+ currentTime: this.playerState.seekPosition,
116
+ duration: this.getDuration(),
117
+ seekableDuration: this.playerState.seekableDuration,
118
+ isLive: this.playerState.isLive,
119
+ });
120
+
121
+ // this.scheduleResumePlayback(DELAYED_SEEK_DELAY, this.delayedSeekPosition);
122
+
123
+ return;
124
+ }
125
+
126
+ if (this.playerState.seekPosition == null) {
127
+ this.playerState.seekPosition = this.playerState.contentPosition;
128
+ }
129
+
130
+ this.playerState.seekPosition -= deltaTime;
131
+ this.wrappedPlayer.rewind(deltaTime);
132
+ };
133
+
134
+ public getConfig = () => this.wrappedPlayer.getConfig();
135
+
136
+ // TODO: replace with enum of supported orientations
137
+ isFullScreenSupported(): boolean {
138
+ return this.wrappedPlayer.isFullScreenSupported();
139
+ }
140
+
141
+ public supportsNativeControls = (): boolean =>
142
+ this.wrappedPlayer.supportsNativeControls();
143
+
144
+ public supportNativeCast = (): boolean =>
145
+ this.wrappedPlayer.supportNativeCast();
146
+
147
+ public isInDelayedSeek = () => this.delayedSeekPosition !== null;
148
+
149
+ public enterDelayedSeek() {
150
+ if (this.delayedSeekPosition !== null) {
151
+ return;
152
+ }
153
+
154
+ if (this.playerState.seekPosition === null) {
155
+ this.playerState.seekPosition = this.playerState.contentPosition;
156
+ }
157
+
158
+ this.delayedSeekPosition = this.playerState.seekPosition;
159
+
160
+ if (!this.isPaused()) {
161
+ this.wasPlaying = true;
162
+ this.wrappedPlayer.pause();
163
+ }
164
+ }
165
+
166
+ public exitDelayedSeek() {
167
+ if (this.delayedSeekPosition === null) {
168
+ return;
169
+ }
170
+
171
+ this.wrappedPlayer.seekTo(this.delayedSeekPosition);
172
+
173
+ if (this.wasPlaying) {
174
+ this.wasPlaying = false;
175
+ this.wrappedPlayer.play();
176
+ }
177
+
178
+ this.delayedSeekPosition = null;
179
+ }
180
+ }
@@ -3,7 +3,6 @@ import * as R from "ramda";
3
3
  import { subscriber } from "../../functionUtils";
4
4
  import { utilsLogger, createLogger } from "../../logger";
5
5
  import { Player } from "./player";
6
- import { AnalyticsTracker } from "../../analyticsUtils/analyticsTracker";
7
6
  import {
8
7
  hasTizenAPIs,
9
8
  subscribeToDeviceNetworkChanges,
@@ -36,7 +35,10 @@ export interface PlayerLifecycleListener {
36
35
  }
37
36
 
38
37
  type PlayersMap = {
39
- [id: string]: { player: Player; isInViewport: boolean };
38
+ [id: string]: {
39
+ player: Player;
40
+ isInViewport: boolean;
41
+ };
40
42
  };
41
43
 
42
44
  export class PlayerManager {
@@ -45,7 +47,6 @@ export class PlayerManager {
45
47
  private playersMap: PlayersMap = {};
46
48
  private manager = subscriber();
47
49
  private castingReceiver: Player;
48
- private analyticsTracker: AnalyticsTracker;
49
50
  private lifecycleListeners: PlayerLifecycleListener[] = [];
50
51
 
51
52
  public static getInstance() {
@@ -56,7 +57,7 @@ export class PlayerManager {
56
57
  return PlayerManager.instance;
57
58
  }
58
59
 
59
- public getActivePlayerId = (): String | null => {
60
+ public getActivePlayerId = (): string | null => {
60
61
  return this.activePlayerId;
61
62
  };
62
63
 
@@ -101,7 +102,10 @@ export class PlayerManager {
101
102
  }
102
103
 
103
104
  private addPlayer = (id: string, player: Player) => {
104
- this.playersMap[id] = { player: player, isInViewport: false };
105
+ this.playersMap[id] = {
106
+ player: player,
107
+ isInViewport: false,
108
+ };
105
109
  };
106
110
 
107
111
  public isPlayerRegistered = (id: string) => !!this.playersMap[id];
@@ -246,28 +250,6 @@ export class PlayerManager {
246
250
  this.castingReceiver = null;
247
251
  }
248
252
 
249
- /**
250
- * Handles analytic events, generates a new analytics tracker and transmits events
251
- * Passes entry data, and playerState to the tracker for additional context
252
- * The end result is an event formatted and passed to AnalyticsBridge.postEvent
253
- * When we get the synthetic event we need to pull the data in the e object
254
- * e contains the return value from native
255
- */
256
- public handleAnalyticEvent(event, data = {}, entry: ZappEntry) {
257
- const playerState = this.getActivePlayer()?.getState();
258
-
259
- if (!this.analyticsTracker?.handleAnalyticEvent) {
260
- this.analyticsTracker = new AnalyticsTracker(entry);
261
- }
262
-
263
- this.analyticsTracker?.handleAnalyticEvent?.(
264
- event,
265
- data,
266
- entry,
267
- playerState
268
- );
269
- }
270
-
271
253
  /**
272
254
  * Method retrieves the instantiated player instance controller
273
255
  * Instance controller exposes methods like getContentDuration, getContentPosision