443 lines
No EOL
14 KiB
JavaScript
443 lines
No EOL
14 KiB
JavaScript
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;
|
|
}); |