UNPKG

@applicaster/zapp-react-native-utils

Version:

Applicaster Zapp React Native utilities package

256 lines (211 loc) • 6.67 kB
import { BehaviorSubject } from "rxjs"; import { sessionStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/SessionStorage"; import { isLgPlatform, isSamsungPlatform, } from "@applicaster/zapp-react-dom-app/App/Loader/utils/platform"; import { PLATFORM_KEYS, PLATFORMS, ZappPlatform } from "./const"; import { createLogger, utilsLogger } from "../../logger"; import { getPlatform } from "../../reactUtils"; import { appStore } from "@applicaster/zapp-react-native-redux/AppStore"; declare global { interface Window { VIZIO?: { exitApplication: () => void; Chromevox: { play: (text: string) => void; }; setClosedCaptionHandler: ( callback: (isCCEnabled: boolean) => void ) => void; }; } } const { log_debug } = createLogger({ category: "General", subsystem: "PlatformUtils", parent: utilsLogger, }); export const getZappPlatform = (): ZappPlatform => { const platform = appStore.get("appData")?.platform; switch (platform) { case "amazon_fire_tv": return ZappPlatform.AmazonFireTV; case ZappPlatform.Vizio: return ZappPlatform.Vizio; default: // TODO: Use only ZappPlatform enum return getPlatform() as ZappPlatform; } }; export const getUserAgent = () => window?.navigator?.userAgent; /** VIZIO UTILS */ /** * Checks if we are on the Vizio platform by using the userAgent string * * Use this method when you need to identify the platform on runtime * before the VIZIO Companion Library has loaded */ export const isVizioPlatform = () => { const userAgent = getUserAgent(); if (!userAgent) return false; const isVizioAgent = userAgent.includes(PLATFORMS.vizio) || userAgent.includes(PLATFORMS.smartcast) || userAgent.includes(PLATFORMS.conjure); return isVizioAgent; }; /** * Checks if we are on the Vizio platform by checking for the global VIZIO object * and the VIZIO Companion Library. This method does not use the userAgent string, * because it mainly checks whether we have access to apis, which may not be available yet */ export const hasVizioAPIs = () => { const hasAPIs = typeof window.VIZIO !== "undefined" && window?.applicaster?.vizioLibraryDidLoad; return hasAPIs; }; /** * Manages device based closed captioning state * Returns an observable that emits the current state and updates whenever it changes */ export class ClosedCaptioningManager { private ccState$ = new BehaviorSubject<boolean>(false); private static ccManagerInstance: ClosedCaptioningManager; private constructor() { this.initialize(); } static getInstance(): ClosedCaptioningManager { if (!ClosedCaptioningManager.ccManagerInstance) { log_debug("ClosedCaptioningManager: Creating new instance"); ClosedCaptioningManager.ccManagerInstance = new ClosedCaptioningManager(); } log_debug("ClosedCaptioningManager: Returning existing instance"); return ClosedCaptioningManager.ccManagerInstance; } async initialize() { const existingState = await sessionStorage.getItem( PLATFORM_KEYS.deviceClosedCaptioningEnabled ); if (existingState !== null) { log_debug( `ClosedCaptioningManager: Setting initial state to ${existingState}` ); this.ccState$.next(existingState === "true" || existingState === true); } else { log_debug("ClosedCaptioningManager: No existing state found"); } if (hasVizioAPIs()) { log_debug("ClosedCaptioningManager: Setting closed captioning handler"); window.VIZIO!.setClosedCaptionHandler((isCCEnabled) => { log_debug( "ClosedCaptioningManager: There was a change in the CC state", { isCCEnabled } ); sessionStorage.setItem( PLATFORM_KEYS.deviceClosedCaptioningEnabled, isCCEnabled ); log_debug( "ClosedCaptioningManager: Saved CC state to session storage", { isCCEnabled } ); this.ccState$.next(isCCEnabled); }); } else { log_debug( "ClosedCaptioningManager: Vizio APIs are not available, skipping setup" ); } } getCurrentState(): boolean { return this.ccState$.getValue(); } getStateAsObservable() { return this.ccState$.asObservable(); } } /** * Subscribe to closed captioning state changes * @returns Observable<boolean> * @example * const subscription = getClosedCaptionState().subscribe( * isEnabled => setClosedCaptionState(isEnabled) * ); * subscription.unsubscribe(), []); */ export const getClosedCaptionState = () => { const ccManager = ClosedCaptioningManager.getInstance(); return ccManager.getStateAsObservable(); }; /** * Manages device based closed captioning state * Returns an observable that emits the current state and updates whenever it changes */ export class TTSManager { private ttsState$ = new BehaviorSubject<boolean>(false); private static ttsManagerInstance: TTSManager; private constructor() { this.initialize(); } static getInstance(): TTSManager { if (!TTSManager.ttsManagerInstance) { TTSManager.ttsManagerInstance = new TTSManager(); } return TTSManager.ttsManagerInstance; } async initialize() { if (!isVizioPlatform()) return; document.addEventListener( "VIZIO_TTS_ENABLED", () => { this.ttsState$.next(true); }, false ); document.addEventListener( "VIZIO_TTS_DISABLED", () => { this.ttsState$.next(false); }, false ); } getCurrentState(): boolean { return this.ttsState$.getValue(); } getStateAsObservable() { return this.ttsState$.asObservable(); } readText(text: string) { if (isSamsungPlatform() && window.speechSynthesis) { const utterance = new SpeechSynthesisUtterance(text); window.speechSynthesis.speak(utterance); } if (isLgPlatform() && window.webOS?.service) { try { window.webOS.service.request("luna://com.webos.service.tts", { method: "speak", onFailure(error: any) { log_debug("There was a failure setting up webOS TTS service", { error, }); }, onSuccess(response: any) { log_debug("webOS TTS service is configured successfully", { response, }); }, parameters: { text, }, }); } catch (error) { log_debug("webOS TTS service error", { error }); } } if (!window.VIZIO?.Chromevox) return; window.VIZIO.Chromevox.play(text); } }