@applicaster/zapp-react-native-utils 12.0.0-alpha.7725319213 → 12.0.0-alpha.7843515010
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.
- package/actionsExecutor/ActionExecutorContext.tsx +16 -8
- package/analyticsUtils/AnalyticPlayerListener.ts +141 -0
- package/analyticsUtils/AnalyticsEvents/index.ts +13 -0
- package/analyticsUtils/AnalyticsEvents/searchEvents.ts +21 -0
- package/analyticsUtils/AnalyticsEvents/sendShareEvent.ts +21 -0
- package/analyticsUtils/PlayerAnalyticsManager.ts +90 -0
- package/analyticsUtils/__tests__/analyticsManager.test.js +75 -73
- package/analyticsUtils/analyticsPlugins.ts +25 -0
- package/analyticsUtils/events.ts +12 -0
- package/analyticsUtils/helpers/hooks.ts +1 -1
- package/analyticsUtils/index.tsx +12 -0
- package/analyticsUtils/{analyticsTracker.ts → playerAnalyticsTracker.ts} +19 -10
- package/appUtils/HooksManager/index.js +3 -1
- package/appUtils/accessibilityManager/const.ts +50 -0
- package/appUtils/accessibilityManager/hooks.ts +40 -0
- package/appUtils/accessibilityManager/index.ts +166 -0
- package/appUtils/accessibilityManager/logger.ts +5 -0
- package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +2 -3
- package/appUtils/focusManager/__tests__/focusManager.test.js +4 -24
- package/appUtils/focusManager/__tests__/index.test.ts +2 -3
- package/appUtils/focusManager/index.ts +76 -57
- package/appUtils/focusManager/treeDataStructure/Utils/index.js +75 -35
- package/appUtils/focusManager/utils/index.ts +100 -0
- package/appUtils/focusManagerAux/index.ts +76 -0
- package/appUtils/focusManagerAux/utils/index.ts +100 -0
- package/appUtils/index.js +2 -0
- package/appUtils/keyCodes/__tests__/__snapshots__/keyCodes.test.js.snap +1 -1
- package/appUtils/keyCodes/__tests__/keyCodes.test.js +80 -85
- package/appUtils/keyCodes/keys.web.js +9 -0
- package/appUtils/keyCodes/keysByPlatform.js +11 -1
- package/appUtils/platform/const.ts +25 -0
- package/appUtils/platform/index.ts +3 -0
- package/appUtils/platform/platformUtils.ts +185 -0
- package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +53 -0
- package/appUtils/playerManager/conts.ts +6 -0
- package/appUtils/playerManager/index.ts +20 -32
- package/appUtils/playerManager/nativePlayerManager.ts +12 -0
- package/appUtils/playerManager/player.ts +56 -9
- package/appUtils/playerManager/playerFactory.ts +12 -10
- package/appUtils/playerManager/playerNative.ts +37 -15
- package/appUtils/playerManager/usePlayerControllerSetup.tsx +7 -1
- package/appUtils/playerManager/usePlayerState.tsx +13 -1
- package/appUtils/playerManager/usePlayerTitleSummaryOverlay.tsx +50 -0
- package/arrayUtils/__tests__/isFilledArray.test.ts +63 -0
- package/arrayUtils/index.ts +5 -0
- package/booleanUtils/index.ts +4 -4
- package/cellUtils/__tests__/cellUtils.test.ts +48 -0
- package/cellUtils/__tests__/fixtures.ts +13 -0
- package/cellUtils/index.ts +65 -7
- package/dateUtils/index.ts +11 -0
- package/focusManager/index.ts +1 -1
- package/functionUtils/__tests__/__snapshots__/functionUtils.test.js.snap +2 -2
- package/functionUtils/__tests__/functionUtils.test.js +244 -248
- package/headersUtils/index.ts +1 -0
- package/index.d.ts +15 -0
- package/inflatedUrlUtils/index.ts +4 -4
- package/keyboardState/index.ts +0 -0
- package/localizationUtils/__tests__/localizationUtils.test.ts +78 -55
- package/localizationUtils/index.ts +13 -19
- package/logger/index.ts +1 -1
- package/manifestUtils/defaultManifestConfigurations/generalContent.js +6 -0
- package/manifestUtils/defaultManifestConfigurations/player.js +10 -1
- package/manifestUtils/index.js +5 -1
- package/manifestUtils/secondaryImage/index.js +18 -15
- package/modalState/index.ts +57 -0
- package/navigationUtils/index.ts +104 -7
- package/numberUtils/__tests__/isLikeNumber.test.ts +18 -0
- package/numberUtils/__tests__/toNumber.test.ts +2 -2
- package/numberUtils/index.ts +9 -18
- package/package.json +3 -2
- package/playerUtils/configurationGenerator.ts +11 -1
- package/playerUtils/imaScriptDom.ts +59 -0
- package/pluginUtils/index.ts +11 -2
- package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +2 -0
- package/reactHooks/autoscrolling/__tests__/{useTrackedView.test.ts → useTrackedView.test.tsx} +18 -1
- package/reactHooks/cell-click/__tests__/index.test.js +10 -1
- package/reactHooks/cell-click/index.ts +12 -12
- package/reactHooks/debugging/__tests__/index.test.js +81 -11
- package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +30 -70
- package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +6 -2
- package/reactHooks/feed/__tests__/useInflatedUrl.test.ts +18 -3
- package/reactHooks/feed/useBuildPipesUrl.ts +7 -10
- package/reactHooks/feed/useFeedRefresh.tsx +9 -7
- package/reactHooks/feed/useInflatedUrl.ts +44 -15
- package/reactHooks/flatList/useLoadNextPageIfNeeded.ts +16 -9
- package/reactHooks/index.ts +2 -0
- package/reactHooks/layout/__tests__/{index.test.js → index.test.tsx} +66 -59
- package/reactHooks/layout/getDeviceInfo/index.ts +4 -2
- package/reactHooks/layout/types/index.ts +2 -0
- package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.native.test.js +11 -16
- package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.test.js +12 -14
- package/reactHooks/layout/useDimensions/useDimensions.ts +13 -7
- package/reactHooks/navigation/__mocks__/index.ts +15 -0
- package/reactHooks/navigation/__mocks__/useNavigation.ts +7 -0
- package/reactHooks/navigation/__tests__/index.test.tsx +240 -81
- package/reactHooks/navigation/index.ts +239 -80
- package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +3 -1
- package/reactHooks/resolvers/useCellResolver.ts +5 -1
- package/reactHooks/screen/__mocks__/useScreenContext.ts +3 -1
- package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +21 -23
- package/reactHooks/screen/index.ts +4 -0
- package/reactHooks/screen/useScreenBackgroundColor.ts +23 -0
- package/reactHooks/screen/useScreenContext.ts +4 -4
- package/reactHooks/screen/useScreenData.ts +1 -1
- package/reactHooks/state/useRivers.ts +3 -1
- package/reactHooks/useListenEventBusEvent.ts +1 -4
- package/reactHooks/videoModal/hooks/useVideoModalScreenData.tsx +10 -9
- package/reactUtils/index.ts +104 -0
- package/riverComponetsMeasurementProvider/index.tsx +2 -2
- package/stringUtils/index.ts +5 -0
- package/testUtils/getByTestId.ts +14 -0
- package/testUtils/index.tsx +38 -23
- package/types.ts +4 -0
- package/appUtils/focusManager/FocusableEvents.ts +0 -8
- package/appUtils/focusManager/treeDataStructure/Utils/__tests__/Utils_android.test.js +0 -1094
- package/appUtils/focusManager/treeDataStructure/Utils/index.android.js +0 -261
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { BehaviorSubject } from "rxjs";
|
|
2
|
+
|
|
3
|
+
import { sessionStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/SessionStorage";
|
|
4
|
+
|
|
5
|
+
import { PLATFORM_KEYS, PLATFORMS } from "./const";
|
|
6
|
+
import { createLogger, utilsLogger } from "../../logger";
|
|
7
|
+
|
|
8
|
+
declare global {
|
|
9
|
+
interface Window {
|
|
10
|
+
VIZIO?: {
|
|
11
|
+
exitApplication: () => void;
|
|
12
|
+
Chromevox: {
|
|
13
|
+
play: (text: string) => void;
|
|
14
|
+
};
|
|
15
|
+
setClosedCaptionHandler: (
|
|
16
|
+
callback: (isCCEnabled: boolean) => void
|
|
17
|
+
) => void;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const { log_debug } = createLogger({
|
|
23
|
+
category: "General",
|
|
24
|
+
subsystem: "PlatformUtils",
|
|
25
|
+
parent: utilsLogger,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export const getUserAgent = () =>
|
|
29
|
+
window?.navigator?.userAgent || global?.navigator?.userAgent;
|
|
30
|
+
|
|
31
|
+
/** VIZIO UTILS */
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Checks if we are on the Vizio platform by using the userAgent string
|
|
35
|
+
*
|
|
36
|
+
* Use this method when you need to identify the platform on runtime
|
|
37
|
+
* before the VIZIO Companion Library has loaded
|
|
38
|
+
*/
|
|
39
|
+
export const isVizioPlatform = () => {
|
|
40
|
+
const userAgent = getUserAgent();
|
|
41
|
+
|
|
42
|
+
const isVizioAgent =
|
|
43
|
+
userAgent.includes(PLATFORMS.vizio) ||
|
|
44
|
+
userAgent.includes(PLATFORMS.smartcast) ||
|
|
45
|
+
userAgent.includes(PLATFORMS.conjure);
|
|
46
|
+
|
|
47
|
+
return isVizioAgent;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Checks if we are on the Vizio platform by checking for the global VIZIO object
|
|
52
|
+
* and the VIZIO Companion Library. This method does not use the userAgent string,
|
|
53
|
+
* because it mainly checks whether we have access to apis, which may not be available yet
|
|
54
|
+
*/
|
|
55
|
+
export const hasVizioAPIs = () => {
|
|
56
|
+
const hasAPIs =
|
|
57
|
+
typeof window.VIZIO !== "undefined" &&
|
|
58
|
+
window?.applicaster?.vizioLibraryDidLoad;
|
|
59
|
+
|
|
60
|
+
return hasAPIs;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Manages device based closed captioning state
|
|
65
|
+
* Returns an observable that emits the current state and updates whenever it changes
|
|
66
|
+
*/
|
|
67
|
+
export class ClosedCaptioningManager {
|
|
68
|
+
private ccState$ = new BehaviorSubject<boolean>(false);
|
|
69
|
+
private static ccManagerInstance: ClosedCaptioningManager;
|
|
70
|
+
|
|
71
|
+
private constructor() {
|
|
72
|
+
this.initialize();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static getInstance(): ClosedCaptioningManager {
|
|
76
|
+
if (!ClosedCaptioningManager.ccManagerInstance) {
|
|
77
|
+
ClosedCaptioningManager.ccManagerInstance = new ClosedCaptioningManager();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return ClosedCaptioningManager.ccManagerInstance;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async initialize() {
|
|
84
|
+
const existingState = await sessionStorage.getItem(
|
|
85
|
+
PLATFORM_KEYS.deviceClosedCaptioningEnabled
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
log_debug("Initializing closed captioning manager", { existingState });
|
|
89
|
+
|
|
90
|
+
if (existingState !== null) {
|
|
91
|
+
this.ccState$.next(existingState === "true" || existingState === true);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (hasVizioAPIs()) {
|
|
95
|
+
window.VIZIO!.setClosedCaptionHandler((isCCEnabled) => {
|
|
96
|
+
log_debug("CC state changed", { isCCEnabled });
|
|
97
|
+
|
|
98
|
+
sessionStorage.setItem(
|
|
99
|
+
PLATFORM_KEYS.deviceClosedCaptioningEnabled,
|
|
100
|
+
isCCEnabled
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
this.ccState$.next(isCCEnabled);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
getCurrentState(): boolean {
|
|
109
|
+
return this.ccState$.getValue();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
getStateAsObservable() {
|
|
113
|
+
return this.ccState$.asObservable();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Subscribe to closed captioning state changes
|
|
119
|
+
* @returns Observable<boolean>
|
|
120
|
+
* @example
|
|
121
|
+
* const subscription = getClosedCaptionState().subscribe(
|
|
122
|
+
* isEnabled => setClosedCaptionState(isEnabled)
|
|
123
|
+
* );
|
|
124
|
+
* subscription.unsubscribe(), []);
|
|
125
|
+
*/
|
|
126
|
+
export const getClosedCaptionState = () => {
|
|
127
|
+
const ccManager = ClosedCaptioningManager.getInstance();
|
|
128
|
+
|
|
129
|
+
return ccManager.getStateAsObservable();
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Manages device based closed captioning state
|
|
134
|
+
* Returns an observable that emits the current state and updates whenever it changes
|
|
135
|
+
*/
|
|
136
|
+
export class TTSManager {
|
|
137
|
+
private ttsState$ = new BehaviorSubject<boolean>(false);
|
|
138
|
+
private static ttsManagerInstance: TTSManager;
|
|
139
|
+
|
|
140
|
+
private constructor() {
|
|
141
|
+
this.initialize();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
static getInstance(): TTSManager {
|
|
145
|
+
if (!TTSManager.ttsManagerInstance) {
|
|
146
|
+
TTSManager.ttsManagerInstance = new TTSManager();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return TTSManager.ttsManagerInstance;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async initialize() {
|
|
153
|
+
if (!isVizioPlatform()) return;
|
|
154
|
+
|
|
155
|
+
document.addEventListener(
|
|
156
|
+
"VIZIO_TTS_ENABLED",
|
|
157
|
+
() => {
|
|
158
|
+
this.ttsState$.next(true);
|
|
159
|
+
},
|
|
160
|
+
false
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
document.addEventListener(
|
|
164
|
+
"VIZIO_TTS_DISABLED",
|
|
165
|
+
() => {
|
|
166
|
+
this.ttsState$.next(false);
|
|
167
|
+
},
|
|
168
|
+
false
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
getCurrentState(): boolean {
|
|
173
|
+
return this.ttsState$.getValue();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
getStateAsObservable() {
|
|
177
|
+
return this.ttsState$.asObservable();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
readText(text: string) {
|
|
181
|
+
if (!window.VIZIO?.Chromevox) return;
|
|
182
|
+
|
|
183
|
+
window.VIZIO.Chromevox.play(text);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
@@ -41,6 +41,11 @@ export type ChapterMarkerEvent = {
|
|
|
41
41
|
actions: ActionChapter[];
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
+
export type TitleSummaryEvent = {
|
|
45
|
+
title: string | number;
|
|
46
|
+
summary: string | number;
|
|
47
|
+
};
|
|
48
|
+
|
|
44
49
|
type ChapterMarkersObserverProps = {
|
|
45
50
|
player: Player;
|
|
46
51
|
};
|
|
@@ -60,6 +65,11 @@ export type PlayNextState = PlayNextConfig & {
|
|
|
60
65
|
export class OverlaysObserver {
|
|
61
66
|
readonly chapterSubject: BehaviorSubject<ChapterMarkerEvent>;
|
|
62
67
|
private playNextSubject: BehaviorSubject<PlayNextState>;
|
|
68
|
+
private titleSummarySubject: BehaviorSubject<TitleSummaryEvent>;
|
|
69
|
+
private feedUrl: string;
|
|
70
|
+
private reloadData: () => void;
|
|
71
|
+
private updateTitleAndDescription: (data: any) => void;
|
|
72
|
+
private feedDataInterval: any;
|
|
63
73
|
private releasePlayerObserver?: () => void;
|
|
64
74
|
readonly entry: ZappEntry;
|
|
65
75
|
private chapterMarkerEvents: ChapterMarkerEvent[];
|
|
@@ -70,14 +80,55 @@ export class OverlaysObserver {
|
|
|
70
80
|
constructor({ player }: ChapterMarkersObserverProps) {
|
|
71
81
|
this.chapterSubject = new BehaviorSubject(null);
|
|
72
82
|
this.playNextSubject = new BehaviorSubject(null);
|
|
83
|
+
|
|
84
|
+
this.titleSummarySubject = new BehaviorSubject<TitleSummaryEvent>({
|
|
85
|
+
title: player.getEntry()?.title || "",
|
|
86
|
+
summary: player.getEntry()?.summary || "",
|
|
87
|
+
});
|
|
88
|
+
|
|
73
89
|
this.entry = player.getEntry();
|
|
74
90
|
this.player = player;
|
|
75
91
|
|
|
76
92
|
this.chapterMarkerEvents = this.prepareChapterMarkers();
|
|
77
93
|
this.releasePlayerObserver = this.subscribeToPlayerEvents();
|
|
94
|
+
this.feedUrl = "";
|
|
95
|
+
this.reloadData = () => {};
|
|
96
|
+
this.updateTitleAndDescription = () => {};
|
|
97
|
+
this.feedDataInterval = null;
|
|
78
98
|
void this.preparePlayNext();
|
|
79
99
|
}
|
|
80
100
|
|
|
101
|
+
private setupFeedDataInterval(interval: number) {
|
|
102
|
+
if (this.feedUrl && this.reloadData && this.updateTitleAndDescription) {
|
|
103
|
+
this.feedDataInterval = setInterval(() => {
|
|
104
|
+
this.reloadData();
|
|
105
|
+
}, interval * 1000);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
public clearFeedDataInterval() {
|
|
110
|
+
if (this.feedDataInterval) {
|
|
111
|
+
clearInterval(this.feedDataInterval);
|
|
112
|
+
this.feedDataInterval = null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public setFeedDataHandlers(
|
|
117
|
+
feedUrl: string,
|
|
118
|
+
reloadData: () => void,
|
|
119
|
+
interval: number,
|
|
120
|
+
updateTitleAndDescription: (data: any) => void
|
|
121
|
+
) {
|
|
122
|
+
this.feedUrl = feedUrl;
|
|
123
|
+
this.reloadData = reloadData;
|
|
124
|
+
this.updateTitleAndDescription = updateTitleAndDescription;
|
|
125
|
+
this.setupFeedDataInterval(interval);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
public getTitleSummaryObservable(): Observable<TitleSummaryEvent> {
|
|
129
|
+
return this.titleSummarySubject.asObservable().pipe(distinctUntilChanged());
|
|
130
|
+
}
|
|
131
|
+
|
|
81
132
|
handleUserCancelPlayNext = () => {
|
|
82
133
|
this.isCanceledByUser = true;
|
|
83
134
|
this.playNextSubject.next(null);
|
|
@@ -281,7 +332,9 @@ export class OverlaysObserver {
|
|
|
281
332
|
onPlayerClose = () => {
|
|
282
333
|
this.chapterSubject.complete();
|
|
283
334
|
this.playNextSubject.complete();
|
|
335
|
+
this.titleSummarySubject.complete();
|
|
284
336
|
this.releasePlayerObserver?.();
|
|
337
|
+
this.clearFeedDataInterval();
|
|
285
338
|
this.releasePlayerObserver = null;
|
|
286
339
|
};
|
|
287
340
|
|
|
@@ -7,6 +7,7 @@ export enum SharedPlayerCallBacksKeys {
|
|
|
7
7
|
OnPlayerPause = "onPlayerPause",
|
|
8
8
|
OnLoad = "onLoad",
|
|
9
9
|
OnError = "onError",
|
|
10
|
+
OnVideoError = "onVideoError",
|
|
10
11
|
OnVideoEnd = "onVideoEnd",
|
|
11
12
|
OnPlaybackRateChange = "onPlaybackRateChange",
|
|
12
13
|
OnVideoLoad = "onVideoLoad",
|
|
@@ -20,6 +21,11 @@ export enum SharedPlayerCallBacksKeys {
|
|
|
20
21
|
OnPlayerMute = "onPlayerMute",
|
|
21
22
|
OnPlayerUnmute = "onPlayerUnmute",
|
|
22
23
|
|
|
24
|
+
onVideoFullscreenPlayerDidDismiss = "onVideoFullscreenPlayerDidDismiss",
|
|
25
|
+
onVideoFullscreenPlayerDidPresent = "onVideoFullscreenPlayerDidPresent",
|
|
26
|
+
onVideoFullscreenPlayerWillDismiss = "onVideoFullscreenPlayerWillDismiss",
|
|
27
|
+
onVideoFullscreenPlayerWillPresent = "onVideoFullscreenPlayerWillPresent",
|
|
28
|
+
|
|
23
29
|
OnAdBegin = "onAdBegin",
|
|
24
30
|
OnAdBreakBegin = "onAdBreakBegin",
|
|
25
31
|
OnAdBreakEnd = "onAdBreakEnd",
|
|
@@ -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,
|
|
@@ -11,6 +10,7 @@ import {
|
|
|
11
10
|
} from "@applicaster/quick-brick-core/App/NetworkStatusProvider/utils";
|
|
12
11
|
import { setUserLanguagePreference } from "./userLanguagePreference";
|
|
13
12
|
import { PlayerRole } from "./conts";
|
|
13
|
+
import { RNPlayerManager } from "./nativePlayerManager";
|
|
14
14
|
|
|
15
15
|
const { log_error, log_debug, log_warning } = createLogger({
|
|
16
16
|
category: "General",
|
|
@@ -36,7 +36,10 @@ export interface PlayerLifecycleListener {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
type PlayersMap = {
|
|
39
|
-
[id: string]: {
|
|
39
|
+
[id: string]: {
|
|
40
|
+
player: Player;
|
|
41
|
+
isInViewport: boolean;
|
|
42
|
+
};
|
|
40
43
|
};
|
|
41
44
|
|
|
42
45
|
export class PlayerManager {
|
|
@@ -45,7 +48,6 @@ export class PlayerManager {
|
|
|
45
48
|
private playersMap: PlayersMap = {};
|
|
46
49
|
private manager = subscriber();
|
|
47
50
|
private castingReceiver: Player;
|
|
48
|
-
private analyticsTracker: AnalyticsTracker;
|
|
49
51
|
private lifecycleListeners: PlayerLifecycleListener[] = [];
|
|
50
52
|
|
|
51
53
|
public static getInstance() {
|
|
@@ -56,7 +58,7 @@ export class PlayerManager {
|
|
|
56
58
|
return PlayerManager.instance;
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
public getActivePlayerId = ():
|
|
61
|
+
public getActivePlayerId = (): string | null => {
|
|
60
62
|
return this.activePlayerId;
|
|
61
63
|
};
|
|
62
64
|
|
|
@@ -101,7 +103,10 @@ export class PlayerManager {
|
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
private addPlayer = (id: string, player: Player) => {
|
|
104
|
-
this.playersMap[id] = {
|
|
106
|
+
this.playersMap[id] = {
|
|
107
|
+
player: player,
|
|
108
|
+
isInViewport: false,
|
|
109
|
+
};
|
|
105
110
|
};
|
|
106
111
|
|
|
107
112
|
public isPlayerRegistered = (id: string) => !!this.playersMap[id];
|
|
@@ -164,6 +169,10 @@ export class PlayerManager {
|
|
|
164
169
|
this.addPlayer(id, playerController);
|
|
165
170
|
|
|
166
171
|
if (playerController.playerRole === PlayerRole.Primary) {
|
|
172
|
+
if (playerController.playerPluginId !== "QuickBrickPlayerPlugin") {
|
|
173
|
+
RNPlayerManager?.["QuickBrickPlayerPlugin"]?.stopBackgroundPlayback?.();
|
|
174
|
+
}
|
|
175
|
+
|
|
167
176
|
playerController.addListener({
|
|
168
177
|
id: this.getPlayerListenerId(id),
|
|
169
178
|
listener: {
|
|
@@ -246,28 +255,6 @@ export class PlayerManager {
|
|
|
246
255
|
this.castingReceiver = null;
|
|
247
256
|
}
|
|
248
257
|
|
|
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
258
|
/**
|
|
272
259
|
* Method retrieves the instantiated player instance controller
|
|
273
260
|
* Instance controller exposes methods like getContentDuration, getContentPosision
|
|
@@ -361,9 +348,9 @@ export class PlayerManager {
|
|
|
361
348
|
// TODO: Remove
|
|
362
349
|
if (this.castingReceiver) {
|
|
363
350
|
this.castingReceiver.rewind(deltaTime);
|
|
351
|
+
} else {
|
|
352
|
+
this.getActivePlayer()?.rewind(deltaTime);
|
|
364
353
|
}
|
|
365
|
-
|
|
366
|
-
this.getActivePlayer()?.rewind(deltaTime);
|
|
367
354
|
}
|
|
368
355
|
|
|
369
356
|
public forward(deltaTime = null) {
|
|
@@ -371,9 +358,9 @@ export class PlayerManager {
|
|
|
371
358
|
|
|
372
359
|
if (this.castingReceiver) {
|
|
373
360
|
this.castingReceiver.forward(deltaTime);
|
|
361
|
+
} else {
|
|
362
|
+
this.getActivePlayer()?.forward(deltaTime);
|
|
374
363
|
}
|
|
375
|
-
|
|
376
|
-
this.getActivePlayer()?.forward(deltaTime);
|
|
377
364
|
}
|
|
378
365
|
|
|
379
366
|
public seeking(time) {
|
|
@@ -436,7 +423,7 @@ export class PlayerManager {
|
|
|
436
423
|
}
|
|
437
424
|
|
|
438
425
|
// Call method on player just in case
|
|
439
|
-
return this.getActivePlayer()?.
|
|
426
|
+
return this.getActivePlayer()?.selectTrack(track);
|
|
440
427
|
}
|
|
441
428
|
|
|
442
429
|
public isRegistered() {
|
|
@@ -461,6 +448,7 @@ export class PlayerManager {
|
|
|
461
448
|
if (this.castingReceiver) {
|
|
462
449
|
this.castingReceiver.closeNativePlayer();
|
|
463
450
|
} else {
|
|
451
|
+
this.getActivePlayer().closeNativePlayer();
|
|
464
452
|
this.invokeHandler("close");
|
|
465
453
|
}
|
|
466
454
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { NativeModules } from "react-native";
|
|
2
|
+
import { isApplePlatform } from "../../reactUtils";
|
|
3
|
+
|
|
4
|
+
export const RNPlayerManager = {
|
|
5
|
+
QuickBrickPlayerPlugin: isApplePlatform()
|
|
6
|
+
? NativeModules.PlayerModule
|
|
7
|
+
: NativeModules.QuickBrickDefaultPlayerModule,
|
|
8
|
+
KalturaPlayerPlugin: isApplePlatform()
|
|
9
|
+
? NativeModules.KalturaPlayerModule
|
|
10
|
+
: NativeModules.QBKalturaPlayerModule,
|
|
11
|
+
"quick-brick-player-brightcove": NativeModules.BrightcovePlayerModule,
|
|
12
|
+
};
|
|
@@ -42,7 +42,7 @@ export class Player {
|
|
|
42
42
|
|
|
43
43
|
protected startPosition?: number | null;
|
|
44
44
|
readonly playerRole: PlayerRole = PlayerRole.Unspecified;
|
|
45
|
-
private
|
|
45
|
+
private overlaysObserver?: OverlaysObserver | null;
|
|
46
46
|
private entryObservable?: BehaviorSubject<ZappEntry> | null;
|
|
47
47
|
|
|
48
48
|
protected listeners: {
|
|
@@ -77,7 +77,7 @@ export class Player {
|
|
|
77
77
|
audioTracks: [],
|
|
78
78
|
audioTrackId: null,
|
|
79
79
|
textTrackId: null,
|
|
80
|
-
}
|
|
80
|
+
},
|
|
81
81
|
};
|
|
82
82
|
|
|
83
83
|
this.playerId = props.playerId || "error, no player id";
|
|
@@ -95,11 +95,11 @@ export class Player {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
getOverlayObservable = () => {
|
|
98
|
-
if (!this.
|
|
99
|
-
this.
|
|
98
|
+
if (!this.overlaysObserver) {
|
|
99
|
+
this.overlaysObserver = new OverlaysObserver({ player: this });
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
return this.
|
|
102
|
+
return this.overlaysObserver;
|
|
103
103
|
};
|
|
104
104
|
|
|
105
105
|
getEntryObservable = (): BehaviorSubject<ZappEntry | null> => {
|
|
@@ -278,6 +278,10 @@ export class Player {
|
|
|
278
278
|
return this.playerState.isBuffering;
|
|
279
279
|
};
|
|
280
280
|
|
|
281
|
+
isReadyToPlay = (): boolean => {
|
|
282
|
+
return this.playerState.isReadyToPlay;
|
|
283
|
+
};
|
|
284
|
+
|
|
281
285
|
// Methods to call actions on the player
|
|
282
286
|
seekTo = (_position: number) => {};
|
|
283
287
|
|
|
@@ -355,6 +359,13 @@ export class Player {
|
|
|
355
359
|
});
|
|
356
360
|
};
|
|
357
361
|
|
|
362
|
+
onVideoError = (error: Error) => {
|
|
363
|
+
this.invokeListenersUpdate({
|
|
364
|
+
callbackName: SharedPlayerCallBacksKeys.OnVideoError,
|
|
365
|
+
event: error,
|
|
366
|
+
});
|
|
367
|
+
};
|
|
368
|
+
|
|
358
369
|
onError = (error: Error) => {
|
|
359
370
|
this.invokeListenersUpdate({
|
|
360
371
|
callbackName: SharedPlayerCallBacksKeys.OnError,
|
|
@@ -410,6 +421,32 @@ export class Player {
|
|
|
410
421
|
});
|
|
411
422
|
};
|
|
412
423
|
|
|
424
|
+
onVideoFullscreenPlayerWillDismiss = () => {
|
|
425
|
+
this.invokeListenersUpdate({
|
|
426
|
+
callbackName:
|
|
427
|
+
SharedPlayerCallBacksKeys.onVideoFullscreenPlayerWillDismiss,
|
|
428
|
+
});
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
onVideoFullscreenPlayerDidDismiss = () => {
|
|
432
|
+
this.invokeListenersUpdate({
|
|
433
|
+
callbackName: SharedPlayerCallBacksKeys.onVideoFullscreenPlayerDidDismiss,
|
|
434
|
+
});
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
onVideoFullscreenPlayerWillPresent = () => {
|
|
438
|
+
this.invokeListenersUpdate({
|
|
439
|
+
callbackName:
|
|
440
|
+
SharedPlayerCallBacksKeys.onVideoFullscreenPlayerWillPresent,
|
|
441
|
+
});
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
onVideoFullscreenPlayerDidPresent = () => {
|
|
445
|
+
this.invokeListenersUpdate({
|
|
446
|
+
callbackName: SharedPlayerCallBacksKeys.onVideoFullscreenPlayerDidPresent,
|
|
447
|
+
});
|
|
448
|
+
};
|
|
449
|
+
|
|
413
450
|
public invokeListenersUpdate = ({
|
|
414
451
|
callbackName,
|
|
415
452
|
event = {},
|
|
@@ -620,6 +657,7 @@ export class Player {
|
|
|
620
657
|
onPlayerSeekComplete: this.onSeekComplete,
|
|
621
658
|
onVideoEnd: this.onVideoEnd,
|
|
622
659
|
onError: this.onError,
|
|
660
|
+
onVideoError: this.onVideoError,
|
|
623
661
|
onLoad: this.onLoad,
|
|
624
662
|
onPlayerPause: this.onPlayerPause,
|
|
625
663
|
onPlayerResume: this.onPlayerResume,
|
|
@@ -630,6 +668,12 @@ export class Player {
|
|
|
630
668
|
onBufferStart: this.onBufferStart,
|
|
631
669
|
onBufferComplete: this.onBufferComplete,
|
|
632
670
|
|
|
671
|
+
onPlayerClose: this.onPlayerClose,
|
|
672
|
+
onVideoFullscreenPlayerWillPresent: this.onVideoFullscreenPlayerWillPresent,
|
|
673
|
+
onVideoFullscreenPlayerDidPresent: this.onVideoFullscreenPlayerDidPresent,
|
|
674
|
+
onVideoFullscreenPlayerWillDismiss: this.onVideoFullscreenPlayerWillDismiss,
|
|
675
|
+
onVideoFullscreenPlayerDidDismiss: this.onVideoFullscreenPlayerDidDismiss,
|
|
676
|
+
|
|
633
677
|
// Ads Callbacks:
|
|
634
678
|
onAdBegin: this.onAdBegin,
|
|
635
679
|
onAdBreakBegin: this.onAdBreakBegin,
|
|
@@ -648,9 +692,10 @@ export class Player {
|
|
|
648
692
|
play = () => {};
|
|
649
693
|
pause = () => {};
|
|
650
694
|
disableBufferAnimation = (): boolean => true;
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
) => {};
|
|
695
|
+
|
|
696
|
+
setPlaybackRate = (_rate) => {};
|
|
697
|
+
startSleepTimer = (_timestamp) => {};
|
|
698
|
+
cancelSleepTimer = () => {};
|
|
654
699
|
|
|
655
700
|
getPluginConfiguration = () => null;
|
|
656
701
|
appStateChange = (_appState, _previousAppState) => {};
|
|
@@ -686,5 +731,7 @@ export class Player {
|
|
|
686
731
|
return true;
|
|
687
732
|
}
|
|
688
733
|
|
|
689
|
-
public supportsNativeControls = ():boolean => false
|
|
734
|
+
public supportsNativeControls = (): boolean => false;
|
|
735
|
+
public supportNativeCast = (): boolean => false;
|
|
736
|
+
public destroy = () => {};
|
|
690
737
|
}
|
|
@@ -9,21 +9,23 @@ type PlayerFactoryItem = {
|
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
type PlayerFactoryProps = {
|
|
12
|
-
player: any
|
|
13
|
-
playerId: string
|
|
14
|
-
autoplay: boolean
|
|
15
|
-
entry: ZappEntry
|
|
16
|
-
muted: boolean
|
|
17
|
-
playerPluginId: string
|
|
18
|
-
screenConfig: Record<string, any
|
|
19
|
-
playerRole: PlayerRole
|
|
20
|
-
}
|
|
12
|
+
player: any;
|
|
13
|
+
playerId: string;
|
|
14
|
+
autoplay: boolean;
|
|
15
|
+
entry: ZappEntry;
|
|
16
|
+
muted: boolean;
|
|
17
|
+
playerPluginId: string;
|
|
18
|
+
screenConfig: Record<string, any>;
|
|
19
|
+
playerRole: PlayerRole;
|
|
20
|
+
};
|
|
21
21
|
|
|
22
22
|
interface PlayerConstructor {
|
|
23
23
|
new (params: any): Player;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
export const playerFactory = (
|
|
26
|
+
export const playerFactory = (
|
|
27
|
+
config: PlayerFactoryProps
|
|
28
|
+
): PlayerFactoryItem | null => {
|
|
27
29
|
const IDENTIFIER = config?.playerPluginId;
|
|
28
30
|
|
|
29
31
|
if (!IDENTIFIER) {
|