define(['appStorage', 'browser', 'events', 'require'], function (appStorage, browser, events, require) { 'use strict'; let applicationInfo = null; let fadeStyleElement = null; var speechRecognitionPromiseResolve = null; var speechRecognitionPromiseReject = null; ////console.log = function () { }; function getDeviceProfile() { const comparePriority = (a, b) => (a.priority || 0) - (b.priority || 0); const filterPlayerByType = (player, mediaType) => player.isLocalPlayer !== false && canPlayerPlayMediaType(player, mediaType); const filterVideoPlayers = (player) => filterPlayerByType(player, 'video'); const filterAudioPlayers = (player) => filterPlayerByType(player, 'audio'); const filterVideoType = (e) => e.Type === 'Video' || !e.Type; const filterAudioType = (e) => e.Type === 'Audio'; const filterVideoAudioType = (e) => e.Type === 'VideoAudio'; const appendRange = (source, target) => (source || []).forEach(e => target.push(e)); const copyProfiles = (source, target, filterFn) => appendRange((source || []).filter(filterFn), target); function canPlayerPlayMediaType(player, mediaType) { if (player.mediaType && player.mediaType.toLowerCase() === mediaType.toLowerCase()) { return true; } if (player.mediaTypes) { return player.mediaTypes.indexOf(mediaType) >= 0; } return player.canPlayMediaType(mediaType); } return require(['pluginManager']).then(function (responses) { const pluginManager = responses[0]; const videoPlayers = pluginManager.ofType('mediaplayer').filter(filterVideoPlayers); const audioPlayers = pluginManager.ofType('mediaplayer').filter(filterAudioPlayers); videoPlayers.sort(comparePriority); audioPlayers.sort(comparePriority); const videoPromise = videoPlayers[0]?.getDeviceProfile() || Promise.resolve(null); const audioPromise = audioPlayers[0]?.getDeviceProfile() || Promise.resolve(null); return Promise.all([videoPromise, audioPromise]).then(function ([videoProfile, audioProfile]) { const syncProfile = { Name: 'SyncProfile for ' + applicationInfo.DeviceName, Id: applicationInfo.DeviceId, SupportedMediaTypes: 'Photo', MaxStreamingBitrate: videoProfile?.MaxStreamingBitrate || 8000000, MusicStreamingTranscodingBitrate: audioProfile?.MusicStreamingTranscodingBitrate || 256000, MaxStaticMusicBitrate: audioProfile?.MaxStaticMusicBitrate, DirectPlayProfiles: [], TranscodingProfiles: [], ContainerProfiles: [], CodecProfiles: [], ResponseProfiles: [], SubtitleProfiles: [] }; if (videoProfile) { syncProfile.SupportedMediaTypes += ',Video'; copyProfiles(videoProfile.DirectPlayProfiles, syncProfile.DirectPlayProfiles, filterVideoType); copyProfiles(videoProfile.TranscodingProfiles, syncProfile.TranscodingProfiles, filterVideoType); copyProfiles(videoProfile.ContainerProfiles, syncProfile.ContainerProfiles, filterVideoType); copyProfiles(videoProfile.CodecProfiles, syncProfile.CodecProfiles, filterVideoType); copyProfiles(videoProfile.CodecProfiles, syncProfile.CodecProfiles, filterVideoAudioType); copyProfiles(videoProfile.ResponseProfiles, syncProfile.ResponseProfiles, filterVideoType); appendRange(videoProfile.SubtitleProfiles, syncProfile.SubtitleProfiles); } if (audioProfile) { syncProfile.SupportedMediaTypes += ',Audio'; copyProfiles(audioProfile.DirectPlayProfiles, syncProfile.DirectPlayProfiles, filterAudioType); copyProfiles(audioProfile.TranscodingProfiles, syncProfile.TranscodingProfiles, filterAudioType); copyProfiles(audioProfile.ContainerProfiles, syncProfile.ContainerProfiles, filterAudioType); copyProfiles(audioProfile.CodecProfiles, syncProfile.CodecProfiles, filterAudioType); copyProfiles(audioProfile.ResponseProfiles, syncProfile.ResponseProfiles, filterAudioType); } return syncProfile; }); }); } function supports(command) { return globalThis.NativeAppHost.supports(command); } var appHost = { init: function () { // Dummy call globalThis.NativeAppHost.supportsAsync('test'); applicationInfo = globalThis.NativeAppHost.getApplicationInfo(); // Feature sharepolyfill if (!navigator.share && supports('sharepolyfill')) { navigator.share = function (data) { return globalThis.NativeFeatures.sharePolyfillAsync(data.text, data.title, data.imageUrl, data.url); }; } // Feature clipboardwritetext if (supports('clipboardwritetext')) { navigator.clipboard.writeText = function (text) { try { globalThis.NativeFeatures.clipboardWriteText(text); } catch (err) { return Promise.reject(err); } return Promise.resolve(); }; } // Feature onconnectionchange if (navigator.connection && navigator.connection.addEventListener && supports('onconnectionchange')) { navigator.connection.addEventListener('change', function (e) { let eventJson = JSON.stringify(e); globalThis.NativeFeatures.onConnectionChange(eventJson); }); } globalThis.NativeAppHost.initialized = true; return Promise.resolve(); }, deviceName: function () { return applicationInfo.DeviceName; }, deviceId: function () { return applicationInfo.DeviceId; }, appName: function () { return applicationInfo.Name; }, appVersion: function () { return applicationInfo.Version; }, deviceIconUrl: function () { return applicationInfo.DeviceIconUrl; }, supports: function (command) { return globalThis.NativeAppHost.supports(command); }, getWindowState: function () { if (supports('getwindowstate')) { return globalThis.NativeFeatures.getWindowState(); } return document.windowState || 'Normal'; }, setWindowState: function (state) { if (supports('windowstate')) { globalThis.NativeFeatures.setWindowState(state); return; } throw new Error('setWindowState is not supported and should not be called'); }, exit: function () { if (supports('exit')) { globalThis.NativeFeatures.exitApp(); } }, sleep: function () { if (supports('sleep')) { globalThis.NativeFeatures.sleepSystem(); } }, shutdown: function () { if (supports('shutdown')) { globalThis.NativeFeatures.shutdownSystem(); } }, restart: function () { if (supports('restart')) { globalThis.NativeFeatures.restartSystem(); } }, getDefaultLayout: function () { if (supports('defaultlayout')) { return globalThis.NativeFeatures.getDefaultLayout(); } return null; }, getPushTokenInfo: function () { if (supports('getpushtokeninfo')) { return globalThis.NativeFeatures.getPushTokenInfo(); } return {}; }, setTheme: function (themeSettings) { if (supports('settheme')) { globalThis.NativeFeatures.setTheme(themeSettings); return; } var metaThemeColor = document.querySelector('meta[name=theme-color]'); if (metaThemeColor) { metaThemeColor.setAttribute('content', themeSettings.themeColor); } }, setUserScalable: function (scalable) { if (supports('setuserscalable')) { globalThis.NativeFeatures.setUserScalable(scalable); return; } if (browser.tv) { return; } var att = scalable ? 'viewport-fit=cover, width=device-width, initial-scale=1, minimum-scale=1, user-scalable=yes' : 'viewport-fit=cover, width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no'; document.querySelector('meta[name=viewport]').setAttribute('content', att); }, requestSpeechRecognitionPermission: function () { if (supports('requestspeechrecognitionpermission')) { var result = globalThis.NativeFeatures.requestSpeechRecognitionPermission(); if (result) { return Promise.resolve(); } return new Promise(function (resolve, reject) { speechRecognitionPromiseResolve = resolve; speechRecognitionPromiseReject = reject; }); } return Promise.resolve(); }, setSystemUIHidden: function (hidden) { if (supports('setsystemuihidden')) { globalThis.NativeFeatures.setSystemUiHidden(hidden); } }, getPreferredTheme: function () { if (supports('preferredtheme')) { return globalThis.NativeFeatures.getPreferredTheme(); } return null; }, getDefaultSoundEffects: function () { if (supports('defaultsoundeffects')) { return globalThis.NativeFeatures.getDefaultSoundEffects(); } return 'defaultsoundeffects'; }, getSyncProfile: getDeviceProfile, prepareFadeIn: function () { var fadeInCss = ` .introFadeIn { opacity: 1; transition: opacity 1s ease-out; background: transparent; } .introFadeInPending { opacity: 0; } `; // Create a new style element fadeStyleElement = document.createElement('style'); fadeStyleElement.textContent = fadeInCss; document.head.appendChild(fadeStyleElement); document.documentElement.classList.add('introFadeIn'); document.documentElement.classList.add('introFadeInPending'); var appSplash = document.querySelector('.app-splash'); if (appSplash) { appSplash.classList.add('hide'); } }, performFadeIn: function () { document.documentElement.classList.remove('introFadeInPending'); setTimeout(() => { document.documentElement.classList.remove('introFadeIn'); if (fadeStyleElement) { fadeStyleElement.remove(); fadeStyleElement = null; } }, 2000); } }; globalThis.onSpeechRecognitionPermissionResult = function (granted) { let fn = granted ? speechRecognitionPromiseResolve : speechRecognitionPromiseReject; if (fn) { fn(); } speechRecognitionPromiseResolve = null; speechRecognitionPromiseReject = null; }; events.on(globalThis.NativeAppHost, 'resume', function () { console.log('RESUME'); events.trigger(appHost, 'resume'); }); //if (!navigator.share) { // navigator.share = sharePolyfill; //} function validateServerAddressWithEndpoint(connectionManager, ajax, url, endpoint) { return ajax({ url: connectionManager.getEmbyServerUrl(url, endpoint), timeout: 20000, type: 'GET', dataType: 'text' }).then(function (result) { if ((result || '').toLowerCase().indexOf(String.fromCharCode(106) + String.fromCharCode(101) + String.fromCharCode(108) + String.fromCharCode(108)) !== -1) { return Promise.reject(); } return Promise.resolve(); }); } function validateServerAddress(connectionManager, ajax, url) { return Promise.all([ validateServerAddressWithEndpoint(connectionManager, ajax, url, 'web/manifest.json'), validateServerAddressWithEndpoint(connectionManager, ajax, url, 'web/index.html'), validateServerAddressWithEndpoint(connectionManager, ajax, url, 'web/strings/en-US.json') ]); } appHost.validateServerAddress = function (connectionManager, ajax, url) { return validateServerAddress(connectionManager, ajax, url); }; var doc = globalThis.document; var _isHidden = false; function onAppVisible() { if (_isHidden) { _isHidden = false; //console.log('triggering app resume event'); events.trigger(appHost, 'resume'); } } function onAppHidden() { if (!_isHidden) { _isHidden = true; //console.log('app is hidden'); } } if (doc) { doc.addEventListener('visibilitychange', function () { if (document.hidden) { onAppHidden(); } else { onAppVisible(); } }); } if (globalThis.addEventListener) { globalThis.addEventListener('focus', onAppVisible); globalThis.addEventListener('blur', onAppHidden); } return appHost; });