@applicaster/zapp-react-native-utils 12.0.0-rc.76 → 12.0.0-rc.78

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.
@@ -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,3 @@
1
1
  export * from "./platformUtils";
2
+
3
+ export * from "./const";
@@ -1 +1,223 @@
1
- export {};
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()?.setLanguage(track);
444
+ return this.getActivePlayer()?.selectTrack(track);
445
445
  }
446
446
 
447
447
  public isRegistered() {
@@ -684,9 +684,6 @@ export class Player {
684
684
  play = () => {};
685
685
  pause = () => {};
686
686
  disableBufferAnimation = (): boolean => true;
687
- setLanguage = (
688
- _selected?: QuickBrickPlayer.TextTrack | QuickBrickPlayer.AudioTrack
689
- ) => {};
690
687
 
691
688
  setPlaybackRate = (_rate) => {};
692
689
  startSleepTimer = (_timestamp) => {};
@@ -188,10 +188,10 @@ export class PlayerNative extends Player {
188
188
 
189
189
  disableBufferAnimation = (): boolean => false;
190
190
 
191
- setLanguage = (
191
+ selectTrack = (
192
192
  selected: QuickBrickPlayer.TextTrack | QuickBrickPlayer.AudioTrack
193
193
  ) => {
194
- this.currentPlayerComponent()?.["setLanguage"]?.(selected);
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-rc.76",
3
+ "version": "12.0.0-rc.78",
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-rc.76",
31
+ "@applicaster/applicaster-types": "12.0.0-rc.78",
32
32
  "buffer": "^5.2.1",
33
33
  "camelize": "^1.0.0",
34
34
  "create-react-context": "^0.2.3",
@@ -186,6 +186,10 @@ export const isSamsungPlatform = () => {
186
186
  export const isVizioPlatform = () => {
187
187
  const userAgent = getUserAgent();
188
188
 
189
+ if (!userAgent) {
190
+ return false;
191
+ }
192
+
189
193
  const isVizioAgent =
190
194
  userAgent.includes(PLATFORMS.vizio) ||
191
195
  userAgent.includes(PLATFORMS.smartcast) ||
@@ -1,49 +0,0 @@
1
- import { PLATFORMS } from "./const";
2
-
3
- declare global {
4
- interface Window {
5
- applicaster: {
6
- vizioLibraryDidLoad: boolean;
7
- useOnScreenKeyboard: boolean;
8
- };
9
- VIZIO?: {
10
- exitApplication: () => void;
11
- setClosedCaptionHandler: (
12
- callback: (isCCEnabled: boolean) => void
13
- ) => void;
14
- };
15
- }
16
- }
17
-
18
- export const getUserAgent = () =>
19
- window?.navigator?.userAgent || global?.navigator?.userAgent;
20
-
21
- /**
22
- * Checks if we are on the Vizio platform by using the userAgent string
23
- *
24
- * Use this method when you need to identify the platform on runtime
25
- * before the VIZIO Companion Library has loaded
26
- */
27
- export const isVizioPlatform = () => {
28
- const userAgent = getUserAgent();
29
-
30
- const isVizioAgent =
31
- userAgent.includes(PLATFORMS.vizio) ||
32
- userAgent.includes(PLATFORMS.smartcast) ||
33
- userAgent.includes(PLATFORMS.conjure);
34
-
35
- return isVizioAgent;
36
- };
37
-
38
- /**
39
- * Checks if we are on the Vizio platform by checking for the global VIZIO object
40
- * and the VIZIO Companion Library. This method does not use the userAgent string,
41
- * because it mainly checks whether we have access to apis, which may not be available yet
42
- */
43
- export const hasVizioAPIs = () => {
44
- const hasAPIs =
45
- typeof window.VIZIO !== "undefined" &&
46
- window?.applicaster?.vizioLibraryDidLoad;
47
-
48
- return hasAPIs;
49
- };