@titan-os/sdk 1.6.2
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/README.md +133 -0
- package/dist/cjs/sdk.js +1 -0
- package/dist/esm/sdk.js +6755 -0
- package/dist/types/sdk.d.ts +166 -0
- package/dist/umd/sdk.js +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
export declare interface AccessibilityReaderConfig {
|
|
2
|
+
enabled: boolean;
|
|
3
|
+
verbosity: 'concise' | 'standard' | 'detailed';
|
|
4
|
+
tvOptimized: boolean;
|
|
5
|
+
liveRegions: boolean;
|
|
6
|
+
focusTracking: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
declare interface DeviceCapabilities {
|
|
10
|
+
os: string;
|
|
11
|
+
browserEngine: string;
|
|
12
|
+
hasStorage: boolean;
|
|
13
|
+
support3d: string | boolean;
|
|
14
|
+
supportUHD: string | boolean;
|
|
15
|
+
supportHDR: string | boolean;
|
|
16
|
+
supportHDR_HDR10?: string | boolean;
|
|
17
|
+
supportHDR_DV?: string | boolean;
|
|
18
|
+
supportWebSocket: boolean;
|
|
19
|
+
supportPlayready: boolean | 'unknown';
|
|
20
|
+
supportWidevineModular: boolean | 'unknown';
|
|
21
|
+
supportAppleHLS: string | boolean;
|
|
22
|
+
supportMSSmoothStreaming: string | boolean;
|
|
23
|
+
supportMSSInitiator: string | boolean;
|
|
24
|
+
supportMPEG_DASH: boolean | 'unknown';
|
|
25
|
+
drmMethod: string;
|
|
26
|
+
supportOIPF: boolean;
|
|
27
|
+
supportEME: boolean;
|
|
28
|
+
supportKeyNumeric?: string | boolean;
|
|
29
|
+
supportKeyColor?: string | boolean;
|
|
30
|
+
supportMultiscreen?: string | boolean;
|
|
31
|
+
supportFHD?: string | boolean;
|
|
32
|
+
supportMultiAudio?: string | boolean;
|
|
33
|
+
supportTTMLInband?: string | boolean;
|
|
34
|
+
supportTTMLOutofband?: string | boolean;
|
|
35
|
+
supportFairplay?: string | boolean;
|
|
36
|
+
supportAdobeHDS?: string | boolean;
|
|
37
|
+
supportPrimetime?: string | boolean;
|
|
38
|
+
supportClearKey?: string | boolean;
|
|
39
|
+
supportWidevineClassic?: string | boolean;
|
|
40
|
+
supportDolbyAtmos?: string | boolean;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export declare interface DeviceInfo {
|
|
44
|
+
Channel: {
|
|
45
|
+
appStore: string;
|
|
46
|
+
vendor: string;
|
|
47
|
+
brand: string;
|
|
48
|
+
};
|
|
49
|
+
Product: {
|
|
50
|
+
platform: string;
|
|
51
|
+
year: string;
|
|
52
|
+
deviceID: string;
|
|
53
|
+
firmwareVersion: string;
|
|
54
|
+
firmwareComponentID: string;
|
|
55
|
+
profileid?: string;
|
|
56
|
+
mac?: string;
|
|
57
|
+
ufversion?: string;
|
|
58
|
+
country?: string;
|
|
59
|
+
language?: string;
|
|
60
|
+
WhaleAdID?: string;
|
|
61
|
+
ifa?: string;
|
|
62
|
+
ifaType?: string;
|
|
63
|
+
};
|
|
64
|
+
Capability: DeviceCapabilities;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export declare const getDeviceInfo: () => Promise<DeviceInfo>;
|
|
68
|
+
|
|
69
|
+
export declare const getTitanSDK: (options?: SDKOptions) => TitanSDK;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Platform detection types
|
|
73
|
+
*/
|
|
74
|
+
declare enum PlatformType {
|
|
75
|
+
PHILIPS = "PHILIPS",
|
|
76
|
+
PHILIPS_OLD = "PHILIPS_OLD",
|
|
77
|
+
VESTEL = "VESTEL",
|
|
78
|
+
BROWSER = "BROWSER",
|
|
79
|
+
UNKNOWN = "UNKNOWN"
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export declare interface PublicAccessibilitySettings {
|
|
83
|
+
getTTSSettings(): Promise<PublicTTSSettings>;
|
|
84
|
+
getTMSettings(): Promise<PublicTTSSettings>;
|
|
85
|
+
isTTSSupported(): Promise<boolean>;
|
|
86
|
+
isTextMagnificationSupported(): Promise<boolean>;
|
|
87
|
+
isTTSEnabled(): Promise<boolean>;
|
|
88
|
+
isTMEnabled(): Promise<boolean>;
|
|
89
|
+
startSpeaking(text: string | string[]): Promise<boolean>;
|
|
90
|
+
stopSpeaking(): Promise<boolean>;
|
|
91
|
+
enableReader(config: AccessibilityReaderConfig): Promise<boolean>;
|
|
92
|
+
disableReader(): Promise<boolean>;
|
|
93
|
+
onTTSSettingsChange(callback: (data: PublicTTSSettings) => void): () => void;
|
|
94
|
+
onTMSettingsChange(callback: (data: PublicTTSSettings) => void): () => void;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export declare interface PublicTMSettings {
|
|
98
|
+
enabled: boolean;
|
|
99
|
+
scale?: number;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export declare interface PublicTTSSettings {
|
|
103
|
+
enabled: boolean;
|
|
104
|
+
rate?: number;
|
|
105
|
+
volume?: number;
|
|
106
|
+
pitch?: number;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
declare interface SDKOptions {
|
|
110
|
+
/**
|
|
111
|
+
* Gateway URL for remote API calls
|
|
112
|
+
*/
|
|
113
|
+
gatewayUrl?: string;
|
|
114
|
+
/**
|
|
115
|
+
* Enable debug mode for additional logging (SDK development)
|
|
116
|
+
*/
|
|
117
|
+
debug?: boolean;
|
|
118
|
+
/**
|
|
119
|
+
* Enable dev mode for app development and emulation features
|
|
120
|
+
*/
|
|
121
|
+
dev?: boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Force a specific platform type (overrides detection)
|
|
124
|
+
*/
|
|
125
|
+
forcePlatform?: PlatformType;
|
|
126
|
+
/**
|
|
127
|
+
* Timeout in milliseconds for legacy device info detection
|
|
128
|
+
* @default 5000
|
|
129
|
+
*/
|
|
130
|
+
legacyDeviceInfoTimeout?: number;
|
|
131
|
+
/**
|
|
132
|
+
* Whether to enable legacy device information collection
|
|
133
|
+
* @default true
|
|
134
|
+
*/
|
|
135
|
+
useLegacyDeviceInfo?: boolean;
|
|
136
|
+
/**
|
|
137
|
+
* Whether to fall back to browser implementation if platform cannot be detected
|
|
138
|
+
* @default true
|
|
139
|
+
*/
|
|
140
|
+
fallbackToBrowser?: boolean;
|
|
141
|
+
/**
|
|
142
|
+
* Custom platform detection order strategies
|
|
143
|
+
*/
|
|
144
|
+
platformDetectionOrder?: string[];
|
|
145
|
+
/**
|
|
146
|
+
* Explicitly set platform (deprecated, use forcePlatform instead)
|
|
147
|
+
* @deprecated
|
|
148
|
+
*/
|
|
149
|
+
platform?: PlatformType;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export declare interface TitanSDK {
|
|
153
|
+
VERSION: string;
|
|
154
|
+
isReady: Promise<boolean>;
|
|
155
|
+
deviceInfo: {
|
|
156
|
+
getDeviceInfo(): Promise<DeviceInfo>;
|
|
157
|
+
};
|
|
158
|
+
accessibility: PublicAccessibilitySettings;
|
|
159
|
+
apps: {
|
|
160
|
+
launch(appId: string, deepLink?: string): Promise<boolean>;
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export declare const VERSION: string;
|
|
165
|
+
|
|
166
|
+
export { }
|
package/dist/umd/sdk.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("rollbar")):"function"==typeof define&&define.amd?define(["exports","rollbar"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).TitanSDK={},e.Rollbar)}(this,(function(e,t){"use strict";var i=Object.defineProperty,n=(e=>(e.PHILIPS="PHILIPS",e.PHILIPS_OLD="PHILIPS_OLD",e.VESTEL="VESTEL",e.BROWSER="BROWSER",e.UNKNOWN="UNKNOWN",e))(n||{}),r=(e=>(e.NOT_INITIALIZED="NOT_INITIALIZED",e.NOT_SUPPORTED="NOT_SUPPORTED",e.NOT_IMPLEMENTED="NOT_IMPLEMENTED",e.INVALID_ARGUMENTS="INVALID_ARGUMENTS",e.INVALID_PARAMETER="INVALID_PARAMETER",e.PLATFORM_NOT_DETECTED="PLATFORM_NOT_DETECTED",e.COMMUNICATION_ERROR="COMMUNICATION_ERROR",e.TIMEOUT="TIMEOUT",e.UNKNOWN="UNKNOWN",e))(r||{});class s extends Error{code;details;constructor(e,t="UNKNOWN",i){super(e),this.name="SDKError",this.code=t,this.details=i,Error.captureStackTrace&&Error.captureStackTrace(this,s)}toString(){return`SDKError [${this.code}]: ${this.message}`}toJSON(){return{name:this.name,code:this.code,message:this.message,details:this.details}}}const o=new class{subscriptions=new Map;logBuffer=[];maxBufferSize=1e3;nextId=1;debugMode=!1;constructor(e=1e3){this.maxBufferSize=e}setDebugMode(e){this.debugMode=e}subscribe(e,t={}){const i="sub-"+this.nextId++,n={id:i,levels:t.levels||["debug","info","warn","error"],modules:t.modules,callback:e,created:Date.now()};if(this.subscriptions.set(i,n),t.includeHistory){this.getFilteredHistory(n.levels,n.modules).forEach((t=>{try{e(t)}catch(i){}}))}return i}unsubscribe(e){return this.subscriptions.delete(e)}addLogEntry(e){this.logBuffer.push(e),this.logBuffer.length>this.maxBufferSize&&this.logBuffer.shift(),this.subscriptions.forEach((t=>{if(this.shouldNotifySubscription(t,e))try{t.callback(e)}catch(i){}}))}getHistory(e,t,i){return this.getFilteredHistory(e,t,i)}clear(){this.logBuffer=[]}getSubscriptionCount(){return this.subscriptions.size}getMetrics(){const e={totalEntries:this.logBuffer.length,entriesByLevel:{},entriesByModule:{},memoryUsageKB:Math.round(JSON.stringify(this.logBuffer).length/1024)};return this.logBuffer.length>0&&(e.oldestEntry=new Date(this.logBuffer[0].timestamp),e.newestEntry=new Date(this.logBuffer[this.logBuffer.length-1].timestamp)),this.logBuffer.forEach((t=>{e.entriesByLevel[t.level]=(e.entriesByLevel[t.level]||0)+1,e.entriesByModule[t.module]=(e.entriesByModule[t.module]||0)+1})),e}exportLogs(e,t){const i=this.getFilteredHistory(e,t);return JSON.stringify(i,null,2)}isDebugMode(){return this.debugMode}shouldNotifySubscription(e,t){return!!e.levels.includes(t.level)&&!(e.modules&&!e.modules.includes(t.module))}getFilteredHistory(e,t,i){let n=this.logBuffer;return e&&(n=n.filter((t=>e.includes(t.level)))),t&&(n=n.filter((e=>t.includes(e.module)))),i&&i>0&&(n=n.slice(-i)),[...n]}};function a(e){const t=(t,i,...n)=>{var r;const s=(()=>{try{const e=(new Error).stack;if(!e)return"";const t=e.split("\n");for(let i=3;i<t.length;i++){const e=t[i];if(e&&!e.includes("logger.ts")&&!e.includes("Logger")){const t=e.match(/\((.*):(\d+):(\d+)\)/)||e.match(/at (.*):(\d+):(\d+)/);if(t){const[,e,i]=t;return`${e.split("/").pop()||e}:${i}`}}}return""}catch{return""}})(),a=(e=>{var t;try{const i=null==(t=e.stack)?void 0:t.split("\n");if(!i||i.length<4)return"Unknown location";const n=i[3].replace("at","").trim()||"Unknown location",{fnName:r,fnPath:s}=(e=>{let t="",i="";return 1===e.split(" ").length?{fnName:"",fnPath:e.split(" ")[0]}:(3===e.split(" ").length?(t=e.split(" (")[0],i=e.split(" (")[1].replace(")","")):(t=e.split(" ")[0],i=e.split(" ")[1].replace(/\((.*)\)/,"$1")),{fnName:t,fnPath:i})})(n);return r?`${r}[${s}]`:`[${s}]`}catch{return"Unknown location"}})(new Error),c={id:`${e}-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,timestamp:Date.now(),level:t,module:e,message:i,args:n,metadata:{url:"undefined"!=typeof window?null==(r=window.location)?void 0:r.href:void 0,caller:s}};if(o.addLogEntry(c),o.isDebugMode()){t}};return{debug:(e,...i)=>t("debug",e,...i),info:(e,...i)=>t("info",e,...i),warn:(e,...i)=>t("warn",e,...i),error:(e,...i)=>t("error",e,...i),subscribe:(e,t)=>o.subscribe(e,t),unsubscribe:e=>o.unsubscribe(e),getHistory:(e,t,i)=>o.getHistory(e,t,i),clear:()=>o.clear()}}function c(e){return a(e)}const l=(e,t)=>o.subscribe(e,t),u=e=>o.unsubscribe(e),d=(e,t,i)=>o.getHistory(e,t,i),h=()=>o.clear(),g=e=>o.addLogEntry(e),p=c("PlatformDetection");class f{strategies=[];register(e){this.strategies.push(e),this.strategies.sort(((e,t)=>t.getPriority()-e.getPriority()))}getStrategies(){return[...this.strategies]}}class m{canDetect(){return"undefined"!=typeof window&&("t9_core"in window||"vestel"===window.deviceBrand||navigator.userAgent.toLowerCase().includes("vestel"))}getPlatform(){return this.canDetect()?n.VESTEL:null}getPriority(){return 3}}class S{canDetect(){return"undefined"!=typeof window&&("jwt"in window||"launcher_env"in window||"undefined"!=typeof navigator&&navigator.userAgent.toLowerCase().indexOf("philips")>-1)}getPlatform(){return this.canDetect()?n.PHILIPS:null}getPriority(){return 5}}class v{canDetect(){if("undefined"==typeof window)return!1;const e=(()=>{const e=navigator.userAgent.match(/Chrome\/(\d+)\./);return e?parseInt(e[1],10):null})(),t=null!==e&&e<=84;return"undefined"!=typeof navigator&&navigator.userAgent.includes("Philips")&&(document.cookie.includes("tos-session")||t)}getPlatform(){return this.canDetect()?n.PHILIPS_OLD:null}getPriority(){return 10}}class b{canDetect(){return!0}getPlatform(){return n.BROWSER}getPriority(){return 1}}const y=new class{factory;lastDetectedPlatform=null;constructor(){this.factory=new f,this.factory.register(new S),this.factory.register(new m),this.factory.register(new v),this.factory.register(new b)}registerStrategy(e){this.factory.register(e)}detectPlatform(e={}){if(e.forcePlatform)return{platform:e.forcePlatform,detectedBy:"forced",confidence:1};if(this.lastDetectedPlatform)return{...this.lastDetectedPlatform};const t=this.factory.getStrategies();for(const n of t)if(n.canDetect()){const t=n.getPlatform();if(null!==t){const i={platform:t,detectedBy:n.constructor.name,confidence:.9};return this.lastDetectedPlatform=i,e.debug&&p.info(`Platform detected as ${t}`),{...i}}}if(!1===e.fallbackToBrowser)throw new s("Could not detect platform and fallback is disabled",r.PLATFORM_NOT_DETECTED);const i={platform:n.BROWSER,detectedBy:"fallback",confidence:.1};return this.lastDetectedPlatform=i,e.debug&&p.info("Fallback to browser platform - no strategy matched"),{...i}}reset(){this.lastDetectedPlatform=null}},w={LAUNCH_APP_REQUEST:"LAUNCH_APP_REQUEST",DEVICE_INFO_REQUEST:"DEVICE_INFO_REQUEST",TTS_REQUEST_SETTINGS:"TTS_REQUEST_SETTINGS",TTS_REQUEST_START_SPEAKING:"TTS_REQUEST_START_SPEAKING",TTS_REQUEST_STOP_SPEAKING:"TTS_REQUEST_STOP_SPEAKING",ERROR_SIMULATION:"ERROR_SIMULATION",LAUNCH_APP_RESPONSE:"LAUNCH_APP_RESPONSE",DEVICE_INFO_RESPONSE:"DEVICE_INFO_RESPONSE",TTS_RESPONSE_SETTINGS:"TTS_RESPONSE_SETTINGS",TTS_RESPONSE_START_SPEAKING:"TTS_RESPONSE_START_SPEAKING",TTS_RESPONSE_STOP_SPEAKING:"TTS_RESPONSE_STOP_SPEAKING",ERROR_SIMULATION_RESPONSE:"ERROR_SIMULATION_RESPONSE",LAUNCHER_READY:"LAUNCHER_READY",BRIDGE_READY:"BRIDGE_READY",TTS_SETTINGS_CHANGE:"TTS_SETTINGS_CHANGE",TM_SETTINGS_CHANGE:"TM_SETTINGS_CHANGE",LOG_ENTRY:"LOG_ENTRY",ERROR_RESPONSE:"ERROR_RESPONSE",TRANSFER_DATA:"TRANSFER_DATA"},T={TTS_SETTINGS_CHANGE:w.TTS_SETTINGS_CHANGE,TM_SETTINGS_CHANGE:w.TM_SETTINGS_CHANGE,LOG_ENTRY:w.LOG_ENTRY},E={enabled:!1,available:!1},I={enabled:!1,available:!1},C={tts:E,tm:I},R="TIMEOUT",D="NOT_SUPPORTED",A="INVALID_REQUEST",P="COMMUNICATION_ERROR",k="LAUNCH_FAILED",M="APP_NOT_FOUND",N="APP_NOT_AVAILABLE",_="INVALID_APP_CODE";var O=(e=>(e.PHILIPS="philips",e.VESTEL="vestel",e.BROWSER="browser",e))(O||{});class L{mocks={};constructor(e){e&&(this.mocks={...e})}get(e){return e in this.mocks?this.mocks[e]:"undefined"!=typeof window&&e in window?window[e]:void 0}has(e){return e in this.mocks||"undefined"!=typeof window&&e in window}get proxy(){return new Proxy({},{get:(e,t)=>{const i=t,n=this.get(i);return"function"==typeof n?(...e)=>{try{return n(...e)}catch(t){return}}:n}})}setMocks(e){this.mocks={...this.mocks,...e}}clearMocks(){this.mocks={}}removeMock(e){const t={};for(const i in this.mocks)i!==e&&(t[i]=this.mocks[i]);this.mocks=t}getAvailableMethods(){const e=new Set;for(const t in this.mocks)Object.prototype.hasOwnProperty.call(this.mocks,t)&&e.add(t);if("undefined"!=typeof window)for(const t in window)Object.prototype.hasOwnProperty.call(window,t)&&t in window&&e.add(t);return Array.from(e)}create(e,t){"undefined"!=typeof window&&(window[e]=t)}removeGlobal(e){"undefined"!=typeof window&&e in window&&delete window[e]}}function x(e,t,i="titanos"){return new Promise(((e,n)=>{const r=new L,s="deviceInfoCallback_"+Date.now()+"_"+Math.floor(1e4*Math.random());r.create(s,(t=>{e(t),r.removeGlobal(s)}));const o=`https://${t}/potamoi/v1/device_info?callback=${s}`,a=`https://smarttv.zeasn.tv/homepage_api/device/clientInfo?callback=${s}`,c=document.createElement("script");c.src="titanos"===i?o:a,c.type="text/javascript",c.onerror=()=>{n(new Error("Failed to load device info script.")),delete r.proxy[s]},document.head.appendChild(c),setTimeout((()=>{r.has(s)&&(n(new Error("Device info request timed out.")),delete r.proxy[s]),c.parentNode&&c.parentNode.removeChild(c)}),7e3)}))}const H=()=>{const e=e=>{const t=(Math.random().toString(16)+"000000000").substring(2,10);return e?"-"+t.substring(0,4)+"-"+t.substring(4,8):t};return e(!1)+e(!0)+e(!0)+e(!1)};function U(){return"undefined"!=typeof document&&!!document.body}function F(e=5e3){return new Promise(((t,i)=>{if(U())return void t();const n=setTimeout((()=>{i(new Error("Timeout waiting for document.body to be available"))}),e),r=()=>{U()?(clearTimeout(n),t()):setTimeout(r,10)};r()}))}const B=(e="en-US")=>"undefined"!=typeof navigator&&navigator.language&&navigator.language||e,V=c("BaseBridge");class z{src="";isInitialized=!1;iframe=null;iframeOrigin="";pendingRequests=new Map;messageTimeout=1e4;iframeTimeout=3e3;connected=!1;debug=!1;initializationPromise=null;aborted=!1;initReject;MESSAGE_TYPES=w;eventHandlers=new Map;constructor(e){this.debug=(null==e?void 0:e.debug)||!1,(null==e?void 0:e.gatewayUrl)&&(this.src=e.gatewayUrl),V.debug("bridge: constructor",this.src)}async initialize(){if(this.isInitialized)return!0;if(this.initializationPromise)return V.debug("bridge: initialization already in progress, waiting..."),this.initializationPromise;V.debug("bridge: initialization not in progress, starting new one"),this.initializationPromise=this.performInitialization();try{return await this.initializationPromise}catch(e){throw this.initializationPromise=null,e}}async performInitialization(){return new Promise(((e,t)=>{this.aborted=!1,this.initReject=t,V.debug("bridge: starting initialization process"),window.addEventListener("message",this.handleMessage.bind(this));const i=()=>{this.aborted||(this.isInitialized=!0,V.debug("bridge initialized successfully"),e(!0))},n=()=>{this.aborted||(V.error("Bridge iframe failed to load or initialize."),this.isInitialized=!1,t(new Error("Bridge iframe failed to load or initialize.")))};(async()=>{try{await this.setupIframe(i,n)}catch(e){V.error("Failed to setup iframe:",e),this.isInitialized=!1,t(e)}})()}))}async sendMessage(e,t){this.isInitialized||await this.initialize();try{const i=this.prepareMessage(e,t);return new Promise(((e,t)=>{const n=setTimeout((()=>{this.pendingRequests.delete(i.requestId),t(new s("Bridge request timeout",r.TIMEOUT))}),this.messageTimeout);this.pendingRequests.set(i.requestId,{resolve:e,reject:t,timeout:n}),this.iframe&&this.iframe.contentWindow?(V.debug("bridge: sendMessage",i),this.iframe.contentWindow.postMessage(i,this.iframeOrigin||"*")):(clearTimeout(n),this.pendingRequests.delete(i.requestId),t(new s("Bridge iframe not available",r.COMMUNICATION_ERROR)))}))}catch(i){V.error("bridge: error sending message:",i);return(await Promise.resolve().then((()=>kt)).then((e=>e.rollbarClient))).reportError(i instanceof Error?i:new Error("Unknown error"),{component:"SDK",operation:"sendMessage",requestId:this.prepareMessage(e,t).requestId}),Promise.reject({success:!1,type:e,error:{code:r.COMMUNICATION_ERROR,message:i instanceof Error?i.message:"Unknown error"}})}}disconnect(){this.aborted=!0,this.initReject&&(this.initReject(new Error("Bridge initialization aborted")),this.initReject=void 0),this.iframe&&(window.removeEventListener("message",this.handleMessage.bind(this)),document.body.removeChild(this.iframe),this.iframe=null),this.isInitialized=!1,this.connected=!1,this.initializationPromise=null,this.pendingRequests.clear(),this.eventHandlers.clear()}isConnected(){return this.isInitialized&&this.connected}getBridgeHealth(){return{connected:this.isConnected()}}registerEventHandler(e,t){var i;this.eventHandlers.has(e)||this.eventHandlers.set(e,new Set);const n=e=>{t(e)};return null==(i=this.eventHandlers.get(e))||i.add(n),window.addEventListener("message",(e=>n(e.data.data))),()=>{var t;window.removeEventListener("message",(e=>{var t;return n(null==(t=e.data)?void 0:t.data)})),null==(t=this.eventHandlers.get(e))||t.delete(n)}}handleMessage(e){var t;if(!this.iframeOrigin||e.origin===this.iframeOrigin)try{const i=e.data;if(this.debug&&i&&i.requestId&&V.debug("bridge handleMessage",i),i&&("BRIDGE_READY"===i.type||"LAUNCHER_READY"===i.type)&&(null==(t=this.iframe)?void 0:t.contentWindow)===e.source)return void(this.connected=!0);if(i&&i.type&&Object.values(T).includes(i.type)&&!i.requestId)return void this.handleNotification(i);if(i&&i.requestId&&this.pendingRequests.has(i.requestId)){const{resolve:e,reject:t,timeout:n}=this.pendingRequests.get(i.requestId);if(clearTimeout(n),this.pendingRequests.delete(i.requestId),!1===i.success&&i.error){const e=this.getOperationFromMessageType(i.type||"unknown");t(this.createSDKErrorFromGatewayResponse(i.error,e))}else e({success:!0,data:i.response||i.data||i.result,requestId:i.requestId,timestamp:i.timestamp||Date.now()})}}catch(i){V.error("Error handling message:",i)}}handleNotification(e){V.debug("bridge notification received:",e);const t=this.eventHandlers.get(e.type);t&&t.forEach((t=>{try{t(e.data)}catch(i){V.error(`Error in ${e.type} handler:`,i)}}))}prepareMessage(e,t){return{payload:t,type:e,requestId:this.generateRequestId(),timestamp:Date.now()}}generateRequestId(){return`bridge_${Date.now()}_${Math.random().toString(36).substring(2,9)}`}createSDKErrorFromGatewayResponse(e,t){const i=this.mapGatewayErrorCodeToSDK(e.code);return new s(e.message,i,{operation:t,gatewayErrorCode:e.code,gatewayErrorMessage:e.message})}mapGatewayErrorCodeToSDK(e){switch(e){case k:case M:case N:case _:return r.INVALID_PARAMETER;case R:return r.TIMEOUT;case D:return r.NOT_SUPPORTED;case P:return r.COMMUNICATION_ERROR;case A:return r.INVALID_ARGUMENTS;default:return r.UNKNOWN}}getOperationFromMessageType(e){switch(e){case w.LAUNCH_APP_REQUEST:return"launchApp";case w.DEVICE_INFO_REQUEST:return"getDeviceInfo";case w.TTS_REQUEST_START_SPEAKING:return"startSpeaking";case w.TTS_REQUEST_STOP_SPEAKING:return"stopSpeaking";case w.TTS_REQUEST_SETTINGS:return"getTTSSettings";default:return"sdkOperation"}}async setupIframe(e,t){if(!this.iframe&&this.src){if(await new Promise((e=>{"undefined"!=typeof document&&"loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>e()),{once:!0}):e()})),this.iframe=document.createElement("iframe"),this.iframe.style.display="none",this.iframe.src=this.src,this.iframe.setAttribute("sandbox","allow-scripts"),!U())try{await F(5e3)}catch(i){throw new Error("Document body is not available even after waiting. Make sure the SDK is initialized after DOM content loaded.")}document.body.appendChild(this.iframe),await new Promise((i=>{const n=setTimeout((()=>{this.aborted||(V.warn("Bridge iframe ready timeout - continuing anyway"),i())}),this.iframeTimeout),r=t=>{var s;this.aborted||t.data&&t.data.type===w.LAUNCHER_READY&&(null==(s=this.iframe)?void 0:s.contentWindow)===t.source&&(V.debug("bridge iframe ready:",t.data),window.removeEventListener("message",r),clearTimeout(n),this.connected=!0,e&&e(),i())};window.addEventListener("message",r),window.addEventListener("message",(e=>{var t;this.aborted||e.data&&e.data.type===w.TRANSFER_DATA&&(null==(t=this.iframe)?void 0:t.contentWindow)===e.source&&V.debug("bridge transferData:",e.data)})),this.iframe&&(this.iframe.onload=()=>{this.aborted||V.debug("bridge iframe loaded: ",this.src)},this.iframe.onerror=()=>{this.aborted||(V.error("bridge iframe error: ",this.src),t&&t())})}))}}promisify(e){return(...t)=>new Promise(((i,n)=>{try{i(e.apply(null,t))}catch(r){n(r)}}))}async getDeviceInfo(){this.isInitialized||await this.initialize();const e=await this.sendMessage(w.DEVICE_INFO_REQUEST,void 0);if(e.success&&"data"in e)return e.data}async launchApp(e){this.isInitialized||await this.initialize();const t={code:e.appId,query:e.deepLink||""};return(await this.sendMessage(w.LAUNCH_APP_REQUEST,t)).success}onLogEntry(e){return this.registerEventHandler(w.LOG_ENTRY,(t=>{g({...t,metadata:{...t.metadata,source:"Gateway",tunneled:!0}}),e(t)}))}}const K=c("CSPDetector");let $=[];const G=class{static async canCreateIframe(e){try{if("undefined"==typeof document)return!1;try{await F(5e3)}catch(t){return K.warn("Timeout waiting for document.body, cannot create iframe"),!1}const i=document.createElement("iframe");return i.style.display="none",i.style.position="absolute",i.style.top="-9999px",i.src=e,i.allow="storage-access",i.setAttribute("sandbox","allow-scripts allow-same-origin"),new Promise((e=>{const n=setTimeout((()=>{r(),e(!1)}),5e3),r=()=>{clearTimeout(n),i.parentNode&&i.parentNode.removeChild(i)};i.onload=()=>{r(),e(!0)},i.onerror=()=>{r(),e(!1)};try{document.body.appendChild(i)}catch(t){r(),e(!1)}}))}catch(t){return K.error("Error checking iframe creation:",t),!1}}static async canPostMessage(e){try{if("undefined"==typeof window)return!1;try{await F(5e3)}catch(t){return K.warn("Timeout waiting for document.body, cannot test postMessage"),!1}const e=document.createElement("iframe");return e.style.display="none",e.src="about:blank",new Promise((i=>{const n=setTimeout((()=>{r(),i(!1)}),1e3),r=()=>{clearTimeout(n),e.parentNode&&e.parentNode.removeChild(e)};e.onload=()=>{try{e.contentWindow?(e.contentWindow.postMessage({type:"test"},"*"),r(),i(!0)):(r(),i(!1))}catch(t){r(),i(!1)}};try{document.body.appendChild(e)}catch(t){r(),i(!1)}}))}catch(t){return K.error("Error checking postMessage:",t),!1}}static async checkBridgeCSP(e){K.debug("Checking CSP compatibility for:",e);const t={canCreateIframe:!1,canPostMessage:!1,cspViolations:[...this.violations]};try{return this.violations.length=0,t.canCreateIframe=await this.canCreateIframe(e),t.canPostMessage=await this.canPostMessage(e),t.cspViolations=[...this.violations],K.debug("CSP check results:",t),t}catch(i){return t.error=i instanceof Error?i.message:"Unknown error",K.error("CSP check failed:",i),t}}static getViolations(){return[...this.violations]}static clearViolations(){this.violations.length=0}static onViolation(e){return $.push(e),()=>{$=$.filter((t=>t!==e))}}static checkWebAPISupport(){return{hasPostMessage:"undefined"!=typeof window&&"postMessage"in window,hasIframe:"undefined"!=typeof document&&"createElement"in document,hasMessageEvent:"undefined"!=typeof MessageEvent,hasDocument:"undefined"!=typeof document}}};var W;((e,t,n)=>{t in e?i(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n})(G,"symbol"!=typeof(W="violations")?W+"":W,[]),"undefined"!=typeof document&&document.addEventListener("securitypolicyviolation",(e=>{const t=`${e.violatedDirective}: ${e.blockedURI}`;G.violations.push(t),K.warn("CSP Violation detected:",t);const i={directive:e.violatedDirective,blockedURI:e.blockedURI,originalEvent:e};$.forEach((e=>{try{e(i)}catch(t){K.error("CSPDetector listener error",t)}}))}));let j=G;const q=c("EnhancedBridge");class Q extends z{bridgeHealthStatus={connected:!1,cspBlocked:!1,iframeCreated:!1,communicationWorking:!1,cspViolations:[]};cspUnsubscribe;cspViolationPromise;resolveCspViolation;enhancedInitializationPromise=null;constructor(e){super(e),this.bridgeHealthStatus.gatewayUrl=this.src,this.cspViolationPromise=new Promise((e=>{this.resolveCspViolation=e})),this.setupCspViolationPromise()}setupCspViolationPromise(){this.cspUnsubscribe=j.onViolation((e=>{(function(e,t){if("frame-src"!==e.directive||!e.blockedURI||!t)return!1;try{const i=new URL(t),n=new URL(e.blockedURI);if(i.origin===n.origin)return!0}catch{}return!!t.startsWith(e.blockedURI)||!!(e.blockedURI&&t&&t.includes(e.blockedURI))})(e,this.src)&&(this.resolveCspViolation(e),this.cspUnsubscribe&&(this.cspUnsubscribe(),this.cspUnsubscribe=void 0))}))}async initialize(){return this.enhancedInitializationPromise||(this.enhancedInitializationPromise=(async()=>{try{q.debug("Starting enhanced bridge initialization");const e=await this.checkCSPCompatibility();if(this.updateHealthStatus(e),e.cspViolations.length>0&&q.warn("CSP violations detected:",e.cspViolations),!e.canCreateIframe)return q.error("Cannot create iframe due to CSP restrictions"),this.bridgeHealthStatus.cspBlocked=!0,!1;const t=await Promise.race([super.initialize(),this.cspViolationPromise.then((e=>{q.warn("[EnhancedBridge] CSP violation detected:",e,this.src),this.bridgeHealthStatus.cspBlocked=!0,this.bridgeHealthStatus.communicationWorking=!1,this.bridgeHealthStatus.lastError="CSP blocked bridge iframe",this.disconnect()}))]);return this.bridgeHealthStatus.connected=!!t,!!t}catch(e){const t=e instanceof Error?e.message:"Unknown error";return this.bridgeHealthStatus.lastError=t,q.error("Enhanced bridge initialization failed:",e),!1}finally{this.enhancedInitializationPromise=null}})()),this.enhancedInitializationPromise}async checkCSPCompatibility(){return this.src?await j.checkBridgeCSP(this.src):{canCreateIframe:!1,canPostMessage:!1,cspViolations:[],error:"No gateway URL configured"}}updateHealthStatus(e){this.bridgeHealthStatus.cspBlocked=!e.canCreateIframe,this.bridgeHealthStatus.communicationWorking=e.canPostMessage,this.bridgeHealthStatus.cspViolations=e.cspViolations,e.error&&(this.bridgeHealthStatus.lastError=e.error)}getBridgeHealth(){return{...this.bridgeHealthStatus,connected:this.isConnected(),iframeCreated:null!==this.iframe}}async setupIframe(e,t){try{const i=await this.checkCSPCompatibility();if(!i.canCreateIframe)throw new s("Cannot create iframe due to CSP restrictions",r.NOT_SUPPORTED,{cspViolations:i.cspViolations});await super.setupIframe(e,t),this.bridgeHealthStatus.iframeCreated=!0}catch(i){throw this.bridgeHealthStatus.iframeCreated=!1,this.bridgeHealthStatus.lastError=i instanceof Error?i.message:"Unknown error",i}}async executeBridgeFunction(e,t){const i=this.getBridgeHealth();if(!i.connected||i.cspBlocked){if(t)return q.debug("Bridge unavailable, using fallback function"),await t();throw new s(i.cspBlocked?"Bridge unavailable due to CSP restrictions":"Bridge not connected",i.cspBlocked?r.NOT_SUPPORTED:r.COMMUNICATION_ERROR,{healthStatus:i})}return await e()}async executeWithFallback(e,t){return await this.executeBridgeFunction(e,t)}async sendMessage(e,t){return await this.executeBridgeFunction((()=>super.sendMessage(e,t)))}getConnectionResult(){const e=this.getBridgeHealth();return{success:e.connected&&!e.cspBlocked,healthStatus:e,error:e.lastError}}async testConnectivity(){try{q.debug("Testing bridge connectivity");const t=await this.checkCSPCompatibility();if(this.updateHealthStatus(t),t.canCreateIframe&&this.isConnected())try{await this.getDeviceInfo(),this.bridgeHealthStatus.communicationWorking=!0}catch(e){this.bridgeHealthStatus.communicationWorking=!1,this.bridgeHealthStatus.lastError=e instanceof Error?e.message:"Communication test failed"}return this.getConnectionResult()}catch(e){const t=e instanceof Error?e.message:"Unknown error";return this.bridgeHealthStatus.lastError=t,{success:!1,healthStatus:this.getBridgeHealth(),error:t}}}disconnect(){this.aborted||(super.disconnect(),this.cspUnsubscribe&&(this.cspUnsubscribe(),this.cspUnsubscribe=void 0),this.bridgeHealthStatus={connected:!1,cspBlocked:!1,iframeCreated:!1,communicationWorking:!1,gatewayUrl:this.src,cspViolations:[]},this.aborted=!0)}}class J extends Q{constructor(e){if(null==e?void 0:e.gatewayUrl)super({gatewayUrl:e.gatewayUrl});else{const e=window.location.hostname.includes("dev01.devview"),t=window.location.hostname.startsWith("dev");super({gatewayUrl:`http://localhost:4660/gateway/${e||t?"dev01":"index"}.html`})}}}const Y=new L;class Z extends Q{constructor(e){var t,i;if(null==e?void 0:e.gatewayUrl)super({gatewayUrl:e.gatewayUrl});else{let e="app";if(Y.proxy.jwt&&!Y.proxy.jwt.includes("null")){const t=(e=>{const t=e.split(".");if(3!==t.length)throw new Error("Invalid JWT token format");try{const e=t[1].replace(/-/g,"+").replace(/_/g,"/"),i=window.atob(e),n=decodeURIComponent(Array.from(i).map((e=>"%"+("00"+e.charCodeAt(0).toString(16)).slice(-2))).join(""));return JSON.parse(n)}catch(i){throw new Error("Error decoding JWT token: "+(i instanceof Error?i.message:String(i)))}})(Y.proxy.jwt);e=("production"===t.iss?"app":t.iss)||"app"}let n=`https://${e}.titanos.tv/gateway/${e.startsWith("dev")?"dev01":"index"}.html`;((null==(i=null==(t=Y.proxy.location)?void 0:t.host)?void 0:i.includes("dev01.devview"))||e.startsWith("dev"))&&(n="https://dev01.devview.titanos.tv/gateway/dev01.html"),super({gatewayUrl:n})}}async getTTSSettings(){return(await this.getA11ySettings()).tts||E}async getTMSettings(){return(await this.getA11ySettings()).tm||I}async getA11ySettings(){const e=await this.sendMessage(w.TTS_REQUEST_SETTINGS,void 0);return e.success&&"data"in e?e.data:C}async startSpeaking(e){this.isInitialized||await this.initialize();return(await this.sendMessage(w.TTS_REQUEST_START_SPEAKING,e)).success}async stopSpeaking(){return(await this.sendMessage(w.TTS_REQUEST_STOP_SPEAKING,void 0)).success}onTTSSettingsChange(e){return this.registerEventHandler(w.TTS_SETTINGS_CHANGE,(t=>{e(t)}))}onTMSettingsChange(e){return this.registerEventHandler(w.TM_SETTINGS_CHANGE,(t=>{e(t)}))}}const X={HIGH:["button","link","heading","listitem"],MEDIUM:["textbox","combobox","checkbox","radio","slider"],LOW:["list","navigation","main","dialog","grid"]},ee=c("AriaProcessor");class te{config;implicitRoles={button:"button",a:"link",'input[type="text"]':"textbox",'input[type="email"]':"textbox",'input[type="password"]':"textbox",'input[type="search"]':"textbox",'input[type="tel"]':"textbox",'input[type="url"]':"textbox",'input[type="checkbox"]':"checkbox",'input[type="radio"]':"radio",'input[type="range"]':"slider",textarea:"textbox",select:"combobox",h1:"heading",h2:"heading",h3:"heading",h4:"heading",h5:"heading",h6:"heading",nav:"navigation",main:"main",aside:"complementary",section:"region",article:"article",ul:"list",ol:"list",li:"listitem",table:"table",tr:"row",td:"cell",th:"columnheader",img:"img",dialog:"dialog"};tvElementTypes={navigation:["nav","menu",'[role="navigation"]','[role="menubar"]'],mediaControl:['[role="button"][aria-label*="play"]','[role="button"][aria-label*="pause"]','[role="slider"][aria-label*="volume"]','[role="progressbar"]'],contentGrid:['[role="grid"]','[role="gridcell"]',".content-grid",".video-grid"],mainContent:["main",'[role="main"]',".main-content","#main"]};constructor(e){this.config={...e}}updateConfig(e){this.config={...e}}async processElement(e){try{if(this.isElementHidden(e))return null;const t=this.getElementRole(e);if(this.config.tvOptimized&&!this.isRelevantForTV(t))return null;const i=this.computeAccessibleName(e);if(!i&&this.isInteractiveElement(t))return ee.warn("Interactive element without accessible name:",e),null;const n=this.getAccessibleDescription(e),r=this.computeElementState(e),s=this.computePositionInfo(e,t),o=this.getAvailableActions(e,t),a=this.config.tvOptimized?this.getTVSpecificProperties(e,t):void 0,c={element:e,role:t,name:i,description:n,state:r,position:s,actions:o,tvProperties:a};return ee.debug("Processed accessibility element:",{role:t,name:i.substring(0,50),state:r,tvOptimized:!!a}),c}catch(t){return ee.error("Error processing element:",t),null}}isElementHidden(e){if("true"===e.getAttribute("aria-hidden"))return!0;const t=window.getComputedStyle(e);if("none"===t.display||"hidden"===t.visibility||"0"===t.opacity)return!0;if(this.config.tvOptimized){const t=e.getBoundingClientRect();if(0===t.width&&0===t.height)return!0}return!1}getElementRole(e){const t=e.getAttribute("role");if(t)return t;const i=e.tagName.toLowerCase(),n=e.getAttribute("type");if("input"===i&&n){const e=`input[type="${n}"]`;if(this.implicitRoles[e])return this.implicitRoles[e]}return this.implicitRoles[i]||"generic"}computeAccessibleName(e){const t=e.getAttribute("aria-labelledby");if(t){const e=[];for(const i of t.split(/\s+/)){const t=document.getElementById(i);t&&e.push(this.getTextContent(t))}if(e.length>0)return e.join(" ").trim()}const i=e.getAttribute("aria-label");if(i)return i.trim();if(this.isFormControl(e)){const t=this.getAssociatedLabels(e);if(t.length>0)return t.map((e=>this.getTextContent(e))).join(" ").trim()}if("input"===e.tagName.toLowerCase()){const t=e.getAttribute("placeholder");if(t)return t.trim()}if("img"===e.tagName.toLowerCase()){const t=e.getAttribute("alt");if(null!==t)return t.trim()}return this.getTextContent(e)}getAccessibleDescription(e){const t=e.getAttribute("aria-describedby");if(!t)return;const i=[];for(const n of t.split(/\s+/)){const e=document.getElementById(n);e&&i.push(this.getTextContent(e))}return i.length>0?i.join(" ").trim():void 0}computeElementState(e){const t={},i=e.getAttribute("aria-expanded");null!==i&&(t.expanded="true"===i);const n=e.getAttribute("aria-checked");null!==n&&(t.checked="mixed"===n?"mixed":"true"===n);const r=e.getAttribute("aria-selected");null!==r&&(t.selected="true"===r);const s=e.getAttribute("aria-disabled")||e.getAttribute("disabled");null!==s&&(t.disabled="true"===s||""===s);const o=e.getAttribute("aria-invalid");null!==o&&(t.invalid="true"===o||o);const a=e.getAttribute("aria-level");null!==a?t.level=parseInt(a,10):e.tagName.match(/^H[1-6]$/)&&(t.level=parseInt(e.tagName.charAt(1),10));const c=e.getAttribute("aria-valuenow");null!==c&&(t.valueNow=parseFloat(c));const l=e.getAttribute("aria-valuetext");return null!==l&&(t.valueText=l),t.focused=document.activeElement===e,t}computePositionInfo(e,t){return"listitem"===t?this.computeListItemPosition(e):"gridcell"===t||"cell"===t?this.computeGridCellPosition(e):void 0}computeListItemPosition(e){const t=e.getAttribute("aria-posinset"),i=e.getAttribute("aria-setsize");if(t&&i)return{position:parseInt(t,10),setSize:parseInt(i,10)};const n=e.closest('ul, ol, [role="list"]');if(n){const t=Array.from(n.querySelectorAll('li, [role="listitem"]')),i=t.indexOf(e)+1;if(i>0)return{position:i,setSize:t.length}}}computeGridCellPosition(e){const t=e.closest('[role="row"], tr'),i=e.closest('[role="grid"], table');if(t&&i){const n=Array.from(i.querySelectorAll('[role="row"], tr')),r=Array.from(t.querySelectorAll('[role="gridcell"], [role="cell"], td, th')),s=n.indexOf(t)+1,o=r.indexOf(e)+1;if(s>0&&o>0)return{position:o,setSize:r.length,row:s,column:o,totalRows:n.length,totalColumns:r.length}}}getAvailableActions(e,t){const i=[];if(this.isClickableElement(e,t)&&i.push({name:"activate",description:this.getActivationDescription(t),tvButton:"OK"}),e.hasAttribute("aria-expanded")){const t="true"===e.getAttribute("aria-expanded");i.push({name:t?"collapse":"expand",description:t?"Collapse":"Expand",tvButton:"OK"})}return"textbox"!==t&&"combobox"!==t||i.push({name:"edit",description:"Enter text",tvButton:"OK"}),i}getTVSpecificProperties(e,t){const i={};return this.matchesSelectors(e,this.tvElementTypes.navigation)&&(i.isMainNavigation=!0,i.priority="high"),this.matchesSelectors(e,this.tvElementTypes.mediaControl)&&(i.isMediaControl=!0,i.priority="high"),this.matchesSelectors(e,this.tvElementTypes.contentGrid)&&(i.isContentGrid=!0,i.priority="medium"),i.priority||(X.HIGH.includes(t)?i.priority="high":X.MEDIUM.includes(t)?i.priority="medium":i.priority="low"),Object.keys(i).length>0?i:void 0}isRelevantForTV(e){return[...X.HIGH,...X.MEDIUM,...X.LOW].includes(e)}isInteractiveElement(e){return["button","link","textbox","combobox","checkbox","radio","slider"].includes(e)}isFormControl(e){return["input","textarea","select","button"].includes(e.tagName.toLowerCase())}isClickableElement(e,t){return["button","link","checkbox","radio","menuitem"].includes(t)||e.hasAttribute("onclick")}getActivationDescription(e){return{button:"Press button",link:"Follow link",checkbox:"Toggle checkbox",radio:"Select option",menuitem:"Select menu item"}[e]||"Activate"}getTextContent(e){let t="";for(const i of e.childNodes)if(i.nodeType===Node.TEXT_NODE)t+=i.textContent||"";else if(i.nodeType===Node.ELEMENT_NODE){const e=i;this.isElementHidden(e)||(t+=this.getTextContent(e))}return t.replace(/\s+/g," ").trim()}getAssociatedLabels(e){const t=[],i=e.getAttribute("id");if(i){const e=document.querySelectorAll(`label[for="${i}"]`);t.push(...Array.from(e))}const n=e.closest("label");return n&&t.push(n),t}matchesSelectors(e,t){return t.some((t=>{try{return e.matches(t)}catch{return!1}}))}}const ie=c("DOMMonitor");class ne{config;ariaProcessor;isTracking=!1;focusHandler;liveRegionHandler;focusListener;keydownListener;mutationObserver;currentFocusedElement=null;liveRegions=new Map;previousFocusedElement=null;constructor(e,t){this.config={...e},this.focusHandler=t,this.ariaProcessor=new te(e)}updateConfig(e){this.config={...e},this.ariaProcessor.updateConfig(e)}async startFocusTracking(){if(this.isTracking)return void ie.debug("Focus tracking already active");ie.info("Starting focus tracking"),this.focusListener=this.handleFocusEvent.bind(this),document.addEventListener("focusin",this.focusListener,!0),document.addEventListener("focusout",this.focusListener,!0),this.keydownListener=this.handleKeydownEvent.bind(this),document.addEventListener("keydown",this.keydownListener,!0);const e=document.activeElement;e&&e!==document.body&&(this.currentFocusedElement=e,await this.processFocusChange(e,"initial")),this.isTracking=!0,ie.info("Focus tracking started")}async startLiveRegionMonitoring(e){this.liveRegionHandler=e,ie.info("Starting live region monitoring"),await this.scanForLiveRegions(),this.mutationObserver=new MutationObserver(this.handleMutations.bind(this)),this.mutationObserver.observe(document.body,{childList:!0,subtree:!0,characterData:!0,attributes:!0,attributeFilter:["aria-live","aria-atomic","aria-relevant","aria-busy"]}),ie.info("Live region monitoring started")}async stop(){ie.info("Stopping DOM monitoring"),this.focusListener&&(document.removeEventListener("focusin",this.focusListener,!0),document.removeEventListener("focusout",this.focusListener,!0),this.focusListener=void 0),this.keydownListener&&(document.removeEventListener("keydown",this.keydownListener,!0),this.keydownListener=void 0),this.mutationObserver&&(this.mutationObserver.disconnect(),this.mutationObserver=void 0),this.currentFocusedElement=null,this.previousFocusedElement=null,this.liveRegions.clear(),this.isTracking=!1,this.liveRegionHandler=void 0,ie.info("DOM monitoring stopped")}async restart(){await this.stop(),this.config.focusTracking&&await this.startFocusTracking(),this.config.liveRegions&&this.liveRegionHandler&&await this.startLiveRegionMonitoring(this.liveRegionHandler)}async handleFocusEvent(e){try{const t=e.target;"focusin"===e.type?t&&t!==this.currentFocusedElement&&(this.currentFocusedElement=t,await this.processFocusChange(t,"user")):"focusout"===e.type&&t===this.currentFocusedElement&&(this.currentFocusedElement=null)}catch(t){ie.error("Error handling focus event:",t)}}async handleKeydownEvent(e){const t={ArrowUp:"UP",ArrowDown:"DOWN",ArrowLeft:"LEFT",ArrowRight:"RIGHT",Enter:"OK",Escape:"BACK",Tab:"TAB"}[e.key];t&&this.currentFocusedElement&&ie.debug("TV remote button pressed:",t)}async processFocusChange(e,t){try{if(this.ariaProcessor.isElementHidden(e))return;const i=await this.ariaProcessor.processElement(e);if(i&&this.focusHandler){const e={previousElement:this.previousFocusedElement||void 0,currentElement:i,reason:t};await this.focusHandler(e),this.previousFocusedElement=i}}catch(i){ie.error("Error processing focus change:",i)}}async scanForLiveRegions(){const e=document.querySelectorAll("[aria-live]");for(const t of e){const e=this.createLiveRegion(t);e&&(this.liveRegions.set(t,e),ie.debug("Found live region:",{politeness:e.politeness,atomic:e.atomic}))}}createLiveRegion(e){const t=e.getAttribute("aria-live");if(!t||"off"===t)return null;const i=t,n="true"===e.getAttribute("aria-atomic"),r=(e.getAttribute("aria-relevant")||"additions text").split(" "),s="true"===e.getAttribute("aria-busy");return{element:e,politeness:i,atomic:n,relevant:r,busy:s}}async handleMutations(e){for(const i of e)try{"attributes"===i.type&&await this.handleAttributeChange(i),"childList"!==i.type&&"characterData"!==i.type||await this.handleContentChange(i)}catch(t){ie.error("Error handling mutation:",t)}}async handleAttributeChange(e){const t=e.target,i=e.attributeName;if("aria-live"===i){const e=this.createLiveRegion(t);e?this.liveRegions.set(t,e):this.liveRegions.delete(t)}else if("aria-busy"===i){const e=this.liveRegions.get(t);e&&(e.busy="true"===t.getAttribute("aria-busy"))}}async handleContentChange(e){let t=e.target;for(;t&&t!==document.body;){const i=this.liveRegions.get(t);if(i&&!i.busy&&this.liveRegionHandler){const n=i.atomic?t.textContent||"":this.extractChangedContent(e);n.trim()&&await this.liveRegionHandler(i,n);break}t=t.parentElement}}extractChangedContent(e){if("characterData"===e.type)return e.target.textContent||"";if("childList"===e.type){let t="";for(const i of e.addedNodes)(i.nodeType===Node.TEXT_NODE||i.nodeType===Node.ELEMENT_NODE)&&(t+=i.textContent||"");return t}return""}}const re=c("AnnouncementProcessor");class se{config;ttsFunction;stopTtsFunction;lastAnnouncementTime=0;announcementQueue=[];isProcessingQueue=!1;tvTimings={minInterval:100,maxQueueSize:5,priorityDelay:50,politeDelay:200};constructor(e,t,i){this.config={...e},this.ttsFunction=t,this.stopTtsFunction=i}updateConfig(e){this.config={...e}}async announce(e,t="polite"){const i=this.processAnnouncementText(e);if(!i||0===i.length)return re.debug("No text to announce after processing"),!1;const n={text:i,priority:t,timestamp:Date.now()};return"assertive"===t?(this.announcementQueue.length=0,await this.speakNow(n)):(this.queueAnnouncement(n),this.processQueue(),!0)}async stopAnnouncement(){try{if(this.announcementQueue.length=0,this.isProcessingQueue=!1,this.stopTtsFunction){const e=await this.stopTtsFunction();return re.debug("TTS stop result:",e),e}return re.debug("No stopTtsFunction available"),!0}catch(e){return re.error("Error stopping announcement:",e),!1}}async announceFocusChange(e){const{currentElement:t}=e;if(!t)return;const i=this.buildFocusAnnouncement(t);i.length>0&&await this.announce(i,"polite")}async announceLiveRegion(e,t){if(!e.trim())return;const i=this.processLiveRegionContent(e);i&&await this.announce([i],t)}buildFocusAnnouncement(e){const t=[],i=this.getRoleAnnouncement(e.role);i&&t.push(i),e.name&&t.push(e.name);const n=this.getStateAnnouncement(e.state,e.role);n.length>0&&t.push(...n);const r=this.getPositionAnnouncement(e.position,e.role);r&&t.push(r),e.description&&this.shouldIncludeDescription()&&t.push(e.description);const s=this.getActionAnnouncement(e.actions||[]);return s&&t.push(s),this.filterAnnouncementContent(t,e.role)}shouldIncludeDescription(){return"concise"!==this.config.verbosity&&(this.config.verbosity,!0)}filterAnnouncementContent(e,t){if(!this.config.tvOptimized)return e;const i=["button","link","heading","alert","dialog"].includes(t);return"concise"===this.config.verbosity?i?e.slice(0,2):e.slice(1,2):"standard"===this.config.verbosity?e.slice(0,4):e}getRoleAnnouncement(e){const t={button:{concise:"",standard:"button",detailed:"button"},link:{concise:"",standard:"link",detailed:"link"},heading:{concise:"",standard:"heading",detailed:"heading"},listitem:{concise:"",standard:"list item",detailed:"list item"},textbox:{concise:"",standard:"text field",detailed:"text field"},combobox:{concise:"",standard:"dropdown",detailed:"combo box"},checkbox:{concise:"check box",standard:"check box",detailed:"check box"},radio:{concise:"radio",standard:"radio button",detailed:"radio button"},slider:{concise:"slider",standard:"slider",detailed:"slider"},navigation:{concise:"",standard:"navigation",detailed:"navigation menu"},main:{concise:"",standard:"main content",detailed:"main content area"},dialog:{concise:"dialog",standard:"dialog",detailed:"dialog box"},grid:{concise:"",standard:"grid",detailed:"content grid"},gridcell:{concise:"",standard:"",detailed:"grid cell"},list:{concise:"",standard:"list",detailed:"list"},menu:{concise:"menu",standard:"menu",detailed:"menu"},menuitem:{concise:"",standard:"menu item",detailed:"menu item"},tab:{concise:"tab",standard:"tab",detailed:"tab"},tabpanel:{concise:"",standard:"tab panel",detailed:"tab panel"},progressbar:{concise:"progress",standard:"progress bar",detailed:"progress indicator"},alert:{concise:"alert",standard:"alert",detailed:"alert message"},status:{concise:"",standard:"status",detailed:"status update"}}[e];if(!t)return null;return t[this.config.verbosity]||t.standard||null}getStateAnnouncement(e,t){const i=[];if(!e)return i;const n="concise"===this.config.verbosity,r="detailed"===this.config.verbosity;if(void 0!==e.expanded&&(n?i.push(e.expanded?"open":"closed"):i.push(e.expanded?"expanded":"collapsed")),void 0!==e.checked&&("mixed"===e.checked?i.push(n?"mixed":"partially checked"):n?i.push(e.checked?"on":"off"):i.push(e.checked?"checked":"not checked")),e.selected&&i.push(n?"on":"selected"),e.disabled&&i.push("disabled"),e.invalid&&(r?i.push("string"==typeof e.invalid?e.invalid:"invalid"):i.push("invalid")),"heading"===t&&e.level&&(n?i.push(`h${e.level}`):i.push(`level ${e.level}`)),e.valueText)i.push(e.valueText);else if(void 0!==e.valueNow)if("progressbar"===t){const t=e.valueMax?Math.round(e.valueNow/e.valueMax*100):e.valueNow;i.push(n?`${t}%`:`${t} percent`)}else"slider"===t?i.push(n?`${e.valueNow}`:`value ${e.valueNow}`):i.push(`${e.valueNow}`);return this.config.tvOptimized&&e.focused&&r&&i.push("focused"),i}getPositionAnnouncement(e,t){if(!e)return null;const i="concise"===this.config.verbosity,n="detailed"===this.config.verbosity;return"listitem"===t?i?null:`${e.position} of ${e.setSize}`:"gridcell"===t&&e.row&&e.column?this.config.tvOptimized?i?`${e.row},${e.column}`:n&&e.totalRows&&e.totalColumns?`row ${e.row} of ${e.totalRows}, column ${e.column} of ${e.totalColumns}`:`row ${e.row}, column ${e.column}`:`row ${e.row}, column ${e.column}`:"tab"===t&&e.position&&e.setSize?i?null:`tab ${e.position} of ${e.setSize}`:"menuitem"===t&&e.position&&e.setSize?i?null:`${e.position} of ${e.setSize}`:null}getActionAnnouncement(e){if(!e||0===e.length)return null;const t="concise"===this.config.verbosity,i="detailed"===this.config.verbosity;if(!this.config.tvOptimized){return`available actions: ${e.map((e=>e.name)).slice(0,2).join(", ")}`}const n=e[0];if(!n)return null;if(n.tvButton){if(t)return null;const e=this.getTVButtonText(n.tvButton),r=n.description||"activate";return i?`press ${e} to ${r.toLowerCase()}`:`press ${e}`}if(n.name){if(t)return null;const e=this.getCommonTVAction(n.name);if(e)return i?`available actions: ${e}`:e}return null}getTVButtonText(e){return{OK:"OK",BACK:"Back",UP:"Up",DOWN:"Down",LEFT:"Left",RIGHT:"Right",MENU:"Menu"}[e]||e}getCommonTVAction(e){return{activate:"activate",click:"select",toggle:"toggle",expand:"expand",collapse:"collapse",select:"select",play:"play",pause:"pause",stop:"stop",mute:"mute",unmute:"unmute"}[e.toLowerCase()]||null}processAnnouncementText(e){if(!e)return[];if("string"==typeof e&&(e=[e]),!Array.isArray(e))return[];let t=[...e];return this.config.tvOptimized&&(t=this.applyTVOptimizations(t)),t=this.applyVerbosityFilter(t),t=t.map((e=>e.trim())).filter((e=>e.length>0)).map((e=>this.cleanupText(e))),t}applyTVOptimizations(e){return e.map((e=>{let t=e.replace(/\bnavigation\b/gi,"nav").replace(/\bmenuitem\b/gi,"menu").replace(/\btextbox\b/gi,"text field").replace(/\bcombobox\b/gi,"dropdown").replace(/\bcheckbox\b/gi,"check box");return t=t.replace(/\bapplication\b/gi,"").replace(/\bregion\b/gi,"").replace(/\blandmark\b/gi,""),t.trim()}))}applyVerbosityFilter(e){switch(this.config.verbosity){case"concise":return e.slice(0,2);case"detailed":return e;default:return e.slice(0,4)}}cleanupText(e){return e.replace(/\s+/g," ").replace(/[_-]+/g," ").replace(/([a-z])([A-Z])/g,"$1 $2").trim()}processLiveRegionContent(e){const t=this.cleanupText(e);return t.length<3||/^\s*[.!?]*\s*$/.test(t)?null:this.config.tvOptimized?this.applyTVOptimizations([t])[0]:t}queueAnnouncement(e){this.announcementQueue.length>=this.tvTimings.maxQueueSize&&this.announcementQueue.shift(),this.announcementQueue.push(e)}async processQueue(){if(!this.isProcessingQueue&&0!==this.announcementQueue.length){for(this.isProcessingQueue=!0;this.announcementQueue.length>0;){const e=this.announcementQueue.shift();if(e){await this.speakNow(e);const t="assertive"===e.priority?this.tvTimings.priorityDelay:this.tvTimings.politeDelay;await this.delay(t)}}this.isProcessingQueue=!1}}async speakNow(e){const t=Date.now()-this.lastAnnouncementTime;t<this.tvTimings.minInterval&&await this.delay(this.tvTimings.minInterval-t);try{const t=await this.ttsFunction(e.text);return this.lastAnnouncementTime=Date.now(),re.debug("Announced:",{text:e.text.join(" ").substring(0,100),priority:e.priority,success:t}),t}catch(i){return re.error("Error speaking announcement:",i),!1}}delay(e){return new Promise((t=>setTimeout(t,e)))}}const oe=c("AccessibilityReader");class ae{config;isActive=!1;domMonitor;ariaProcessor;announcementProcessor;currentElement=null;liveRegions=new Map;constructor(e,t,i){this.config={...e},this.ariaProcessor=new te(e),this.announcementProcessor=new se(e,t,i),this.domMonitor=new ne(e,this.handleFocusChange.bind(this))}async start(){if(this.isActive)return oe.debug("Accessibility Reader already active"),!0;try{oe.info("Starting Accessibility Reader",this.config),this.config.focusTracking&&await this.domMonitor.startFocusTracking(),this.config.liveRegions&&await this.domMonitor.startLiveRegionMonitoring(this.handleLiveRegionChange.bind(this));const e=document.activeElement;return e&&e!==document.body&&await this.announceElement(e),this.isActive=!0,oe.info("Accessibility Reader started successfully"),!0}catch(e){return oe.error("Failed to start Accessibility Reader:",e),!1}}async stop(){if(!this.isActive)return oe.debug("Accessibility Reader not active"),!0;try{return oe.info("Stopping Accessibility Reader"),await this.domMonitor.stop(),this.currentElement=null,this.liveRegions.clear(),this.isActive=!1,oe.info("Accessibility Reader stopped"),!0}catch(e){return oe.error("Failed to stop Accessibility Reader:",e),!1}}async updateConfig(e){try{const t={...this.config};if(this.config={...this.config,...e},this.ariaProcessor.updateConfig(this.config),this.announcementProcessor.updateConfig(this.config),this.domMonitor.updateConfig(this.config),this.isActive){const e=t.focusTracking!==this.config.focusTracking,i=t.liveRegions!==this.config.liveRegions;(e||i)&&await this.domMonitor.restart()}return oe.info("Accessibility Reader configuration updated",this.config),!0}catch(t){return oe.error("Failed to update Accessibility Reader config:",t),!1}}getConfig(){return{...this.config}}isReaderActive(){return this.isActive}async announce(e,t="polite"){return this.isActive?await this.announcementProcessor.announce(e,t):(oe.debug("Accessibility Reader not active, skipping announcement"),!1)}async stopAnnouncement(){return this.isActive?await this.announcementProcessor.stopAnnouncement():(oe.debug("Accessibility Reader not active, skipping stop"),!1)}getCurrentElement(){return this.currentElement}async handleFocusChange(e){var t,i;try{oe.debug("Focus changed",{from:null==(t=e.previousElement)?void 0:t.role,to:null==(i=e.currentElement)?void 0:i.role,reason:e.reason}),this.currentElement=e.currentElement||null,e.currentElement&&await this.announcementProcessor.announceFocusChange(e)}catch(n){oe.error("Error handling focus change:",n)}}async handleLiveRegionChange(e,t){try{if(oe.debug("Live region changed",{politeness:e.politeness,content:t.substring(0,100)}),e.busy)return;const i="assertive"===e.politeness?"assertive":"polite";await this.announcementProcessor.announceLiveRegion(t,i)}catch(i){oe.error("Error handling live region change:",i)}}async announceElement(e){try{const t=await this.ariaProcessor.processElement(e);if(t){const e={previousElement:this.currentElement||void 0,currentElement:t,reason:"programmatic"};await this.handleFocusChange(e)}}catch(t){oe.error("Error announcing element:",t)}}}class ce{static sanitizeSpeechCues(e){return e.map((e=>this.sanitizeSpeechCue(e)))}static sanitizeSpeechCue(e){return"string"==typeof e?this.sanitizeText(e):{...e,Name:this.sanitizeText(e.Name),Value:e.Value?this.sanitizeText(e.Value):void 0,ItemSubType:e.ItemSubType?this.sanitizeText(e.ItemSubType):void 0,Status:e.Status?this.sanitizeText(e.Status):void 0}}static sanitizeText(e){return e?e.replace(/<[^>]*>/g,"").replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"").replace(/(javascript|data|vbscript):/gi,"blocked:").replace(/\\{2,}/g,"\\").slice(0,1e3):e}static sanitizeHtml(e){return e.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"").replace(/on\w+=/gi,"disabled-event=").replace(/allow=/gi,"data-blocked-allow=").replace(/(javascript|data|vbscript):/gi,"blocked:")}static sanitizeInput(e){return e.replace(/[\x00-\x1F\x7F]/g,"").replace(/['"\\]/g,"\\$&").replace(/\0/g,"").slice(0,500)}static checkRateLimit(e,t=10,i=6e4){const n=Date.now();return e.filter((e=>n-e.timestamp<i)).length<t}}const le=c("PhilipsTTS"),ue=e=>e?{available:!0,enabled:"1"===e.setVoiceGuidance,rate:e.speechRate?Number(e.speechRate):1,volume:e.speechVolume?Number(e.speechVolume):1}:E,de=e=>e?{available:!0,enabled:"on"===e.setTextMagnification,scale:e.fontSizeBase?Number(e.fontSizeBase):1}:I;class he{windowApi;constructor(e){this.windowApi=e||new L}messageToJSON(e){const t=JSON.stringify(e.info).replace(/'/g,"''");return JSON.stringify({...e,info:t})}getSettings(){const e=this.windowApi.get("getDeviceContent");if(!e)return C;const t=e("getVoiceGuidance",!1)??"",i=e("getTextMagnification",!1)??"";try{return{tts:ue(this.hexToObject(t)),tm:de(this.hexToObject(i))}}catch(n){return le.warn("JSON Parsing Error:",n),C}}sendTTSMessage(e){const t=this.windowApi.get("omi_platform");if(t)try{t.sendPlatformMessage(this.messageToJSON(e))}catch(i){le.warn("Failed to send platform message:",i)}}startSpeaking(e){const t=ce.sanitizeSpeechCues(e).filter((e=>!(e=>"string"==typeof e?""===e.trim():""===e.Name.trim())(e)));if(0===t.length)return!1;const i=Object.fromEntries(t.map(((e,t)=>[`tts${t+1}`,e])));return this.sendTTSMessage({cmd:"startToSpeak",info:i}),!0}stopSpeaking(){return this.sendTTSMessage({cmd:"stopToSpeak",info:{param1:"false"}}),!0}stopSpeakingButKeepHighlightTask(){this.sendTTSMessage({cmd:"stopSpeakAndKeepInHighlightTask",info:{param1:"false"}})}hexToString(e){var t;return(null==(t=e.match(/.{2}/g))?void 0:t.map((e=>String.fromCharCode(parseInt(e,16)))).join(""))||""}hexToObject(e){if(!e)return null;try{let t=this.hexToString(e).replace(/\\/g,"").trim();t.startsWith('"')&&t.endsWith('"')&&(t=t.slice(1,-1));return JSON.parse(t)}catch(t){return null}}getTTSSettings(){return this.getSettings().tts}getTMSettings(){return this.getSettings().tm}createPlatformEventHandler(e,t){return i=>{try{const r=JSON.parse(i),s=decodeURIComponent(r.data),o=/cmd:\s*'(?<command>[^']+)'\s*,\s*info:\s*'(?<info>[^']+)'\s*;/,a=s.match(o);if(!a||!a.groups)return;if(a.groups.command!==e)return;try{let e=JSON.parse(a.groups.info);"string"==typeof e&&(e=JSON.parse(e)),t(e)}catch(n){le.warn(`[tts] Could not parse info as JSON: ${n}`)}}catch(r){le.warn(`[tts] Failed to parse platform event: ${r}`)}}}onTTSSettingsChange(e){var t;const i=this.windowApi.get("omi_platform");if(!i)return()=>{};const n=this.createPlatformEventHandler("VoiceGuidanceNotify",(t=>e(ue(t))));return null==(t=i.addPlatformEventListener)||t.call(i,n),()=>{var e;null==(e=i.removePlatformEventListener)||e.call(i,n)}}onTMSettingsChange(e){var t;const i=this.windowApi.get("omi_platform");if(!i)return()=>{};const n=this.createPlatformEventHandler("TextMagnificationNotify",(t=>e(de(t))));return null==(t=i.addPlatformEventListener)||t.call(i,n),()=>{var e;null==(e=i.removePlatformEventListener)||e.call(i,n)}}}const ge=c("AccessibilityService");class pe{tts;reader=null;ttsSettings=E;tmSettings=I;constructor(){this.tts=new he,this.tts.onTTSSettingsChange((e=>{this.ttsSettings=e})),this.tts.onTMSettingsChange((e=>{this.tmSettings=e}))}async startSpeaking(e){if("string"==typeof e&&(e=[e]),await this.isTTSEnabled())try{return this.tts.startSpeaking(e),!0}catch(t){return ge.error("Error starting speaking:",t),!1}return!0}async stopSpeaking(){return await this.isTTSEnabled()&&this.tts.stopSpeaking(),!0}async enableReader(e){try{if(!(await this.isTTSSupported()))return ge.warn("Cannot enable Reader: TTS not supported"),!1;if(!(await this.isTTSEnabled()))return ge.warn("Cannot enable Reader: TTS not enabled"),!1;this.reader=new ae(e,this.startSpeaking.bind(this),this.stopSpeaking.bind(this));return!!(await this.reader.start())&&(ge.info("Reader enabled"),!0)}catch(t){return ge.error("Error enabling Reader:",t),!1}}async disableReader(){try{if(this.reader){const e=await this.reader.stop();return this.reader=null,e&&ge.info("Reader disabled"),e}return ge.debug("Reader was not active"),!0}catch(e){return ge.error("Error disabling Reader:",e),!1}}getReader(){if(!this.reader)throw new Error("Reader is not active");return this.reader}async isTTSSupported(){try{return(await this.getTTSSettings()).available}catch(e){return ge.error("Error checking TTS support:",e),!1}}async isTextMagnificationSupported(){try{return(await this.getTMSettings()).available}catch(e){return ge.error("Error checking magnification support:",e),!1}}onTTSSettingsChange(e){return this.tts.onTTSSettingsChange(e)}onTMSettingsChange(e){return this.tts.onTMSettingsChange(e)}async getTTSSettings(){return this.ttsSettings}async getTMSettings(){return this.tmSettings}async isTTSEnabled(){return(await this.getTTSSettings()).enabled}async isTMEnabled(){return(await this.getTMSettings()).enabled}}class fe{config;waitReady=new Promise((()=>{}));waitReadyResolver;constructor(e){this.config=e,this.waitReady=new Promise((e=>{this.waitReadyResolver=e}))}logError(...e){this.config.debug}}var me,Se={exports:{}};var ve,be,ye=(me||(me=1,ve=Se,be=function(){var e=String.fromCharCode,t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",n={};function r(e,t){if(!n[e]){n[e]={};for(var i=0;i<e.length;i++)n[e][e.charAt(i)]=i}return n[e][t]}var s={compressToBase64:function(e){if(null==e)return"";var i=s._compress(e,6,(function(e){return t.charAt(e)}));switch(i.length%4){default:case 0:return i;case 1:return i+"===";case 2:return i+"==";case 3:return i+"="}},decompressFromBase64:function(e){return null==e?"":""==e?null:s._decompress(e.length,32,(function(i){return r(t,e.charAt(i))}))},compressToUTF16:function(t){return null==t?"":s._compress(t,15,(function(t){return e(t+32)}))+" "},decompressFromUTF16:function(e){return null==e?"":""==e?null:s._decompress(e.length,16384,(function(t){return e.charCodeAt(t)-32}))},compressToUint8Array:function(e){for(var t=s.compress(e),i=new Uint8Array(2*t.length),n=0,r=t.length;n<r;n++){var o=t.charCodeAt(n);i[2*n]=o>>>8,i[2*n+1]=o%256}return i},decompressFromUint8Array:function(t){if(null==t)return s.decompress(t);for(var i=new Array(t.length/2),n=0,r=i.length;n<r;n++)i[n]=256*t[2*n]+t[2*n+1];var o=[];return i.forEach((function(t){o.push(e(t))})),s.decompress(o.join(""))},compressToEncodedURIComponent:function(e){return null==e?"":s._compress(e,6,(function(e){return i.charAt(e)}))},decompressFromEncodedURIComponent:function(e){return null==e?"":""==e?null:(e=e.replace(/ /g,"+"),s._decompress(e.length,32,(function(t){return r(i,e.charAt(t))})))},compress:function(t){return s._compress(t,16,(function(t){return e(t)}))},_compress:function(e,t,i){if(null==e)return"";var n,r,s,o={},a={},c="",l="",u="",d=2,h=3,g=2,p=[],f=0,m=0;for(s=0;s<e.length;s+=1)if(c=e.charAt(s),Object.prototype.hasOwnProperty.call(o,c)||(o[c]=h++,a[c]=!0),l=u+c,Object.prototype.hasOwnProperty.call(o,l))u=l;else{if(Object.prototype.hasOwnProperty.call(a,u)){if(u.charCodeAt(0)<256){for(n=0;n<g;n++)f<<=1,m==t-1?(m=0,p.push(i(f)),f=0):m++;for(r=u.charCodeAt(0),n=0;n<8;n++)f=f<<1|1&r,m==t-1?(m=0,p.push(i(f)),f=0):m++,r>>=1}else{for(r=1,n=0;n<g;n++)f=f<<1|r,m==t-1?(m=0,p.push(i(f)),f=0):m++,r=0;for(r=u.charCodeAt(0),n=0;n<16;n++)f=f<<1|1&r,m==t-1?(m=0,p.push(i(f)),f=0):m++,r>>=1}0==--d&&(d=Math.pow(2,g),g++),delete a[u]}else for(r=o[u],n=0;n<g;n++)f=f<<1|1&r,m==t-1?(m=0,p.push(i(f)),f=0):m++,r>>=1;0==--d&&(d=Math.pow(2,g),g++),o[l]=h++,u=String(c)}if(""!==u){if(Object.prototype.hasOwnProperty.call(a,u)){if(u.charCodeAt(0)<256){for(n=0;n<g;n++)f<<=1,m==t-1?(m=0,p.push(i(f)),f=0):m++;for(r=u.charCodeAt(0),n=0;n<8;n++)f=f<<1|1&r,m==t-1?(m=0,p.push(i(f)),f=0):m++,r>>=1}else{for(r=1,n=0;n<g;n++)f=f<<1|r,m==t-1?(m=0,p.push(i(f)),f=0):m++,r=0;for(r=u.charCodeAt(0),n=0;n<16;n++)f=f<<1|1&r,m==t-1?(m=0,p.push(i(f)),f=0):m++,r>>=1}0==--d&&(d=Math.pow(2,g),g++),delete a[u]}else for(r=o[u],n=0;n<g;n++)f=f<<1|1&r,m==t-1?(m=0,p.push(i(f)),f=0):m++,r>>=1;0==--d&&(d=Math.pow(2,g),g++)}for(r=2,n=0;n<g;n++)f=f<<1|1&r,m==t-1?(m=0,p.push(i(f)),f=0):m++,r>>=1;for(;;){if(f<<=1,m==t-1){p.push(i(f));break}m++}return p.join("")},decompress:function(e){return null==e?"":""==e?null:s._decompress(e.length,32768,(function(t){return e.charCodeAt(t)}))},_decompress:function(t,i,n){var r,s,o,a,c,l,u,d=[],h=4,g=4,p=3,f="",m=[],S={val:n(0),position:i,index:1};for(r=0;r<3;r+=1)d[r]=r;for(o=0,c=Math.pow(2,2),l=1;l!=c;)a=S.val&S.position,S.position>>=1,0==S.position&&(S.position=i,S.val=n(S.index++)),o|=(a>0?1:0)*l,l<<=1;switch(o){case 0:for(o=0,c=Math.pow(2,8),l=1;l!=c;)a=S.val&S.position,S.position>>=1,0==S.position&&(S.position=i,S.val=n(S.index++)),o|=(a>0?1:0)*l,l<<=1;u=e(o);break;case 1:for(o=0,c=Math.pow(2,16),l=1;l!=c;)a=S.val&S.position,S.position>>=1,0==S.position&&(S.position=i,S.val=n(S.index++)),o|=(a>0?1:0)*l,l<<=1;u=e(o);break;case 2:return""}for(d[3]=u,s=u,m.push(u);;){if(S.index>t)return"";for(o=0,c=Math.pow(2,p),l=1;l!=c;)a=S.val&S.position,S.position>>=1,0==S.position&&(S.position=i,S.val=n(S.index++)),o|=(a>0?1:0)*l,l<<=1;switch(u=o){case 0:for(o=0,c=Math.pow(2,8),l=1;l!=c;)a=S.val&S.position,S.position>>=1,0==S.position&&(S.position=i,S.val=n(S.index++)),o|=(a>0?1:0)*l,l<<=1;d[g++]=e(o),u=g-1,h--;break;case 1:for(o=0,c=Math.pow(2,16),l=1;l!=c;)a=S.val&S.position,S.position>>=1,0==S.position&&(S.position=i,S.val=n(S.index++)),o|=(a>0?1:0)*l,l<<=1;d[g++]=e(o),u=g-1,h--;break;case 2:return m.join("")}if(0==h&&(h=Math.pow(2,p),p++),d[u])f=d[u];else{if(u!==g)return null;f=s+s.charAt(0)}m.push(f),d[g++]=s+f.charAt(0),s=f,0==--h&&(h=Math.pow(2,p),p++)}}};return s}(),null!=ve?ve.exports=be:"undefined"!=typeof angular&&null!=angular&&angular.module("LZString",[]).factory("LZString",(function(){return be}))),Se.exports);const we=c("TVPlatform");class Te extends fe{DEFAULT_DEVICE_INFO={};bridge;isInitialized=!1;CACHE_KEY="titansdk";CACHE_EXPIRY=6048e5;constructor(e,t){if(super(e),t)this.bridge=t;else{const e={gatewayUrl:this.config.gatewayUrl};this.bridge=new Q(e)}this.initializeBridgeSafely()}async initializeBridgeSafely(){try{await this.bridge.initialize()&&(this.isInitialized=!0)}catch(e){we.warn("Bridge initialization failed:",e)}this.waitReadyResolver(!0)}getFromLocalStorage(){try{if("undefined"==typeof localStorage)return null;if(!localStorage.getItem)return null;const e=localStorage.getItem(this.CACHE_KEY);if(!e)return null;const t=JSON.parse(e);return Date.now()-t.timestamp>this.CACHE_EXPIRY?(localStorage.removeItem(this.CACHE_KEY),null):(we.debug("Device info loaded from localStorage cache"),t)}catch(e){return we.warn("Failed to load device info from localStorage:",e),null}}getFromURL(){try{const i=new URLSearchParams(window.location.search).get("titandata");if(!i)return null;let n=null;const r=new L;try{n=ye.decompressFromEncodedURIComponent(i),n&&we.debug("Device info loaded from URL parameter (lz-string)")}catch(e){we.debug("lz-string decompression failed, trying base64")}if(!n)try{const e=r.get("atob");if(!e)return we.warn("atob function not available"),null;n=e(decodeURIComponent(i)),we.debug("Device info loaded from URL parameter (base64)")}catch(t){return we.warn("Both lz-string and base64 decoding failed"),null}if(!n)return we.warn("Failed to decode URL parameter"),null;return JSON.parse(n)}catch(i){return we.warn("Failed to load device info from URL parameter:",i),null}}saveToLocalStorage(e){try{if("undefined"==typeof localStorage)return;if(!(e&&e.deviceId&&e.brand&&e.model))return void we.warn("Skipping cache save - invalid or empty device info");const t={data:e,timestamp:Date.now()};localStorage.setItem(this.CACHE_KEY,JSON.stringify(t)),we.debug("Device info saved to localStorage cache")}catch(t){we.warn("Failed to save device info to localStorage:",t)}}async getBaseDeviceInfo(){const e=this.getFromURL();if(e)return this.saveToLocalStorage(e),this.waitReadyResolver(!0),{deviceInfo:e,tts:E,tm:I};const t=this.getFromLocalStorage();if(t)return this.waitReadyResolver(!0),{deviceInfo:t.data,tts:E,tm:I};try{return await this.waitReady,await this.bridge.executeWithFallback((async()=>{const e=await this.bridge.getDeviceInfo();if(!e)throw new Error("Failed to get device info");return e}),(async()=>{we.warn("Bridge unavailable, returning fallback device info");return{deviceInfo:null,tts:E,tm:I}}))}catch(i){return we.warn("Failed to get device info from bridge:",i),{deviceInfo:null,tts:E,tm:I}}}isTV(){return"undefined"!=typeof window&&(navigator.userAgent.includes("TV")||navigator.userAgent.includes("SmartTV")||navigator.userAgent.includes("SMART-TV")||window.location.href.includes("file://"))}}const Ee=new L,Ie=new L;function Ce(){const e=document.createElement("video");return e.canPlayType&&"function"==typeof e.canPlayType?{supportAppleHLS:""!==e.canPlayType("application/vnd.apple.mpegURL")||""!==e.canPlayType("audio/mpegurl"),supportMSSmoothStreaming:""!==e.canPlayType("application/vnd.ms-sstr+xml"),supportMSSInitiator:""!==e.canPlayType("application/vnd.ms-playready.initiator+xml"),supportMPEG_DASH:""!==e.canPlayType("application/dash+xml")||"unknown"}:{supportAppleHLS:!1,supportMSSmoothStreaming:!1,supportMSSInitiator:!1,supportMPEG_DASH:"unknown"}}function Re(){try{if(void 0!==Ee.get("oipfObjectFactory"))return{supportOIPF:!0};const e=document.createElement("object");e.type="application/oipfdrmagent";return"function"==typeof e.sendDRMMessage?{supportOIPF:!0}:{supportOIPF:!1}}catch(e){return{supportOIPF:!1}}}function De(){try{const e=(new L).get("navigator"),t=void 0!==e&&"function"==typeof e.requestMediaKeySystemAccess,i=Ie.has("MSMediaKeys");return{supportWebSocket:Ie.has("WebSocket"),supportEME:t||i,hasStorage:Ie.has("localStorage")&&Ie.has("sessionStorage")}}catch(e){return{supportWebSocket:!1,supportEME:!1,hasStorage:!1}}}const Ae=new L;function Pe(){let e="";e=function(){try{const e=document.createElement("object");e.type="application/oipfdrmagent";return"function"==typeof e.sendDRMMessage?"OIPF":""}catch(e){return""}}();try{const t=Ae.has("MediaKeys"),i=Ae.has("WebKitMediaKeys"),n=Ae.has("MSMediaKeys");return e=t||i||n?"EME":e,{drmMethod:e}}catch(t){return{drmMethod:""}}}function ke(){try{const e=Ae.has("MediaKeys"),t=Ae.has("WebKitMediaKeys"),i=Ae.has("MSMediaKeys");return{supportEME:e||t||i}}catch(e){return{supportEME:!1}}}const Me=c("PhilipsCapabilities");async function Ne(){const e={os:"Linux",browserEngine:"Blink",supportPlayready:!0===await function(){const e=[{initDataTypes:["cenc"],audioCapabilities:[{contentType:'audio/mp4;codecs="mp4a.40.2"'}],videoCapabilities:[{contentType:'video/mp4;codecs="avc1.42E01E"'}]}];return new Promise((t=>{try{navigator.requestMediaKeySystemAccess("com.microsoft.playready",e).then((()=>{t(!0)})).catch((()=>{t(!1)}))}catch(i){t(!1)}}))}()||"unknown",supportWidevineModular:!0===await function(){const e=[{initDataTypes:["cenc"],audioCapabilities:[{contentType:'audio/mp4;codecs="mp4a.40.2"'}],videoCapabilities:[{contentType:'video/mp4;codecs="avc1.42E01E"'}]}];return new Promise((t=>{try{navigator.requestMediaKeySystemAccess("com.widevine.alpha",e).then((()=>{t(!0)})).catch((()=>{t(!1)}))}catch(i){t(!1)}}))}()||"unknown"},t=function(){try{const e={support3d:!1,supportKeyNumeric:!1,supportKeyColor:!1,supportMultiscreen:!1,supportUHD:!1,supportFHD:!1,supportHDR_HDR10:!1,supportHDR_DV:!1,supportHDR:"unknown",supportMultiAudio:!1,supportTTMLInband:!1,supportTTMLOutofband:!1,supportAdobeHDS:"unknown",supportWidevineClassic:"unknown",supportDolbyAtmos:"unknown"},t=_e.get("ols3DSupport");t&&t()&&(e.support3d=!0),e.supportKeyNumeric=!0,e.supportKeyColor=!0,e.supportMultiscreen=!1,e.supportMultiAudio=!0,e.supportTTMLInband=!0,e.supportTTMLOutofband=!0,e.supportFHD=!0;const i=_e.get("olsUHD"),n=_e.get("olsDVSupport"),r=i&&i(),s=n&&n();!0===r?(e.supportUHD=!0,e.supportHDR_HDR10=!0,e.supportHDR_DV=!!s,e.supportHDR_HDR10||e.supportHDR_DV?e.supportHDR=!0:e.supportHDR=!1):!1===r?(e.supportUHD=!1,e.supportHDR_HDR10=!1,e.supportHDR_DV=!1,e.supportHDR=!1):(e.supportUHD=!1,e.supportHDR_HDR10=!1,e.supportHDR_DV=!1,e.supportHDR="unknown");const o=_e.get("olsAtmosSupport");return e.supportDolbyAtmos="function"==typeof o?o():"function"==typeof n?n():"unknown",e}catch(e){return Me.error("Error detecting SmartTV API capabilities:",e),{support3d:!1,supportKeyNumeric:!1,supportKeyColor:!1,supportMultiscreen:!1,supportUHD:!1,supportFHD:!1,supportHDR_HDR10:!1,supportHDR_DV:!1,supportMultiAudio:!1,supportTTMLInband:!1,supportTTMLOutofband:!1,supportAdobeHDS:"unknown",supportHDR:"unknown",supportWidevineClassic:"unknown",supportDolbyAtmos:"unknown"}}}();return{...e,...t,...De(),...Ce(),...Pe(),...ke(),...Re()}}const _e=new L;const Oe=c("PhilipsCompat");class Le extends Te{deviceInfo=null;deviceInfoPromise=null;DEFAULT_DEVICE_INFO={Channel:{appStore:"TitanOS",vendor:"TPV",brand:"Philips"},Product:{platform:"TitanOS",year:"2025",deviceID:"philips-device",firmwareVersion:"1.0.0",firmwareComponentID:"",mac:"",WhaleAdID:H(),language:"en"}};constructor(e,t){super(e,t)}async isSupported(){return this.isTV()}async canHandle(){if(this.config.forcePlatform===this.getId())return!0;const e=navigator.userAgent.toLowerCase();return["philips","saphi","nettv","tpvision"].some((t=>e.includes(t)))}async getDeviceInfo(){if(this.deviceInfo)return this.deviceInfo;if(this.deviceInfoPromise)return await this.deviceInfoPromise;this.deviceInfoPromise=this.fetchDeviceInfoInternal();try{const e=await this.deviceInfoPromise;return this.deviceInfo=e,e}catch(e){throw this.deviceInfoPromise=null,e}}async fetchDeviceInfoInternal(){try{const e=await Ne(),t={...this.DEFAULT_DEVICE_INFO,Capability:e},i=await this.getBaseDeviceInfo();return this.formatBridgeResponse(i,t)}catch(e){throw Oe.error("Error getting device info:",e),e}}formatBridgeResponse(e,t){if(!e.deviceInfo)return t;let i=e.deviceInfo.platformName;e.deviceInfo.profileId&&(i=(e.deviceInfo.profileId.split("_")[1]||i).replace(/\d+$/,""));return t.Product.firmwareVersion=e.deviceInfo.firmwareVersion,t.Product.country=e.deviceInfo.country,t.Product.deviceID=e.deviceInfo.deviceId,t.Product.platform=i,t.Product.language=e.deviceInfo.language,t.Product.mac=e.deviceInfo.mac,t.Product.ifa=e.deviceInfo.ifa||"",t.Product.ifaType=e.deviceInfo.ifaType||"",t.Product.year=e.deviceInfo.year||"",t.Product.firmwareComponentID=i||"",t}getPriority(){return 100}getId(){return"philips"}}const xe=c("PhilipsDeviceInfoService");class He{platform;info;bridge;constructor(e,t){this.platform=new Le(e,t),this.bridge=t,this.info=null}async getDeviceInfo(){try{const e=await this.platform.getDeviceInfo();return this.info=e,this.info}catch(e){throw xe.error("Failed to get device info:",e),e}}async getCapabilities(){return this.info||(this.info=await this.getDeviceInfo()),this.info.Capability}}const Ue=c("PhilipsAppControlService");class Fe{bridge;constructor(e){this.bridge=e}async launch(e,t){return await this.bridge.executeWithFallback((()=>this.bridge.launchApp({appId:e,deepLink:t})),(async()=>(Ue.warn("Function unavailable, app launch failed gracefully",{appId:e,deepLink:t}),!1)))}}const Be=c("ChromeTTS");class Ve{voices=[];currentVoice=null;settings={available:!0,enabled:!0,rate:1,volume:1};speechSynthesis;constructor(){const e=new L;this.speechSynthesis=e.get("speechSynthesis"),this.speechSynthesis&&(this.initVoices(),"onvoiceschanged"in this.speechSynthesis&&(this.speechSynthesis.onvoiceschanged=()=>{this.initVoices()}))}initVoices(){var e,t,i,n,r,s;if(!("speechSynthesis"in window))return;const o=null==(e=this.speechSynthesis)?void 0:e.getVoices();this.voices=null==o?void 0:o.map((e=>({voiceName:e.name,lang:e.lang,gender:e.name.toLowerCase().includes("female")?"female":"male",remote:!1===e.localService}))),this.currentVoice=(null==(t=this.voices)?void 0:t.find((e=>"en-GB"===e.lang)))||(null==(i=this.voices)?void 0:i.find((e=>e.lang.startsWith("en-"))))||(null==(n=this.voices)?void 0:n[0]),Be.info(`Initialized with ${null==(r=this.voices)?void 0:r.length} voices, using ${null==(s=this.currentVoice)?void 0:s.voiceName}`)}getTTSSettings(){return this.settings}getTMSettings(){return{available:!0,enabled:!1,scale:1}}getSettings(){return{tts:this.getTTSSettings(),tm:this.getTMSettings()}}startSpeaking(e){return Be.info("Starting speaking:",e),!(!("speechSynthesis"in window)||!e||0===e.length)&&(e.forEach(((e,t)=>{var i,n,r,s;if(!e)return;const o=new SpeechSynthesisUtterance(e);if(o.rate=this.settings.rate??1,o.volume=this.settings.volume??1,o.lang=(null==(i=this.currentVoice)?void 0:i.lang)??"en-GB",this.currentVoice){const e=null==(n=this.speechSynthesis)?void 0:n.getVoices().find((e=>e.name===this.currentVoice.voiceName));e&&(o.voice=e)}0===t&&(null==(r=this.speechSynthesis)||r.cancel()),null==(s=this.speechSynthesis)||s.speak(o)})),!0)}stopSpeaking(){var e;return"speechSynthesis"in window&&(null==(e=this.speechSynthesis)||e.cancel(),!0)}stopSpeakingButKeepHighlightTask(){this.stopSpeaking()}onTTSSettingsChange(e){return()=>{}}onTMSettingsChange(e){return()=>{}}sendTTSMessage(e){}}const ze=c("VestelTTS"),Ke=e=>({available:!0,enabled:e.enabled,rate:e.rate,pitch:e.pitch,volume:e.level});class $e extends Ve{vestelSettings={available:!0,enabled:!1,rate:1,volume:1};windowApi=new L;ttsCallbacks=new Set;tmCallbacks=new Set;settingsInitialized=!1;constructor(){super(),this.initializeSettings()}async initializeSettings(){var e,t;const i=this.windowApi.get("TTSHelper");if(!i)return void ze.warn("TTSHelper not available during initialization");const n={onSuccess:e=>{this.vestelSettings=Ke(e),this.settingsInitialized=!0},onError:e=>{ze.error("Error initializing TTS settings:",e),this.settingsInitialized=!0}},r={onSuccess:e=>{this.vestelSettings=Ke(e)},onError:e=>{ze.error("Error getting TTS info:",e)}};null==(e=i.getTextToSpeechSettings)||e.call(i,n,!1),null==(t=i.getTTSInfo)||t.call(i,r)}getTTSSettings(){var e;if(!this.settingsInitialized){const t=this.windowApi.get("TTSHelper");if(t){const i={onSuccess:e=>{ze.info("Current TTS settings:",e,e.toString()),this.vestelSettings=Ke(e)},onError:e=>{ze.error("Error getting current TTS settings:",e)}};null==(e=t.getTextToSpeechSettings)||e.call(t,i,!1)}}return this.vestelSettings}getTMSettings(){return{available:this.getTTSSettings().available,enabled:!1,scale:1}}getSettings(){return{tts:this.getTTSSettings(),tm:this.getTMSettings()}}stopSpeakingButKeepHighlightTask(){this.stopSpeaking()}onTTSSettingsChange(e){var t;const i=this.windowApi.get("TTSHelper");if(!i)return ze.warn("TTSHelper not available"),()=>{};const n={onSuccess:t=>{ze.info("TTS settings changed:",t,t.toString()),e(Ke(t)),this.settingsInitialized=!0},onError:e=>{ze.error("Error getting TTS settings:",e)}};return this.ttsCallbacks.add(n),null==(t=i.getTextToSpeechSettings)||t.call(i,n,!0),()=>{var e;i&&this.ttsCallbacks.has(n)&&(null==(e=i.unsubscribe)||e.call(i,n),this.ttsCallbacks.delete(n))}}onTMSettingsChange(e){this.tmCallbacks.add(e);const t=this.onTTSSettingsChange((t=>{const i={available:t.available,enabled:!1,scale:1};e(i)})),i=this.getTMSettings();return e(i),()=>{this.tmCallbacks.delete(e),t()}}destroy(){const e=this.windowApi.get("TTSHelper");e&&this.ttsCallbacks.forEach((t=>{var i;null==(i=e.unsubscribe)||i.call(e,t)})),this.ttsCallbacks.clear(),this.tmCallbacks.clear()}}const Ge=c("AccessibilityService"),We=e=>{const{available:t,...i}=e;return i};class je{tts;reader=null;constructor(){this.tts=new $e}async startSpeaking(e){if("string"==typeof e&&(e=[e]),await this.isTTSEnabled())try{return this.tts.startSpeaking(e),!0}catch(t){return Ge.error("Error starting speaking:",t),!1}return!1}async stopSpeaking(){return await this.isTTSEnabled()&&this.tts.stopSpeaking(),!0}async enableReader(e){try{if(!(await this.isTTSSupported()))return Ge.warn("Cannot enable Reader: TTS not supported"),!1;if(!(await this.isTTSEnabled()))return Ge.warn("Cannot enable Reader: TTS not enabled"),!1;this.reader=new ae(e,this.startSpeaking.bind(this),this.stopSpeaking.bind(this));return!!(await this.reader.start())&&(Ge.info("Reader enabled"),!0)}catch(t){return Ge.error("Error enabling Reader:",t),!1}}async disableReader(){try{if(this.reader){const e=await this.reader.stop();return this.reader=null,e&&Ge.info("Reader disabled"),e}return Ge.debug("Reader was not active"),!0}catch(e){return Ge.error("Error disabling Reader:",e),!1}}getReader(){if(!this.reader)throw new Error("Reader is not active");return this.reader}async isTTSSupported(){try{return(await this.getTTSSettings()).available}catch(e){return Ge.error("Error checking TTS support:",e),!1}}async isTextMagnificationSupported(){try{return(await this.getTMSettings()).available}catch(e){return Ge.error("Error checking magnification support:",e),!1}}onTTSSettingsChange(e){return this.tts.onTTSSettingsChange(e)}onTMSettingsChange(e){return this.tts.onTMSettingsChange(e)}async getTTSSettings(){return this.tts.getTTSSettings()}async getTMSettings(){return this.tts.getTMSettings()}async isTTSEnabled(){return(await this.getTTSSettings()).enabled}async isTMEnabled(){return(await this.getTMSettings()).enabled}}class qe{subscribe(e,t){const i=l(e,t);return()=>{u(i)}}getHistory(){return d()}clear(){h()}}const Qe=c("PhilipsSDK");class Je{bridge;accessibilityService;deviceInfoService;appControlService;constructor(e){this.accessibilityService=new pe,this.bridge=new Z({gatewayUrl:null==e?void 0:e.gatewayUrl,debug:null==e?void 0:e.debug}),this.deviceInfoService=new He(e,this.bridge),this.appControlService=new Fe(this.bridge)}deviceInfo={getDeviceInfo:()=>this.deviceInfoService.getDeviceInfo(),getCapabilities:()=>this.deviceInfoService.getCapabilities()};accessibility={enableReader:e=>this.accessibilityService.enableReader(e),disableReader:()=>this.accessibilityService.disableReader(),isTTSSupported:()=>this.accessibilityService.isTTSSupported(),isTTSEnabled:()=>this.accessibilityService.isTTSEnabled(),isTMEnabled:()=>this.accessibilityService.isTMEnabled(),isTextMagnificationSupported:()=>this.accessibilityService.isTextMagnificationSupported(),getTTSSettings:async()=>We(await this.accessibilityService.getTTSSettings()),getTMSettings:async()=>We(await this.accessibilityService.getTMSettings()),startSpeaking:e=>this.accessibilityService.startSpeaking(e),stopSpeaking:()=>this.accessibilityService.stopSpeaking(),onTTSSettingsChange:e=>this.accessibilityService.onTTSSettingsChange((t=>{e(We(t))})),onTMSettingsChange:e=>this.accessibilityService.onTMSettingsChange((t=>{e(We(t))}))};apps={launch:(e,t)=>this.appControlService.launch(e,t)};get logging(){return new qe}get dev(){return{isBridgeConnected:async()=>{try{return this.bridge.isConnected()}catch(e){return!1}}}}async init(){try{return await this.deviceInfo.getDeviceInfo(),!0}catch(e){throw Qe.error("TitanSDK initialization failed:",e),e}}}function Ye(){return{os:"Linux",browserEngine:"Blink",hasStorage:!0,support3d:!1,supportUHD:!0,supportFHD:!1,supportHDR:!0,supportHDR_HDR10:!0,supportHDR_DV:!0,supportWebSocket:!0,supportPlayready:!0,supportWidevineModular:!0,supportAppleHLS:!0,supportMSSmoothStreaming:!1,supportMSSInitiator:!1,supportMPEG_DASH:!0,drmMethod:"widevine",supportOIPF:!1,supportEME:!0,supportFairplay:!1,supportAdobeHDS:!1,supportPrimetime:!1,supportClearKey:!0,supportWidevineClassic:!0,supportDolbyAtmos:!0,supportMultiscreen:!0,supportMultiAudio:!0,supportTTMLInband:!0,supportTTMLOutofband:!0,...function(){var e;try{const t=document.createElement("object");t.setAttribute("id","sysinfo"),t.setAttribute("type","systeminfoobject"),document.body.appendChild(t);const i=t,n={support3d:Boolean(i.has3D),supportUHD:(null==(e=i.panelinfo)?void 0:e.toLowerCase().includes("uhd"))||!1};return{...n,supportFHD:!n.supportUHD}}catch(t){return{support3d:!1,supportUHD:!1,supportFHD:!0}}}(),...De(),...Ce(),...Pe(),...ke(),...Re()}}const Ze=c("VestelCompat");class Xe extends Te{deviceInfo=null;deviceInfoPromise=null;DEFAULT_DEVICE_INFO={Channel:{appStore:"TitanOS",vendor:"Vestel",brand:"JVC"},Product:{platform:"TitanOS",year:"2025",deviceID:"vestel-device",firmwareVersion:"1.0.0",firmwareComponentID:"",mac:"",WhaleAdID:H(),language:"en"}};constructor(e,t){super(e,t)}async isSupported(){return this.isTV()}async canHandle(){if(this.config.forcePlatform===this.getId())return!0;const e=navigator.userAgent.toLowerCase();return["vestel"].some((t=>e.includes(t)))}async getDeviceInfo(){if(this.deviceInfo)return this.deviceInfo;if(this.deviceInfoPromise)return await this.deviceInfoPromise;this.deviceInfoPromise=this.fetchDeviceInfoInternal();try{const e=await this.deviceInfoPromise;return this.deviceInfo=e,e}catch(e){throw this.deviceInfoPromise=null,e}}async fetchDeviceInfoInternal(){try{const e=Ye(),t={...this.DEFAULT_DEVICE_INFO,Capability:e};if(await this.waitReady){const e=await this.getBaseDeviceInfo();return this.formatBridgeResponse(e,t)}return t}catch(e){throw Ze.error("Error getting device info:",e),e}}formatBridgeResponse(e,t){return e.deviceInfo?(t.Product.firmwareVersion=e.deviceInfo.firmwareVersion,t.Product.country=e.deviceInfo.country.toUpperCase(),t.Product.deviceID=e.deviceInfo.deviceId,t.Product.platform=e.deviceInfo.model,t.Product.ifa=e.deviceInfo.ifa||"",t.Product.ifaType=e.deviceInfo.ifaType||"",t.Product.mac=e.deviceInfo.mac,t.Product.year=e.deviceInfo.year||"",t):t}getPriority(){return 90}getId(){return"vestel"}}const et=c("VestelDeviceInfoService");class tt{platform;info;bridge;constructor(e,t){this.platform=new Xe(e,t),this.bridge=t,this.info=null}async getDeviceInfo(){try{const e=await this.platform.getDeviceInfo();return this.info=e,this.info}catch(e){throw et.error("Failed to get device info:",e),e}}async getCapabilities(){return this.info||(this.info=await this.getDeviceInfo()),this.info.Capability}}const it=c("VestelAppControlService");class nt{bridge;constructor(e){this.bridge=e}async launch(e,t){return await this.bridge.executeWithFallback((()=>this.bridge.launchApp({appId:e,deepLink:t})),(async()=>(it.warn("Function unavailable, app launch failed gracefully",{appId:e,deepLink:t}),!1)))}}const rt=c("VestelSDK");class st{bridge;accessibilityService;deviceInfoService;appControlService;constructor(e){this.bridge=new J({gatewayUrl:null==e?void 0:e.gatewayUrl,debug:null==e?void 0:e.debug}),this.accessibilityService=new je,this.deviceInfoService=new tt(e,this.bridge),this.appControlService=new nt(this.bridge)}deviceInfo={getDeviceInfo:()=>this.deviceInfoService.getDeviceInfo(),getCapabilities:()=>this.deviceInfoService.getCapabilities()};accessibility={enableReader:e=>this.accessibilityService.enableReader(e),disableReader:()=>this.accessibilityService.disableReader(),isTTSSupported:()=>this.accessibilityService.isTTSSupported(),isTextMagnificationSupported:()=>this.accessibilityService.isTextMagnificationSupported(),isTTSEnabled:()=>this.accessibilityService.isTTSEnabled(),isTMEnabled:()=>this.accessibilityService.isTMEnabled(),getTTSSettings:async()=>We(await this.accessibilityService.getTTSSettings()),getTMSettings:async()=>We(await this.accessibilityService.getTMSettings()),startSpeaking:e=>this.accessibilityService.startSpeaking(e),stopSpeaking:()=>this.accessibilityService.stopSpeaking(),onTTSSettingsChange:e=>this.accessibilityService.onTTSSettingsChange((t=>{e(We(t))})),onTMSettingsChange:e=>this.accessibilityService.onTMSettingsChange((t=>{e(We(t))}))};apps={launch:(e,t)=>this.appControlService.launch(e,t)};get logging(){return new qe}get dev(){return{isBridgeConnected:async()=>{try{return this.bridge.isConnected()}catch(e){return!1}}}}async init(){try{return await this.deviceInfo.getDeviceInfo(),!0}catch(e){throw rt.error("TitanSDK initialization failed:",e),e}}}const ot="titanSDK_tts_settings",at="titanSDK_tm_settings",ct=c("BrowserAccessibilityService"),lt=e=>{const{available:t,...i}=e;return i};class ut{reader=null;chromeTTS;windowMock;mockStorage;ttsSettings;tmSettings;constructor(e,t,i=!1){this.windowMock=e,this.mockStorage=t,this.chromeTTS=new Ve,this.ttsSettings=this.loadTTSSettings(),this.tmSettings=this.loadTMSettings()}loadTTSSettings(){try{const e=localStorage.getItem(ot);if(e)return{...this.getDefaultTTSSettings(),...JSON.parse(e)}}catch(e){}return this.getDefaultTTSSettings()}loadTMSettings(){try{const e=localStorage.getItem(at);if(e)return{...this.getDefaultTMSettings(),...JSON.parse(e)}}catch(e){}return this.getDefaultTMSettings()}getDefaultTTSSettings(){return{available:!0,enabled:!0,rate:1,volume:1}}getDefaultTMSettings(){return{available:!0,enabled:!1,scale:1}}saveTTSSettings(){try{localStorage.setItem(ot,JSON.stringify(this.ttsSettings))}catch(e){}}saveTMSettings(){try{localStorage.setItem(at,JSON.stringify(this.tmSettings))}catch(e){}}async startSpeaking(e){try{if(!this.ttsSettings.enabled)return ct.info("TTS is disabled in settings"),!1;const t=Array.isArray(e)?e.join(" "):e,i=this.chromeTTS.startSpeaking([t]);return i&&ct.info("🔊 Speaking:",t),i}catch(t){return ct.error("Error starting speech:",t),!1}}async stopSpeaking(){try{const e=this.chromeTTS.stopSpeaking();return e&&ct.info("🔇 Speech stopped"),e}catch(e){return ct.error("Error stopping speech:",e),!1}}async enableReader(e){try{if(!(await this.isTTSSupported()))return ct.warn("Cannot enable Reader: TTS not supported"),!1;this.reader=new ae(e,this.startSpeaking.bind(this),this.stopSpeaking.bind(this));return!!(await this.reader.start())&&(ct.info("Reader enabled"),!0)}catch(t){return ct.error("Error enabling Reader:",t),!1}}async disableReader(){try{return!!this.reader&&(await this.reader.stop(),this.reader=null,ct.info("Reader disabled"),!0)}catch(e){return ct.error("Error disabling Reader:",e),!1}}getReader(){return this.reader}async isTTSSupported(){var e,t;return void 0!==(null==(t=null==(e=this.mockStorage)?void 0:e.features)?void 0:t.tts)?this.mockStorage.features.tts:"undefined"!=typeof window&&"speechSynthesis"in window}async isTextMagnificationSupported(){var e,t;return void 0===(null==(t=null==(e=this.mockStorage)?void 0:e.features)?void 0:t.magnification)||this.mockStorage.features.magnification}onTTSSettingsChange(e){return()=>{}}onTMSettingsChange(e){return()=>{}}async getTTSSettings(){return{...this.ttsSettings}}async getTMSettings(){return{...this.tmSettings}}async isTTSEnabled(){const e=await this.getTTSSettings();return e.available&&e.enabled}async isTMEnabled(){const e=await this.getTMSettings();return e.available&&e.enabled}updateTTSSettings(e){this.ttsSettings={...this.ttsSettings,...e},this.saveTTSSettings(),ct.info("TTS settings updated:",this.ttsSettings)}updateTMSettings(e){this.tmSettings={...this.tmSettings,...e},this.saveTMSettings(),ct.info("TM settings updated:",this.tmSettings)}}const dt=c("BrowserPlatform");class ht extends fe{constructor(e){super(e),this.waitReady=new Promise((e=>{this.waitReadyResolver=e})),this.waitReadyResolver(!0)}async isSupported(){return!0}async canHandle(){return!0}async getDeviceInfo(){return dt.debug("Getting default device info for browser"),this.getDefaultDeviceInfo()}getDefaultDeviceInfo(){return{Channel:{appStore:"browser",vendor:"browser",brand:"browser"},Product:{platform:"browser",year:(new Date).getFullYear().toString(),deviceID:"browser-"+Math.random().toString(36).substring(2,10),firmwareVersion:"unknown",firmwareComponentID:"unknown",mac:"unknown"},Capability:{os:(null==navigator?void 0:navigator.platform)||"unknown",browserEngine:this.detectBrowserEngine(),hasStorage:this.hasLocalStorage(),support3d:!1,supportUHD:!1,supportHDR:!1,supportWebSocket:"WebSocket"in window,supportPlayready:!1,supportWidevineModular:!1,supportAppleHLS:!1,supportMSSmoothStreaming:!1,supportMSSInitiator:!1,supportMPEG_DASH:!1,drmMethod:"",supportOIPF:!1,supportEME:"mediaKeys"in Document.prototype}}}detectBrowserEngine(){const e=navigator.userAgent;return e.includes("Chrome")?"Blink":e.includes("Firefox")?"Gecko":e.includes("Safari")?"WebKit":e.includes("Edge")?"EdgeHTML":e.includes("Trident")?"Trident":"unknown"}hasLocalStorage(){try{return"localStorage"in window&&null!==window.localStorage}catch(e){return!1}}getPriority(){return 10}getId(){return"browser"}}const gt=c("BrowserDeviceInfoService");class pt{platform;info;options;constructor(e,t,i){this.options=e,this.info=null;const n={debug:null==e?void 0:e.debug,timeout:(null==e?void 0:e.legacyDeviceInfoTimeout)||5e3,gatewayUrl:null==e?void 0:e.gatewayUrl,useCache:!0};this.platform=new ht(n)}async getDeviceInfo(){try{const e=await this.platform.getDeviceInfo();return this.info=e,this.info}catch(e){throw gt.error("Error getting device info:",e),e}}async getCapabilities(){try{return this.info||(this.info=await this.getDeviceInfo()),this.info.Capability}catch(e){throw gt.error("Error getting device capabilities:",e),e}}}const ft=c("BrowserAppControlService");class mt{windowMock;constructor(e){this.windowMock=e}async launch(e,t){ft.debug(`Launching app: ${e} with deepLink: ${t||"none"}`);const i=this.windowMock||window;if(!i||"function"!=typeof i.open)throw new s("Cannot open new window for app launch (window.open not available)",r.NOT_SUPPORTED,{operation:"launch",appId:e,deepLink:t,platform:"browser"});try{return i.open(t||e,"_blank"),ft.info(`Opened new tab for app: ${e}`),!0}catch(n){throw ft.error("Error opening new window for app launch:",n),new s(`Failed to launch app: ${e}`,r.COMMUNICATION_ERROR,{operation:"launch",appId:e,deepLink:t,platform:"browser",originalError:n})}}}const St=c("BrowserSDK");class vt{accessibilityService;deviceInfoService;appControlService;constructor(e){this.accessibilityService=new ut(null==e?void 0:e.windowMock,null==e?void 0:e.mockStorage,(null==e?void 0:e.dev)||!1),this.deviceInfoService=new pt(e,null==e?void 0:e.windowMock,null==e?void 0:e.mockStorage),this.appControlService=new mt(null==e?void 0:e.windowMock),"undefined"!=typeof window&&Object.defineProperty(window,"titanSDK",{value:this,writable:!0,configurable:!0}),(null==e?void 0:e.debug)&&St.debug("BrowserSDK constructor finished")}deviceInfo={getDeviceInfo:()=>this.deviceInfoService.getDeviceInfo(),getCapabilities:()=>this.deviceInfoService.getCapabilities()};accessibility={enableReader:e=>this.accessibilityService.enableReader(e),disableReader:()=>this.accessibilityService.disableReader(),isTTSSupported:()=>this.accessibilityService.isTTSSupported(),isTTSEnabled:()=>this.accessibilityService.isTTSEnabled(),isTMEnabled:()=>this.accessibilityService.isTMEnabled(),isTextMagnificationSupported:()=>this.accessibilityService.isTextMagnificationSupported(),getTTSSettings:async()=>lt(await this.accessibilityService.getTTSSettings()),getTMSettings:async()=>lt(await this.accessibilityService.getTMSettings()),startSpeaking:e=>this.accessibilityService.startSpeaking(e),stopSpeaking:()=>this.accessibilityService.stopSpeaking(),onTTSSettingsChange:e=>this.accessibilityService.onTTSSettingsChange((t=>{e(lt(t))})),onTMSettingsChange:e=>this.accessibilityService.onTMSettingsChange((t=>{e(lt(t))}))};apps={launch:(e,t)=>this.appControlService.launch(e,t)};get logging(){return new qe}get dev(){return{updateTTSSettings:e=>{this.accessibilityService.updateTTSSettings(e)},updateTMSettings:e=>{this.accessibilityService.updateTMSettings(e)}}}async init(){try{return St.debug("BrowserSDK initialization started"),St.info("BrowserSDK initialized successfully"),!0}catch(e){throw St.error("BrowserSDK initialization failed:",e),e}}}const bt=c("AccessibilityService"),yt=e=>{const{available:t,...i}=e;return i};class wt{reader=null;async startSpeaking(e){return!1}async stopSpeaking(){return!1}async enableReader(e){return bt.warn("Cannot enable Reader: TTS not supported"),!1}async disableReader(){return!1}getReader(){return null}async isTTSSupported(){return!1}async isTextMagnificationSupported(){return!1}onTTSSettingsChange(e){return()=>{}}onTMSettingsChange(e){return()=>{}}async getTTSSettings(){return E}async getTMSettings(){return I}async isTTSEnabled(){return!1}async isTMEnabled(){return!1}}const Tt=c("PhilipsOldPlatform");class Et extends fe{deviceInfo=null;deviceInfoPromise=null;timeout=7e3;DEFAULT_DEVICE_INFO={Channel:{appStore:"TitanOS",vendor:"TPV",brand:"Philips"},Product:{platform:"TitanOS",year:"2023",deviceID:"philips-device",firmwareVersion:"1.0.0",firmwareComponentID:"",mac:"",WhaleAdID:H(),language:"en"}};constructor(e){super(e),this.waitReady=new Promise((e=>{this.waitReadyResolver=e})),this.waitReadyResolver(!0)}async isSupported(){return"undefined"!=typeof window&&(navigator.userAgent.includes("TV")||navigator.userAgent.includes("SmartTV")||navigator.userAgent.includes("SMART-TV")||window.location.href.includes("file://"))}async canHandle(){if(this.config.forcePlatform===this.getId())return!0;const e=navigator.userAgent.toLowerCase();return["philips","saphi","nettv","tpvision"].some((t=>e.includes(t)))}async getDeviceInfo(){if(this.deviceInfo)return this.deviceInfo;if(this.deviceInfoPromise)return await this.deviceInfoPromise;this.deviceInfoPromise=this.fetchDeviceInfoInternal();try{const e=await this.deviceInfoPromise;return this.deviceInfo=e,e}catch(e){throw this.deviceInfoPromise=null,e}}async fetchDeviceInfoInternal(){var e;try{const t=new L,i=await Ne(),n={...this.DEFAULT_DEVICE_INFO,Capability:i,supportDolbyAtmos:(null==(e=t.get("olsDVSupport"))?void 0:e())||!1};if(await this.waitReady){const e=await this.fetchDeviceInfo();return e?this.formatBridgeResponse({deviceInfo:e,tts:E,tm:I},n):n}return n}catch(t){throw Tt.warn("Error getting device info:",t),t}}async fetchDeviceInfo(){var e;try{const t="app.titanos.tv",i=await Promise.race([x(0,t,"zeasn"),new Promise((e=>{setTimeout((()=>{Tt.warn("Zeasn backend device info request timed out"),e(null)}),this.timeout)}))]);if(!i||!(null==(e=i.datas)?void 0:e.cookies))return null;const n=i.datas.cookies.profileid;return{profileId:n,deviceId:decodeURIComponent(i.datas.cookies.deviceid||""),model:i.datas.cookies.deviceYear||"",year:i.datas.cookies.deviceYear||"",firmwareVersion:i.datas.cookies.ufversion||"",country:i.datas.cookies.country||"",language:B("en"),brand:O.PHILIPS,platformName:O.PHILIPS,mac:decodeURIComponent(i.datas.cookies.mac||""),ifa:"",ifaType:""}}catch(t){return Tt.warn("Error fetching device info from backend",t),null}}formatBridgeResponse(e,t){let i="TitanOS",n="unknown";if(!e.deviceInfo)return t;if(e.deviceInfo.profileId&&(i=e.deviceInfo.platformName,e.deviceInfo.profileId)){var r=e.deviceInfo.profileId.split("_");i=(r[1]||i).replace(/\d+$/,""),n=r[1]?decodeURIComponent(r[1]):"unknown"}return t.Product.firmwareVersion=e.deviceInfo.firmwareVersion,t.Product.country=e.deviceInfo.country,t.Product.deviceID=e.deviceInfo.deviceId,t.Product.platform=i,t.Product.language=e.deviceInfo.language,t.Product.mac=e.deviceInfo.mac,t.Product.ifa=e.deviceInfo.ifa||"",t.Product.ifaType=e.deviceInfo.ifaType||"",t.Product.year=e.deviceInfo.year||"",t.Product.firmwareComponentID=n,t}getPriority(){return 100}getId(){return"philips"}}class It{platform;info;constructor(e){this.platform=new Et(e),this.info=null}async getDeviceInfo(){const e=await this.platform.getDeviceInfo();return this.info=e,this.info}async getCapabilities(){return this.info||(this.info=await this.getDeviceInfo()),this.info.Capability}}class Ct{async launch(e,t){return!1}}class Rt{accessibilityService;deviceInfoService;appControlService;constructor(e){this.accessibilityService=new wt,this.deviceInfoService=new It(e),this.appControlService=new Ct}deviceInfo={getDeviceInfo:()=>this.deviceInfoService.getDeviceInfo(),getCapabilities:()=>this.deviceInfoService.getCapabilities()};accessibility={enableReader:e=>this.accessibilityService.enableReader(e),disableReader:()=>this.accessibilityService.disableReader(),isTTSSupported:()=>this.accessibilityService.isTTSSupported(),isTTSEnabled:()=>this.accessibilityService.isTTSEnabled(),isTMEnabled:()=>this.accessibilityService.isTMEnabled(),isTextMagnificationSupported:()=>this.accessibilityService.isTextMagnificationSupported(),getTTSSettings:async()=>yt(await this.accessibilityService.getTTSSettings()),getTMSettings:async()=>yt(await this.accessibilityService.getTMSettings()),startSpeaking:e=>this.accessibilityService.startSpeaking(e),stopSpeaking:()=>this.accessibilityService.stopSpeaking(),onTTSSettingsChange:e=>()=>{},onTMSettingsChange:e=>()=>{}};apps={launch:(e,t)=>this.appControlService.launch(e,t)};get logging(){return new qe}async init(){return!0}}const Dt=c("RollbarClient"),At=["chrome://userjs/","chrome-extension://","moz-extension://","getJWTString","getjwtstring","user.js","userscript","tampermonkey","greasemonkey","can't find variable getjwtstring","referenceerror: can't find variable: getjwtstring","unexpected end of json input","jsonparse"];const Pt=new class{rollbar=null;config=null;windowWrapper=new L;initialize(e){if(e.enabled&&e.accessToken)try{this.config=e,this.rollbar=new t({accessToken:e.accessToken,environment:e.environment||"development",captureUncaught:!0,captureUnhandledRejections:!0,verbose:!1,reportLevel:"error",captureIp:!1,captureUsername:!1,captureEmail:!1,maxItems:100,itemsPerMinute:60,captureLambdaTimeouts:!1,endpoint:"https://sdk.titanos.tv/logs/",autoInstrument:{network:!1,log:!1,dom:!1,navigation:!1,connectivity:!1},payload:{client:{javascript:{code_version:"unknown",source_map_enabled:!0}}},transform:e=>{e.context&&(e.context=`hephaestus-${e.context}`)},checkIgnore:(e,t,i)=>{const n=t[0],r="string"==typeof n?n:null==n?void 0:n.message,s="object"==typeof n&&n?n.stack:"",o=String(n).toLowerCase();return At.some((e=>(null==r?void 0:r.toLowerCase().includes(e.toLowerCase()))||(null==s?void 0:s.toLowerCase().includes(e.toLowerCase()))||o.includes(e.toLowerCase())))}}),this.setupGlobalErrorHandlers(),Dt.info("Rollbar initialized successfully",{environment:e.environment})}catch(i){Dt.error("Failed to initialize Rollbar",{error:i,config:e})}else Dt.warn("Rollbar not initialized - disabled or missing access token")}shouldIgnoreError(e){if(!e)return!0;const t="string"==typeof e?e:e.message||"",i="object"==typeof e&&e.stack||"",n=String(e).toLowerCase();return At.some((e=>(null==t?void 0:t.toLowerCase().includes(e.toLowerCase()))||(null==i?void 0:i.toLowerCase().includes(e.toLowerCase()))||n.includes(e.toLowerCase())))}async reportError(e,t,i="error"){var n;return this.rollbar&&(null==(n=this.config)?void 0:n.enabled)&&e?this.shouldIgnoreError(e)?Promise.resolve(null):new Promise((n=>{this.getDeviceContext().then((r=>{var s,o,a;try{const c=d().filter((e=>!e.module.includes("RollbarClient")&&!e.message.includes("Rollbar")&&"debug"!==e.level)).slice(-20),l={logs:c.map((e=>`[${e.timestamp}] ${e.module}: ${e.message}${e.args&&e.args.length>0?"\n Args: "+JSON.stringify(e.args):""}`)).join("\n"),component:(null==t?void 0:t.component)||"SDK",operation:null==t?void 0:t.operation,requestId:null==t?void 0:t.requestId,timestamp:Date.now(),url:"undefined"!=typeof window?null==(s=window.location)?void 0:s.href:void 0,userAgent:"undefined"!=typeof navigator?navigator.userAgent:"unknown",sessionId:this.generateSessionId(),errorStack:"object"==typeof e?e.stack:void 0,version:"undefined"!=typeof window&&(null==(o=this.windowWrapper.get("TitanSDK"))?void 0:o.VERSION)||"unknown",...r,...t},u="critical"===i?"critical":"error",h="critical"===i?"critical_error_with_logs":"error_with_logs";null==(a=this.rollbar)||a[u](e,{custom:{type:h,context:l,logCount:c.length}},((t,r)=>{var s;if(t)this.shouldIgnoreError(t)||Dt.error(`Failed to send ${i} error to Rollbar`,{error:t,originalError:e}),n(null);else{const t=r&&(r.uuid||(null==(s=r.result)?void 0:s.uuid))||null;Dt.info(("critical"===i?"Critical error":"Error")+" sent to Rollbar",{message:"string"==typeof e?e:(null==e?void 0:e.message)||"Unknown error",component:l.component,rollbarId:t,logCount:c.length}),n(t)}}))}catch(c){Dt.error(`Failed to send ${i} error to Rollbar`,{error:c,originalError:e}),n(null)}})).catch((e=>{Dt.error(`Failed to get device context for ${i} error`,{error:e}),n(null)}))})):Promise.resolve(null)}collectSDKUsage(e,t,i,n){var r,s;if(this.rollbar&&(null==(r=this.config)?void 0:r.enabled))try{const r=i?"info":"warning";this.rollbar[r](`SDK function execution: ${e}`,{custom:{type:"sdk_function_execution",functionName:e,success:i,component:n,result:i?t:void 0,error:i?void 0:t,timestamp:Date.now(),url:"undefined"!=typeof window?null==(s=window.location)?void 0:s.href:void 0}}),Dt.info("SDK function execution logged",{functionName:e,success:i,component:n})}catch(o){Dt.error("Failed to log SDK function execution",{error:o,functionName:e,component:n})}}generateSessionId(){return`session_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}async getDeviceContext(){var e,t,i;try{if(null==window?void 0:window.TitanSDK)try{const n=await(null==(i=null==(t=null==(e=null==window?void 0:window.TitanSDK)?void 0:e.deviceInfo)?void 0:t.getDeviceInfo)?void 0:i.call(t));return{deviceInfo:n?JSON.stringify(n):"unavailable"}}catch(n){}return{deviceInfo:`OS: ${(null==navigator?void 0:navigator.platform)||"unknown"}, Browser: ${this.detectBrowserEngine()}, Storage: ${"localStorage"in(window||{})}`}}catch(r){return{}}}detectBrowserEngine(){if("undefined"==typeof navigator)return"unknown";const e=navigator.userAgent;return e.includes("Chrome")?"Blink":e.includes("Firefox")?"Gecko":e.includes("Safari")&&!e.includes("Chrome")?"WebKit":e.includes("Edge")?"EdgeHTML":"unknown"}setupGlobalErrorHandlers(){if("undefined"==typeof window)return;const e=console.error;console.error=(...t)=>{e.apply(console,t);const i=t.find((e=>e instanceof Error||"string"==typeof e&&e.includes("Error")));i&&!this.shouldIgnoreError(i)&&this.reportError(i,{component:"SDK",operation:"console.error"})},"undefined"!=typeof window&&(window.addEventListener("error",(e=>{this.shouldIgnoreError(e.error)||this.reportError(e.error||e.message,{component:"SDK",operation:"window.onerror"})})),window.addEventListener("unhandledrejection",(e=>{this.shouldIgnoreError(e.reason)||this.reportError(e.reason,{component:"SDK",operation:"unhandledrejection"})})))}isInitialized(){var e;return null!==this.rollbar&&!0===(null==(e=this.config)?void 0:e.enabled)}},kt=Object.freeze(Object.defineProperty({__proto__:null,rollbarClient:Pt},Symbol.toStringTag,{value:"Module"})),Mt=c("SmartTvA_API"),Nt=(e,t)=>{var i,n,r,s;try{if(!t)return Mt.warn(`Device info not available, cannot check capability: ${e}`),!1;const o=t.Product||{},a=t.Channel||{},c=t.Capability||{};switch(e){case"3d":return Boolean(c.support3d);case"uhd":return Boolean(c.supportUHD);case"dolby-vision":return Boolean(c.supportHDR&&((null==(i=o.platform)?void 0:i.toLowerCase().includes("dolby"))||(null==(n=a.brand)?void 0:n.toLowerCase().includes("dolby"))));case"atmos":return Boolean((null==(r=o.platform)?void 0:r.toLowerCase().includes("atmos"))||(null==(s=a.brand)?void 0:s.toLowerCase().includes("dolby")));default:return Mt.warn(`Unknown device capability: ${e}`),!1}}catch(o){return Mt.error(`Error checking device capability ${e}:`,o),!1}},_t=async e=>{if("undefined"==typeof window)return void Mt.warn("Window object not available, cannot attach SmartTvA_API");if("object"==typeof window.SmartTvA_API)return void Mt.info("SmartTvA_API already exists on window, skipping initialization");const t=await(async e=>{Mt.info("Initializing SmartTvA_API with TitanSDK");let t=null;try{Mt.info("Waiting for device info to be ready..."),t=await e.deviceInfo.getDeviceInfo(),Mt.info("Device info is ready, proceeding with SmartTvA_API initialization")}catch(i){Mt.warn("Failed to get device info during SmartTvA_API initialization:",i)}return{exit:()=>{Mt.info("SmartTvA_API.exit() called"),window.close()},hasCapability:(e,...i)=>{switch(Mt.debug(`SmartTvA_API.hasCapability('${e}', ${i.join(", ")})`),e){case"3DSupport":return Nt("3d",t);case"MultiScreen":return 1===i.length&&i[0],!1;case"DRM":if(2===i.length){const[e,t]=i;if("PlayReady"===e&&"DASH"===t)return!0;if("Widevine"===e&&"AdaptiveStreaming"===t)return!1}return!1;case"Key":if(1===i.length)switch(i[0]){case"numerickeys":case"colorkeys":case"prev_next":return!0;default:return!1}return!1;case"UHD":return Nt("uhd",t);case"FHD":case"Multiaudio":return!0;case"TTML":if(1===i.length)switch(i[0]){case"inband":case"outofband":case"EBU-TT-D":case"CFF-TT":return!0;default:return!1}return!1;case"HLS":return 1===i.length&&"DISCONTINUITY"===i[0];case"HDR":if(1===i.length){const e=i[0];if(!Nt("uhd",t))return!1;switch(e){case"HDR10":case"DA":case"HDR10+":return!0;case"DV":return Nt("dolby-vision",t);default:return!1}}return!1;case"8K":case"WidevineClassic":case"AdobeHDS":return!1;case"ATMOS":return Nt("atmos",t);default:return Mt.warn(`Unknown capability requested: ${e}`),!1}}}})(e);Object.defineProperty(window,"SmartTvA_API",{value:t,writable:!1,configurable:!0}),Mt.info("SmartTvA_API successfully attached to window object")},Ot=c("WrapperUtils");function Lt(e){return{getTTSSettings:async()=>(await e()).accessibility.getTTSSettings(),getTMSettings:async()=>(await e()).accessibility.getTMSettings(),isTTSSupported:async()=>(await e()).accessibility.isTTSSupported(),isTTSEnabled:async()=>(await e()).accessibility.isTTSEnabled(),isTMEnabled:async()=>(await e()).accessibility.isTMEnabled(),isTextMagnificationSupported:async()=>(await e()).accessibility.isTextMagnificationSupported(),startSpeaking:async t=>(await e()).accessibility.startSpeaking(t),stopSpeaking:async()=>(await e()).accessibility.stopSpeaking(),enableReader:async t=>(await e()).accessibility.enableReader(t),disableReader:async()=>(await e()).accessibility.disableReader(),onTTSSettingsChange:t=>{let i=null;return e().then((e=>{i=e.accessibility.onTTSSettingsChange(t)})).catch((e=>{Ot.error("Failed to set up TTS settings change handler:",e)})),()=>{i&&i()}},onTMSettingsChange:t=>{let i=null;return e().then((e=>{i=e.accessibility.onTMSettingsChange(t)})).catch((e=>{Ot.error("Failed to set up TM settings change handler:",e)})),()=>{i&&i()}}}}function xt(e){return{launch:async(t,i)=>(await e()).apps.launch(t,i)}}const Ht="1.6.3-HEAD.1",Ut=c("SDK"),Ft={debug:!1,useLegacyDeviceInfo:!1,legacyDeviceInfoTimeout:5e3,fallbackToBrowser:!0};let Bt=null,Vt=null,zt=null,Kt=null;Pt.initialize({accessToken:"",enabled:!1});const $t=async()=>{if(!Bt)throw new s("SDK not created. Call getTitanSDK() first.",r.NOT_INITIALIZED);if(!zt)throw Ut.error("SDK initialization not started"),new s("SDK initialization not started.",r.NOT_INITIALIZED);if(!(await zt))throw new s("SDK initialization failed.",r.UNKNOWN);return Bt},Gt=e=>{if(Vt)return Vt;const t={...Ft,...e};o.setDebugMode(t.debug??!1);const i=y.detectPlatform(t).platform;Ut.info("Platform detected:",i);try{switch(i){case n.PHILIPS:Bt=new Je(t);break;case n.PHILIPS_OLD:Bt=new Rt(t);break;case n.VESTEL:Bt=new st(t);break;case n.BROWSER:default:i!==n.BROWSER&&t.debug&&Ut.warn(`Platform ${i} detected but no specific SDK found, using BrowserSDK as fallback.`),Bt=new vt(t)}if(!Bt)throw new s("Failed to create SDK instance after platform detection",r.UNKNOWN)}catch(u){throw Ut.error("Error creating SDK instance:",u),new s(`Failed to create SDK instance after platform detection: ${u}`,r.UNKNOWN)}zt=Bt.init(),Ut.info("SDK Version:",Ht);const a={VERSION:Ht,isReady:zt,deviceInfo:(c=$t,l=e=>{Kt=e},{getDeviceInfo:async()=>{const e=await c(),t=await e.deviceInfo.getDeviceInfo();return null==l||l(t),t}}),accessibility:Lt($t),apps:xt($t)};var c,l;return t.debug&&(Ut.info("🔧 [DEBUG MODE] TitanSDK debug access enabled"),a.logging=function(e){let t=null;return{subscribe:(i,n)=>{let r=null;return e().then((e=>{t=e,e.logging&&(r=e.logging.subscribe(i,n))})).catch((e=>{Ot.error("Failed to set up logging subscription:",e)})),()=>{r&&r()}},getHistory:()=>(null==t?void 0:t.logging)?t.logging.getHistory():[],clear:()=>{(null==t?void 0:t.logging)&&t.logging.clear()}}}($t)),t.dev&&(t.debug&&Ut.info("🔧 [DEV MODE] TitanSDK dev access enabled"),i===n.BROWSER&&t.dev&&(Ut.info("Available dev methods:"),Ut.info(" sdk.dev.updateTTSSettings({ enabled: true, rate: 1.5 })"),Ut.info(" sdk.dev.updateTMSettings({ enabled: true, scale: 1.8 })")),a.dev=function(e){return{updateTTSSettings:async t=>{var i,n;return null==(n=null==(i=(await e()).dev)?void 0:i.updateTTSSettings)?void 0:n.call(i,t)},updateTMSettings:async t=>{var i,n;return null==(n=null==(i=(await e()).dev)?void 0:i.updateTMSettings)?void 0:n.call(i,t)},simulateError:async t=>{var i,n;return null==(n=null==(i=(await e()).dev)?void 0:i.simulateError)?void 0:n.call(i,t)},simulateGatewayError:async(t,i)=>{var n,r;return null==(r=null==(n=(await e()).dev)?void 0:n.simulateGatewayError)?void 0:r.call(n,t,i)},isBridgeConnected:async()=>{var t,i;return(null==(i=null==(t=(await e()).dev)?void 0:t.isBridgeConnected)?void 0:i.call(t))??!1}}}($t)),Vt=a,zt.then((async()=>{try{Kt=await Bt.deviceInfo.getDeviceInfo()}catch(u){t.debug&&Ut.warn("Failed to pre-cache device info:",u)}})).catch((e=>{Ut.error(`Initialization failed for platform ${i}:`,e)})),Vt},Wt=async()=>{const e=await $t(),t=await e.deviceInfo.getDeviceInfo();return Kt=t,t};if("undefined"!=typeof document&&document.addEventListener("securitypolicyviolation",(e=>{j.getViolations()})),"undefined"!=typeof window)if(window.TitanSDK&&window.TitanSDK.deviceInfo)Ut.info("TitanSDK already exists on window, skipping initialization"),Ut.info("You can still create a new SDK instance using window.getTitanSDK(options)"),window.getTitanSDK=Gt;else{const e=()=>{window.onDeviceInfoReady=function(e){Wt().then((t=>e(t))).catch((t=>e({},String(t))))},Object.defineProperty(window,"DeviceInfo",{get:()=>{if(Kt)return Kt;if(Bt&&Vt)try{return Bt.deviceInfo.getDeviceInfo()}catch{return null}return null},configurable:!0}),void 0===window.SmartTvA_API&&Object.defineProperty(window,"SmartTvA_API",{value:{exit:()=>window.close()},writable:!1,configurable:!0})},t=e=>{const t=null==localStorage?void 0:localStorage.getItem(e);return t?JSON.parse(t):{}},i=(new L).get("TITAN_SDK_PARAMS")||t("TITAN_SDK_PARAMS");i&&Ut.info("Initializing TitanSDK with params:",i),window.TitanSDK=Gt(i),e(),_t(window.TitanSDK).catch((e=>{Ut.error("Failed to initialize SmartTvA_API:",e)}))}e.VERSION=Ht,e.getDeviceInfo=Wt,e.getTitanSDK=Gt,Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})}));
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@titan-os/sdk",
|
|
3
|
+
"version": "1.6.2",
|
|
4
|
+
"description": "TitanOS SDK for TV platforms",
|
|
5
|
+
"main": "dist/cjs/sdk.js",
|
|
6
|
+
"module": "dist/esm/sdk.js",
|
|
7
|
+
"types": "dist/types/sdk.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
"types": "./dist/types/sdk.d.ts",
|
|
10
|
+
"import": "./dist/esm/sdk.js",
|
|
11
|
+
"require": "./dist/cjs/sdk.js"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist/types/",
|
|
15
|
+
"dist/esm/",
|
|
16
|
+
"dist/cjs/",
|
|
17
|
+
"dist/umd/"
|
|
18
|
+
],
|
|
19
|
+
"sideEffects": false,
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"rollbar": "^2.26.2"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"vite": "^6.3.5",
|
|
25
|
+
"rollup-plugin-visualizer": "^5.12.0",
|
|
26
|
+
"typescript": "^5.7.2"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "npm run build:types && npm run build:esm && npm run build:cjs && npm run build:umd",
|
|
30
|
+
"build:types": "vite build --config vite.types.config.ts && rm -rf dist/temp",
|
|
31
|
+
"build:esm": "vite build --config vite.esm.config.ts",
|
|
32
|
+
"build:cjs": "vite build --config vite.cjs.config.ts",
|
|
33
|
+
"build:umd": "vite build --config vite.umd.config.ts",
|
|
34
|
+
"build:debug": "DEBUG_BUILD=true npm run build",
|
|
35
|
+
"test": "node tests/test-build.js",
|
|
36
|
+
"test:imports": "node tests/test-imports.js",
|
|
37
|
+
"test:real": "node tests/test-real-imports.js",
|
|
38
|
+
"test:types": "node tests/test-types.js",
|
|
39
|
+
"test:all": "npm run test && npm run test:imports && npm run test:real && npm run test:types",
|
|
40
|
+
"clean": "rm -rf dist/",
|
|
41
|
+
"prepublishOnly": "npm run build"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"titanos",
|
|
45
|
+
"sdk",
|
|
46
|
+
"tv",
|
|
47
|
+
"smart-tv",
|
|
48
|
+
"philips",
|
|
49
|
+
"vestel",
|
|
50
|
+
"browser",
|
|
51
|
+
"accessibility",
|
|
52
|
+
"device-info"
|
|
53
|
+
],
|
|
54
|
+
"author": "TitanOS",
|
|
55
|
+
"license": "Apache-2.0",
|
|
56
|
+
"bugs": {
|
|
57
|
+
"email": "titan-sdk-support@titanos.tv"
|
|
58
|
+
},
|
|
59
|
+
"homepage": "https://docs.titanos.tv/titan-sdk"
|
|
60
|
+
}
|