@applicaster/zapp-react-native-utils 12.0.0-alpha.5471145113 → 12.0.0-alpha.5522474195
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/appUtils/focusManager/treeDataStructure/Utils/index.js +1 -1
- package/appUtils/platform/const.ts +7 -0
- package/appUtils/platform/index.ts +2 -0
- package/appUtils/platform/platformUtils.ts +223 -1
- package/appUtils/playerManager/conts.ts +1 -0
- package/appUtils/playerManager/index.ts +5 -5
- package/appUtils/playerManager/player.ts +8 -3
- package/appUtils/playerManager/playerNative.ts +2 -2
- package/package.json +2 -2
- 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/platform/platformUtils.web.ts +0 -49
|
@@ -206,7 +206,7 @@ export function getTargetInDirection(
|
|
|
206
206
|
const overrideTarget = currentNode?.component?.props[overridePropName];
|
|
207
207
|
|
|
208
208
|
if (overrideTarget) {
|
|
209
|
-
const target = targetNodes.find((n) => n
|
|
209
|
+
const target = targetNodes.find((n) => n?.id === overrideTarget);
|
|
210
210
|
|
|
211
211
|
if (target) return target;
|
|
212
212
|
}
|
|
@@ -16,3 +16,10 @@ export const PLATFORMS = {
|
|
|
16
16
|
smartcast: "SmartCast",
|
|
17
17
|
conjure: "Conjure",
|
|
18
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
|
+
};
|
|
@@ -1 +1,223 @@
|
|
|
1
|
-
|
|
1
|
+
import { BehaviorSubject } from "rxjs";
|
|
2
|
+
|
|
3
|
+
import { sessionStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/SessionStorage";
|
|
4
|
+
import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
|
|
5
|
+
import { PlayerWebController } from "@applicaster/zapp-react-native-default-player/src/playerFactory/players/playerWebController";
|
|
6
|
+
|
|
7
|
+
import { PLATFORM_KEYS, PLATFORMS } from "./const";
|
|
8
|
+
import { createLogger, utilsLogger } from "../../logger";
|
|
9
|
+
|
|
10
|
+
declare global {
|
|
11
|
+
interface Window {
|
|
12
|
+
VIZIO?: {
|
|
13
|
+
exitApplication: () => void;
|
|
14
|
+
setClosedCaptionHandler: (
|
|
15
|
+
callback: (isCCEnabled: boolean) => void
|
|
16
|
+
) => void;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const { log_debug, log_error } = createLogger({
|
|
22
|
+
category: "General",
|
|
23
|
+
subsystem: "PlatformUtils",
|
|
24
|
+
parent: utilsLogger,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export const getUserAgent = () =>
|
|
28
|
+
window?.navigator?.userAgent || global?.navigator?.userAgent;
|
|
29
|
+
|
|
30
|
+
/** VIZIO UTILS */
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Checks if we are on the Vizio platform by using the userAgent string
|
|
34
|
+
*
|
|
35
|
+
* Use this method when you need to identify the platform on runtime
|
|
36
|
+
* before the VIZIO Companion Library has loaded
|
|
37
|
+
*/
|
|
38
|
+
export const isVizioPlatform = () => {
|
|
39
|
+
const userAgent = getUserAgent();
|
|
40
|
+
|
|
41
|
+
const isVizioAgent =
|
|
42
|
+
userAgent.includes(PLATFORMS.vizio) ||
|
|
43
|
+
userAgent.includes(PLATFORMS.smartcast) ||
|
|
44
|
+
userAgent.includes(PLATFORMS.conjure);
|
|
45
|
+
|
|
46
|
+
return isVizioAgent;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Checks if we are on the Vizio platform by checking for the global VIZIO object
|
|
51
|
+
* and the VIZIO Companion Library. This method does not use the userAgent string,
|
|
52
|
+
* because it mainly checks whether we have access to apis, which may not be available yet
|
|
53
|
+
*/
|
|
54
|
+
export const hasVizioAPIs = () => {
|
|
55
|
+
const hasAPIs =
|
|
56
|
+
typeof window.VIZIO !== "undefined" &&
|
|
57
|
+
window?.applicaster?.vizioLibraryDidLoad;
|
|
58
|
+
|
|
59
|
+
return hasAPIs;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Manages device based closed captioning state
|
|
64
|
+
* Returns an observable that emits the current state and updates whenever it changes
|
|
65
|
+
*/
|
|
66
|
+
class ClosedCaptioningManager {
|
|
67
|
+
private ccState$ = new BehaviorSubject<boolean>(false);
|
|
68
|
+
private static ccManagerInstance: ClosedCaptioningManager;
|
|
69
|
+
|
|
70
|
+
private constructor() {
|
|
71
|
+
this.initialize();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
static getInstance(): ClosedCaptioningManager {
|
|
75
|
+
if (!ClosedCaptioningManager.ccManagerInstance) {
|
|
76
|
+
ClosedCaptioningManager.ccManagerInstance = new ClosedCaptioningManager();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return ClosedCaptioningManager.ccManagerInstance;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async initialize() {
|
|
83
|
+
const existingState = await sessionStorage.getItem(
|
|
84
|
+
PLATFORM_KEYS.deviceClosedCaptioningEnabled
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
log_debug("Initializing closed captioning manager", { existingState });
|
|
88
|
+
|
|
89
|
+
if (existingState !== null) {
|
|
90
|
+
this.ccState$.next(existingState === "true" || existingState === true);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (hasVizioAPIs()) {
|
|
94
|
+
window.VIZIO!.setClosedCaptionHandler((isCCEnabled) => {
|
|
95
|
+
log_debug("CC state changed", { isCCEnabled });
|
|
96
|
+
|
|
97
|
+
sessionStorage.setItem(
|
|
98
|
+
PLATFORM_KEYS.deviceClosedCaptioningEnabled,
|
|
99
|
+
isCCEnabled
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
this.ccState$.next(isCCEnabled);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
getCurrentState(): boolean {
|
|
108
|
+
return this.ccState$.getValue();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
getStateAsObservable() {
|
|
112
|
+
return this.ccState$.asObservable();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Subscribe to closed captioning state changes
|
|
118
|
+
* @returns Observable<boolean>
|
|
119
|
+
* @example
|
|
120
|
+
* const subscription = getClosedCaptionState().subscribe(
|
|
121
|
+
* isEnabled => setClosedCaptionState(isEnabled)
|
|
122
|
+
* );
|
|
123
|
+
* subscription.unsubscribe(), []);
|
|
124
|
+
*/
|
|
125
|
+
export const getClosedCaptionState = () => {
|
|
126
|
+
const ccManager = ClosedCaptioningManager.getInstance();
|
|
127
|
+
|
|
128
|
+
return ccManager.getStateAsObservable();
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export class TextTrackManager {
|
|
132
|
+
private controller?: PlayerWebController;
|
|
133
|
+
private static instance: TextTrackManager;
|
|
134
|
+
|
|
135
|
+
private constructor() {}
|
|
136
|
+
|
|
137
|
+
static getInstance(): TextTrackManager {
|
|
138
|
+
if (!TextTrackManager.instance) {
|
|
139
|
+
TextTrackManager.instance = new TextTrackManager();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return TextTrackManager.instance;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
initialize(controller: PlayerWebController) {
|
|
146
|
+
if (!controller) {
|
|
147
|
+
throw new Error(
|
|
148
|
+
"Controller is required for TextTrackManager initialization"
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
this.controller = controller;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
async setTextTrackBasedOnCaptions(closedCaptionsState: boolean) {
|
|
156
|
+
if (!this.controller) {
|
|
157
|
+
log_error("Controller is not initialized");
|
|
158
|
+
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (closedCaptionsState) {
|
|
163
|
+
const textTracks = this.controller.getTracksState().textTracks;
|
|
164
|
+
const preferredTextTrack = await this.getPreferredTextTrack(textTracks);
|
|
165
|
+
|
|
166
|
+
if (preferredTextTrack) {
|
|
167
|
+
this.controller.selectTrack(preferredTextTrack);
|
|
168
|
+
}
|
|
169
|
+
} else {
|
|
170
|
+
this.controller.selectTrack(null);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async getPreferredTextTrack(
|
|
175
|
+
textTracks: QuickBrickPlayer.TextTrack[]
|
|
176
|
+
): Promise<QuickBrickPlayer.TextTrack | undefined> {
|
|
177
|
+
if (!this.controller) return;
|
|
178
|
+
|
|
179
|
+
const userPreferredTextLanguageLocalStorage = await localStorage.getItem(
|
|
180
|
+
"preferred_text_language",
|
|
181
|
+
"user_preferences"
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
let userPreferredTextLanguage;
|
|
185
|
+
|
|
186
|
+
if (userPreferredTextLanguageLocalStorage) {
|
|
187
|
+
userPreferredTextLanguage = textTracks.find(
|
|
188
|
+
(track) => track.language === userPreferredTextLanguageLocalStorage
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (userPreferredTextLanguage?.id) {
|
|
193
|
+
return userPreferredTextLanguage;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const enableAutoTextTrackSelection =
|
|
197
|
+
this.controller.getPluginConfiguration()
|
|
198
|
+
?.enable_auto_text_track_selection ||
|
|
199
|
+
this.controller.getTracksState().textTracks.length > 0;
|
|
200
|
+
|
|
201
|
+
if (enableAutoTextTrackSelection) {
|
|
202
|
+
const languageCode = await sessionStorage.getItem("languageCode");
|
|
203
|
+
|
|
204
|
+
if (languageCode) {
|
|
205
|
+
const chosenTextTrackBySystemLanguage = textTracks.find(
|
|
206
|
+
(track) => track.language === languageCode
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
if (chosenTextTrackBySystemLanguage?.id) {
|
|
210
|
+
return chosenTextTrackBySystemLanguage;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return textTracks?.[0];
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
isTextTrackEnabled(): boolean {
|
|
219
|
+
if (!this.controller) return false;
|
|
220
|
+
|
|
221
|
+
return this.controller.getTracksState().textTrackId !== null;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
@@ -366,9 +366,9 @@ export class PlayerManager {
|
|
|
366
366
|
// TODO: Remove
|
|
367
367
|
if (this.castingReceiver) {
|
|
368
368
|
this.castingReceiver.rewind(deltaTime);
|
|
369
|
+
} else {
|
|
370
|
+
this.getActivePlayer()?.rewind(deltaTime);
|
|
369
371
|
}
|
|
370
|
-
|
|
371
|
-
this.getActivePlayer()?.rewind(deltaTime);
|
|
372
372
|
}
|
|
373
373
|
|
|
374
374
|
public forward(deltaTime = null) {
|
|
@@ -376,9 +376,9 @@ export class PlayerManager {
|
|
|
376
376
|
|
|
377
377
|
if (this.castingReceiver) {
|
|
378
378
|
this.castingReceiver.forward(deltaTime);
|
|
379
|
+
} else {
|
|
380
|
+
this.getActivePlayer()?.forward(deltaTime);
|
|
379
381
|
}
|
|
380
|
-
|
|
381
|
-
this.getActivePlayer()?.forward(deltaTime);
|
|
382
382
|
}
|
|
383
383
|
|
|
384
384
|
public seeking(time) {
|
|
@@ -441,7 +441,7 @@ export class PlayerManager {
|
|
|
441
441
|
}
|
|
442
442
|
|
|
443
443
|
// Call method on player just in case
|
|
444
|
-
return this.getActivePlayer()?.
|
|
444
|
+
return this.getActivePlayer()?.selectTrack(track);
|
|
445
445
|
}
|
|
446
446
|
|
|
447
447
|
public isRegistered() {
|
|
@@ -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) => {};
|
|
@@ -188,10 +188,10 @@ export class PlayerNative extends Player {
|
|
|
188
188
|
|
|
189
189
|
disableBufferAnimation = (): boolean => false;
|
|
190
190
|
|
|
191
|
-
|
|
191
|
+
selectTrack = (
|
|
192
192
|
selected: QuickBrickPlayer.TextTrack | QuickBrickPlayer.AudioTrack
|
|
193
193
|
) => {
|
|
194
|
-
this.currentPlayerComponent()?.["
|
|
194
|
+
this.currentPlayerComponent()?.["selectTrack"]?.(selected);
|
|
195
195
|
};
|
|
196
196
|
|
|
197
197
|
setPlaybackRate = (rate: number) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-utils",
|
|
3
|
-
"version": "12.0.0-alpha.
|
|
3
|
+
"version": "12.0.0-alpha.5522474195",
|
|
4
4
|
"description": "Applicaster Zapp React Native utilities package",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"homepage": "https://github.com/applicaster/quickbrick#readme",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@applicaster/applicaster-types": "12.0.0-alpha.
|
|
31
|
+
"@applicaster/applicaster-types": "12.0.0-alpha.5522474195",
|
|
32
32
|
"buffer": "^5.2.1",
|
|
33
33
|
"camelize": "^1.0.0",
|
|
34
34
|
"create-react-context": "^0.2.3",
|