@applicaster/zapp-react-native-utils 12.0.0-alpha.7754333813 → 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/analyticsUtils/AnalyticPlayerListener.ts +141 -0
- package/analyticsUtils/AnalyticsEvents/index.ts +7 -0
- package/analyticsUtils/AnalyticsEvents/sendShareEvent.ts +21 -0
- package/analyticsUtils/PlayerAnalyticsManager.ts +90 -0
- package/analyticsUtils/analyticsPlugins.ts +25 -0
- package/analyticsUtils/events.ts +6 -0
- package/analyticsUtils/index.tsx +6 -0
- package/analyticsUtils/{analyticsTracker.ts → playerAnalyticsTracker.ts} +19 -10
- 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 -44
- 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/keys.web.js +8 -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/conts.ts +1 -0
- package/appUtils/playerManager/index.ts +20 -32
- package/appUtils/playerManager/nativePlayerManager.ts +12 -0
- package/appUtils/playerManager/player.ts +9 -3
- package/appUtils/playerManager/playerNative.ts +6 -15
- package/appUtils/playerManager/usePlayerControllerSetup.tsx +7 -1
- package/arrayUtils/__tests__/isFilledArray.test.ts +63 -0
- package/arrayUtils/index.ts +5 -0
- package/booleanUtils/index.ts +4 -4
- package/cellUtils/index.ts +38 -5
- package/index.d.ts +15 -0
- package/keyboardState/index.ts +0 -0
- package/navigationUtils/index.ts +48 -0
- package/numberUtils/__tests__/isLikeNumber.test.ts +18 -0
- package/numberUtils/__tests__/toNumber.test.ts +2 -2
- package/numberUtils/index.ts +5 -18
- package/package.json +2 -2
- package/playerUtils/imaScriptDom.ts +59 -0
- package/pluginUtils/index.ts +9 -0
- 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/useBuildPipesUrl.ts +7 -10
- package/reactHooks/feed/useFeedRefresh.tsx +9 -7
- package/reactHooks/navigation/__tests__/index.test.tsx +11 -8
- package/reactHooks/navigation/index.ts +60 -67
- package/reactHooks/resolvers/useCellResolver.ts +5 -1
- package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +21 -23
- package/reactHooks/screen/index.ts +2 -0
- package/reactHooks/screen/useScreenBackgroundColor.ts +23 -0
- package/reactHooks/screen/useScreenContext.ts +2 -2
- package/reactUtils/index.ts +104 -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
package/appUtils/index.js
CHANGED
|
@@ -9,6 +9,8 @@ export { KEYS, ARROW_KEYS } from "./keyCodes/keys";
|
|
|
9
9
|
|
|
10
10
|
export { playerManager } from "./playerManager";
|
|
11
11
|
|
|
12
|
+
export { accessibilityManager } from "./accessibilityManager";
|
|
13
|
+
|
|
12
14
|
export function deprecationMessage(fn, replacement) {
|
|
13
15
|
if (__DEV__ && process.env.NODE_ENV !== "test") {
|
|
14
16
|
console.warn("/** DEPRECATION WARNING **/");
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* global tizen */
|
|
2
2
|
const isTizen = typeof tizen !== "undefined";
|
|
3
3
|
|
|
4
|
+
import { isVizioPlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
4
5
|
import * as platformKeys from "./keysByPlatform";
|
|
5
6
|
import { Platform } from "react-native";
|
|
6
7
|
|
|
@@ -21,6 +22,13 @@ export const ARROW_KEYS = [
|
|
|
21
22
|
KEYS.ArrowRight,
|
|
22
23
|
];
|
|
23
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Platform.OS currently identifies Vizio as LG_TV, therefore we are using isVizioPlatform to identify platform and add keys.
|
|
27
|
+
*/
|
|
28
|
+
if (isVizioPlatform()) {
|
|
29
|
+
Object.assign(KEYS, platformKeys.vizio);
|
|
30
|
+
}
|
|
31
|
+
|
|
24
32
|
/**
|
|
25
33
|
* In TizenOS we need to register all of the keys that we are going to use.
|
|
26
34
|
* You need to register using the name Tizen has for the key.
|
|
@@ -102,4 +102,14 @@ const tvos = {
|
|
|
102
102
|
Menu: { code: "Menu", eventType: "menu" },
|
|
103
103
|
};
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
const vizio = {
|
|
106
|
+
...samsung_tv,
|
|
107
|
+
Exit: { code: "Exit", keyCode: 27 },
|
|
108
|
+
PageUp: { code: "PageUp", keyCode: 33 },
|
|
109
|
+
PageDown: { code: "PageDown", keyCode: 34 },
|
|
110
|
+
MediaTrackNext: { code: "MediaTrackNext", keyCode: 418 },
|
|
111
|
+
MediaTrackPrevious: { code: "MediaTrackPrevious", keyCode: 419 },
|
|
112
|
+
PrevCh: { code: "PrevCh", keyCode: 500 },
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export { lg_tv, samsung_tv, web, tvos, android_tv, vizio };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platforms found in userAgent string, please note that simulators
|
|
3
|
+
* might not have the same agents that the devices have
|
|
4
|
+
*/
|
|
5
|
+
export const PLATFORMS = {
|
|
6
|
+
webos: "Web0S",
|
|
7
|
+
tizen: "Tizen",
|
|
8
|
+
samsung: "SMART-TV",
|
|
9
|
+
mac: "Mac",
|
|
10
|
+
win: "Win",
|
|
11
|
+
linux: "Linux",
|
|
12
|
+
iphone: "iPhone",
|
|
13
|
+
android: "Android",
|
|
14
|
+
mobile: "Mobile",
|
|
15
|
+
vizio: "VIZIO",
|
|
16
|
+
smartcast: "SmartCast",
|
|
17
|
+
conjure: "Conjure",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Keys used to store the platform / device state in the session storage
|
|
22
|
+
*/
|
|
23
|
+
export const PLATFORM_KEYS = {
|
|
24
|
+
deviceClosedCaptioningEnabled: "device_closed_captioning_enabled",
|
|
25
|
+
};
|
|
@@ -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
|
+
}
|
|
@@ -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
|
+
};
|
|
@@ -359,6 +359,13 @@ export class Player {
|
|
|
359
359
|
});
|
|
360
360
|
};
|
|
361
361
|
|
|
362
|
+
onVideoError = (error: Error) => {
|
|
363
|
+
this.invokeListenersUpdate({
|
|
364
|
+
callbackName: SharedPlayerCallBacksKeys.OnVideoError,
|
|
365
|
+
event: error,
|
|
366
|
+
});
|
|
367
|
+
};
|
|
368
|
+
|
|
362
369
|
onError = (error: Error) => {
|
|
363
370
|
this.invokeListenersUpdate({
|
|
364
371
|
callbackName: SharedPlayerCallBacksKeys.OnError,
|
|
@@ -650,6 +657,7 @@ export class Player {
|
|
|
650
657
|
onPlayerSeekComplete: this.onSeekComplete,
|
|
651
658
|
onVideoEnd: this.onVideoEnd,
|
|
652
659
|
onError: this.onError,
|
|
660
|
+
onVideoError: this.onVideoError,
|
|
653
661
|
onLoad: this.onLoad,
|
|
654
662
|
onPlayerPause: this.onPlayerPause,
|
|
655
663
|
onPlayerResume: this.onPlayerResume,
|
|
@@ -684,9 +692,6 @@ export class Player {
|
|
|
684
692
|
play = () => {};
|
|
685
693
|
pause = () => {};
|
|
686
694
|
disableBufferAnimation = (): boolean => true;
|
|
687
|
-
setLanguage = (
|
|
688
|
-
_selected?: QuickBrickPlayer.TextTrack | QuickBrickPlayer.AudioTrack
|
|
689
|
-
) => {};
|
|
690
695
|
|
|
691
696
|
setPlaybackRate = (_rate) => {};
|
|
692
697
|
startSleepTimer = (_timestamp) => {};
|
|
@@ -728,4 +733,5 @@ export class Player {
|
|
|
728
733
|
|
|
729
734
|
public supportsNativeControls = (): boolean => false;
|
|
730
735
|
public supportNativeCast = (): boolean => false;
|
|
736
|
+
public destroy = () => {};
|
|
731
737
|
}
|
|
@@ -2,19 +2,10 @@ import * as R from "ramda";
|
|
|
2
2
|
import { isEmptyOrNil } from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
3
3
|
import { createLogger, utilsLogger } from "../../logger";
|
|
4
4
|
import { Player } from "./player";
|
|
5
|
-
import { findNodeHandle
|
|
6
|
-
import { isApplePlatform } from "../../reactUtils";
|
|
5
|
+
import { findNodeHandle } from "react-native";
|
|
7
6
|
import { PlayerRole } from "./conts";
|
|
8
7
|
import { toBooleanWithDefaultFalse } from "../../booleanUtils";
|
|
9
|
-
|
|
10
|
-
const RNPlayerManager = {
|
|
11
|
-
QuickBrickPlayerPlugin: isApplePlatform()
|
|
12
|
-
? NativeModules.PlayerModule
|
|
13
|
-
: NativeModules.QuickBrickDefaultPlayerModule,
|
|
14
|
-
KalturaPlayerPlugin: isApplePlatform()
|
|
15
|
-
? NativeModules.KalturaPlayerModule
|
|
16
|
-
: NativeModules.QBKalturaPlayerModule,
|
|
17
|
-
};
|
|
8
|
+
import { RNPlayerManager } from "./nativePlayerManager";
|
|
18
9
|
|
|
19
10
|
const logger = createLogger({
|
|
20
11
|
category: "PlayerNativeController",
|
|
@@ -70,7 +61,7 @@ export class PlayerNative extends Player {
|
|
|
70
61
|
currentPlayerComponent = (): ReactComponent<PlayerProps> =>
|
|
71
62
|
this.playerComponent?.current;
|
|
72
63
|
|
|
73
|
-
getState = () => this.
|
|
64
|
+
getState = () => this.playerState;
|
|
74
65
|
|
|
75
66
|
// TODO: Try to add module interface
|
|
76
67
|
invokeNativeFunction = (funcName: string, ...params: any[]): boolean => {
|
|
@@ -111,7 +102,7 @@ export class PlayerNative extends Player {
|
|
|
111
102
|
return;
|
|
112
103
|
}
|
|
113
104
|
|
|
114
|
-
const newPosition = R.clamp(0,
|
|
105
|
+
const newPosition = R.clamp(0, this.playerState.seekableDuration, position);
|
|
115
106
|
|
|
116
107
|
if (
|
|
117
108
|
!this.invokeNativeFunction(
|
|
@@ -197,10 +188,10 @@ export class PlayerNative extends Player {
|
|
|
197
188
|
|
|
198
189
|
disableBufferAnimation = (): boolean => false;
|
|
199
190
|
|
|
200
|
-
|
|
191
|
+
selectTrack = (
|
|
201
192
|
selected: QuickBrickPlayer.TextTrack | QuickBrickPlayer.AudioTrack
|
|
202
193
|
) => {
|
|
203
|
-
this.currentPlayerComponent()?.["
|
|
194
|
+
this.currentPlayerComponent()?.["selectTrack"]?.(selected);
|
|
204
195
|
};
|
|
205
196
|
|
|
206
197
|
setPlaybackRate = (rate: number) => {
|
|
@@ -4,6 +4,7 @@ import { useEffect } from "react";
|
|
|
4
4
|
import { playerManager } from "./index";
|
|
5
5
|
import { useValidatePlayerConfig } from "../../playerUtils/useValidatePlayerConfig";
|
|
6
6
|
import { PlayerRole } from "./conts";
|
|
7
|
+
import { isAppleTV } from "@applicaster/zapp-react-native-ui-components/Helpers/Platform";
|
|
7
8
|
|
|
8
9
|
// TODO: Rename to ControllerType
|
|
9
10
|
export const usePlayerControllerSetup = ({
|
|
@@ -34,10 +35,14 @@ export const usePlayerControllerSetup = ({
|
|
|
34
35
|
useValidatePlayerConfig(config);
|
|
35
36
|
|
|
36
37
|
useEffect(() => {
|
|
38
|
+
const newConfig = isAppleTV()
|
|
39
|
+
? { supports_native_controls: true, ...config }
|
|
40
|
+
: config;
|
|
41
|
+
|
|
37
42
|
const newPlayerController = new ControllerType({
|
|
38
43
|
player: ref,
|
|
39
44
|
listener: props as any,
|
|
40
|
-
config,
|
|
45
|
+
config: newConfig,
|
|
41
46
|
playerId,
|
|
42
47
|
entry,
|
|
43
48
|
playerPluginId: pluginId,
|
|
@@ -67,6 +72,7 @@ export const usePlayerControllerSetup = ({
|
|
|
67
72
|
|
|
68
73
|
return () => {
|
|
69
74
|
playerManager.unregisterPlayer(playerId);
|
|
75
|
+
playerController.destroy?.();
|
|
70
76
|
};
|
|
71
77
|
}, [playerId, playerController]);
|
|
72
78
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { isFilledArray } from "..";
|
|
2
|
+
|
|
3
|
+
describe("isFilledArray", () => {
|
|
4
|
+
it("non-empty array is not empty", () => {
|
|
5
|
+
const value = [1, 2, 3];
|
|
6
|
+
|
|
7
|
+
expect(isFilledArray(value)).toBe(true);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("empty array is empty", () => {
|
|
11
|
+
const value = [];
|
|
12
|
+
|
|
13
|
+
expect(isFilledArray(value)).toBe(false);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("number is not array", () => {
|
|
17
|
+
const value = 123;
|
|
18
|
+
|
|
19
|
+
expect(isFilledArray(value)).toBe(false);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("string is not array", () => {
|
|
23
|
+
const value = "vfnjdk";
|
|
24
|
+
|
|
25
|
+
expect(isFilledArray(value)).toBe(false);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("empty string is not array", () => {
|
|
29
|
+
const value = "";
|
|
30
|
+
|
|
31
|
+
expect(isFilledArray(value)).toBe(false);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("NaN is not array", () => {
|
|
35
|
+
const value = "";
|
|
36
|
+
|
|
37
|
+
expect(isFilledArray(value)).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("object is not array", () => {
|
|
41
|
+
const value = { test: 1 };
|
|
42
|
+
|
|
43
|
+
expect(isFilledArray(value)).toBe(false);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("empty object is not array", () => {
|
|
47
|
+
const value = {};
|
|
48
|
+
|
|
49
|
+
expect(isFilledArray(value)).toBe(false);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("undefined is not array", () => {
|
|
53
|
+
const value = undefined;
|
|
54
|
+
|
|
55
|
+
expect(isFilledArray(value)).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("null is not array", () => {
|
|
59
|
+
const value = null;
|
|
60
|
+
|
|
61
|
+
expect(isFilledArray(value)).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
});
|
package/arrayUtils/index.ts
CHANGED
|
@@ -95,3 +95,8 @@ export const makeListOfIndexes = (size: number): number[] =>
|
|
|
95
95
|
export const makeListOf = (value: unknown, size: number): number[] => {
|
|
96
96
|
return Array(size).fill(value);
|
|
97
97
|
};
|
|
98
|
+
|
|
99
|
+
/** Checks if a value is a non-empty array */
|
|
100
|
+
export function isFilledArray(value: unknown): boolean {
|
|
101
|
+
return R.is(Array, value) && R.length(value) > 0;
|
|
102
|
+
}
|
package/booleanUtils/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { is, toLower } from "ramda";
|
|
2
2
|
|
|
3
3
|
export const toBoolean = (value: any): boolean | undefined => {
|
|
4
|
-
if (
|
|
4
|
+
if (is(Boolean, value)) {
|
|
5
5
|
return value;
|
|
6
6
|
}
|
|
7
7
|
|
|
@@ -17,12 +17,12 @@ export const toBooleanWithDefaultTrue = toBooleanWithDefault(true);
|
|
|
17
17
|
|
|
18
18
|
export const toBooleanWithDefaultFalse = toBooleanWithDefault(false);
|
|
19
19
|
|
|
20
|
-
export const isTrue = (value:
|
|
20
|
+
export const isTrue = (value: unknown): boolean => {
|
|
21
21
|
if (value === true) {
|
|
22
22
|
return true;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
if (
|
|
25
|
+
if (is(String, value) && toLower(value) === "true") {
|
|
26
26
|
return true;
|
|
27
27
|
}
|
|
28
28
|
|