EmbyCrackedClient/web/native/interop/apphost.js
2025-06-25 11:46:04 +08:00

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;
});